Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resetting setTimeout object if exists

When somebody clicks my checkboxes, from a long list of checkboxes, I want to show the number of selected checkboxes in a little popup element. My problem is, the little popup element should disappear 5 seconds after the last click, which is OK for one checkbox being clicked, but if I quickly check 5 boxes, the timer is still set on the first box, resulting in the popup element disappearing too quickly.

As you can see in my function, I've tried using the clearTimeout(timeoutName) function but have experienced some troubles applying it. The console log states that the clearTimeout(timeoutName) is undefined, which I can understand: the setTimeout hasn't even started yet.

How can I check that the timer exists before I clear it? Or is this really not the best method? When a checkbox is checked (this function runs) there could be a timer running but sometimes there could not be.

$('.name_boxes').live('click', function() {
    var checked_count = $('.name_boxes:checked').length;
    // other stuff

    clearTimeout(hide_checked_count_timer); // if exists????????

    $(".checked_count").hide();
    $(".checked_count").text(checked_count+" names selected");
    $(".checked_count").show();

    hide_checked_count_timer = setTimeout(function() {
        $(".checked_count").hide();
    },5000);
});

Any help gratefully received...

like image 420
TheCarver Avatar asked Feb 22 '12 01:02

TheCarver


2 Answers

Just declare the timer variable outside the click handler:

var hide_checked_count_timer;
$('.name_boxes').live('click', function() {
    var checked_count = $('.name_boxes:checked').length;
    // other stuff

    clearTimeout(hide_checked_count_timer); // if exists????????

    $(".checked_count").hide();
    $(".checked_count").text(checked_count+" names selected");
    $(".checked_count").show();

    hide_checked_count_timer = setTimeout(function() {
        $(".checked_count").hide();
    },5000);
});

http://jsfiddle.net/kkhRE/


Considering .live has been deprecated, you should be delegating the event with .on instead:

// Bind to an ancestor. Here I'm using document because it an
// ancestor of everything, but a more specific ancestor
// would be preferred.
$(document).on('click', '.name_boxes', function() {
    // ...
});
like image 122
bfavaretto Avatar answered Oct 17 '22 04:10

bfavaretto


Q. The console log states that the clearTimeout(timeoutName) is undefined, which I can understand: the setTimeout hasn't even started yet.

A. The clearTimeout() function's return value is undefined regardless of whether there was a timeout to be cleared. It doesn't have a concept of "success" that can be tested. If there is a queued timeout associated with the id you pass then it will be cleared, otherwise nothing happens.

Q. How can I check that the timer exists before I clear it?

You can't, at least not in the sense of there being some registry of outstanding timeouts that you can query. As you already know, the .setTimeout() function returns an id for the timeout just queued, and you can use that id to clear it before it runs, but there is no way to test whether it has already been run. The id is just a number so the variable that you saved it in will continue to hold that number even after the timeout has either run or been cleared.

It does no harm at all to call clearTimeout() with an id for a timeout that already ran - basically if the timeout for that id is in the queue it will be cleared otherwise nothing will happen.

The easiest way to test "Is there an outstanding timeout that hasn't run yet" is to set the variable holding the timerid to null when the timeout runs, i.e., within the function you queued:

var timerid = setTimout(function() {
                 timerid = null;
                 // other operations here as needed
              }, 5000);

// in some other code somewhere
if (timerid != null) {
   // timer hasn't run yet
} else {
   // timer has run
}

The variable you save the timerid in needs to be in a scope that can be accessed both where you set it and where you test it, i.e., don't declare it as a local variable within an event handler.

like image 41
nnnnnn Avatar answered Oct 17 '22 03:10

nnnnnn