4

I want to have one button, functioning as both the "start" and "stop" button for some reoccurring timed events.

To do this, I can have a global variable on the top of everything:

toggleOn = false; 

And then, inside of <button onClick="..., I can have:

toggleOn =! toggleOn;
foo(); 
function foo() {
  // do my stuff
  if (toggleOn) {
    setTimeout(foo, 5000);
  }
}

But the problem is, I must not use a global variable to complete the same task. How should I do it? Is there a persist variable that can carry a value outside its scope?

6
  • 4
    set a prop on the button itself, like this.busy = !this.busy; Commented Sep 26, 2013 at 19:50
  • @dandavis This sounds brilliant. Could you elaborate it as an answer and provide some code snippet please? Commented Sep 26, 2013 at 19:54
  • setting a property on DOM reference (i.e. this/button as dandavis suggested) will cause memory leaks in old browsers. You are better off wrapping it in a function to close scope as jods demonstrated. Commented Sep 26, 2013 at 19:54
  • @cbayram: so will a closure from an event handler. besides, aren't those warnings for like IE6 ? and above that, leaking a boolean? man, that will crash everything in no time </sarcasm>. or, use classList.toggle if you want to be cool. Commented Sep 26, 2013 at 20:20
  • @dandavis, didn't mean to hurt your feelings, simply stating a fact. IE7 too some degree too, refreshing the page will clean it up. Having dealt with IE6 web applications that stay open in the browser for days/weeks, it's a reality. Bad practice is bad practice, today a boolean, tomorrow your whole data :) Commented Sep 26, 2013 at 20:38

3 Answers 3

4

This is an example for something where closures are great feature of the language.

(function()
{
    var active = false;
    myButton.addEventListener('click', function myButtonClick(event)
    {
        if (active) {
            // recursion..?
            setTimeout(myButtonClick, 5000);
        }

        active = !active;
    }
})();

More on closures here.

Sign up to request clarification or add additional context in comments.

Comments

2

Use the javascript module pattern. Something like this:

var handler = function () {
  var private_state = true;
  return function() {
    private_state = !private_state;
    if (private_state) {
      // Do something
    }
  }
}();

Use handler as your button onclick handler.

4 Comments

you're missing a couple of parens to wrap the immediate function
funny thing is, you don't need them.
go figure, I guess you learn something new every day =). Still, wouldn't that trip up older browsers?
Not sure which browser/why. function() {} is an expression, let's call that X. Now in the statement var y = X();, the call () has always had a higher priority than the assignment =. JS hasn't changed in this regard for a long time.
0

Earlier answers already noted that you could use closures to store a "private" variable that would keep track of state. Alternatively you could use HTML5 data to store this as well.

html

<button data-toggleOn="false">Click me!</button>

javascript

button.addEventListener('click', function() {
  var toggleOn = this.dataset.toggleOn = !JSON.parse(this.dataset.toggleOn);

  if (toggleOn) {
    // do stuff!
  }
});

and if you're using jQuery..

$('button').click(function() {
  var toggleOn = !$(this).data('toggleOn');
  $(this).data('toggleOn', toggleOn);
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.