Erik Wahlström
Erik Wahlström

Reputation: 19

Animation effect before ajax call

I've watched several tutorials on how to load content without having to refresh the browser. I'm also using history pushState and popstate to update the url dynamically depending on what site that is displaying. However even if this code works, I would like to be able to make som page transition animation effects > call the Ajax function > then make some fadeIn animation effects. So far i've had no luck in trying to do so. I tried to read up on Ajax (beforeSend: function(){}), but the success function seems to execute before the (beforeSend) function. Is there anyone that could point me in the right direction, or tell me what i possibly am doing wrong? I'd appriciate it!

   $(document).ready(function() {

        var content, fetchAndInsert;

        content = $('div#content');

        // Fetches and inserts content into the container
        fetchAndInsert = function(href) {
            $.ajax({
                url: 'http://localhost:8000/phpexample/content/' + href.split('/').pop(),
                method: 'GET',
                cache: false,
                success: function(data) {
                    content.html(data);
                }
            });
        };

        // User goes back/forward
        $(window).on('popstate', function() {
            fetchAndInsert(location.pathname);
        }); 

        $('.buttonlink').click(function(){
            var href =  $(this).attr('href');

            // Manipulate history
            history.pushState(null, null, href);

            // Fetch and insert content
            fetchAndInsert(href);

            return false;
        });
});

Questions? Just ask!

Thanks beforehand!

/// E !

Upvotes: 0

Views: 4601

Answers (5)

guest271314
guest271314

Reputation: 1

I tried to read up on Ajax (beforeSend: function(){}), but the success function seems to execute before the (beforeSend) function

You can wait for animation to complete before appending new content to html using .queue(), .promise(), .finish()

beforeSend: function() {
  element.queue(function() {
   $(this).animate({/* do animation stuff */:500}, {duration:5000}).dequeue()
  });
},
success: function(content) {
  element.finish().promise("fx").then(function() {
    container.append(content).fadeIn()
  })
}

var element = $("#loading").hide();
var container = $("#content");
var button = $("button");
var ajax = {
  // do asynchronous stuff
  request: function() {
    return new $.Deferred(function(d) {
      setTimeout(function() {
        d.resolve("complete")
      }, Math.random() * 5000)
    })
  },
  beforeSend: function() {
    element.fadeIn().queue(function() {
      $(this).animate({
        fontSize: 100
      }, {
        duration: 2500
      }).dequeue()
    });
  },
  success: function(content) {
    element.finish().promise("fx").then(function() {
      element.fadeOut("slow", function() {
        $(this).css("fontSize", "inherit");
        container.append(content + "<br>").fadeIn("slow");
        button.removeAttr("disabled")
      })
    })
  }
}

button.click(function() {
  $(this).attr("disabled", "disabled");
  $.when(ajax.beforeSend()).then(ajax.request).then(ajax.success)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">    
</script>
<div id="loading">loading...</div>
<div id="content"></div>
<button>load content</button>

jsfiddle https://jsfiddle.net/ajmL5g1a/

Upvotes: 1

Corey Clark
Corey Clark

Reputation: 116

I would probably try using some css for this.

#content { 
   opacity: 0;
   transition: all 1s;
}

#content.fade-in { 
   opacity: 1;
}

...

const content = $('#content');
const btn = $('.buttonlink');

const success = data => 
   content.html(data).addClass('fade-in');

const fetchAndInsert = url => 
   $.ajax({ url, cache: 'false' }).done(success);

const getData = function(e) { 
   e.preventDefault();

  content.removeClass('fade-in');
  fetchAndInsert($(this).attr('href'));
};

btn.on('click', getData)

Upvotes: 0

Andrew Moore
Andrew Moore

Reputation: 159

You need to use callbacks. The provided solutions will work, but not necessarily sequentially. $.animate() and $.ajax both run asynchronously. If unfamiliar with this term, here's a good intro: http://code.tutsplus.com/tutorials/event-based-programming-what-async-has-over-sync--net-30027

Here's what I might do:

   fetchAndInsert = function(href) {
       $('#some-element').animate({'opacity':'0.0'}, 1000, function () {
           $.ajax({
               url: 'http://localhost:8000/phpexample/content/' + href.split('/').pop(),
               method: 'GET',
               cache: false,
               success: function(data) {
                   content.html(data);
                   content.animate({'opacity':'1.0'}, 1000);
               }
           });
       });
    };

That will fade out whatever is currently in content, fetch the new data, replace what's currently in content, and then fade back in.

Upvotes: 2

jedrzejginter
jedrzejginter

Reputation: 412

My solution:

    fetchAndInsert = function(href) {
        var timeBeforeAnimation = Date.now(), animationDuration = 500;

        /* Do some animation, I assume that with jQuery,
           so you probably know how much time is takes - store that
           time in variable `animationDuration`. */

        /* Run your "before" animation here. */

        $.ajax({ ...,
            success: function(data) {
                /* Check, if request processing was longer than
                   animation time... */

                var timeoutDuration = animationDuration -
                                      (Date.now() - timeBeforeAnimation);

                /* ...and if so, delay refreshing the content,
                   and perform the final animation. */

                setTimeout(function() {
                    content.html(data);
                    /* Perfom final animation. */
                }, Math.max(0, timeoutDuration);
            }
        });
    };

Upvotes: 0

KmasterYC
KmasterYC

Reputation: 2354

Try this:

fetchAndInsert = function(href) {
            // Before send ajax. Do some effects here
            $.ajax({
                url: 'http://localhost:8000/phpexample/content/' + href.split('/').pop(),
                method: 'GET',
                cache: false,
                success: function(data) {
                    // After loading. Do some effects here
                    content.html(data);
                }
            });
        };

Upvotes: 0

Related Questions