Den Browser-Cursor von "Warten" auf "Auto" bewegen, ohne dass der Benutzer die Maus bewegt

68

Ich verwende diesen jQuery-Code, um den Mauszeiger während eines Ajax-Aufrufs auf den Besetztzustand (Sanduhr) zu setzen ...

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

und dieser entsprechende Code, um ihn wieder auf normal zu setzen ...

$('body').css('cursor', 'auto');

Dies funktioniert gut ... in einigen Browsern.

In Firefox und IE ändert sich der Mauszeiger, sobald ich den Befehl ausführe. Das ist das Verhalten, das ich will.

In Chrome und Safari ändert sich der Mauszeiger nicht sichtbar von "Besetzt" in "Automatisch", bis der Benutzer den Zeiger bewegt.

Was ist der beste Weg, um die widerstrebenden Browser dazu zu bringen, den Mauszeiger zu wechseln?

Nosredna
quelle
Chrome: Das hat es für mich getan
Valamas
Wie unten von @ j-allen erwähnt, wurde dieses Problem in Chrome v50 + behoben, wenn die Entwicklertools / -konsole geschlossen werden.
Erikus Maximus
Trotz der Fehler in Chrome habe ich eine Lösung gefunden, die ich in meiner Antwort unten beschreibe .
Ninjakannon

Antworten:

36

Es ist im Moment ein Fehler in beiden Browsern. Weitere Details unter beiden Links (auch in Kommentaren):

http://code.google.com/p/chromium/issues/detail?id=26723

und

http://code.google.com/p/chromium/issues/detail?id=20717

user213788
quelle
2
Fehler im Jahr 2009 gemeldet und immer noch unbestätigt. Traurig.
StriplingWarrior
2
danke für die links. Der erste Link enthält einige nützliche Kommentare, darunter # 87 ( code.google.com/p/chromium/issues/detail?id=26723#c87 ). Dies ist die Problemumgehung, die ich jetzt verwende
Greg Jackman
9
Für Leute, die jetzt darauf stoßen, obwohl der Fehler anscheinend 2013 behoben wurde, tritt er manchmal immer noch auf, wenn Entwickler-Tools geöffnet sind (siehe die Kommentare zum Chrom-Fehler 26723 vom Dezember 2016). Also, schließen Sie Entwickler-Tools wie Ihre Benutzer, und dann alles gut :)
Tim Malone
1
@ TimMalone Dies ist das spezielle Problem für die Entwickler-Tools. bugs.chromium.org/p/chromium/issues/detail?id=676644
Coburn
3
Noch passiert in 2017/08/20 Chrom 60, mit oder ohne
Entwickler-
38

Ich würde es lieber eleganter machen:

$(function(){  
  $("html").bind("ajaxStart", function(){  
     $(this).addClass('busy');  
   }).bind("ajaxStop", function(){  
     $(this).removeClass('busy');  
   });  
});

CSS:

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

Quelle: http://postpostmodern.com/instructional/global-ajax-cursor-change/

Korayem
quelle
2
Korayem - +1. schöner sauberer Ansatz. Ich habe es als Ersatz für eine ziemlich chaotische Implementierung geklaut, die ich zusammengeschustert hatte. Vielen Dank!! ;-)
Jim Tollan
2
Für meinen Anwendungsfall musste ich diese Logik in ein SetTimeout von 1 Millisekunde setzen, damit sie wirksam wird
jedierikb
14
Dies beantwortet die Frage nicht wirklich. Wenn Sie die Maus nicht bewegen, wechselt der Cursor beim Entfernen der Klasse nicht zurück in die automatische Position.
Greg Jackman
Ich mag diese Lösung, aber ich musste das Ereignis an $ (Dokument) binden und dann die Klasse an $ ('html) hinzufügen, damit es funktioniert.
Zach Greenberger
23

Ich glaube, dieses Problem (einschließlich des Mousedown-Problems) ist jetzt in Chrome 50 behoben.

Aber nur, wenn Sie die Entwicklertools nicht verwenden !!

Schließen Sie die Werkzeuge und der Cursor sollte sofort besser reagieren.

J. Allen
quelle
4
Ha, hätte nicht daran gedacht, Entwicklertools zu schließen. Vielen Dank!
Ykay sagt Reinstate Monica
Das ist der Schlüssel: Entwickler-Tools schließen!
Bobort
immer noch nicht in Chrom 60 fixiert
Seabizkit
1
Nur um klar zu sein, es ist nicht behoben, wenn Sie die Seite neu laden, dh location.reload (); wirklich nervig ... also im Ajax-Aufruf, wenn Sie fertig sind, location.reload (); und der Cursor wird falsch sein.
Seabizkit
Nicht behoben in 63.0.3239.108 (Official Build) (64-Bit) auch :(
RobAu
7

Ich habe mich von der Korayem-Lösung inspirieren lassen.

Javascript:

jQuery.ajaxSetup({
    beforeSend: function() {
       $('body').addClass('busy');
    },
    complete: function() {
       $('body').removeClass('busy');
    }
});

CSS:

.busy * {
    cursor: wait !important;
}

Getestet auf Chrome, Firefox und IE 10. Der Cursor ändert sich, ohne die Maus zu bewegen. "! wichtig" wird für IE10 benötigt.

Bearbeiten: Sie müssen den Cursor in IE 10 noch bewegen, nachdem die AJAX-Anforderung abgeschlossen ist (damit der normale Cursor angezeigt wird). Der Wartecursor wird angezeigt, ohne die Maus zu bewegen.

Sergiu
quelle
1
Und stellen Sie sicher, dass die Entwicklungstools geschlossen sind!
Bobort
1

Zuallererst sollten Sie sich darüber im Klaren sein, dass, wenn Sie einem Tag in Ihrem Körper einen Cursor zugewiesen haben, $('body').css('cursor', 'wait');der Cursor dieses Tags nicht geändert wird (wie ich, verwende ich ihn cursor: pointer;für alle meine Ankertags). Vielleicht möchten Sie zuerst meine Lösung für dieses spezielle Problem betrachten: Cursor warten auf Ajax-Aufruf

Für das Problem, dass der Cursor erst aktualisiert wird, wenn der Benutzer die Maus in Webkit-Browsern bewegt, gibt es, wie andere sagten, keine wirkliche Lösung.

Abgesehen davon gibt es immer noch eine Problemumgehung, wenn Sie dem aktuellen Cursor dynamisch einen CSS-Spinner hinzufügen. Dies ist keine perfekte Lösung, da Sie die Größe des Cursors und die korrekte Positionierung des Drehfelds nicht genau kennen.

CSS-Spinner nach dem Cursor: DEMO

$.fn.extend(
{
    reset_on : function(event_name, callback)
    { return this.off(event_name).on(event_name, callback); }
});

var g_loader = $('.loader');

function add_cursor_progress(evt)
{
    function refresh_pos(e_)
    {
        g_loader.css({
            display : "inline",
            left : e_.pageX + 8,
            top : e_.pageY - 8
        });
    }
    refresh_pos(evt);
    var id = ".addcursorprog"; // to avoid duplicate events

    $('html').reset_on('mousemove' + id, refresh_pos);

    $(window).
    reset_on('mouseenter' + id, function(){ g_loader.css('display', 'inline'); }).
    reset_on('mouseleave' + id, function(){ g_loader.css('display', 'none'); });
}

function remove_cursor_progress(evt)
{
    var id = ".addcursorprog";
    g_loader.css('display', 'none');

    $('html').off('mousemove' + id);
    $(window).off('mouseenter' + id).off('mouseleave' + id);
}

$('.action').click(add_cursor_progress);
$('.stop').click(remove_cursor_progress);

Sie müssen überprüfen, ob es sich ebenfalls um ein Touch-Gerät handelt var isTouchDevice = typeof window.ontouchstart !== 'undefined';

Abschließend sollten Sie versuchen, Ihrer Seite einen statischen Spinner oder etwas anderes hinzuzufügen, das den Ladevorgang anzeigt, anstatt zu versuchen, dies mit dem Cursor zu tun.

pmrotule
quelle
1

Korayems Lösung funktioniert für mich in 100% der Fälle in modernem Chrome, Safari, in 95% der Fälle in Firefox, aber nicht in Opera und IE.

Ich habe es ein bisschen verbessert:

$('html').bind('ajaxStart', function() {
    $(this).removeClass('notbusy').addClass('busy');
}).bind('ajaxStop', function() {
    $(this).removeClass('busy').addClass('notbusy');
});

CSS:

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

html.notbusy, html.notbusy * {
    cursor: default !important;
}

Jetzt funktioniert es in 100% Fällen in Chrome, Safari, Firefox und Opera. Ich weiß nicht, was ich mit IE machen soll :(

Felix
quelle
1

Arbeitslösung auf CodeSandbox

Einige der anderen Lösungen funktionieren nicht unter allen Umständen. Wir können das gewünschte Ergebnis mit zwei CSS-Regeln erzielen:

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

.not-busy {
  cursor: auto;
}

Ersteres zeigt an, dass wir beschäftigt sind und gilt für alle Elemente auf der Seite, wobei versucht wird, andere Cursorstile zu überschreiben. Letzteres gilt nur für den Seitenkörper und wird lediglich zum Erzwingen einer Aktualisierung der Benutzeroberfläche verwendet. Wir möchten, dass diese Regel so unspezifisch wie möglich ist und nicht auf andere Seitenelemente angewendet werden muss.

Wir können dann den Besetztzustand wie folgt auslösen und beenden:

function onBusyStart() {
    document.body.classList.add('busy');
    document.body.classList.remove('not-busy');
}

function onBusyEnd() {
    document.body.classList.remove('busy');
    document.body.classList.add('not-busy');
}

Obwohl wir den Cursorstil ändern müssen, um den Cursor zu aktualisieren, hat das direkte Ändern document.body.style.cursoroder Ähnliches bei einigen Engines wie Webkit nicht die beabsichtigte Wirkung, bis der Cursor bewegt wird. Die Verwendung von Klassen zur Beeinflussung der Änderung ist robuster. Um die Benutzeroberfläche jedoch zuverlässig zum Aktualisieren zu zwingen (erneut bei einigen Engines), müssen wir eine weitere Klasse hinzufügen. Es scheint, dass das Entfernen von Klassen anders behandelt wird als das Hinzufügen.

Ninjakannon
quelle
Die Lösung funktioniert bei Chrome 70 bei mir nicht. Der Cursor bleibt als Wartecursor, bis die Maus bewegt wird.
Phil B
1
@PhilB Seltsam. Es funktioniert für mich unter Chrome 70.0.3538.77 unter Windows 10. Ich habe diese Lösung auch erfolgreich in Dutzenden von Umgebungen bereitgestellt, einschließlich Windows und MacOS, ohne dass ein solcher Fehlerbericht vorliegt.
Ninjakannon
Ich bin unter Windows 7, ob das einen Unterschied machen könnte? : /
Phil B
@PhilB Es kann gut tun, vielleicht daher die Vielfalt der Lösungen. Ich werde ein Auge dafür offen halten
Ninjakannon
1
Ok, ich habe ein bisschen mehr getestet und es scheint (wie bereits erwähnt), dass ich das Problem nur mit geöffneten Entwicklertools reproduzieren kann. Gut für mich, denke ich. Lösung ok sowieso. :)
Phil B
0

Ich glaube nicht, dass du es schaffen wirst.

Versuchen Sie jedoch, die Bildlaufposition zu ändern. es könnte helfen.

SLaks
quelle
3
Versuchte das. Versuchte viele Änderungen. Keiner von ihnen war ausreichend für Chrome oder Safari. Scheint dumm. Warum sollte der Benutzer die Maus berühren wollen, wenn der Cursor Wartezeit anzeigt?
Nosredna
0

HIER ist meine Lösung:

function yourFunc(){

$('body').removeClass('wait'); // this is my wait class on body you can $('body').css('cursor','auto');
$('body').blur();
$('body').focus(function(e){
$('body')
 .mouseXPos(e.pageX + 1)
 .mouseYPos(e.pageX - 1);
});

}
Zestar
quelle
0

Ab jquery 1.9 sollten Sie ajaxStart und ajaxStop dokumentieren . Sie funktionieren gut für mich in Firefox. Habe nicht in anderen Browsern getestet.

In CSS:

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

In JavaScript:

// Makes the mousecursor show busy during ajax 
// 
$( document )

   .ajaxStart( function startBusy() { $( 'html' ).addClass   ( 'busy' ) } )     
   .ajaxStop ( function stopBusy () { $( 'html' ).removeClass( 'busy' ) } )

quelle
-1

Versuchen Sie, den richtigen CSS-Wert für die Cursoreigenschaft zu verwenden:

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

http://www.w3schools.com/CSS/pr_class_cursor.asp

PetersenDidIt
quelle
Ja entschuldigung. Das ist ein Tippfehler. Ich benutze (und habe Probleme damit) "warten", nicht "beschäftigt".
Nosredna
-1

Es ist wahrscheinlich ein Fehler in WebKit; du solltest es melden .

SLaks
quelle
-1

Ich habe dies nicht versucht, aber was ist, wenn Sie ein transparentes Div erstellen, das absolut positioniert ist und das Ansichtsfenster unmittelbar vor dem Ändern des CSS ausfüllt? Wenn dann das CSS am Körper geändert wird, entfernen Sie das Div. Dies kann ein Mouseover-Ereignis im Body auslösen, das dazu führen kann, dass der Cursor auf den neuesten CSS-Wert aktualisiert wird.

Auch hier habe ich das nicht getestet, aber es ist einen Versuch wert.

Adam Raney
quelle
Ich habe viele funky Dinge ausprobiert und die Browser scheinen sie alle zu ignorieren. Aber wenn ich Zeit habe, werde ich es mit deiner versuchen.
Nosredna
2
Ich habe das gleiche Problem auch mit einem Overlay in voller Größe, und der Cursor ändert sich nicht, wenn er nicht bewegt wird.
Omiod
-1

Hey Leute, ich habe eine ziemlich knifflige Lösung, die auf allen Browsern funktioniert. Annahme ist, dass eine Prototypbibliothek verwendet wird. Jemand kann dies auch als einfaches Javascript schreiben. Die Lösung besteht darin, unmittelbar nach dem Zurücksetzen des Cursors ein Div darüber zu haben und es ein wenig zu schütteln, damit sich der Cursor bewegt. Dies wird in meinem Blog http://arunmobc.blogspot.com/2011/02/cursor-not-changing-issue.html veröffentlicht .

Arun George
quelle
-3

$ ('*'). css ('cursor', 'wait'); funktioniert überall auf der Seite, einschließlich Links

Dan Hunex
quelle
1
Das auf ALLE Elemente anwenden? Wird nicht passieren. Und behebt den Fehler auch nicht.
Camilo Martin
Dies überwindet den Fehler nicht.
Adam Smith