B. Clay Shannon B. Clay Shannon - 2 months ago 7
jQuery Question

Why is my jQuery wait cursor code not working?

I've got this jQuery in a page:

<script>
$(document).ready(function () {
$("#btnGetData").click(function () {
var _begdate = $("#datepickerFrom").val();
var _enddate = $("#datepickerTo").val();
var _unit = $("#unitName").text();
document.body.style.cursor = 'wait';

$.ajax({
type: 'GET',
url: '@Url.RouteUrl(routeName: "QuadrantData", routeValues: new { httpRoute = true, unit = "un", begdate = "bd", enddate = "ed" })'
.replace("un", encodeURIComponent(_unit))
.replace("bd", encodeURIComponent(_begdate))
.replace("ed", encodeURIComponent(_enddate)),
contentType: 'text/plain',
cache: false,
xhrFields: {
withCredentials: false
},
success: function (returneddata) {
$("body").html(returneddata);
},
error: function () {
console.log('hey, boo-boo!');
}
});

document.body.style.cursor = 'pointer';
});
});
</script>


Note that I try to create a wait cursor early on in the click handler:

document.body.style.cursor = 'wait';


...and then revert back to the default at the end:

document.body.style.cursor = 'pointer';


However, it doesn't work - the cursor never changes. The code does work (the ajax call completes successfully), but the cursor remains stonefaced, causing the user to wonder whether anything is happening.

What do I need to do yet to get the cursor to morph into a waiting attitude?

Answer

Because of the nature of the ajax calls (i.e. being async) the code executes the first line to change the cursor

document.body.style.cursor = 'wait';

then executes the ajax call (note: it does not wait for the response).

and then executes the last line:

document.body.style.cursor = 'pointer';

It all happens so fast, you probably don't notice.

At some point later, the ajax response is received and handled by either the success or fail callback handlers.

To change the cursor always after the ajax response is received (either success or failure), you need to add another callback called always - something along the lines of:

...
,
 always: function () {
       document.body.style.cursor = 'pointer';
  });
...

Note, depending of the version of Jquery, this could be called a done() callback instead.

Check documentation here: http://api.jquery.com/jquery.ajax/

UPDATE

I updated the format to current practice and added the missing call...

$(document).ready(function() {
  $("#btnGetData").click(function() {
    //var _begdate = $("#datepickerFrom").val();
    // var _enddate = $("#datepickerTo").val();
    // var _unit = $("#unitName").text();
    document.body.style.cursor = 'wait';

    $.ajax({
        type: 'GET',
        url: 'http://stackoverflow.com/',
        contentType: 'text/plain',
        cache: false
      })
      .done(function() {
        console.log('hey, success!');
      })
      .fail(function() {
        console.log('hey, boo-boo!');
      })
      .always(function() {
        console.log('hey, done!');
        document.body.style.cursor = 'pointer';
      });
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button id="btnGetData">Get it</button>