boz
boz

Reputation: 4907

Removing setTimeout on click

I'm getting some odd behavior in a part of my js code.

I have some notifications which appear in a bar on top of the page and then disappear after a certain amount of time. I have used a simple setTimeout() to acheive this.

Sometimes, a notification will appear as a result of a particular url query string when the page loads but then a new one would need to be displayed when the user clicks on a button. I want the old one to disappear and the new one to appear. I'm using a variable to keep a reference to the setTimeout() in order to cancel it. However, when I try to do this I manage to create a loop that eventually crashes my chrome tab.

I have put together a jsfiddle illustrating my problem - http://jsfiddle.net/5Nm4c/

Clicking on show notification while another is visible will crash the browser tab. If you click on it when nothing is shown, it is fine.

Here is my js:

var Notification = {
    // close main notification bar
    close: function (callback) {
        $('#notification-bar').fadeOut(250, function () {
            // reset its position and fade it back in so it is ready to go again
            $(this).css('top', -100).fadeIn(1);
            // check if a callback function has been passed in
            if (typeof callback === 'function') {
                callback();
            }
        });
    },
    // open notification bar with the appropriate css class and message
    open: function (message) {
        // if the notification bar is already visisble
        if (verge.inViewport($('#notification-bar'))) {

            // hide and then show it with the new message
            window.clearTimeout(Notification.timeout);
            Notification.close(Notification.open(message));

            return false;
        }

        $('#notification-bar').html(message);

        $('#notification-bar').animate({
            'top': 0
        }, 250, function () {
            Notification.timeout = window.setTimeout(function () { Notification.close() }, 1500);
        });
    },
    timeout: null
}

Notification.open('hello');

$('#button').click(function(e){
    e.preventDefault();
    Notification.open('link clicked');
});

I'm using https://github.com/ryanve/verge/ as it has some nice methods to check if elements are visible in the viewport.

Could someone please tell me where my error is?

Upvotes: 2

Views: 239

Answers (1)

nbar
nbar

Reputation: 6158

I think the error Uncaught RangeError: Maximum call stack size exceededcomes from jsfiddle itself, so I am not able to test it. I see what you did there:

var Notification = {
open: function (message) {
Notification.close(Notification.open(message)); //Here you create the loop!!
}
}

Another problem I see in your code is, that when Notification.open is called while a animation is running Notification.timeout is not actuell. Try a $('#notification-bar').stop(true, true); to stop the actuell animation befor you call window.clearTimeout(Notification.timeout);. Maybe it would be even better to use $('#notification-bar').stop(true, false);, so the "old" setTimeout will not even be called.

Upvotes: 1

Related Questions