Espere el cursor sobre toda la página html

89

¿Es posible configurar el cursor para 'esperar' en toda la página html de una manera simple? La idea es mostrar al usuario que algo está sucediendo mientras se completa una llamada ajax. El siguiente código muestra una versión simplificada de lo que probé y también demuestra los problemas con los que me encuentro:

  1. si un elemento (# id1) tiene un estilo de cursor establecido, ignorará el establecido en el cuerpo (obviamente)
  2. algunos elementos tienen un estilo de cursor predeterminado (a) y no mostrarán el cursor de espera al pasar el mouse
  3. el elemento del cuerpo tiene una cierta altura dependiendo del contenido y si la página es corta, el cursor no se mostrará debajo del pie de página

La prueba:

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

Edición posterior ...
Funcionó en Firefox e IE con:

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>

El problema con (o característica de) esta solución es que evitará clics debido al div superpuesto (gracias Kibbee)

Más tarde editar ...
Una solución más simple de Dorward:

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

y entonces

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

Esta solución solo muestra el cursor de espera pero permite clics.

Aleris
fuente
Como parece, no puedo cambiar el cursor de los elementos seleccionados. ¿Hay alguna forma de cambiar el cursor para el elemento seleccionado también?
Biswanath

Respuestas:

33

Entiendo que es posible que no tenga control sobre esto, pero podría optar por un div de "enmascaramiento" que cubra todo el cuerpo con un índice z superior a 1. La parte central del div podría contener un mensaje de carga si lo desea.

Luego, puede configurar el cursor para que espere en el div y no tenga que preocuparse por los enlaces, ya que están "debajo" de su div de enmascaramiento. Aquí hay un ejemplo de CSS para el "div de enmascaramiento":

cuerpo {altura: 100%; }
div # máscara {cursor: espera; índice z: 999; altura: 100%; ancho: 100%; }
Eric Wendelin
fuente
3
Esto a menudo puede causar problemas. En Firefox, colocar un div fijo en toda la página hace que no se pueda hacer clic en toda la página. es decir, no puede hacer clic en enlaces, porque no está haciendo clic en el enlace, está haciendo clic en el div frente al enlace.
Kibbee
1
Funciona bien en Firefox. No hubo suerte en IE :(. En IE se comporta exactamente como si el div no estuviera allí. La única forma de tener el comportamiento deseado es establecer un color en el fondo del div.
Aleris
2
Ok, después de jugar un poco más, finalmente funcionó con: div # mask {display: none; cursor: espera; índice z: 9999; posición: absoluta; arriba: 0; izquierda: 0; altura: 100%; ancho: 100%; color de fondo: #fff; opacidad: 0; filtro: alfa (opacidad = 0);}
Aleris
De acuerdo, Kibbee, realmente depende de tu comportamiento deseado. Parece que Aleris no quiere que el usuario haga nada (de ahí el cursor de espera) hasta que AJAX vuelva a llamar.
Eric Wendelin
3
Usé la posición: fija para que siempre esté en la pantalla, con la posición: absoluta no se mostraría cuando estaba en la parte inferior de la página.
Jj.
111

Si usa esta versión ligeramente modificada del CSS que publicó desde Dorward,

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

luego puede agregar un jQuery realmente simple para que funcione para todas las llamadas ajax:

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

o, para versiones anteriores de jQuery (antes de 1.9):

$(document).ready(function () {
    $("html").ajaxStart(function () { $(this).addClass("wait"); });
    $("html").ajaxStop(function () { $(this).removeClass("wait"); });
});
Dani
fuente
4
Realmente quiero usar esta respuesta ... ¿por qué no es la aceptada?
gloomy.penguin
1
@ gloomy.penguin Esta pregunta estuvo activa más de 3 años antes de mi respuesta, pero la encontré en mi propia búsqueda de una solución, y decidí compartir la solución que terminé usando: una mezcla de la respuesta de Dorward, jQuery, y el buen sentido de Kyle. Es un poco diferente de lo que estaba buscando el OP, pero si funciona para usted, ¡utilícelo! :)
Dani
Estoy de acuerdo. Funciona muy bien y en mi humilde opinión debería ser la respuesta aceptada.
savehansson
1
Si esto no le funciona, marque aquí: JQuery.com "A partir de JQuery 1.9, los eventos globales de Ajax solo se activan en el elemento del documento". Ej .:$(document).ajaxStart(function () { $("html").addClass("wait"); });
Debbie A
1
Antes de eliminar la clase de espera, probablemente desee verificar si $.activees 0, en caso de que se hayan realizado varias solicitudes y aún no hayan finalizado.
Shane Reustle
12

Esto parece funcionar en Firefox

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

La parte * asegura que el cursor no cambie cuando pasas el cursor sobre un enlace. Aunque todavía se podrá hacer clic en los enlaces.

Kibbee
fuente
* {cursor: ¡espera! importante; } sería más simple y más probable que funcione en IE (que tiene muchos errores con la palabra clave heredar)
Quentin
1
¿Se puede aplicar * {cursor: wait} desde javascript? - excepto iterando todos los elementos en todo el DOM :)
Aleris
tal vez podría agregar un elemento de estilo y establecer el innerHTML. No sería muy elegante, pero podría funcionar.
Kibbee
3
.wait, .wait * {cliente: espera! importante; } y luego establezca document.body.className = 'esperar'; con JavaScript
Quentin
1
Tenga en cuenta que hay un error tipográfico de "cursor" en el comentario anterior, en caso de que lo copie / pegue.
devios1
7

Hoy he estado luchando con este problema durante horas. Básicamente, todo funcionaba bien en FireFox pero (por supuesto) no en IE. En IE, el cursor de espera se mostraba DESPUÉS de que se ejecutó la función que consumía mucho tiempo.

Finalmente encontré el truco en este sitio: http://www.codingforums.com/archive/index.php/t-37185.html

Código:

//...
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) {...}

Mi código se ejecuta en una clase de JavaScript, por lo tanto, this y MyClass (MyClass es un singleton).

Tuve los mismos problemas al intentar mostrar un div como se describe en esta página. En IE se mostraba después de que se había ejecutado la función. Así que supongo que este truco también resolvería ese problema.

Un trillón de gracias a Glenngv, el autor de la publicación. Realmente me alegraste el día !!!

pasx
fuente
4

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

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

redbmk
fuente
2

¿Por qué no usas uno de esos elegantes gráficos de carga (por ejemplo: http://ajaxload.info/ )? El cursor de espera es para el navegador en sí, por lo que siempre que aparece tiene algo que ver con el navegador y no con la página.

inexistente
fuente
Estoy de acuerdo parcialmente. Al menos en Windows, el cursor que aparece, si el propio navegador está cargando una página, cursor: progressno lo está cursor: wait. Usar ese cursor sería mucho más coherente con la experiencia del usuario del navegador. Pero realmente me gusta la idea de cambiar el cursor para indicar que el navegador está funcionando igual que cuando carga una página.
gripe
2

La forma más fácil que conozco es usar JQuery así:

$('*').css('cursor','wait');
jere_hr
fuente
eso podría llevar "una eternidad" si tiene muchos elementos, especialmente en una computadora lenta
redbmk
1

Prueba el CSS:

html.waiting {
cursor: wait;
}

Parece que si la propiedad bodyse usa como apostada html, no muestra el cursor de espera en toda la página. Además, si usa una clase css, puede controlar fácilmente cuándo realmente la muestra.

Adicto a los juegos
fuente
¿Qué es esa clase de espera? ¿Es algo personalizado?
Sebas
1

Aquí hay una solución más elaborada que no requiere CSS externo:

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

con esto puedes hacer:

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
kofifus
fuente
1

Usé una adaptación de la solución de Eric Wendelin . Mostrará un wait-div superpuesto, transparente y animado en todo el cuerpo, el clic será bloqueado por el wait-div mientras esté 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 ...
ungalcrys
fuente
1

Mis dos peniques:

Paso 1: declare una matriz. Esto se utilizará para almacenar los cursores originales que se asignaron:

var vArrOriginalCursors = new Array(2);

Paso 2: implementar la función 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;
    }
}

Qué hace: Obtiene todos los elementos de la página. Almacena los cursores originales asignados a ellos en la matriz declarada en el paso 1. Modifica los cursores al cursor deseado según lo pasado por el parámetro CursorType

Paso 3: restaura los cursores en la página

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

He ejecutado esto en una aplicación y funciona bien. La única advertencia es que no lo he probado cuando está agregando dinámicamente los elementos.

indiaaditya
fuente
1

Para configurar el cursor desde JavaScript para toda la ventana, use:

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

De CSS:

html { cursor: wait; }

Agregue más lógica según sea necesario.

Peter J. de Bruin
fuente
Esta solución de JavaScript es la mejor, hace el trabajo sin tocar el equipaje HTML. Esto es mucho mejor que alternar clases en elementos, lo cual es muy lento si tiene muchos nodos en su DOM.
Rajshekar Reddy
0

Este JavaScript puro parece funcionar bastante bien ... probado en navegadores FireFox, Chrome y Edge.

No estoy seguro del rendimiento de esto si tuvieras una sobreabundancia de elementos en tu página y una computadora lenta ... pruébalo y verás.

Coloque el cursor para que todos los elementos esperen:

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

Establecer el cursor para todos los elementos de nuevo al valor predeterminado:

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

Una versión alternativa (y quizás un poco más legible) sería crear una función setCursor de la siguiente manera:

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

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

y luego llamar

setCursor("wait");

y

setCursor("default");

para configurar el cursor de espera y el cursor predeterminado respectivamente.

javocidad
fuente