Wait cursor over entire html page

2019-01-10 18:25发布

问题:

Is it possible to set the cursor to 'wait' on the entire html page in a simple way? The idea is to show the user that something is going on while an ajax call is being completed. The code below shows a simplified version of what I tried and also demonstrate the problems I run into:

  1. if an element (#id1) has a cursor style set it will ignore the one set on body (obviously)
  2. some elements have a default cursor style (a) and will not show the wait cursor on hover
  3. the body element has a certain height depending on the content and if the page is short, the cursor will not show below the footer

The test:

<html>
    <head>
        <style type="text/css">
            #id1 {
                background-color: #06f;
                cursor: pointer;
            }

            #id2 {
                background-color: #f60;
            }
        </style>
    </head>
    <body>
        <div id="id1">cursor: pointer</div>
        <div id="id2">no cursor</div>
        <a href="#" onclick="document.body.style.cursor = 'wait'; return false">Do something</a>
    </body>
</html>

Later edit...
It worked in firefox and IE with:

div#mask { display: none; cursor: wait; z-index: 9999; 
position: absolute; top: 0; left: 0; height: 100%; 
width: 100%; background-color: #fff; opacity: 0; filter: alpha(opacity = 0);}

<a href="#" onclick="document.getElementById('mask').style.display = 'block'; return false">
Do something</a>

The problem with (or feature of) this solution is that it will prevent clicks because of the overlapping div (thanks Kibbee)

Later later edit...
A simpler solution from Dorward:

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

and then

<a href="#" onclick="document.body.className = 'wait'; return false">Do something</a>

This solution only shows the wait cursor but allows clicks.

回答1:

I understand you may not have control over this, but you might instead go for a "masking" div that covers the entire body with a z-index higher than 1. The center part of the div could contain a loading message if you like.

Then, you can set the cursor to wait on the div and don't have to worry about links as they are "under" your masking div. Here's some example CSS for the "masking div":

body { height: 100%; }
div#mask { cursor: wait; z-index: 999; height: 100%; width: 100%; }


回答2:

If you use this slightly modified version of the CSS you posted from Dorward,

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

you can then add some really simple jQuery to work for all ajax calls:

$(document).ready(function () {
    $(document).ajaxStart(function () { $("html").addClass("wait"); });
    $(document).ajaxStop(function () { $("html").removeClass("wait"); });
});

or, for older jQuery versions (before 1.9):

$(document).ready(function () {
    $("html").ajaxStart(function () { $(this).addClass("wait"); });
    $("html").ajaxStop(function () { $(this).removeClass("wait"); });
});


回答3:

This seems to work in firefox

<style>
*{ cursor: inherit;}
body{ cursor: wait;}
</style>

The * part ensures that the cursor doesn't change when you hover over a link. Although links will still be clickable.



回答4:

I have been struggling with this problem for hours today. Basically everything was working just fine in FireFox but (of course) not in IE. In IE the wait cursor was showing AFTER the time consuming function was executed.

I finally found the trick on this site: http://www.codingforums.com/archive/index.php/t-37185.html

Code:

//...
document.body.style.cursor = 'wait';
setTimeout(this.SomeLongFunction, 1);

//setTimeout syntax when calling a function with parameters
//setTimeout(function() {MyClass.SomeLongFunction(someParam);}, 1);

//no () after function name this is a function ref not a function call
setTimeout(this.SetDefaultCursor, 1);
...

function SetDefaultCursor() {document.body.style.cursor = 'default';}

function SomeLongFunction(someParam) {...}

My code runs in a JavaScript class hence the this and MyClass (MyClass is a singleton).

I had the same problems when trying to display a div as described on this page. In IE it was showing after the function had been executed. So I guess this trick would solve that problem too.

Thanks a zillion time to glenngv the author of the post. You really made my day!!!



回答5:

css: .waiting * { cursor: 'wait' }

jQuery: $('body').toggleClass('waiting');



回答6:

Why don't you just use one of those fancy loading graphics (eg: http://ajaxload.info/)? The waiting cursor is for the browser itself - so whenever it appears it has something to do with the browser and not with the page.



回答7:

Easiest way I know is using JQuery like this:

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


回答8:

Try the css:

html.waiting {
cursor: wait;
}

It seems that if the property body is used as apposed to html it doesn't show the wait cursor over the whole page. Furthermore if you use a css class you can easily control when it actually shows it.



回答9:

Here is a more elaborate solution that does not require external CSS:

function changeCursor(elem, cursor, decendents) {
    if (!elem) elem=$('body');

    // remove all classes starting with changeCursor-
    elem.removeClass (function (index, css) {
        return (css.match (/(^|\s)changeCursor-\S+/g) || []).join(' ');
    });

    if (!cursor) return;

    if (typeof decendents==='undefined' || decendents===null) decendents=true;

    let cname;

    if (decendents) {
        cname='changeCursor-Dec-'+cursor;
        if ($('style:contains("'+cname+'")').length < 1) $('<style>').text('.'+cname+' , .'+cname+' * { cursor: '+cursor+' !important; }').appendTo('head');
    } else {
        cname='changeCursor-'+cursor;
        if ($('style:contains("'+cname+'")').length < 1) $('<style>').text('.'+cname+' { cursor: '+cursor+' !important; }').appendTo('head');
    }

    elem.addClass(cname);
}

with this you can do:

changeCursor(, 'wait'); // wait cursor on all decendents of body
changeCursor($('#id'), 'wait', false); // wait cursor on elem with id only
changeCursor(); // remove changed cursor from body


回答10:

BlockUI is the answer for everything. Give it a try.

http://www.malsup.com/jquery/block/



回答11:

I used a adaptation of Eric Wendelin's solution. It will show a transparent, animated overlay wait-div over the whole body, the click will be blocked by the wait-div while visible:

css:

div#waitMask {
    z-index: 999;
    position: absolute;
    top: 0;
    right: 0;
    height: 100%;
    width: 100%;
    cursor: wait;
    background-color: #000;
    opacity: 0;
    transition-duration: 0.5s;
    -webkit-transition-duration: 0.5s;
}

js:

// to show it
$("#waitMask").show();
$("#waitMask").css("opacity"); // must read it first
$("#waitMask").css("opacity", "0.8");

...

// to hide it
$("#waitMask").css("opacity", "0");
setTimeout(function() {
    $("#waitMask").hide();
}, 500) // wait for animation to end

html:

<body>
    <div id="waitMask" style="display:none;">&nbsp;</div>
    ... rest of html ...


回答12:

My Two pence:

Step 1: Declare an array. This will be used to store the original cursors that were assigned:

var vArrOriginalCursors = new Array(2);

Step 2: Implement the function cursorModifyEntirePage

 function CursorModifyEntirePage(CursorType){
    var elements = document.body.getElementsByTagName('*');
    alert("These are the elements found:" + elements.length);
    let lclCntr = 0;
    vArrOriginalCursors.length = elements.length; 
    for(lclCntr = 0; lclCntr < elements.length; lclCntr++){
        vArrOriginalCursors[lclCntr] = elements[lclCntr].style.cursor;
        elements[lclCntr].style.cursor = CursorType;
    }
}

What it does: Gets all the elements on the page. Stores the original cursors assigned to them in the array declared in step 1. Modifies the cursors to the desired cursor as passed by parameter CursorType

Step 3: Restore the cursors on the page

 function CursorRestoreEntirePage(){
    let lclCntr = 0;
    var elements = document.body.getElementsByTagName('*');
    for(lclCntr = 0; lclCntr < elements.length; lclCntr++){
        elements[lclCntr].style.cursor = vArrOriginalCursors[lclCntr];
    }
}

I have run this in an application and it works fine. Only caveat is that I have not tested it when you are dynamically adding the elements.