Getting the browser cursor from "wait" to "auto" without the user moving the mouse

JqueryMouse CursorBusy CursorHourglass

Jquery Problem Overview


I use this jQuery code to set the mouse pointer to its busy state (hourglass) during an Ajax call...

$('body').css('cursor', 'wait');

and this corresponding code to set it back to normal...

$('body').css('cursor', 'auto');

This works fine... on some browsers.

On Firefox and IE, as soon as I execute the command, the mouse cursor changes. This is the behavior I want.

On Chrome and Safari, the mouse cursor does not visibly change from "busy" to "auto" until the user moves the pointer.

What is the best way to get the reluctant browsers to switch the mouse pointer?

Jquery Solutions


Solution 1 - Jquery

I would rather do it more elegantly like so:

$(function(){  
  $("html").bind("ajaxStart", function(){  
     $(this).addClass('busy');  
   }).bind("ajaxStop", function(){  
     $(this).removeClass('busy');  
   });  
});

CSS:

html.busy, html.busy * {  
  cursor: wait !important;  
}  

Source: http://postpostmodern.com/instructional/global-ajax-cursor-change/

Solution 2 - Jquery

It is a bug in both browsers at the moment. More details at both links (in comments as well):

http://code.google.com/p/chromium/issues/detail?id=26723

and

http://code.google.com/p/chromium/issues/detail?id=20717

Solution 3 - Jquery

I believe this issue (including the mousedown problem) is now fixed in Chrome 50.

But only if you are not using the developer tools!!

Close the tools and the cursor should immediately respond better.

Solution 4 - Jquery

I got inspired from Korayem solution.

Javascript:

jQuery.ajaxSetup({
	beforeSend: function() {
	   $('body').addClass('busy');
    },
    complete: function() {
	   $('body').removeClass('busy');
    }
});

CSS:

.busy * {
    cursor: wait !important;
}

Tested on Chrome, Firefox and IE 10. Cursor changes without moving the mouse. "!important" is needed for IE10.

Edit: You still have to move cursor on IE 10 after the AJAX request is complete (so the normal cursor appear). Wait cursor appears without moving the mouse..

Solution 5 - Jquery

Korayem's solution works for me in 100% cases in modern Chrome, Safari, in 95% cases in Firefox, but does not work in Opera and IE.

I improved it a bit:

$('html').bind('ajaxStart', function() {
    $(this).removeClass('notbusy').addClass('busy');
}).bind('ajaxStop', function() {
    $(this).removeClass('busy').addClass('notbusy');
});

CSS:

html.busy, html.busy * {
    cursor: wait !important;
}

html.notbusy, html.notbusy * {
    cursor: default !important;
}

Now it works in 100% cases in Chrome, Safari, Firefox and Opera. I do not know what to do with IE :(

Solution 6 - Jquery

First of all, you should be aware that if you have a cursor assigned to any tag within your body, $('body').css('cursor', 'wait'); will not change the cursor of that tag (like me, I use cursor: pointer; on all my anchor tag). You might want to look at my solution to this particular problem first : cursor wait for ajax call

For the problem that the cursor is only updated once the user move the mouse on webkit browsers, as other people said, there is no real solution.

That being said, there is still a workaround if you add a css spinner to the current cursor dynamically. This is not a perfect solution because you don't know for sure the size of the cursor and if the spinner will be correctly positioned.

CSS spinner following the cursor: DEMO

$.fn.extend(
{
	reset_on : function(event_name, callback)
    { return this.off(event_name).on(event_name, callback); }
});

var g_loader = $('.loader');

function add_cursor_progress(evt)
{
    function refresh_pos(e_)
    {
    	g_loader.css({
            display : "inline",
            left : e_.pageX + 8,
            top : e_.pageY - 8
        });
    }
    refresh_pos(evt);
    var id = ".addcursorprog"; // to avoid duplicate events
    
    $('html').reset_on('mousemove' + id, refresh_pos);

    $(window).
    reset_on('mouseenter' + id, function(){ g_loader.css('display', 'inline'); }).
    reset_on('mouseleave' + id, function(){ g_loader.css('display', 'none'); });
}

function remove_cursor_progress(evt)
{
    var id = ".addcursorprog";
    g_loader.css('display', 'none');
    
    $('html').off('mousemove' + id);
    $(window).off('mouseenter' + id).off('mouseleave' + id);
}

$('.action').click(add_cursor_progress);
$('.stop').click(remove_cursor_progress);

You will need to check if it is a touch device as well var isTouchDevice = typeof window.ontouchstart !== 'undefined';

In conclusion, you better try to add in your page a static spinner or something else that shows the loading process instead of trying to do it with the cursor.

Solution 7 - Jquery

Working solution on CodeSandbox

Some of the other solutions do not work in all circumstances. We can achieve the desired result with two css rules:

body.busy, .busy * {
  cursor: wait !important;
}

.not-busy {
  cursor: auto;
}

The former indicates that we are busy and applies to all elements on the page, attempting to override other cursor styles. The latter applies only to the page body and is used simply to force a UI update; we want this rule to be as non-specific as possible and it doesn't need to apply to other page elements.

We can then trigger and end the busy state as follows:

function onBusyStart() {
    document.body.classList.add('busy');
    document.body.classList.remove('not-busy');
}

function onBusyEnd() {
    document.body.classList.remove('busy');
    document.body.classList.add('not-busy');
}

In summary, although we have to change the cursor style to update the cursor, directly modifying document.body.style.cursor or similar does not have the intended effect, on some engines such as Webkit, until the cursor is moved. Using classes to affect the change is more robust. However, in order to reliably force the UI to update (again, on some engines), we have to add another class. It seems removing classes is treated differently from adding them.

Solution 8 - Jquery

I don't think you'll be able to do it.

However, try changing the scroll position; it might help.

Solution 9 - Jquery

HERE is my solution:

function yourFunc(){

$('body').removeClass('wait'); // this is my wait class on body you can $('body').css('cursor','auto');
$('body').blur();
$('body').focus(function(e){
$('body')
 .mouseXPos(e.pageX + 1)
 .mouseYPos(e.pageX - 1);
});

}

Solution 10 - Jquery

As of jquery 1.9 you should ajaxStart and ajaxStop to document. They work fine for me in firefox. Have not tested in other browsers.

In CSS:

html.busy *
{
   cursor: wait !important;
}

In javaScript:

// Makes the mousecursor show busy during ajax 
// 
$( document )

   .ajaxStart( function startBusy() { $( 'html' ).addClass   ( 'busy' ) } ) 	
   .ajaxStop ( function stopBusy () { $( 'html' ).removeClass( 'busy' ) } )

Solution 11 - Jquery

Try using the correct css value for the cursor property:

$('body').css('cursor','wait');

http://www.w3schools.com/CSS/pr_class_cursor.asp

Solution 12 - Jquery

I haven't tried this, but what about if you create a transparent div that is absolutely positioned and fills the viewport just before changing the CSS. Then, when the css is changed on the body, remove the div. This might trigger a mouseover event on the body, which might cause the cursor to update to the latest CSS value.

Again, I haven't tested this, but it's worth a shot.

Solution 13 - Jquery

Hey Guys, I have a nitty gritty solution which works on all browsers. Assumption is protoype library is used. Someone can write this as plain Javascript too. The solution is to have a div on top of all just after you reset the cursor and shake it a little bit to cause the cursor to move. This is published in my blog http://arunmobc.blogspot.com/2011/02/cursor-not-changing-issue.html.

Solution 14 - Jquery

$('*').css('cursor','wait'); will work everywhere on the page including links

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNosrednaView Question on Stackoverflow
Solution 1 - JqueryKorayemView Answer on Stackoverflow
Solution 2 - Jqueryuser213788View Answer on Stackoverflow
Solution 3 - JqueryJ. AllenView Answer on Stackoverflow
Solution 4 - JquerySergiuView Answer on Stackoverflow
Solution 5 - JqueryFelixView Answer on Stackoverflow
Solution 6 - JquerypmrotuleView Answer on Stackoverflow
Solution 7 - JqueryNinjakannonView Answer on Stackoverflow
Solution 8 - JquerySLaksView Answer on Stackoverflow
Solution 9 - JquerycestarView Answer on Stackoverflow
Solution 10 - Jqueryuser1115652View Answer on Stackoverflow
Solution 11 - JqueryPetersenDidItView Answer on Stackoverflow
Solution 12 - JqueryAdam RaneyView Answer on Stackoverflow
Solution 13 - JqueryArun GeorgeView Answer on Stackoverflow
Solution 14 - JqueryDan HunexView Answer on Stackoverflow