-1

I just wanna make a button to start adding some text in my body, and a button to stop adding this text.

I figured out that I can use a setTimeout in a function or a setInterval...but I couldn't Clear both of them because of the local scope...I can't declare both of them as a global scope, I want my button.onclick activate them not by default.

/* global document*/
 
      
var myStart = document.querySelector('#start'),
        myEnd = document.querySelector('#end'),
        myRepeat;

function start() {
    "use strict";
    document.body.innerHTML += '<br>Welcome StackOverFlowMembers!';
    myRepeat = setTimeout(start, 1000)
}

function stop() {
    "use strict";
    clearTimeout(myRepeat);
}

myStart.onclick = start;
myEnd.onclick = stop;
<body>
    <button id="start">Start!</button>
    <button id="end">End!</button>
    <script src="script.js"></script>
</body>
Chilarai
  • 1,842
  • 2
  • 15
  • 33

2 Answers2

0

The problem here is not the scope of the variables. Everything is actually fine with your code on that.

The problem is here:

document.body.innerHTML += '<br>Welcome StackOverFlowMembers!';

If you replace it with:

console.log('Hello!');

Both buttons will work normally. Check this fiddle.

Basically, when you use innerHTML you destroy the event listeners. You can find more on that in this answer

anpel
  • 931
  • 6
  • 16
0

As @anpel's answer explains, your innerHTML call is trashing your event listeners. In the code below, I work around that by putting the onclick attribute directly into the HTML button elements. The boolean doRepeat variable governs whether a subsequent timeout gets initiated.

/* global document*/      
var myStart = document.querySelector('#start'),
        myEnd = document.querySelector('#end'),
        doRepeat;

function start() {
    "use strict";
    document.body.innerHTML += '<br>Welcome StackOverFlowMembers!';
    if (doRepeat) {
       setTimeout(start, 1000);
    }
}
<body>
    <button id="start" onclick="doRepeat=true;start();">Start!</button>
    <button id="end" onclick="doRepeat=false;">End!</button>
    <script src="script.js"></script>
</body>

Alternatively, you can make a separate <div> into which your function writes its text-- instead how you're doing innerHTML to the entire HTML body, which destroys all child listeners-- and you won't have to worry about your event listeners getting destroyed since those listeners aren't on children of the target div.

Here's a JS Fiddle to demonstrate that: https://jsfiddle.net/j9voxg7s/

Marc
  • 11,403
  • 2
  • 35
  • 45