Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery animate "complete" callback firing too soon

According to the jQuery documentation .animate has a parameter called 'Complete' that should only fire once the animation has finished. Unfortunately I'm finding that it fires before the animation has even started.

if ($('html').scrollTop()) {
    $('html').animate({ scrollTop: 0 }, callback);
    return;
}

JSFiddle showing the problem: http://jsfiddle.net/JohnnyWalkerDesign/5zu90ygz/

What am I missing?

like image 227
Chuck Le Butt Avatar asked Dec 06 '22 20:12

Chuck Le Butt


1 Answers

The callback parameter should be a function pointer. It's not a term used very often these days, but it means that you pass the function itself, not the result of a function.

What does this mean?

Given the example:

function message(q) {
    alert(q);
}

Here, message is a function. To pass that function as a callback, use the name of the function, eg:

setTimeout(message, 100);
$("#id").click(message);

Note that there's no () after the name of the function.

In javascript terms, the function itself is a variable and you pass the variable, but as soon as you add () you are calling the function and passing the result, not the function itself.

If you use message() then the function will be executed and the result of the function passed as the callback, ie:

setTimeout(message("x"), 100);

is the equivalent of:

var x = message("x");
setTimeout(x, 100);

So you can see from this code why message runs immediately (more obvious with click event or longer timeout).

The format setTimeout(message, 100); isn't used very often as a) it looks like a typo (should that be message()?) and b) it doesn't allow you to pass a parameter, so this would frequently be written as:

setTimeout(function() { message("x") }, 100);

which uses an anonymous in-line function as the callback variable / function pointer.


Back the question:

In your original fiddle, all you needed to do was change the callback to a true callback without the need to add a separate parameter, ie:

$('#scroll').on('click', function(e) {
    e.preventDefault;
    scrollToTop(function() { message("Reached Top")});
});

Updated fiddle: http://jsfiddle.net/5zu90ygz/9/

like image 56
freedomn-m Avatar answered Dec 31 '22 03:12

freedomn-m