在整个 html 页面上等待光标

是否可以简单地将光标设置为“等待”整个 html 页面?这个想法是为了向用户展示当一个 ajax 调用完成时正在发生的事情。下面的代码显示了我尝试的一个简化版本,也演示了我遇到的问题:

  1. 如果一个元素(# id1)有一个游标样式集,它将忽略 body 上的样式集(很明显)
  2. 有些元素具有默认的游标样式(a) ,并且在悬停时不显示等待游标
  3. Body 元素具有一定的高度,这取决于页面的内容,如果页面很短,则光标不会显示在页脚下方

测试:

<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>

稍后编辑..。
它可以在 Firefox 和 IE 中使用:

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>

这个解决方案的问题(或特点)在于它会阻止点击,因为重叠的 div (感谢 Kibbee)

稍后编辑..。
多沃德提出了一个更简单的解决方案:

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

然后

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

此解决方案只显示等待光标,但允许单击。

97862 次浏览

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.

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%; }

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.

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.

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"); });
});

Easiest way I know is using JQuery like this:

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

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!!!

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

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

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

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

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

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 ...

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.

To set the cursor from JavaScript for the whole window, use:

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

From CSS:

html { cursor: wait; }

Add further logic as needed.

This pure JavaScript seems to work pretty well ... tested on FireFox, Chrome, and Edge browsers.

I'm not sure about the performance of this if you had an overabundance of elements on your page and a slow computer ... try it and see.

Set cursor for all elements to wait:

Object.values(document.querySelectorAll('*')).forEach(element => element.style.cursor = "wait");

Set cursor for all elements back to default:

Object.values(document.querySelectorAll('*')).forEach(element => element.style.cursor = "default");

An alternative (and perhaps a bit more readable) version would be to create a setCursor function as follows:

function setCursor(cursor)
{
var x = document.querySelectorAll("*");


for (var i = 0; i < x.length; i++)
{
x[i].style.cursor = cursor;
}
}

and then call

setCursor("wait");

and

setCursor("default");

to set the wait cursor and default cursor respectively.

Late to the party but simply give the Html tag an id by targeting

document.documentElement

and in the CSS place at the top

html#wait * {
cursor: wait !important;
}

and simply remove it when you want to stop this cursor.

Lots of good answers already, but none of them mentions the <dialog> element.

Using this element we can create a solution similar to the masking <div>.

Here we use showModal() to "hide" elements, and we use ::backdrop to set the cursor style to wait on the entire page:

function showWaitDialog() {
document.getElementById('id_dialog').showModal();
}
#id_dialog, #id_dialog::backdrop {
cursor: wait;
}
<button onclick="showWaitDialog()">click me</button>
<dialog id="id_dialog">busy...</dialog>

The dialog is hidden by default, and can be shown using either the show() method, or the showModal() method, which prevents clicking outside the dialog.

The dialog can be forced to close using the close() method, if necessary. However, if your button links to another page, for example, then the dialog will disappear automatically as soon as the new page is loaded.

Note that the dialog can also be closed at any time by hitting the Esc key.

CSS can be used to style the dialog however you like.

The example uses the html onclick attribute, just for simplicity. Obviously, addEventListener() could also be used.