Search code examples
jquerycssajaxcursor

How To Change The Cursor Icon When Performing AJAX Action Inside A JQuery Dialog?


Why when I have a JQuery dialog open and I do some $.ajax calls can't I change the cursor?

I'd like to show a progress cursor while the code is off working as the user will be waiting and watching for the action to complete, but the although the CSS is updated to "cursor: progress" the browser UI doesn't update ( Firefox 23.0.1). However, the cursor will change if I take out the $.ajax calls and put in some setTimeOut callbacks to mimic time passing. Any ideas what's going on? Thanks.

This test code reproduces the problem:

$( "#dialog-confirm" ).dialog({

                resizable   : true,
                height      : 240,
                modal       : true,

                buttons: {

                    "Take Action": function() {

                            $( "body" ).css( 'cursor', 'progress' );

                            for ( i = 0; i < 2000; i++ ) 
                            {

                                $.ajax({
                                    async   : false,  
                                    type    : 'GET',
                                    url     :  "test2.html", 
                                    cache   : false,
                                    dataType: 'html',   
                                    success : function(data) {
                                        $("#junk").append ( data + "number: " + i );
                                    },
                                    error: function(data) {     

                                    }
                                });

                            }

                            $( "body" ).css( 'cursor', 'default' );
                    },

                    "Exit": function() {
                        $( this ).dialog( "close" );
                    }
                }
            });

Test page HTML:

                <div id="dialog-confirm" title="Show Something here">
                    <p>
                        <span class="ui-icon ui-icon-alert" style="float: left; margin: 0 7px 20px 0;"></span>
                        Text of the dialog box here
                    </p>
                </div>
            <div id ="junk"> Some rubbish text so I can see the div </div>
            <div>

This is the HTML is loads:

<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>

Edit: After some further testing it's clear the Dialog has nothing to do with the problem, this issue is related to the single threaded nature of Javascript and the fact that the code is hogging the processor without relinquishing it. Comments and answers below have proved helpful but not answered my question. Changing the code too:

var j = 0;  
var set = false;
//for ( i = 0; i < 1000; i++ ) 
{
    setTimeout ( function doStuff () 
    {
        $.ajax({
            async   : false,  
            type    : 'GET',
            url     :  "test2.html", 
            cache   : false,
            dataType: 'html',   
            beforeSend: function () 
            {
                if ( set === false )
                    { $("body").css('cursor', 'wait'); set = true; }
            },
            complete: function () {                        
            },

            success : function(data) {
                $("#junk").append ( data + "number: " + ++j );      
                if ( j === 1000 ) {
                    $( "body" ).css( 'cursor', 'auto' );
                }
            },
            error: function(data) {     
            }
        });

        if ( j < 1000 ) {
            setTimeout(doStuff,20);
        }           

    }, 0);      
}

Solves the problem by relinquishing the processor following every $.ajax call, it's not ideal, but it appears to work;

Note: the for loop was made redundant in this new test code which kind of changed the problem\issue.


Solution

  • Relinquish the processor using setTimeout so the browser's UI can update the cursor.

    setTimeout ( function doStuff () 
    {
        $.ajax({
            async   : false,  
            type    : 'GET',
            url     :  "test2.html", 
            cache   : false,
            dataType: 'html',   
            beforeSend: function () 
            {
                if ( set === false )
                    { $("body").css('cursor', 'wait'); set = true; }
            },
            complete: function () {                        
            },
    
            success : function(data) {
                $("#junk").append ( data + "number: " + ++j );      
                if ( j === 1000 ) {
                    $( "body" ).css( 'cursor', 'auto' );
                }
            },
            error: function(data) {     
            }
        });
    
        if ( j < 1000 ) {
            setTimeout(doStuff,20);
        }           
    
    }, 0);