user441521
user441521

Reputation: 6998

Hiding div while making ajax call with JQuery for a smooth experience

Currently I'm hiding a div with id "countries" slowly and in it's complete function I'm making an ajax call in which in it's done function I get a partial view and replace the div with the result and then show() again slowly.

This waits until the hide animation is complete before it makes the ajax call. To make this more efficient and to use the time it takes to hide the div efficiently is there a way that I can make the ajax call before I hide, and only show again once both the ajax is done AND the hide animation is complete?

Sometimes the hide isn't finished before the ajax is done and it doesn't make a smooth transition and if I place the ajax call inside the hide complete animation function there can be a delay that isn't so smooth.

So the smoothest possible transition is make the ajax call right away, but only reshow the div when the hide animation is complete. How could I do that?

Below is what I have now but it waits until the hide animation is complete before making the ajax call which isn't the most efficient to make a smooth experience.

$("#countries").hide("slow", function(){
   $.ajax({
      url: 'blah',
      type: 'get',
      data: { region: region }
   })
   .done(function(result){
      $("#divCountries").html(result);
      $("#countries").show("slow");
   });
});

Upvotes: 3

Views: 2054

Answers (5)

ThisClark
ThisClark

Reputation: 14823

I posted a revised answer that uses $.when. For history sake, I'm not going to change this code.

Try your URL with the following. If you have a problem let me know in a comment. This is how it works for me:

Some HTML

<div style="background-color: red;" id="countries">countries div</div>
<button id="get">Get</button>

Some Javascript

var hidden = false;
var ajax = false;
$(document).ready(function() {
    $('#get').click(function() {
        $("#countries").hide("slow", function() {
           $.ajax({
              url: 'blah',
              type: 'get',
              data: { region: region },
              success: setAjaxFlag(),
              error: setAjaxFlag()
           }).done(function(){
              setHiddenFlag();
              showCountries();
           });
        })
    });
});
function setAjaxFlag() {
    ajax = true;
}
function setHiddenFlag() {
    hidden = true;
}
function showCountries() {
    if(ajax === true && hidden === true) {
        $("#divCountries").html(result);
        $("#countries").show("slow");    
    } else {
        showCountries();
    }
}

Upvotes: 1

ThisClark
ThisClark

Reputation: 14823

This is better. It takes care of the problem with less mess, using JQuery.when http://api.jquery.com/jquery.when/ It's less ridiculous, removing the boolean states and possible infinite loop. Oh, and I added a Fiddle - plug your Ajax in and Fork the fiddle till you get it how you want it - http://jsfiddle.net/Xorat/uzjLchmx/

Truth told, I had a problem getting my response data from success to function showResults. I tried using a variable outside the scope to pass the data. If you fix, please comment a fiddle with proper ajax that works.

HTML

<div id="countries">country data</div>
<button id="get">Get</button>

Javascript

var https = 'https://www.googleapis.com/calendar/v3/calendars/';

$(document).ready(function() {
    $('#get').click(function() {
        $.when($.ajax({
            url: https,
            dataType: 'jsonp',
            type: "GET",
            success: function (response) {
                //do something
            },
            error: function() {
                //do something else                
            }
        }), $("#countries").hide("slow")).done(showResults());
    });
});
function showResults() {
    $("#countries").show("slow")
    //and do some stuff with your data
}

Upvotes: 0

Mike Feng
Mike Feng

Reputation: 833

I may be missing something, but it seems the solution you're looking for is pretty simple:

var hidden = false, ajaxed = false;
$("#countries").hide("slow", function() {
  hidden = true;
  if (ajaxed)
    $("#countries").show("slow");
});
$.ajax({
  url: 'blah',
  type: 'get',
  data: { region: region }
}).done(function(result) {
  ajaxed = true;
  $("#divCountries").html(result);
  if (hidden)
    $("#countries").show("slow");
});

-edit- I should elaborate a little. Both hidden and ajaxed are flags: hidden will be set to true once the div is completely hidden, and ajaxed will be set to true once the ajax request receives a response. Also, the ajax request will be sent immediately rather than having to wait for the div to be hidden.

If you traverse through the codes, you'll see that one of the flags will always be set to true first, depending on which occur first. Whichever the case, the "show" will only happen if the other flag is also true (double positive).

Upvotes: 0

Gaurav Kalyan
Gaurav Kalyan

Reputation: 1897

If you want to show the result after the complete and div is hidden of the ajax call then you need to create certain conditions like below:-

function getResult() { window.lock1 = 0; /*This means animation is not done*/ window.data1 = -1; /*The data by ajax is not yet fetched*/ $.ajax({ url: 'blah', type: 'get', data: { region: region }, success: function (result) { if (window.lock1 !== 0) { $("#divCountries").html(result); $("#countries").show("slow"); } else { window.data1 = result; } } }); $("#countries").hide("slow", function { if (window.data1 !== -1) { $("#divCountries").html(window.data1); $("#countries").show("slow"); } else { window.lock1 = 1 } }); }

I have created a two variable which check that if div is hidden or not and ajax call is complete or not if the div is hidden and ajax call is complete after it then it fetch data straight forward else it wait till the div is hidden and once it's hidden it gets the data from the global variable window.data1

Upvotes: 0

Cayce K
Cayce K

Reputation: 2338

I'm not sure if you want to do it this way, but create some sort of click or change event that forces it to occur. (Not sure if that is how you have it now or not, but this is how I would imagine it...). This way both start immediately. If the ajax finishes first then the hide will be the one to return the show. If the hide finishes first then the ajax will return the show.

$(document).on('click','#someelement',function(){
        var dvals = {}, aj = false, hide = false;
        dvals['region'] = region;
        $.ajax({
            type: "POST",
            url: '/',
            data: dvals,
            success: function(data){
                aj = true;
                if(aj && hide){
                    $("#divCountries").html(result);
                    $('#countries').show('slow');
                }
            }
        });
        $('#countries').hide('slow',function(){
            hide = true;
            if(aj && hide){
                $(this).show('slow');
            }
        });
});

Upvotes: 0

Related Questions