Is it possible to do something like this:
if ($(this).mousedown() == true) {
I thought that would work but it doesn't.
Additional details: I'm trying to check if the mouse button is down when the mouse leaves a specific DIV, so if the person is holding the mouse button down while their mouse leaves the div, do this, otherwise do that.
The easiest way I can think of is to bind mousedown and mouseup event listeners to the document and update a global variable accordingly. In the mouseout event of your element you can check the state of that variable and act as appropriate. (Note: this assumes that you don't care whether or not the mouse was pressed down while over the div or not... you'll have to clarify your question around that).
var down = false;
$(document).mousedown(function() {
down = true;
}).mouseup(function() {
down = false;
});
$("#example").mouseout(function() {
if(down) {
console.log("down");
}
else {
console.log("up");
}
});
Here's a working example of the above.
Answering your original question, yes this is possible. When the mousedown event fires over an element the element becomes active and is selectable by the pseudo selector :active. In jQuery if nothing is selected an empty array is returned, we can use this to our advantage in combination with the .length array property and turn the active pseudo selector into a check to see if the mouse is down over a particular element or not like so:
if ( $('#id:active').length ) {
//do something
}
Checking if the mouse was down over a particular element at a given point in time is a different event and does not go with the title of this question and should be changed might I add. Google brought me here and this answer is for those that will inevitably follow.
http://jsfiddle.net/5HrWF/
something like this?
Code:
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<p>Press mouse and release here.</p>
<script>
$("p").mouseup(function(){
$(this).append('<span style="color:#F00;">Mouse up.</span>');
}).mousedown(function(){
$(this).append('<span style="color:#00F;">Mouse down.</span>');
});
</script>
</body>
</html>
Alright, well the best option I can give you is this:
http://jsfiddle.net/qK8rr/2/
Check out this one.
http://jsfiddle.net/b1Lzo60n/
Mousedown starts a timer that checks if mouse is still down after 1 second.
<button id="button">Press me</button>
<div id="log"></div>
Code:
var mousedown = false;
var mousedown_timer = '';
$('#button').mousedown(function(e) {
mousedown = true;
$('#log').text('mousedown...');
mousedown_timer = setTimeout(function () {
if(mousedown) {
$('#log').text('1 second');
}
}, 1000);
}).mouseup(function(e) {
mousedown = false;
clearTimeout(mousedown_timer);
$('#log').text('aborted');
});
Related
<body>
<div id="aaa">
<div id="bbb">
</div>
</div>
</body>
$(#?????).click(function(){
$('#bbb').hide();
})
http://jsfiddle.net/GkRY2/
What i must use if i want hide #bbb if user click outside box #bbb? But if i click on div #bbb then box is still visible - only outside.
$('body').click(function(e){
if( e.target.id == 'bbb' )
{ return true; }
else
{ $('#bbb').hide(); }
});
A note of explanation: There are a few ways to do this, either way we need to listen for a click on a parent element, weather it be a direct parent like #aaa or a distant parent like the body or the document. This way we can capture clicks that occur outside of #bbb.
Now that we have that we need the .hide to NOT occur if the user did click inside of #bbb. We can do this two ways
Stop propagation if the user clicks on #bbb. This will make the click event not 'bubble' up to the parent. That way the click event never reaches the parent and so #bbb will not hide. I personally don't like this method because stop propagation will so ALL click events from bubbling, and you may have click events that you would like to bubble to a local parent and not a distant parent. Or you may have listeners delegated from a distant parent, which will stop working if click propagation is stopped.
Check for the #bbb element in the parent listener. This is the method shown above. Basically this listens on a distant parent, and when a click occurs it checks to see if that click is on #bbb specifically. If it IS NOT on #bbb .hide is fired, otherwise it returns true, so other things that may be tied into the click event will continue working. I prefer this method for that reason alone, but secondarily its a-little bit more readable and understandable.
Finally the manner in which you check to see if the click originated at #bbb you have many options. Any will work, the pattern is the real meat of this thing.
http://jsfiddle.net/tpBq4/ //Modded from #Raminson who's answer is very similar.
New suggestion, leverage event bubbling without jQuery.
var isOutSide = true
bbb = documment.getElementById('bbb');
document.body.addEventListener('click', function(){
if(!isOutSide){
bbb.style.display = 'none';
}
isOutSide = true;
});
bbb.addEventListener('click', function(){
isOutSide = false;
});
Catch the click event as it bubbles-up to the document element. When it hits the document element, hide the element. Then in a click event handler for the element, stop the propagation of the event so it doesn't reach the document element:
$(function () {
$(document).on('click', function () {
$('#bbb').hide();
});
$('#bbb').on('click', function (event) {
event.stopPropagation();
});
});
Here is a demo: http://jsfiddle.net/KVXNL/
Docs for event.stopPropagation(): http://api.jquery.com/event.stopPropagation/
I made a plugin that does this. It preserves the value for this where as these other solutions' this value will refer to document.
https://github.com/tylercrompton/clickOut
Use:
$('#bbb').clickOut(function () {
$(this).hide();
});
You can use target property of the event object, try the following:
$(document).click(function(e) {
if (e.target.id != 'bbb') {
$('#bbb').hide();
}
})
DEMO
This will work
$("#aaa").click(function(){
$('#bbb').hide();
});
$("#bbb").click(function(event){
event.stopPropagation();
})
Becouse bbb is inside the aaa the event will "bubbel up to aaa". So you have to stop the bubbling by using the event.stopPropagation when bbb is clicked
http://jsfiddle.net/GkRY2/5/
OK
* this is none jquery. you can easly modify it to work with IE
first create helper method to facilitate codding don't get confused with JQuery $()
function $g(element) {
return document.getElementById(element);
}
create our listener class
function globalClickEventListener(obj){
this.fire = function(event){
obj.onOutSideClick(event);
}
}
let's say we need to capture every click on document body
so we need to create listeners array and initialize our work. This method will be called on load
function initialize(){
// $g('body') will return reference to our document body. parameter 'body' is the id of our document body
$g('body').globalClickEventListeners = new Array();
$g('body').addGlobalClickEventListener = function (listener)
{
$g('body').globalClickEventListeners.push(listener);
}
// capture onclick event on document body and inform all listeners
$g('body').onclick = function(event) {
for(var i =0;i < $g('body').globalClickEventListeners.length; i++){
$g('body').globalClickEventListeners[i].fire(event);
}
}
}
after initialization we create event listener and pass reference of the object that needs to know every clcik on our document
function goListening(){
var icanSeeEveryClick = $g('myid');
var lsnr = new globalClickEventListener(icanSeeEveryClick);
// add our listener to listeners array
$g('body').addGlobalClickEventListener(lsnr);
// add event handling method to div
icanSeeEveryClick.onOutSideClick = function (event){
alert('Element with id : ' + event.target.id + ' has been clicked');
}
}
* Take into account the document body height and width
* Remove event listeners when you don't need them
$(document).click(function(event) {
if(!$(event.target).closest('#elementId').length) {
if($('#elementId').is(":visible")) {
$('#elementId').hide('fast');
}
}
})
Change the "#elementId" with your div.
Using jQuery/Javascript, how can I check which was the first element that the mouse hovered after a MouseLeave event?
Basically, I want to check from an array of elements if the mouse is rolling over those elements or not.
I'm trying to use the event.relatedTarget.
Any help?
There exists a relatedTarget property on the mouse events
The MouseEvent.relatedTarget read-only property is the secondary target for the mouse event, if there is one
and for the mouseleave it points to the element that was entered.
So you could just do
$('element').mouseleave(function(event){
// assuming that allowedList holds the array of allowed elements
if ( allowedList.indexOf( event.relatedTarget ) > -1 ){
// found
} else {
// not found
}
});
demo at http://jsfiddle.net/gaby/V4pJb/
Using jQuery, you can do this:
$("#foo").mouseleave(function(e) {
var element = $(e.target);
});
Here's a working example. You can mouse over the text "Hello" and on mouseout, it will tell you which element it is leaving.
http://jsfiddle.net/k7Gfv/
If the mouseenter (or hover) is different from the mouseleave, then you'll need to track this using a variable. On mouseenter (or hover), set a variable that will store that element. On mouseleave, you can then reference that variable (just remember to clear or reset the value for the next time the mouseenter even is fired).
Not sure what you're looking for, but maybe it's somehing like this:
var elements = $("#a1, #a2");
$("#a3").on('mouseleave', nextElm);
function nextElm() {
$('div').on('mouseenter', thisIsIt);
$("#r").html('Now hover another element ?');
}
function thisIsIt(e) {
if ($.inArray(e.target, elements)!=-1){
$("#r").html('yes');
}else{
$("#r").html('no');
}
$("#a3").off('mouseleave', nextElm);
$('div').off('mouseenter', thisIsIt);
}
FIDDLE
You can do something like this. Here's a fiddle
var hovered = false;;
$('div').mouseleave(function(e) {
hovered = true;
});
$('div').hover(function(ev) {
if (hovered) {
alert(ev.target);
hovered = false;
}
});
This has been asked here before, but several years ago, and there was no cross-platform solution at the time (other than the setTimeout solution, which is really not very handy).
I'd like to do onblur="foo(parm);" and have foo be able to determine which element now has focus.
I'm using regular javascript; no jQuery for this one, please.
Is that possible these days?
You can try something like this:
function whereDidYouGo() {
var all = document.getElementsByTagName('*');
for (var i = 0; i < all.length; i++)
if (all[i] === all[i].ownerDocument.activeElement)
return all[i];
}
EDIT:
function whereDidYouGo() { return document.activeElement; }
In jQuery, at the OP's request:
$(':input').blur(function() {
$focusedElement = $(':input:focus');
//Do stuff with $focusedElement
}
Interesting question. The heart of the matter is - when does the 'focus' event fire, before or after the blur event? If it fires before the blur event, the problem is easy, because you can just store the current focus in a variable that your blur event can access.
However, at least in Chrome 13, it appears the blur event happens before the focus event. One possible solution.
Given the following HTML:
<input id="foo" value='foo' />
<input id="bar" value='bar' />
You can then:
var currentFocus;
var pendingBlur;
var foo = document.getElementById('foo');
foo.addEventListener('focus', function(){
currentFocus = foo;
if(pendingBlur !== undefined){
pendingBlur();
pendingBlur = undefined;
}
});
foo.addEventListener('blur', function(){
pendingBlur = function(){
console.log('new focus:', currentFocus);
};
});
var bar= document.getElementById('bar');
bar.addEventListener('focus', function(){
currentFocus = bar;
if(pendingBlur !== undefined){
pendingBlur();
pendingBlur = undefined;
}
});
bar.addEventListener('blur', function(){
pendingBlur = function(){
console.log('new focus:', currentFocus);
};
});
Basically, I just not the blur callback so it is handy for the focus event to call after we know about which element was focused.
Here is a working example on JSFiddle.
EDIT: This solution suffers from the problem that if you blur on the form by clicking on something other than another form element, the blur event never fires (since we wait for the focus event). The only way around that, that I can conceive, is using a timer to check if pendingBlur is defined, and if so, call it. At which point you don't really need the focus event to call the blur callback anymore...
Year 2020: All major browsers (desktop and mobile) support FocusEvent.relatedTarget.
event.relatedTarget couldn't find the newly-focused element(was div type in my case), but only null gets returned.
After attaching the attribute tabindex="0" on the element, now it works.
<div id="myDiv">myDiv</div>
console.log(e.relatedTarget) // null
<div id="myDiv" tabindex="0"> tabindexed div </div>
console.log(e.relatedTarget) // <div id="myDiv" tabindex="0">
tabindex is an attribute that make elements focusable using tab key on keyboard. I guess it is mainly for web accessibility.
And I guess you won't need to set tabindex attribute as long as to-be focused elements are already accessible by tab key (such as a, select.. and so on)
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.
I am having the following problem under Internet Explorer 7/8:
I have a popup that gets activated when user mouseover a link. The popup is a simple <div> that contains some data. Inside this <div> tag there is a <select> tag with some <option>s. I have attached mouseover/mouseout events to the <div>, so that this popup will stay open while cursor is over it. The problem comes when you click on the <select> and then move the cursor over any of the <option>s. This triggers the mouseout event of the <div> tag and respectively closes it.
How can I prevent the closing of the popup in IE ?
You should be able to detect if the situation is the one you want just with the values off the event. It is a little convoluted but it seems to work.
In the event handler of your outer div, do something like this:
<div onmouseover="if (isReal()) { toggle(); }"
onmouseout="if (isReal()) { toggle(); }">
</div>
Then implement the isReal method:
function isReal() {
var evt = window.event;
if (!evt) {
return true;
}
var el;
if (evt.type === "mouseout") {
el = evt.toElement;
} else if (evt.type === "mouseover") {
el = evt.fromElement;
}
if (!el) {
return false;
}
while (el) {
if (el === evt.srcElement) {
return false;
}
el = el.parentNode;
}
return true;
}
Basically the isReal method just detects if the event was coming from within the div. If so, then it returns false which avoids calling the hide toggle.
My suggestion would be to set another flag while the select box has focus. Do not close the div while the flag is set.
How about re-showing the div when the mouse is over the <options>s through mouseover events of <options>s.
Edit: execution order of mouseover of option and mouseout of div might cause problems though.
In the mouseout event for the div add a timeout to the div element that will hide the div in 200 milliseconds or so.
Then in the mouseover event for the div/select and the click event of the select clear the timeout stored in the div element.
This gives a very slight delay before hiding the div that allows the mouseover or click events to clear the timeout before it is executed. It's not pretty but it should work.
instead of using mouseout as the event to close the div, use mouseleave, then the event will only be triggered when the pointer leaves the boundary of the div, not when it moves onto other elements within it
you could try adding another mouseover event specifically for the options list.
Well, the reason for this behavior is because the mouseover/out events bubble, which effectively means that whenever you mouseover any of the elements inside the popup, the popup receives the event also.
You can read more here about these events, and here about event bubbling.
You have 3 possible solutions here:
Change the events to onmouseenter/leave. You've mentioned that this didn't help, which just sounds plain odd, since these aren't supposed to bubble.
Check srcElement in relation to from/toElement in the event.
An improved version of McKAMEY's check would be:
function isReal() {
var evt = window.event;
if (!evt) {
return true;
}
var el;
if (evt.type === "mouseout") {
el = evt.toElement;
} else if (evt.type === "mouseover") {
el = evt.fromElement;
}
if (!el) {
return false;
}
// this will also return true if el == evt.srcElement
return evt.srcElement.contains(el);
}
Does the same thing, just shorter.
3 . Another option would be to create a transparent, invisible div just under your popup that covers the area that the select box drops down into. I'm assuming that it's dropping outside the actual area of the popup.
Hope this helps!
have you tried hover instead of mouseover/out effects?
$(".myDiv").hover(function(){
$(this).show();
}, function {
$(this).hide();
});
What about something like this:
<div id="trigger">
Hover over me!
</div>
<div class="container">
<select>
<option>Blah</option>
<option>Blah</option>
</select>
</div>
$("#trigger").mouseover(function(){
$('.container).show();
});
$(".container").mouseleave(function(){
$(this).hide();
});
The basic idea is that you show the container element when you hover over the trigger then when you leave the container you hide the container. You'd need to position the container so it clipped the trigger element, otherwise it would hide straight away.
Why have mouseover / mouseout on the <div>? Why not just show the <div> on the mouse over, then set <body onmouseover="hidedivs();"> I don't know if this would work, but if the <div> is on top of the body, then the <div> should stay visible.
Many people posting solutions/examples do not seem to realize one thing: onmouseout event on <div> fires before onmouseover event on <select>.
When <div> loses focus (onmouseout) do not close it immediately, but after say, 500 milliseconds. If during this time <select> gets focus (mouseover) do not close <div> at all (clearTimeout).
Also, try to play with event propagation/bubling.
Given that selects in IE are a pain, especially when it comes to the whole layering issue where a select appears above a div even though it shouldn't, can I point you in the direction of YUI's Menu button controls. They look really nice, are easy to implement and won't cause this issue
Here is a link: http://developer.yahoo.com/yui/examples/button/btn_example07.html
You should use event.stopPropagation() while in <select>, or cancelBubble() in <select> element itself.