0

I am trying to teach myself to code. I am coding a simple quiz. I would like my timer to fire on "start", and eventually, "next question". My timer starts once the page loads. Not sure why.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
    <button id="b1">Click Me!</button>
    <p id="demo"></p>
    <script>
        var sec = 5;
        var time = setInterval(myTimer, 1000);

        function myTimer() {
            document.getElementById("b1").onclick = function() {  
                 myTimer()  
            };  

            document.getElementById('demo').innerHTML = sec + "sec.";
            sec--;
            if (sec <= -1) {
                clearInterval(time);
                // alert("Time out!! :(");
                document.getElementById("demo").innerHTML="Time's up!";
            }
        }

Have tried several different ways, including "addEventListener". Nothing seems to work.

a2k42
  • 672
  • 6
  • 19
astroboyee
  • 13
  • 1
  • 1
  • 5

2 Answers2

1

If you take a look at a minimal example you'll see that this also runs as soon as the page is loaded. Here setInterval() is called when the script loads in the page. In turn the run() function is called every second.

var timerID = setInterval(run, 1000);

function run() {
    console.log("I'm running");
}

Think of the difference between var timer = run; and var timer = run(). The first assigns the function run to timer. The later executes run() and assigns the return value.

Here's your code with comments:

var sec = 5;
// start interval timer and assign the return value "intervalID" to time
var time = setInterval(myTimer, 1000);

// to be called every second
function myTimer() {
    // assign an onclick handler to "b1" EVERY SECOND!
    document.getElementById("b1").onclick = function() {
        myTimer()
    };

    // update the demo DOM element with sec
    document.getElementById('demo').innerHTML = sec + "sec.";
    sec--;
    if (sec <= -1) {
        clearInterval(time);
        // alert("Time out!! :(");
        document.getElementById("demo").innerHTML="Time's up!";
    }
}

For a solution I've moved setInterval into the onclick handler and moved said handler assignment out of the myTimer function as you only want to setup your handlers once.

I've also renamed time to timerID to make it clear what it is.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
    <button id="b1">Click Me!</button>
    <p id="demo"></p>

    <script>
        var sec = 5;
        var timerID;

        document.getElementById("b1").onclick = function() {
            timerID = setInterval(myTimer, 1000);
        };

        function myTimer() {
            document.getElementById('demo').innerHTML = sec + "sec.";
            sec--;
            if (sec <= -1) {
                clearInterval(timerID);
                // alert("Time out!! :(");
                document.getElementById("demo").innerHTML="Time's up!";
            }
        }
    </script>
</body>
</html>

I would suggest a couple of extra exercises to help you:

  1. Reset the timer so that you can click on the button to start the timer again
  2. Prevent the timer being started again (which would run multiple timers with different IDs) while a timer is running
a2k42
  • 672
  • 6
  • 19
  • Thank you for your reply! I'll have to study and digest your solution. In coding, I think it is just as important to understand why I'm doing something, as opposed to just copying and pasting!! – astroboyee Oct 23 '21 at 15:22
0

The myTimer() function is never invoked. Even if you invoke it, it does not take any action. It's just repeating itself on click.

So, instead of:

function myTimer() {

document.getElementById("b1").onclick = function() { 
myTimer()  
};

Try adding an Event Listener:

 document.getElementById("b1").addEventListener('click', function() {  
 // inside here you put the code for going into next question
 })

Or use just the same code, but not inside a function, and its content to be a meaningful code that leads to the next answer:

document.getElementById("b1").onclick = function() { 
    // code to proceed into next question
}
  • Thank you also for the reply. As I commented earlier I'll need to digest your solution. I am code beginner, so the help is appreciated! – astroboyee Oct 23 '21 at 15:24
  • I'm not sure I understand what you mean "The myTimer() function is never declared? `function myTimer()` is the [function declaration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function) – a2k42 Oct 23 '21 at 16:38
  • You're right. It is not invoked is what I meant. Thanks for the correction. – Γιάννης Μπινής Oct 24 '21 at 16:03
  • It's passed to `setInterval` as its callback function. Still not sure I understand your answer. You've suggested add an event listener, is there some reason you're suggesting [this instead of onlick](https://stackoverflow.com/questions/6348494/addeventlistener-vs-onclick)? – a2k42 Oct 24 '21 at 19:19