0

I tried to follow the advice in another question but I may not be getting the syntax correct.

When I click on a div, it fires a JQuery call - which calls an AJAX function, loading a document. The AJAX call has to go back to the server and grab some calculation-heavy elements, so my idea is to have the JQuery slider slide down ONLY when the AJAX call has finished loading the document into the target div. Using the $.when ... .done(...) does wait until it's finished, but it just POPS the div all the way down, not giving me the nice "slide" on the first click.

BONUS: Would love to have the cursor change to a little "loading" or hourglass icon while it's waiting to let the user know something is happening. But this is not totally necessary.

The AJAX and Jquery:

function loadDoc(myUrl, id) {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
            document.getElementById(id).innerHTML =
                this.responseText;
        }
    };
    xhttp.open("GET", myUrl, true);
    xhttp.send();
}

$(document).ready(function () {

    $('.projSliderContent').hide();

    $('.projectSliders').on('click', function () {
        var targetArea = $(this).next('.projSliderContent');
        var urlToPass = $(targetArea).attr('url');
        var idOftarget = $(targetArea).attr('id');
        $.when(loadDoc(urlToPass, idOftarget)).done(   //fires AJAX func
            $(this).next('.projSliderContent').slideToggle("slow")
        );
    });
});

And here is the HTML:

 <div class="container-fluid" id="userProjectsSelectors">
        <div class="row-fluid">   
                <h2 id="projSlidersHeader">PROJECTS</h2>
                <div class="projectSliders" id="projleadSlider">
                    <h3>View Projects You Lead</h3>
                </div>
                <div class="projSliderContent" id="userLeadProjectsDiv" url='/my/url/here'>
                </div>
        </div>
    </div>

Here's a jsfiddle of it - it doesn't work properly but may help with visualization.

NateH06
  • 3,154
  • 7
  • 32
  • 56
  • why not use `$.ajax` and put it in the `success` call? – CumminUp07 Jul 31 '17 at 16:39
  • @CumminUp07 I'm pretty new to JQuery and AJAX, so forgive me if I'm misunderstanding you. I'm using that AJAX method in several places across my site, and not all of them trigger a slider. I'd like to reuse that `loadDoc` method if possible without tailoring it specifically to this Jquery call. – NateH06 Jul 31 '17 at 16:41

2 Answers2

3

$.when() expects promises as arguments but your function doesn't return one.

Can simplify it to use jQuery ajax methods which do return a promise

function loadDoc(myUrl, id) {    
  return $.get(myUrl).then(function(data) {
    $('#' + id).html(data)
  });    
}

Or even easier use jQuery load():

$('.projectSliders').on('click', function () {
    var targetArea = $(this).next('.projSliderContent');
    var urlToPass = $(targetArea).attr('url');

    targetArea.load(urlToPass , function(){
       $(this).slideToggle()
    })
})

DEMO

charlietfl
  • 170,828
  • 13
  • 121
  • 150
2

You are almost there.

The thing is, you are not waiting for the AJAX call to complete before you slideToggle

You should use Deferred

function loadDoc(myUrl, id) {
  var d1 = $.Deferred();
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById(id).innerHTML =
        this.responseText;
      d1.resolve();
    }
  };
  xhttp.open("GET", myUrl, true);
  xhttp.send();
  return d1;
}

Notice that I am returning a deferred object back to $.when. When the AJAX call is completed, I am resolving that deferred which then executes the .then() part

Learn more about Deferred here

PS. you fiddle is broken. you didn't load jQuery

U.P
  • 7,357
  • 7
  • 39
  • 61