Mouse cursor set using jQuery/CSS not changing until mouse moved - javascript

In my code I use the jQuery/CSS to set and unset the 'wait' mouse cursor with the following code:
function setWaitCursor() {
$('body').css('cursor', 'wait');
}
function setDefaultCursor() {
$('body').css('cursor', '');
}
I use this code to change the mouse cursor for a long operation:
setWaitCursor();
... do stuff that takes a few seconds ...
setDefaultCursor();
This code doesn't seem to work unless you move the mouse, however (at least for Chrome on Win 10). If the mouse is not moved after setDefaultCursor is called, the cursor displays the 'wait' cursor until the mouse is moved (or vice versa).
Example: https://jsfiddle.net/antonyakushin/0jv6rqkf/
In this fiddle, the cursor changes for 2 seconds after the link is
clicked. If you don't move the mouse when you click the link, the
cursor does not change.
What is the best way to resolve this issue, so that even if the mouse is not moved the cursor is changed?

Although this is not the answer to this specific problem, this behavior can happen:
On Chrome
With DevTools open (which is very likely, in order to debug this issue)
The solution is simply to close the Chrome DevTools.

Some elements have default cursor styles. So wile changing the cursor style we need to change that too.
$(document).ready(function() {
function setWaitCursor(elem) {
elem.css('cursor', 'wait');
$('body').css('cursor', 'wait');
}
function setDefaultCursor(elem) {
elem.css('cursor', '');
$('body').css('cursor', '');
}
$('#testLink').on('click', function() {
var x = $(this)
setWaitCursor(x);
setTimeout(function() {
setDefaultCursor(x);
}, 5000);
return false;
});
});
Demo fiddle

Just change the body to *. It will be applicable to all the elements.
Fiidle Demo
Code snippets:
$(document).ready(function() {
function setWaitCursor() {
$('*').css('cursor', 'wait');
}
function setDefaultCursor() {
$('*').css('cursor', '');
}
$('#testLink').on('click', function() {
setWaitCursor();
setTimeout(function() {
setDefaultCursor();
}, 2000);
return false;
});
});
body {
min-width: 500px;
min-height: 500px;
background-color: gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div id="mouseContainer">
Test Link
</div>

I think I solved it! Just call setTimeout() after you change the cursor. For example
$('body').addClass('in-progress-cursor');
setTimeout(null, 0); //in typescript we need to provide arguments
This is well-known trick (Why is setTimeout(fn, 0) sometimes useful?) but I didn't expect this would work in this case.
This is my favorite method of telling user unobtrusively that there is something going on. For example I use it to indicate that http requests are in progress. It is such a relief that the solution is found. Why I feel stupid again...
Actually I see the timeout in John R's answer now. But it is not evident enough.

I had the same problem and I noticed on another post cursor won't change until mouse moves that they had suggested doing a blur and focus to fix this. It worked for me. So, your setWaitCursor() should look something like this. That should force it to change without the mouse move. It worked for me in Chrome, but haven't tried other browsers.
function setWaitCursor(elem) {
elem.css('cursor', 'wait');
$('body').css('cursor', 'wait');
window.blur();
window.focus();
}

Related

JavaScript Function, Click Button and Resizing (Reverses Button Function)

My code has a button that changes some CSS via adding and removing classes. I have the JS working fine to do this. The first click adds the class, clicking again removes it and so on around it goes, nothing unusual there.
However, I've also incorporated a function that removes the classes if the browser window is resized at all. My issue is, if I then go back to press the button again after resizing the window, it thinks it should be doing the second click (almost reversing the function) and removes the classes (even though they've already been removed by the resizing), whereas I need the button function to almost reset and have it think the button hasn't been clicked yet after the resizing, so the process can be started from the beginning.
I really hope this makes sense, because its been driving me around the bend, and nothing I've tried will make it work how I would like it to.
Thank you for any help!
Heres the code:
JS/jQuery
{
/* Button Function to add and remove classes. */
$("#nav-icon").click(function () {
var clicks = $(this).data("clicks");
if (!clicks) {
$(".logo-container").addClass("border-change-image");
$(".container-fluid").addClass("border-change-header");
} else {
$(".logo-container").removeClass("border-change-image");
$(".container-fluid").removeClass("border-change-header");
}
$(this).data("clicks", !clicks);
});
/* Window Resizing Function */
$(window).on("resize", function () {
var size = $(this).on("resize");
if (size) {
$(".logo-container").removeClass("border-change-image");
$(".container-fluid").removeClass("border-change-header");
} else {
}
});
}
Removed the variable storing the data and just "asked" if one of the div's had one of the classes then add or remove, based on that. Works like a charm.
JS
$("#nav-icon").click(function () {
if ($(".logo-container").hasClass("border-change-image")) {
$(".logo-container").removeClass("border-change-image");
$(".container-fluid").removeClass("border-change-header");
} else {
$(".logo-container").addClass("border-change-image");
$(".container-fluid").addClass("border-change-header");
}
});

jQuery + CSS cursor mousedown + Chrome = not working

I decided to make/test Cursors cross-browser, so far on Firefox its working perfect, but on Chrome - somewhat..
Now, the custom cursor shows, but when you click somewhere, it doesn't change, it does trigger mousedown event, but it doesn't change the cursor. I tried just mousedown(); and it changed the cursor. I guess the the mouseup event is causing this trouble.
$("body").mousedown(function() {
$("body").addClass("clicked");
console.log("down");
});
$("body").mouseup(function() {
$("body").removeClass("clicked");
console.log("up");
});
CSS
body {
cursor: url("../img/cursor1.cur"), default;
}
.clicked {
cursor: url("../img/cursor2.cur"), default;
}
Try clicking and moving the mouse.
I think chrome only changes cursor on mousemove.
EDIT: This is a known bug, see Getting the browser cursor from "wait" to "auto" without the user moving the mouse
I just tried out the following:
$('body').mousedown(function(){
$(this).css('background-color', 'red');
});
$('body').mouseup(function(){
$(this).css('background-color', 'green');
});
The result was as expected, click down -> red BG, click up -> green BG
BUT: this only happened, when i assigned css: html, body { height:100%; min-height:100%; }
Without the CSS the events were not really working as "fluent" as they should be.
Little tip: with firebug (at least chrome dev tools) you can monitor events using the following snipped:
monitorEvents( $$('body')[0] )
Hope this helped
The problem is that you are using the global window.event object, and not jQuery's event object. window.event only works in some browsers, and it is not a W3C standard.
jQuery normalizes the event object so it's the same in all browsers. The event handler is passed that jQuery event object as a parameter. You should be using that.
$(".class_name").mousedown(function (e) {
switch (e.which) {
case 1: //leftclick
//...
break;
case 3: //rightclick
//...
break;
}
});

If Mouseover Div Equals False - JQuery / Javascript

I'm trying to get this to work:
if($('#myDiv').hover() == false) {
myFunction();
}
Not getting much in the way of errors in Chrome or Firebug consoles. I've had a look at some other posts, and there was an answer that used something like:
if($('#myDiv').is(':hover') == false) {
myFunction();
}
However this also doesn't work.
Here's a jsfiddle if that helps: http://jsfiddle.net/yuwPR/2/
Any ideas greatly appreciated.
Thanks
EDIT:
Thanks for the answers, I wasn't able to get anything working. I'm thinking it might not be possible. Oh well, I'll try something else!
Thanks again
p.s. Most inventive answer marked as right and upvotes all round.
Without knowing your ultimate intent, you could wire up a hover on the document and check the current target.id
$(document).mouseover(function(event) {
if (event.target.id == "myDiv") {
$("body").css("background-color", "red"); //over the div so change the color
return;
}
$("body").css("background-color", "green"); //no on the div
});
code example on jsfiddle.
This code sample sets up a global js variable to store the hover state of the div. Then I use jquery hover to toggle that between true / false. Then, we just fire off a function every 10ms that checks the hover state. Currently I am just setting the window status telling you if you're hovered or not.
var _MOUSEOVER_IN_PROGRESS = false; //stores the hover state
function isover(){
if(_MOUSEOVER_IN_PROGRESS){
window.status = 'Still over!';
} else {
window.status = 'You are not hovering on me!';
}
setTimeout("isover()",10); //checking every 10ms!
}
$(document).ready(function(){
isover();
$('#mydiv').hover(
function(){ _MOUSEOVER_IN_PROGRESS = true; },
function(){ _MOUSEOVER_IN_PROGRESS = false; }
);
});
Edited my code! My mydiv hover catch was not wrapped in a document ready
The hover function takes 2 callback functions:
('#myDiv').hover(function () {
// function to call when hovering
},
function () {
myFunction();
}
);
So, when hovering is "false", ie, on mouse out, the second function will be called.
If you're only interested in doing something when the hover stops, you can use the mouseout() function:
$('#myDiv').mouseout(function() {
myFunction();
}
);
Your first call could never work:
$('#myDiv').hover()
This actually says "trigger the hover event on the element". It does not check to see if your user is currently hovering over the element.
Your second formulation should work:
$('#myDiv').is(':hover')
This checks to see if the element currently has the mouse hovering over it. However, it doesn't seem to work on document load. An example that works can be seen here. If you can clarify what you're trying to do, it might be possible to find some working code in this style.

$.slideToggle() & $.hover() animation queue issue

I'm trying to set up a pretty basic hover animation in jQuery. Mouse over a div and the major content is slid down, mouse up and it slides up.
<script type="text/javascript">
$(function () {
$('.listItem').hover(function () {
$(this).find('.errorData').slideToggle('slow');
});
});</script>
This piece of code works fine, but the obvious problem is the animation queuing if you mouse in and out really quickly.
To alleviate this I have read that the .stop(true) function placed before the .slideToggle() stops the previous animation and clears the animation queue. So I tried this code:
<script type="text/javascript">
$(function () {
$('.listItem').hover(function () {
$(this).find('.errorData').stop(true).slideToggle('slow');
});
});</script>
My problem now is that this only seems to work on the first mousein and mouseout. After that the animations no longer trigger and nothing happens. This is Google Chrome DEV channel.
This seems to be exacerbated by how fast you move the mouse in and out.
I can't seem to work out what the issue is, this JSFiddle has a working (and breaking on my computer) example.
EDIT: I suspect this is a bug in jQuery 1.4.2 and have lodged a bug ticket: http://dev.jquery.com/ticket/6772
try
.stop(true,true)
or you can use this hoverIntent plugin
.stop(true, true)
works like a champ:
$('.subpage-block').hover(function(){
$('.subpage-block-heading span', this).stop(true,true).fadeToggle('fast');
$('.subpage-block-content', this).stop(true,true).slideToggle();
});
MayBe better?
$('.listitem').hover(function(){
if (!$(this).find('.errorData').hasClass('down') &&
!$(this).find('.errorData').hasClass('up')) {
$(this).find('.errorData').addClass('down').slideDown('fast', function() {
$(this).removeClass('down');
});
}
}, function() {
if (!$(this).find('.errorData').hasClass('up')) {
$(this).find('.errorData').addClass('up').slideUp('fast', function() {
$(this).removeClass('up');
});
}
});
This way the queue is at most 2, one when is up and other when is down.
With the first condition we prevents to stay down.

jQuery delay doesn't work as expected

I have the following jQuery code
$("#dropdown").hover(function() {
$(this).stop(true,true).fadeTo('fast',1);
$("#options").stop(true,true).slideDown();
}, function() {
$(this).delay(1000).stop(true,true).fadeTo('fast',0.1);
$("#options").delay(1000).stop(true,true).slideUp();
}
);
What I expect to happen is when the mouse leaves #dropdown it will wait 1 second before continuing. This is not happening.
What I am trying to achieve, in case there is a better way, is to leave the drop down menu visible for a second or two after moving your mouse and I would also like to prevent the events from happening again to prevent artifacts and "funnies" if you were to move the mouse over and out from the div very quickly
The problem is .stop(). If you take that out it works:
http://jsfiddle.net/LZ8yt/
Your calls to stop aren't placed on the animation queue - they run immediately. I'm not sure whether you really need them in the "hover out" routine.
edit removed dumbness
You can always go lo-tech with setTimeout.
var dropDownElement = $(this);
setTimeout(function()
{
dropDownElement.fadeTo('fast', 0.1);
// Other Code
}, 1000);

Categories

Resources