I'm stuck trying to figure out how to make this JS work

Below is the script I created to get several things done, one after another. It is supposed to:

  1. Spin a round icon onload. (It will be onclick, but I haven’t incorporated that yet, but I know how to.)
  2. Pick a random number from 1-21 inclusive. For some reason, console.log displays two numbers, each on its own line. So there’s something wrong right there.
  3. Connect each number with the ID of a card on the page, and choose the ID of the card that matches the random number. Save that number in localStorage.
  4. Jump to the ID and color the font a contrasting color so it briefly stands out. Two error messages in the console are given (below). Don’t know what steps to take to fix them.
<script>
    // spin the wheel
    const myTimeout = setTimeout(jumpToRandom, 3000); // give wheel time to spin before doing rest of code
    const icon = document.getElementById('icon');
icon.addEventListener('click', () => {
  icon.classList.add('spin');
});
icon.addEventListener('animationend', ()=>{
	icon.classList.remove('spin');
}); 
    
    // make a random choice and slide the screen to display the choice
    // save the choice to storage for use in the next function
icon.addEventListener("click", jumpToRandom);
    
function jumpToRandom() {
let choice = Math.floor(Math.random() * 20) + 1;
console.log("Random choice number is " + choice); // Why are two different numbers displayed?
    switch (choice) {
  case 1:
    "window.location.assign('#gooddeeds')"; localStorage.setItem("choice", gooddeeds); getAttn();
    break;
  case 2:
    "window.location.assign('#doesgotwant')"; localStorage.setItem("choice", doesgotwant); getAttn();
    break;
  case 3:
    "window.location.assign('#doesjesusforgive')"; localStorage.setItem("choice", doesjesusforgive); getAttn();
    break;
  case 4:
    "window.location.assign('#doyouhaveeternal')"; localStorage.setItem("choice", doyouhaveeternal); getAttn();
    break;
  case 5:
    "window.location.assign('#howdoyouget')"; localStorage.setItem("choice", howdoyouget); getAttn();
    break;
  case 6:
    "window.location.assign('#ifyouwere')"; localStorage.setItem("choice", ifyouwere); getAttn();
    break;
  case 7:
    "window.location.assign('#iseveryone')"; localStorage.setItem("choice", iseveryone); getAttn();
    break;
  case 8:
    "window.location.assign('#isjesusdead')"; localStorage.setItem("choice", isjesusdead); getAttn();
    break;
  case 9:
    "window.location.assign('#isjesusthe')"; localStorage.setItem("choice", isjesusthe); getAttn();
    break;
  case 10:
    "window.location.assign('#iamthe')"; localStorage.setItem("choice", iamthe); getAttn();
    break;
  case 11:
    "window.location.assign('#name3of')"; localStorage.setItem("choice", name3of); getAttn();
    break;
  case 12:
    "window.location.assign('#recitejohn')"; localStorage.setItem("choice", recitejohn); getAttn();
    break;
  case 13:
    "window.location.assign('#namesofjesus')"; localStorage.setItem("choice", namesofjesus); getAttn();
    break;
  case 14:
    "window.location.assign('#whatdidjesusdo')"; localStorage.setItem("choice", whatdidjesusdo); getAttn();
    break;
  case 15:
    "window.location.assign('#bornagain')"; localStorage.setItem("choice", bornagain); getAttn();
    break;
  case 16:
    "window.location.assign('#comeback')"; localStorage.setItem("choice", comeback); getAttn();
    break;
  case 17:
    "window.location.assign('#enterheaven')"; localStorage.setItem("choice", enterheaven); getAttn();
    break;
  case 18:
    "window.location.assign('#havetodie')"; localStorage.setItem("choice", havetodie); getAttn();
    break;
  case 19:
    "window.location.assign('#needsaving')"; localStorage.setItem("choice", needsaving); getAttn();
    break;
  case 20:
    "window.location.assign('#lambofgod')"; localStorage.setItem("choice", lambofgod); getAttn();
    break;
  case 21:
    "window.location.assign('#bigdeal')"; localStorage.setItem("choice", bigdeal); getAttn();
    break;
    }
// grab the choice from storage
function getAttn() {
    var elem = localStorage.getItem("choice");
alert("elem is " + elem); // console: "elem is [object HTMLDivElement]"
// select the ID of the choice and change the font color to highlight the choice
    var elem2 = document.getElementById('elem'); // console says "Uncaught TypeError: elem2 is null"
alert("elem2 is " + elem2); 
    elem2.style.color = 'green';
    }
}
</script>

You have a few issues. First:

Because you’re calling the function twice. Once with a 3 second delay:

And again when you click the icon:

Your giant switch statement could be simplified. Every branch does the same thing, just with a different element (I am assuming the gooddeeds, etc. are defined elsewhere). Your strings "window.location.assign('#gooddeeds')"; do nothing. Either make that code not a string, or remove it entirely. If you put all your element variables into an array, you can access them by using your choice as the index.

You also cannot store DOM elements into localStorage, and you shouldn’t be using localStorage just to pass data around between functions. localStorage is meant for data you want to persist across browser sessions. If you do in fact want the choice to persist, you need to store either the selected choice number or the ID string of the element, not the element itself.

Once you remove the giant switch statement, you don’t need your separate getAttn function, that code can just come after you choose an element. The refactored function would be something like:

function jumpToRandom(){
    const choiceList = [
        gooddeeds, doesgotwant, doesjesusforgive, doyouhaveeternal, howdoyouget, ifyouwere, iseveryone,
        isjesusdead, isjesusthe, iamthe, name3of, recitejohn, namesofjesus, whatdidjesusdo, bornagain,
        comeback, enterheaven, havetodie, needsaving, lambofgod, bigdeal
    ]
    let choiceIndex = Math.floor(Math.random() * choiceList.length);
    console.log("Random choice number is " + choiceIndex); // Why are two different numbers displayed?

    let choice = choiceList[choiceIndex];
    window.location.assign('#' + choice.id);
    choice.style.color = 'green';
}

You define an array of all the choices. You then select a random number between 0 and choiceList.length. This way, just adding an item to the choice list will make it part of the selection, no need to keep the number of choices and your random number generation code in sync.

Once you have your random choice index, access that choice element with a simple index operation. Update your window location with it’s id attribute, and set it’s color directly.

1 Like

So the code in the switch statements are seen as strings and not code to run? Thanks for all the help.

How do I change the beginning so that the events happen after tapping on the “icon” instead of automatically on page load? I’d like to scroll to top (already have that functionality) and click again for another spin.

This is just a string:

"window.location.assign('#gooddeeds')"; 

Since it has quotes around it. It doesn’t do anything.

You already have the code to run the spin on click, by binding to the click event.

If you want to delay the jumpToRandom function until the spin is complete, then just call it in the animationend event handler. There is no need to use setTimeout with a fixed delay. There’s no need to attach that function as a click event handler either, so you’d delete those two pieces of code.

So you’d end up with just:

const icon = document.getElementById('icon');
icon.addEventListener('click', () => {
  icon.classList.add('spin');
});
icon.addEventListener('animationend', ()=>{
	icon.classList.remove('spin');
	jumpToRandom();
}); 
1 Like

My project is done. Thank you so much for all your help!!