How can I write this function on mouse hover a div? - javascript

How can I write this function so that when the mouse is resting over the div .resting it will trigger the call. Here is the code:
$(document).bind('mousemove', function() {
resetActive()
});
I want it to call the resetActive when the mouse is resting over a desired div .resting. How can I write the code?

$('.resting').mouseenter(resetActive);
Or, to be clean and better practice,
$('.resting').on('mouseenter', resetActive);
// and later
$('.resting').off('mouseenter', resetActive);
And to get the event:
var resetActive = function(e) {
// do something...
}

$(".resting").mouseover(function() {
resetActive();
});

Related

DOM - timing of simultaneous events vs setTimeout

Suppose I have an element containing several children and want to run some code whenever the mouse enters or leaves the container. If I naively write:
var onHover = function (el, f) {
el.addEventListener('mouseover', function () {
f(true);
});
el.addEventListener('mouseout', function () {
f(false);
});
};
Then I get the desired behavior in some cases - depending on the nature of the callback f. However, when the mouse moves from child to child within the container, f(false) runs immediately followed by f(true). I don't want this to happen - I only want f to be run when the mouse enters or leaves the container as a whole, not called machine-gun style as the user drags their mouse over the elements that are inside the container.
Here's the solution that I came up with:
var onHover = function (el, f) {
var previousMouseover = false;
var receivedMouseover = false;
var pushing = false;
var pushEv = function () {
if (pushing) { return; }
pushing = true;
setTimeout(function () {
pushing = false;
if (previousMouseover !== receivedMouseover) {
f(receivedMouseover);
previousMouseover = receivedMouseover;
}
});
};
el.addEventListener('mouseover', function () {
receivedMouseover = true;
pushEv();
});
el.addEventListener('mouseout', function () {
receivedMouseover = false;
pushEv();
});
};
This solution, like the first solution, assumes and works by the virtue that the mouseout event is sent before the mouseover event is. I would also like to know whether that is formally specified by any W3C documentation, but that is not the topic of this question, and even if it were not the case, it would be easy to write a functioning algorithm in spite of that by setting two separate variables, say receivedMouseover and receivedMouseout inside of the mouseover and mouseout callbacks, both of which are then inspected inside of the setTimeout callback.
The question is: Is it required that both the mouseover and mouseout events be processed before any setTimeout callbacks signed up by either event are run?
Use the mouseenter and mouseleave events instead of mouseover and mouseout.
Since you have attached the event listener to the parent element you may compare the event origin (event.target) with the parent element (this or event.currentTarget) before you take an action. You may do as follows;
var onHover = function (el, f) {
el.addEventListener('mouseover', function (evt) {
this === evt.target && f(true);
});
el.addEventListener('mouseout', function (evt) {
this === evt.target && f(false);
});
};
Most of the elements bubble so at some point this might be the right way to do this job.
Edit: As mentioned in the comments the mouseover and mouseout events can be problematic under some circumstances such as when the parent element has no padding or margins defined and children cover all the parent. Even if they don't the speed of the mouse could be fast enough to make the JS engine fail to sample the mouse over the parent element. This fact is beautifuly explained in this article.
So, as mentioned in the accepted answer, i suppose the mouseenter and mouseleave events are there to solve this problem. Accordingly the right code should be like;
var onHover = function (el, f) {
el.addEventListener('mouseenter', () => f(true));
el.addEventListener('mouseleave', () => f(false));
};
Edit 2: Well... Actually there is a safe way of using mouseover and mouseout in this particular condition. It's about using CSS pointer-events property on the children which disables them from event emitting for mouse activity.
var container = document.getElementById('container');
container.addEventListener('mouseover', function (ev) {
console.log(container === ev.target);
});
container.addEventListener('mouseout', function (ev) {
console.log(container === ev.target);
});
#container * {
pointer-events: none
}
<div id="container">
<div>
<span>text</span>
</div>
</div>

Best way to catch mouseup outside of mousedown element

$('#clickableElement').bind({
mousedown: function(e)
{
console.log('mousedown on element');
$(document).bind('mouseup',function(e){
console.log('mouseup caught');
//Do some magic here
$(this).unbind('mouseup');
});
},
mouseup:function(e)
{
//mouseup within element, no use here.
}
});
I'm trying to catch the mouseup event from a mousedown that's released inside or outside of an element. This code almost works, but the problem is the unbind('mouseup') which is unbinding other scripts attached to the mouseup event (jqueryui). If unbind() is not set then the code gets stacked within mouseup event and called x number of times, where x is the times you've mousedowned.
Route 1: is there some kind of self destructing function that calls itself once and destroys?
Route 2: any way to copy/clone the mouseup function prior to inserting the code, then unbind, then set as previous?
Ideally I'd like to keep this code structure for neatness as I have lots of clickable elements, so binding the document.mouseup outside of element.mousedown would be messy.
Here's the Fiddle I forgot to add http://jsfiddle.net/9gFNk/
Can giv your click event a namespace so only that namespaced event gets unbound, and not any others
$(document).on('mouseup.clickableElement',function(e){
console.log('mouseup caught');
//Do some magic here
$(this).off('mouseup.clickableElement');
});
I created a global object to catch mouse events from the document. It's currently set for mouseup only but can be easily expanded for others. The mouseup code is still customizable within the mousedown functions of the clickable elements so it this handy if you have lots of clickable things like I do.
var MouseCatcher=function()
{
this.init=function()
{
var mc = this;
$(document).bind({
mouseup:function(e)
{
mc.mouseup();
}
});
}
this.mouseup=function()
{
return false;
}
}
var mouseCatcher = new MouseCatcher();
mouseCatcher.init();
$('#clickableElement').bind({
mousedown: function(e)
{
console.log('mousedown on element');
mouseCatcher.mouseup=function()
{
console.log('mouseup called from MouseCatcher');
this.mouseup = function(){return false;}
}
},
mouseup:function(e)
{
//mouseup within element, no use here.
}
});
With "on" event its possible, its may not be an exact solution. Please refer this code
$(document).on('mousedown', function() {
$('#clickableElement').css('display', 'none');
$(document).bind('mouseup', function() {
$('#clickableElement').css('display', 'block');
});
});
http://jsfiddle.net/9gFNk/13/

How to know whether the mouse is inside the window?

I can't seem to find the answer.
I have a mouseleave event, in which I want to check, when the event fired, whether the mouse is currently inside the window or not (if not, it can be the tab bar of the browser, back button, etc).
var cursorInPage = false;
$(window).on('mouseout', function() {
cursorInPage = false;
});
$(window).on('mouseover', function() {
cursorInPage = true;
});
$('#some_element').on("mouseleave",function(){
if(cursorInPage === true){
//Code here runs despite mouse not being inside window
}
});
Can I bind to a window mouseleave event? If you leave the outside scope of the document/window, does such an event fire? The above code has a problem since i believe the mouseleave of the element fires before the window
I'm not really sure what you're asking us to put for "what to write here?", but you can simply set a boolean:
var cursorInPage = false;
$(window).on('mouseout', function() {
cursorInPage = false;
});
$(window).on('mouseover', function() {
cursorInPage = true;
});
Then use that boolean to proceed:
if (cursorInPage === true) {
alert('Woo, the cursor is inside the page!');
}
Here's an example JSFiddle which changes the body background colour when the cursor enters or leaves the window area, better displayed when looking at the full-screen result.
just tested this hope it helps. heres the jsFiddle for it.
$(document,window,'html').mouseleave(function(){alert('bye')}).mouseenter(function(){alert('welcome back!')})
You can try :
$('body').mouseout(function() {
alert('Bazzinga...');
});
or
$(window).mouseleave(function() {
alert('Bazzinga...');
});
When mouse is inside element
$('#outer').mouseover(function() {
$('#log').append('<div>Handler for .mouseover() called.</div>');
});
When mouseleave element
$('#outer').mouseleave(function() {
$('#log').append('<div>Handler for .mouseleave() called.</div>');
});

JQuery and strange behavior on hover function

I'm using a hover effect for all DIVs with class="box" on a page:
Javascript:
JQ(".box").hover(function() {
JQ(this).nextAll(".tooltip:first").css('visibility','visible');
});
JQ(".box").mouseleave(function(event) {
JQ(this).nextAll(".tooltip:first").css('visibility','hidden');
});
It works fine in Firefox and Chrome but in IE9 and Opera the .tooltip div disappears and re-appears continuously when the mouse moves within the boundaries of the .box DIV.
any ideas why the hover function keeps being called for every pixel of the DIV?
You can see a working version here
When you only pass one function to .hover() that function is called when the mouse both enters and leaves. So, you're making it visible on both entering and leaving which is conflicting with your mouseleave handler.
You could just do this:
JQ(".box").hover(function() {
JQ(this).nextAll(".tooltip:first").css('visibility','visible');
}, function() {
JQ(this).nextAll(".tooltip:first").css('visibility','hidden');
});
Or, a little more DRY (less repeated code):
JQ.fn.nextTip = function(vis) {
return this.nextAll(".tooltip:first").css('visibility', vis);
}
JQ(".box").hover(function() {
JQ(this).nextTip('visible');
}, function() {
JQ(this).nextTip('hidden');
});
Working demo: http://jsfiddle.net/jfriend00/DkgVg/
You should try replacing the hover part with:
JQ(".box").mouseenter(function() {
JQ(this).nextAll(".tooltip:first").css('visibility','visible');
});
Or keep hover and do:
JQ(".box").hover(function() {
JQ(this).nextAll(".tooltip:first").css('visibility','visible');
}, function(){
JQ(this).nextAll(".tooltip:first").css('visibility','hidden');
});
Just stop execution of event functions for this jQuery object
JQ(".box").hover(function() {
JQ(this).nextAll(".tooltip:first").stop(true,true).css('visibility','visible');
}, function(){
JQ(this).nextAll(".tooltip:first").stop(true,true).css('visibility','hidden');
});

jQuery refactored function

I like to keep my code as DRY as possible and would like to know if the following is possible.
I'll need to reuse the code below many times with the only difference being what I do in the following function.
.on("click", "a", function(e) {})
I could just duplicate the addToBooking function, give it a different name, make the slight change in the click handler but that feels wasteful and repetitive.
Can I perhaps pass a code block to the addToBooking function?
Or maybe there's another cool, efficient way I'm not aware of.
The full code block
var addToBooking = function(that, event) {
var left, top;
event.stopPropagation();
//Turn off all calendar tracking
$(".track").off();
//Get proper sticky positioning (Checks to make sure it wont display off screen)
left = getPosition(".add_to_booking", "left");
top = getPosition(".add_to_booking", "top");
//Position sticky, display and listen for click event to see what to do next
$(".add_to_booking").css({top: top, left: left})
.fadeIn('fast')
.on("click", function(e) { e.stopPropagation(); })
.on("click", "a", function(e) {
if($(this).text() === "YES") {
//Close dialog
closeTT();
//Open new add to booking box
addBooking(that, event);
} else {
closeTT();
}
});
}
Pass in the function and assign it
var addToBooking = function(that, event, custFnc) {
...
...
.on("click", "a", custFnc );
}
Fiddle
To pass parameters, you need to use call()
jQuery( function(){
function hey(evt, test){
var text = jQuery(this).text();
alert(text + ":" + test);
}
function addClick( custFnc ){
var test=99;
jQuery("#foo").on("click",
function(e){
custFnc.call(this, e,test);
}
);
}
addClick(hey);
});
​
Fiddle

Categories