jQuery ajax, wait until beforeSend animation finishes

28,308

Solution 1

You can use a custom event to wait until the animation is complete, like this:

$("a").click(function(){
    var img = $("img"),
        div = $("div");
    $.ajax({
        url: "test.php",
        contentType: "html",
        beforeSend: function(){
            img.fadeIn(600, function(){
                div.append(" | beforeSend finished | ");
                div.trigger("animationComplete");
            });
        },
        error: function(){
            if(img.is(':animated')) {
                div.one("animationComplete", function() {
                    div.append(" | error | ");
                });
            } else {
                div.append(" | error | ");
            }
        }
    });
    return false
});

Notes:

  1. jQuery.one() attaches an event handler that fires once and is then removed.
  2. jQuery.is(':animated') is a custom selector provided by jQuery to determine if an element is animated using jQuery's built-in animation methods (eg fadeIn).

New jsFiddle: http://jsfiddle.net/pgjHx/


In the comments, Happy has asked how to handle multiple animations. One way would be to add a condition to the animationComplete event handler to see if animation is ongoing. For example:

$("a").click(function(){
    var img = $("img"),
        div = $("div");

    $.ajax({
        url: "test.php",
        contentType: "html",
        beforeSend: function(){
            img.fadeIn(600, function(){
                div.append(" | beforeSend finished | ");
                div.trigger("animationComplete");
            });

            // Add another animation just to demonstrate waiting for more than one animation
            img.animate({
                marginTop: '-=5',
                opacity: '-=.5'
            }, 700, function() {    
                div.trigger("animationComplete");
            });
        },
        error: function(){
            if(img.is(":animated")) {
                // Note I've switched to bind, because it shouldn't be unbound
                // until all animations complete
                div.bind("animationComplete", function() {
                    if(img.is(":animated")) {
                        return;
                    }
                    div.append(" | error | ");
                    div.unbind("animationComplete");
                });
            } else {
                div.append(" | error | ");
            }
        }
    });
    return false
});

Solution 2

you can do this

//run your animation on link click, and when animation gets completed, // then start your ajax request.

$("a").click(function () {
    $("img").fadeIn(600, function () {
        $("div").append(" | beforeSend finished | ");
         $.ajax({
                    url: "test.php",
                    contentType: "html",
                    error: function () {
                        $("div").append(" | error | ");
                    }
                });
                return false
            });
    });
});
Share:
28,308
James
Author by

James

Updated on March 07, 2020

Comments

  • James
    James about 4 years

    HTML & CSS:

    <a href="#">link</a>
    <img src="http://2.bp.blogspot.com/_OIHTbzY7a8I/TOaiTKLqszI/AAAAAAAAAHM/eb3iiOqxzKg/s640/Auto_Audi_Audi_concept_car_005130_.jpg" />
    <div></div>
    
    img { display: none; }
    a { display: block; }
    

    JS:

    $("a").click(function(){
        $.ajax({
            url: "test.php",
            contentType: "html",
            beforeSend: function(){
                $("img").fadeIn(600, function(){
                    $("div").append(" | beforeSend finished | ");
                });
            },
            error: function(){
                $("div").append(" | error | ");
            }
        });
        return false
    });
    

    The problem is, error function starts, before animation in beforeSend function finishes.

    Here is working example http://jsfiddle.net/H4Jtk/2/

    error should begin to work only when beforeSend is finished. How to do this?

    I use beforeSend function to start animation of the blocks when ajax starts. I can't remove it.

    Thanks.