Aguarde o cursor sobre a página html inteira

89

É possível definir o cursor para 'esperar' em toda a página html de uma forma simples? A ideia é mostrar ao usuário que algo está acontecendo enquanto uma chamada ajax está sendo completada. O código abaixo mostra uma versão simplificada do que tentei e também demonstra os problemas que encontro:

  1. se um elemento (# id1) tiver um estilo de cursor definido, ele irá ignorar o definido no corpo (obviamente)
  2. alguns elementos têm um estilo de cursor padrão (a) e não mostrarão o cursor de espera ao passar o mouse
  3. o elemento do corpo tem uma certa altura dependendo do conteúdo e se a página for curta, o cursor não aparecerá abaixo do rodapé

O teste:

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

Editar mais tarde ...
Funcionou no firefox e no IE com:

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>

O problema (ou recurso) dessa solução é que ela evitará cliques devido à div sobreposição (obrigado, Kibbee)

Mais tarde, edite mais tarde ...
Uma solução mais simples de Dorward:

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

e depois

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

Esta solução mostra apenas o cursor de espera, mas permite cliques.

Aleris
fonte
Parece que não consigo alterar o cursor para os elementos selecionados. Existe uma maneira de alterar o cursor para o elemento selecionado também?
Biswanath,

Respostas:

34

Eu entendo que você pode não ter controle sobre isso, mas você pode ir para um div "mascarado" que cubra todo o corpo com um índice z superior a 1. A parte central do div pode conter uma mensagem de carregamento, se desejar.

Em seguida, você pode definir o cursor para aguardar o div e não precisa se preocupar com links, pois eles estão "sob" seu div de mascaramento. Aqui está um exemplo de CSS para o "div de máscara":

corpo {altura: 100%; }
div # mask {cursor: wait; índice z: 999; altura: 100%; largura: 100%; }
Eric Wendelin
fonte
3
Isso geralmente pode causar problemas. No Firefox, colocar um div fixo em toda a página faz com que ela se torne impossível de clicar. ou seja, você não pode clicar em links, porque você não está clicando no link, está clicando no div na frente do link.
Kibbee
1
Funciona bem no firefox. Sem sorte no IE :(. No IE, ele se comporta exatamente como se o div não existisse. A única maneira de ter o comportamento desejado é definir uma cor no fundo do div.
Aleris
2
Ok, depois de jogar um pouco mais, finalmente funcionou com: div # mask {display: none; cursor: espere; índice z: 9999; posição: absoluta; topo: 0; esquerda: 0; altura: 100%; largura: 100%; cor de fundo: #fff; opacidade: 0; filtro: alfa (opacidade = 0);}
Aleris
Concordo, Kibbee, realmente depende do comportamento desejado. Parece que o Aleris não quer que o usuário faça nada (daí o cursor de espera) até que o AJAX ligue de volta.
Eric Wendelin,
3
Usei position: fixed para ficar sempre na tela, com position: absolute não apareceria quando eu estivesse no final da página.
Jj.
111

Se você usar esta versão ligeiramente modificada do CSS que postou de Dorward,

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

você pode adicionar um jQuery realmente simples para funcionar em todas as chamadas de Ajax:

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

ou, para versões mais antigas do jQuery (antes de 1.9):

$(document).ready(function () {
    $("html").ajaxStart(function () { $(this).addClass("wait"); });
    $("html").ajaxStop(function () { $(this).removeClass("wait"); });
});
Dani
fonte
4
Eu realmente quero usar esta resposta ... por que não é a aceita?
gloomy.penguin
1
@ gloomy.penguin Esta pergunta estava ativa mais de 3 anos antes de minha resposta, mas me deparei com ela em minha própria busca por uma solução e decidi compartilhar a solução que acabei usando: uma mistura da resposta de Dorward, jQuery, e o bom senso de Kyle. É um pouco diferente do que o OP estava procurando, mas se funcionar para você, use-o! :)
Dani
Concordo. Funciona muito bem e IMHO deve ser a resposta aceita.
savehansson
1
Se isso não estiver funcionando para você, verifique aqui: JQuery.com "A partir do JQuery 1.9, os eventos globais Ajax são acionados apenas no elemento do documento." Ex:$(document).ajaxStart(function () { $("html").addClass("wait"); });
Debbie A
1
Antes de remover a classe de espera, você provavelmente deseja verificar se $.activeé 0, caso várias solicitações tenham sido feitas e todas ainda não foram concluídas.
Shane Reustle
12

Isso parece funcionar no firefox

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

A parte * garante que o cursor não mude quando você passa o mouse sobre um link. Embora os links ainda sejam clicáveis.

Kibee
fonte
* {cursor: espere! importante; } seria mais simples e mais provável de funcionar no IE (que tem muitos bugs com a palavra-chave inherit)
Quentin,
1
* {Cursor: aguarde} pode ser aplicado a partir de javascript? - exceto pela iteração de todos os elementos em todo o DOM :)
Aleris
talvez você possa adicionar um elemento de estilo e definir o innerHTML. Não seria muito elegante, mas pode funcionar.
Kibbee
3
.wait, .wait * {cusor: wait! important; } e então defina document.body.className = 'wait'; com JavaScript
Quentin,
1
Observe que há um erro de digitação de "cursor" no comentário acima, caso você o copie / cole.
devios1
7

Tenho lutado com esse problema por horas hoje. Basicamente, tudo estava funcionando bem no FireFox, mas (é claro) não no IE. No IE, o cursor de espera era mostrado APÓS a execução da função demorada.

Finalmente encontrei o truque neste site: 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) {...}

Meu código é executado em uma classe JavaScript, portanto, o this e MyClass (MyClass é um singleton).

Tive os mesmos problemas ao tentar exibir um div, conforme descrito nesta página. No IE, ela era exibida após a execução da função. Portanto, acho que esse truque resolveria esse problema também.

Agradeço um zilhão de vezes a Glenngv, o autor do post. Você realmente fez o meu dia!!!

pasx
fonte
4

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

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

redbmk
fonte
2

Por que você simplesmente não usa um desses gráficos de carregamento sofisticados (por exemplo: http://ajaxload.info/ )? O cursor de espera é para o próprio navegador - portanto, sempre que aparece, tem algo a ver com o navegador e não com a página.

não existe
fonte
Eu concordo parcialmente. Pelo menos nas janelas o cursor que aparece, se o próprio navegador estiver carregando uma página, cursor: progressnão está cursor: wait. Usar esse cursor seria muito mais coerente com a experiência do usuário do navegador. Mas eu realmente gosto da ideia de mudar o cursor para indicar que o navegador está funcionando exatamente como quando carrega uma página.
gripe
2

A maneira mais fácil que conheço é usando JQuery assim:

$('*').css('cursor','wait');
jere_hr
fonte
isso pode levar "para sempre" se você tiver muitos elementos, especialmente em um computador lento
redbmk
1

Experimente o css:

html.waiting {
cursor: wait;
}

Parece que, se a propriedade bodyfor usada em oposição a htmlela, não mostra o cursor de espera sobre a página inteira. Além disso, se você usar uma classe css, poderá controlar facilmente quando ela realmente será exibida.

GameFreak
fonte
O que é essa aula de espera? É algo personalizado?
Sebas
1

Aqui está uma solução mais elaborada que não requer 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);
}

com isso você pode fazer:

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

Usei uma adaptação da solução de Eric Wendelin . Ele mostrará uma div de espera de sobreposição transparente e animada sobre todo o corpo, o clique será bloqueado pela div de espera enquanto estiver visível:

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

Meus dois pence:

Etapa 1: declare uma matriz. Isso será usado para armazenar os cursores originais que foram atribuídos:

var vArrOriginalCursors = new Array(2);

Etapa 2: implemente a função 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;
    }
}

O que faz: obtém todos os elementos da página. Armazena os cursores originais atribuídos a eles na matriz declarada na etapa 1. Modifica os cursores para o cursor desejado conforme passado pelo parâmetro CursorType

Etapa 3: restaurar os cursores na 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];
    }
}

Eu executei isso em um aplicativo e funciona bem. A única ressalva é que eu não testei quando você está adicionando os elementos dinamicamente.

indiaaditya
fonte
1

Para definir o cursor do JavaScript para a janela inteira, use:

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

De CSS:

html { cursor: wait; }

Adicione mais lógica conforme necessário.

Peter J. de Bruin
fonte
Esta solução javascript é a melhor, faz o trabalho sem mexer na bagagem do HTML. Isso é muito melhor do que alternar classes em elementos, o que é muito lento se você tiver muitos nós em seu DOM.
Rajshekar Reddy
0

Este JavaScript puro parece funcionar muito bem ... testado em navegadores FireFox, Chrome e Edge.

Não tenho certeza sobre o desempenho disso se você tiver uma superabundância de elementos em sua página e um computador lento ... experimente e veja.

Defina o cursor para que todos os elementos aguardem:

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

Defina o cursor para todos os elementos de volta ao padrão:

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

Uma versão alternativa (e talvez um pouco mais legível) seria criar uma função setCursor da seguinte maneira:

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

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

e então ligar

setCursor("wait");

e

setCursor("default");

para definir o cursor de espera e o cursor padrão, respectivamente.

javocidade
fonte