Detect IF hovering over element with jQuery - javascript

I'm not looking for an action to call when hovering, but instead a way to tell if an element is being hovered over currently. For instance:
$('#elem').mouseIsOver(); // returns true or false
Is there a jQuery method that accomplishes this?

Original (And Correct) Answer:
You can use is() and check for the selector :hover.
var isHovered = $('#elem').is(":hover"); // returns true or false
Example: http://jsfiddle.net/Meligy/2kyaJ/3/
(This only works when the selector matches ONE element max. See Edit 3 for more)
.
Edit 1 (June 29, 2013): (Applicable to jQuery 1.9.x only, as it works with 1.10+, see next Edit 2)
This answer was the best solution at the time the question was answered. This ':hover' selector was removed with the .hover() method removal in jQuery 1.9.x.
Interestingly a recent answer by "allicarn" shows it's possible to use :hover as CSS selector (vs. Sizzle) when you prefix it with a selector $($(this).selector + ":hover").length > 0, and it seems to work!
Also, hoverIntent plugin mentioned in a another answer looks very nice as well.
Edit 2 (September 21, 2013): .is(":hover") works
Based on another comment I have noticed that the original way I posted, .is(":hover"), actually still works in jQuery, so.
It worked in jQuery 1.7.x.
It stopped working in 1.9.1, when someone reported it to me, and we all thought it was related to jQuery removing the hover alias for event handling in that version.
It worked again in jQuery 1.10.1 and 2.0.2 (maybe 2.0.x), which suggests that the failure in 1.9.x was a bug or so not an intentional behaviour as we thought in the previous point.
If you want to test this in a particular jQuery version, just open the JSFidlle example at the beginning of this answer, change to the desired jQuery version and click "Run". If the colour changes on hover, it works.
.
Edit 3 (March 9, 2014): It only works when the jQuery sequence contains a single element
As shown by #Wilmer in the comments, he has a fiddle which doesn't even work against jQuery versions I and others here tested it against. When I tried to find what's special about his case I noticed that he was trying to check multiple elements at a time. This was throwing Uncaught Error: Syntax error, unrecognized expression: unsupported pseudo: hover.
So, working with his fiddle, this does NOT work:
var isHovered = !!$('#up, #down').filter(":hover").length;
While this DOES work:
var isHovered = !!$('#up,#down').
filter(function() { return $(this).is(":hover"); }).length;
It also works with jQuery sequences that contain a single element, like if the original selector matched only one element, or if you called .first() on the results, etc.
This is also referenced at my JavaScript + Web Dev Tips & Resources Newsletter.

Use:
var hovered = $("#parent").find("#element:hover").length;
jQuery 1.9+

It does not work in jQuery 1.9. Made this plugin based on user2444818's answer.
jQuery.fn.mouseIsOver = function () {
return $(this).parent().find($(this).selector + ":hover").length > 0;
};
http://jsfiddle.net/Wp2v4/1/

The accepted answer didn't work for me on JQuery 2.x
.is(":hover") returns false on every call.
I ended up with a pretty simple solution that works:
function isHovered(selector) {
return $(selector+":hover").length > 0
}

Set a flag on hover:
var over = false;
$('#elem').hover(function() {
over = true;
},
function () {
over = false;
});
Then just check your flag.

Couple updates to add after working on this subject for a while:
all solutions with .is(":hover") break on jQuery 1.9.1
The most likely reason to check if the mouse is still over an element is to attempt to prevent events firing over each other. For example, we were having issues with our mouseleave being triggered and completed before our mouseenter event even completed. Of course this was because of a quick mouse movement.
We used hoverIntent https://github.com/briancherne/jquery-hoverIntent to solve the issue for us. Essentially it triggers if the mouse movement is more deliberate. (one thing to note is that it will trigger on both mouse entering an element and leaving - if you only want to use one pass the constructor an empty function )

You can filter your elment from all hovered elements.
Problematic code:
element.filter(':hover')
Save code:
jQuery(':hover').filter(element)
To return boolean:
jQuery(':hover').filter(element).length===0

Expanding on #Mohamed's answer. You could use a little encapsulation
Like this:
jQuery.fn.mouseIsOver = function () {
if($(this[0]).is(":hover"))
{
return true;
}
return false;
};
Use it like:
$("#elem").mouseIsOver();//returns true or false
Forked the fiddle:
http://jsfiddle.net/cgWdF/1/

I like the first response, but for me it's weird. When attempting to check just after page load for the mouse, I have to put in at least a 500 millisecond delay for it to work:
$(window).on('load', function() {
setTimeout(function() {
$('img:hover').fadeOut().fadeIn();
}, 500);
});
http://codepen.io/molokoloco/pen/Grvkx/

https://api.jquery.com/hover/
Asynchronous function in line 38:
$( ".class#id" ).hover(function() {
Your javascript
});

Setting a flag per kinakuta's answer seems reasonable, you can put a listener on the body so you can check if any element is being hovered over at a particular instant.
However, how do you want to deal with child nodes? You should perhaps check if the element is an ancestor of the currently hovered element.
<script>
var isOver = (function() {
var overElement;
return {
// Set the "over" element
set: function(e) {
overElement = e.target || e.srcElement;
},
// Return the current "over" element
get: function() {
return overElement;
},
// Check if element is the current "over" element
check: function(element) {
return element == overElement;
},
// Check if element is, or an ancestor of, the
// current "over" element
checkAll: function(element) {
while (overElement.parentNode) {
if (element == overElement) return true;
overElement = overElement.parentNode;
}
return false;
}
};
}());
// Check every second if p0 is being hovered over
window.setInterval( function() {
var el = document.getElementById('p0');
document.getElementById('msg').innerHTML = isOver.checkAll(el);
}, 1000);
</script>
<body onmouseover="isOver.set(event);">
<div>Here is a div
<p id="p0">Here is a p in the div<span> here is a span in the p</span> foo bar </p>
</div>
<div id="msg"></div>
</body>

Related

why does my button disappear when I add the toggle event in jquery?

I want to toggle text between bold and normal I made this code for it, but when I open my page the bold button disappears?
$("#bold").toggle(function() {
$('.focus').css("font-weight", $(this).val());
}, function() {
$('.focus').css("font-weight", "normal");
});
Is there something wrong with my code?
Please help, thanks in advance.
Assuming you're using jQuery 1.9 or later the problem is that the .toggle() event handling method was removed from the library. So what you're actually calling is the .toggle() function that hides/shows elements. (In earlier versions of jQuery both functions existed and jQuery figured out which one you meant based on the arguments passed in.)
You can implement your own toggle easily enough with a standard .click() handler:
$("#bold").click(function() {
var f = !$(this).data("toggleFlag");
if (f) {
$('.focus').css("font-weight", $(this).val());
} else {
$('.focus').css("font-weight", "normal");
}
$(this).data("toggleFlag", f);
});
This uses the .data() method to keep track of a boolean flag to indicate which code to execute. The very first time the click handler is called the flag will be returned as undefined because it hasn't previously been set, but we just convert that to a boolean with ! (assuming you want to execute the if and not the else case on the first click).
It disappears because that version of toggle is deprecated and removed, and in newer versions of jQuery all it does is toggle visibility.
You could do something like this instead :
var state = true;
$("#bold").on('click', function() {
$('.focus').css("font-weight", state ? this.value : 'normal');
state = !state;
});
FIDDLE
The only solution I fount to the disappearing element after click... is Callback function after the toggle effect finished.
here a link that explain the Callback function.
and here is my code:
jQuery('.menu li.item-487').click(function(){
jQuery('#main-menu .moduletable .menu li').toggle("slow",function(){jQuery('.menu li.item-487').css('display' , 'block');});
});

Issue regarding javascript function not firing on hover of div

I have a use case whereby i know that all the divs i am interested in will have the word 'tabz' in them but have yet to find a way to fire my jquery when a user clicks on a div with such an id.
$('div[id=*"tabz"]').on("click", function()
{
alert(event.target.id);
});
This is what i have however the alert never fires.
When I replace the method with :
$('div').on("click", function()
{
alert(event.target.id);
});
it will give me the following:
tabz91
So i know there are divs that meet my selector but it I am unsure as to why the alert is not firing.
Any help greatly appreciated
The correct syntax is simply
$('div[id*="tabz"]')
(the = and the * are inverted in your example).
You may use
$('div[id$="tabz"]')
if the id attribute ends with your pattern.
$('div[id*="tabz"]').on("click", function()
{
alert(event.target.id);
});
It's a typo, * and = inverted. See this example : http://jsfiddle.net/Xcn6N/
try instead of =* it is *=
$('div[id*="tabz"]').on("click", function() {
alert(event.target.id);
});
For Further Assistance on Selectors in jQuery see this page
jQuery Selectors

Trigger event on specific condition

I have a div that will serve as container to other element, I have buttons that add element to that div.
Please see the demo for a get an idea about it.
So, what I want to do is to check before adding a new element is the div reached a maximum number of elements that I define, let's say 4.
I can check this condition before every add, but I am sure this is not the best way (we learned that if the code contains copy/paste then is not the best solution) Also, this is just a sample, in my case, I have many buttons..
Is there a way to have a listener like this?
$('#container').bind('divFull', function(){
//My code
});
So that I can disable buttons..
First, you have to listen to DOM change event, then you can trigger a custom event based on the number of children
$('#container').bind('DOMSubtreeModified', function(){
if($(this).children().length>=4){
$(this).trigger('divFull');
}
});
then you can bind to your custom divFull event
$('#container').bind('divFull', function(){
alert('container is full');
$('button').prop('disabled',true);
});
a working demo based on your example
I change a bit the #skafandri method because the event DOMSubtreeModified doesn't work on IE < 9 and it's depreciated.
The main change is to create a function which will call the divFull event if their is 4 children in the container.
var checkFull = function() {
if ($container.children().length === 4) {
$container.trigger('divFull');
}
}
$('#button1').click(function(){
$container.append('<div class="element">some text</div>');
checkFull();
});
Here is the demo.

Javascript Sticky Notes

I made some sticky notes in javascript for fun.
When there are multiple sticky notes on the screen, I want the one that is selected to be brought forward. IE. raise the z-index to be higher then the other sticky notes.
Currently I am doing this with CSS using :hover, which is kind of annoying. I want to do it in javascript/jquery. I tried to do addClass/removeClass with focus() and blur()
This is what I have so far
$('.darkYellow').click(function() {
$(this).focus(function() {
$(this).addClass("index");
});
});
$('.darkYellow').blur(function() {
$(this).removeClass("index");
});
Updated and Working thanks to Christoph
http://jsfiddle.net/EnigmaMaster/aQMhk/6/
Class selectors start with a . character, class names do not (well, they can, but that way lies madness).
$(this).addClass("index")
for addClass there is no need to include '.'
Simply
$(this).addClass("index");
http://api.jquery.com/addClass/
Though at the moment I don't know, why .on() does not work (this shoud be the preferred method!), the following code should work:
$('.darkYellow').live("click", function() {
$(".index").removeClass("index");
$(this).addClass("index");
});
This is all you need.
live event handler on click ( use of on() should be preferred )
look for index note and remove class
add Class to current "clicked" element
DEMO
You're calling $('.darkYellow').click() before the sticky notes actually exist. .click() will add an event to each element that matches the selector at the time of calling. What you want is something like .live() which will handle all elements, present and future E.g.
$('.darkYellow').live('click', function() {
$(this).focus(function() {
$(this).addClass("index");
});
});
UPDATE
Try:
$('.darkYellow').live('click', function() {
$(this).addClass("index");
});
$('.darkYellow').live('blur', function() {
$(this).removeClass("index");
});
As someone else pointed out, the call to .focus() should be unnecessary.
Here's a toggleFocus() function I recently wrote, it's designed to add a .is-focused class the parentNode on focus/blur events.
CodePen Demo
function toggleFocus(e) {
setTimeout(() => {
e.addEventListener('focus', ({path}) => {
path[2].classList.add("is-focused");
}, true);
e.addEventListener('blur', ({path}) => {
path[2].classList.remove("is-focused");
}, true);
}, 0);
}
const items = document.getElementById('items');
const itemsArray = items.querySelectorAll(".item");
[].forEach.call(itemsArray, (item) => {
toggleFocus(item)
});

Using jQuery to test if an input has focus

On the front page of a site I am building, several <div>s use the CSS :hover pseudo-class to add a border when the mouse is over them. One of the <div>s contains a <form> which, using jQuery, will keep the border if an input within it has focus. This works perfectly except that IE6 does not support :hover on any elements other than <a>s. So, for this browser only we are using jQuery to mimic CSS :hover using the $(#element).hover() method. The only problem is, now that jQuery handles both the form focus() and hover(), when an input has focus then the user moves the mouse in and out, the border goes away.
I was thinking we could use some kind of conditional to stop this behavior. For instance, if we tested on mouse out if any of the inputs had focus, we could stop the border from going away. AFAIK, there is no :focus selector in jQuery, so I'm not sure how to make this happen. Any ideas?
jQuery 1.6+
jQuery added a :focus selector so we no longer need to add it ourselves. Just use $("..").is(":focus")
jQuery 1.5 and below
Edit: As times change, we find better methods for testing focus, the new favorite is this gist from Ben Alman:
jQuery.expr[':'].focus = function( elem ) {
return elem === document.activeElement && ( elem.type || elem.href );
};
Quoted from Mathias Bynens here:
Note that the (elem.type || elem.href) test was added to filter out false positives like body. This way, we make sure to filter out all elements except form controls and hyperlinks.
You're defining a new selector. See Plugins/Authoring. Then you can do:
if ($("...").is(":focus")) {
...
}
or:
$("input:focus").doStuff();
Any jQuery
If you just want to figure out which element has focus, you can use
$(document.activeElement)
If you aren't sure if the version will be 1.6 or lower, you can add the :focus selector if it is missing:
(function ( $ ) {
var filters = $.expr[":"];
if ( !filters.focus ) {
filters.focus = function( elem ) {
return elem === document.activeElement && ( elem.type || elem.href );
};
}
})( jQuery );
CSS:
.focus {
border-color:red;
}
JQuery:
$(document).ready(function() {
$('input').blur(function() {
$('input').removeClass("focus");
})
.focus(function() {
$(this).addClass("focus")
});
});
Here’s a more robust answer than the currently accepted one:
jQuery.expr[':'].focus = function(elem) {
return elem === document.activeElement && (elem.type || elem.href);
};
Note that the (elem.type || elem.href) test was added to filter out false positives like body. This way, we make sure to filter out all elements except form controls and hyperlinks.
(Taken from this gist by Ben Alman.)
April 2015 Update
Since this question has been around a while, and some new conventions have come into play, I feel that I should mention the .live method has been depreciated.
In its place, the .on method has now been introduced.
Their documentation is quite useful in explaining how it works;
The .on() method attaches event handlers to the currently selected set
of elements in the jQuery object. As of jQuery 1.7, the .on() method
provides all functionality required for attaching event handlers. For
help in converting from older jQuery event methods, see .bind(),
.delegate(), and .live().
So, in order for you to target the 'input focused' event, you can use this in a script. Something like:
$('input').on("focus", function(){
//do some stuff
});
This is quite robust and even allows you to use the TAB key as well.
I'm not entirely sure what you're after but this sounds like it can be achieved by storing the state of the input elements (or the div?) as a variable:
$('div').each(function(){
var childInputHasFocus = false;
$(this).hover(function(){
if (childInputHasFocus) {
// do something
} else { }
}, function() {
if (childInputHasFocus) {
// do something
} else { }
});
$('input', this)
.focus(function(){
childInputHasFocus = true;
})
.blur(function(){
childInputHasFocus = false;
});
});
An alternative to using classes to mark the state of an element is the internal data store functionality.
P.S.: You are able to store booleans and whatever you desire using the data() function. It's not just about strings :)
$("...").mouseover(function ()
{
// store state on element
}).mouseout(function ()
{
// remove stored state on element
});
And then it's just a matter of accessing the state of elements.
if anyone cares there is a much better way to capture focus now, $(foo).focus(...)
http://api.jquery.com/focus/
Have you thought about using mouseOver and mouseOut to simulate this. Also look into mouseEnter and mouseLeave
Keep track of both states (hovered, focused) as true/false flags, and whenever one changes, run a function that removes border if both are false, otherwise shows border.
So: onfocus sets focused = true, onblur sets focused = false. onmouseover sets hovered = true, onmouseout sets hovered = false. After each of these events run a function that adds/removes border.
As far as I know, you can't ask the browser if any input on the screen has focus, you have to set up some sort of focus tracking.
I usually have a variable called "noFocus" and set it to true. Then I add a focus event to all inputs that makes noFocus false. Then I add a blur event to all inputs that set noFocus back to true.
I have a MooTools class that handles this quite easily, I'm sure you could create a jquery plugin to do the same.
Once that's created, you could do check noFocus before doing any border swapping.
There is no :focus, but there is :selected
http://docs.jquery.com/Selectors/selected
but if you want to change how things look based on what is selected you should probably be working with the blur events.
http://docs.jquery.com/Events/blur
There is a plugin to check if an element is focused: http://plugins.jquery.com/project/focused
$('input').each(function(){
if ($(this) == $.focused()) {
$(this).addClass('focused');
}
})
I had a .live("focus") event set to select() (highlight) the contents of a text input so that the user wouldn't have to select it before typing a new value.
$(formObj).select();
Because of quirks between different browsers, the select would sometimes be superseded by the click that caused it, and it would deselect the contents right after in favor of placing the cursor within the text field (worked mostly ok in FF but failed in IE)
I thought I could solve this by putting a slight delay on the select...
setTimeout(function(){$(formObj).select();},200);
This worked fine and the select would persist, but a funny problem arose.. If you tabbed from one field to the next, the focus would switch to the next field before the select took place. Since select steals focus, the focus would then go back and trigger a new "focus" event. This ended up in a cascade of input selects dancing all over the screen.
A workable solution would be to check that the field still has focus before executing the select(), but as mentioned, there's no simple way to check... I ended up just dispensing with the whole auto highlight, rather than turning what should be a single jQuery select() call into a huge function laden with subroutines...
What I wound up doing is creating an arbitrary class called .elementhasfocus which is added and removed within the jQuery focus() function. When the hover() function runs on mouse out, it checks for .elementhasfocus:
if(!$("#quotebox").is(".boxhasfocus")) $(this).removeClass("box_border");
So if it doesn't have that class (read: no elements within the div have focus) the border is removed. Otherwise, nothing happens.
Simple
<input type="text" />
<script>
$("input").focusin(function() {
alert("I am in Focus");
});
</script>

Categories