delay mouseenter event and raise event if mouse inside the element - javascript

I use this tab view that developed base on jQuery:
https://d2o0t5hpnwv4c1.cloudfront.net/001_Tabbed/site/jQuery.html#
I change the code that tabs change by mouseenter event. and I want to delay execution of the mouseenter event so if mouse enter the elemnt and remain there for portion of time mouseenter executes else (if mouse go outside in time less that that portion of time) mouseenter does not execute.I write this code:
$(document).ready(function () {
$('a.tab').on('mouseenter', function () {
var thisElement = $(this);
setTimeout(function () {
$(".active").removeClass("active");
thisElement.addClass("active");
$(".content").slideUp();
var content_show = thisElement.attr("title");
$("#" + content_show).slideDown();
}, 300);
});
});
but if I bring mouse out of element mouseenter excecutes.How to solve this problem?
thanks

You need to store the timeout handle and cancel it on mouseleave:
var timeout;
$(document).ready(function () {
$('a.tab').on('mouseenter', function () {
var thisElement = $(this);
if (timeout != null) { clearTimeout(timeout); }
timeout = setTimeout(function () {
$(".active").removeClass("active");
thisElement.addClass("active");
$(".content").slideUp();
var content_show = thisElement.attr("title");
$("#" + content_show).slideDown();
}, 300);
});
$('a.tab').on('mouseleave', function () {
if (timeout != null) {
clearTimeout(timeout);
timeout = null;
}
});
});

Related

Prototype.js how to fix use of clearTimeout( )

I'm using Prototype.js to load an html element when the user performs a mouseover on certain list items. I'm using setTimeout() to load the content only if the mouse is still over the list item after a given amount of time. I want to use clearTimeout when the user performs a mouseout on the same list item.
clearTimeout() is not clearing my timeout. I am pretty sure this is because of a common variable scope issue hidden from me by my lack of familiarity with Prototype.js
Can someone point out the flaw in this code or determine what I need to add to make the clearTimeout() function work properly?
document.observe( 'dom:loaded', function() {
var timeout;
$$('.nav-primary li.category').each( function( item ) {
item.observe('mouseover', function(event) {
event.stopPropagation();
categoryId = event.currentTarget.id;
getCategoryBlurb(categoryId);
timeout = setTimeout( function() {
showCategoryInfo(categoryData, categoryId);
}, waitTime);
});
item.observe('mouseout', function(event) {
event.stopPropagation();
clearTimeout(timeout);
});
});
});
Updated Code
$$('.nav-primary li.category').each( function( item ) {
var timeout = null;
item.observe('mouseover', function(event) {
event.stopPropagation();
categoryId = event.currentTarget.id;
getCategoryBlurb(categoryId);
if( timeout === null ) {
timeout = setTimeout( function() {
showCategoryInfo(categoryData, categoryId);
}, waitTime);
}
console.log(timeout);
});
item.observe('mouseout', function(event) {
if( timeout !== null ) {
console.log(timeout);
clearTimeout(timeout);
timeout = null;
}
});
});
clear the timeout before you set it
if (timeout) { clearTimeout(timeout); }
timeout = setTimeout( function() { /* code here */ });

Reverse jQuery effect after a given time

one quick question!
I am using the following code which does a "flip" card effect to flip a specific div element, when a certain link is mouse clicked. Is it possible to make the "flip" effect reverse after some time? Exactly as if I was clicking again with the mouse, but timed. I can do it now by cliking, but I would like to time it.
$(document).ready(function () {
$('.flip_card').click(function () {
var x = $(this).attr("id");
var i = x.substring(10);
$('.flip' + i + '').find('.card').toggleClass('flipped');
});
});
I have tried using the jquery functions delay() or settimeout, but I can only achieve that the first "flip" effect is delayed and happens after certain time. That is not what I want...
I hope my question is understanble enough.
Many thanks!
Try this.
$(document).ready(function () {
$('.flip_card').click(function () {
var x = $(this).attr("id");
var i = x.substring(10);
var ele = '.flip' + i + '';
$(ele).find('.card').toggleClass('flipped');
setTimeout(function(){
$(ele).find('.card').toggleClass('flipped');
}, 1000);
});
});
Try utilizing .queue()
$(document).ready(function () {
$(".flip_card").click(function () {
var x = this.id;
var i = x.substring(10);
$(".flip" + i).find(".card").toggleClass("flipped")
.queue("reset", function() {
setTimeout(function() {
$(".flip"+ i + " .card.flipped:eq(-1)").toggleClass("flipped");
// set duration here
}, 3000);
}).dequeue("reset");
});
});
You can use setTimeout(), but you should keep track of the timer ID so you can cancel it if the user clicks again before the timeout has executed. You can use the .data() function to store the timer ID so each card keeps track of its own timer ID.
$(document).ready(function () {
$('.flip_card').click(function () {
var i = $(this).attr('id').substring(10);
var $card = $('.flip' + i).find('.card');
// Clear the timeout if there is one.
var timerId = $card.data('timerId');
if (timerId) {
clearTimeout(timerId);
}
// Flip the card.
if (!$card.hasClass('flipped')) {
$card.addClass('flipped');
// Set the timeout so the card is flipped back after 3 seconds.
$card.data('timerId', setTimeout(function () {
$card.removeClass('flipped');
}, 3000));
} else {
$card.removeClass('flipped');
}
});
});
jsfiddle
How about something this simple. Just chaining should make it.
$(document).ready(function () {
$('.flip_card').bind('click', function() {
var x = $(this).attr("id");
var i = x.substring(10);
var ele = '.flip' + i + '';
$(ele).find('.card').toggleClass('flipped').delay(3000).toggleClass('flipped');
});
});

One mouseleave event logs $(this) as element; another logs it as delegated object

I have attached to mouseleave events to two HTML elements. I'm confused why in one printing $(this) to the console shows the div element the event is attached to, and the other prints out the entire window.
$(function () {
$(document).on({
mouseenter: function (evt) {
$(evt.target).data('hovering', true);
},
mouseleave: function (evt) {
$(evt.target).data('hovering', false);
}
}, "*");
$.expr[":"].hovering = function (elem) {
return $(elem).data('hovering') ? true : false;
};
$(document).on({
mouseenter: function () {
var $menu = $(".menu[data-a='" + $(this).attr("data-a") + "']");
//console.log($menu)
$menu.addClass("menu_vis");
$(".menu").hide();
$menu.show();
},
mouseleave: function () {
console.log($(this)) //the div
var s = setTimeout(function () {
var $menu = $(".menu[data-a='" + $(this).attr("data-a") + "']");
var over_menu = $menu.is(":hovering");
if (!over_menu) {
$menu.hide();
}
}, 100);
}
}, ".activate");
$(document).on({
mouseleave: function () {
var s = setTimeout(function(){
var $activate = $(".activate[data-a='" + $(this).attr("data-a") + "']");
var over_activate = $activate.is(":hovering");
console.log($(this)); //the window ??
if (!over_activate){
$(this).hide();
}
}, 100)
}
}, ".menu");
});
Inside the nested function the this keyword refers to the window. (you're using setTimeout i.e. nested inside mouseleave)
To solve: use a variable before using nested function
var that = $(this);
//now when you use function, use like this:
setTimeout(function(){
console.log(that);//logs the Div
},100)
Or use bind method:
setTimeout(function(){
console.log($(this));//logs the Div
}.bind(this),100)

After setTimeout() check if still mouse out

I have a piece of code that hides an element on mouseout.
The code looks like this:
var myMouseOutFunction = function (event) {
setTimeout(function () {
$(".classToHide").hide();
$(".classToShow").show();
}, 200);
};
This produces a result very close to what I want to do. However, I want to wait the time on the timeout (in this case 200 ms) then check to see if my mouse is still "out" of the element. If it is, I want to do .hide() and .show() on the desired elements.
I want to do this because if a user slightly mouses out then quickly mouses back in, I don't want the elements to flicker (meaning: hide then show real quick) when the user just wants to see the element.
Assign the timeout's return value to a variable, then use clearTimeout in the onmouseover event.
Detailing Kolink answer
DEMO: http://jsfiddle.net/EpMQ2/1/
var timer = null;
element.onmouseout = function () {
timer = setTimeout(function () {
$(".classToHide").hide();
$(".classToShow").show();
}, 200);
}
element.onmouseover = function () {
clearTimeout(timer);
}
You should use mouseenter and mouseleave of jquery. mouseenter and mouseleave will get called only once.and use a flag if to check if mouseenter again called.
var isMouseEnter ;
var mouseLeaveFunction = function (event) {
isMouseEnter = false;
setTimeout(function () {
if(isMouseEnter ){ return;}
$(".classToHide").hide();
$(".classToShow").show();
}, 200);
};
var mouseEnterFunction = function(){
isMouseEnter = true;
}
Use a boolean flag:
var mustWait = true;
var myMouseOutFunction = function (event) {
setTimeout(function () {
if(mustWait){
mustWait = false;
}
else{
$(".classToHide").hide();
$(".classToShow").show();
mustWait = true;
}
}, 200);
};

How can I listen for a click-and-hold in jQuery?

I want to be able to fire an event when a user clicks on a button, then holds that click down for 1000 to 1500 ms.
Is there jQuery core functionality or a plugin that already enables this?
Should I roll my own? Where should I start?
var timeoutId = 0;
$('#myElement').on('mousedown', function() {
timeoutId = setTimeout(myFunction, 1000);
}).on('mouseup mouseleave', function() {
clearTimeout(timeoutId);
});
Edit: correction per AndyE...thanks!
Edit 2: using bind now for two events with same handler per gnarf
Aircoded (but tested on this fiddle)
(function($) {
function startTrigger(e) {
var $elem = $(this);
$elem.data('mouseheld_timeout', setTimeout(function() {
$elem.trigger('mouseheld');
}, e.data));
}
function stopTrigger() {
var $elem = $(this);
clearTimeout($elem.data('mouseheld_timeout'));
}
var mouseheld = $.event.special.mouseheld = {
setup: function(data) {
// the first binding of a mouseheld event on an element will trigger this
// lets bind our event handlers
var $this = $(this);
$this.bind('mousedown', +data || mouseheld.time, startTrigger);
$this.bind('mouseleave mouseup', stopTrigger);
},
teardown: function() {
var $this = $(this);
$this.unbind('mousedown', startTrigger);
$this.unbind('mouseleave mouseup', stopTrigger);
},
time: 750 // default to 750ms
};
})(jQuery);
// usage
$("div").bind('mouseheld', function(e) {
console.log('Held', e);
})
I made a simple JQuery plugin for this if anyone is interested.
http://plugins.jquery.com/pressAndHold/
Presumably you could kick off a setTimeout call in mousedown, and then cancel it in mouseup (if mouseup happens before your timeout completes).
However, looks like there is a plugin: longclick.
var _timeoutId = 0;
var _startHoldEvent = function(e) {
_timeoutId = setInterval(function() {
myFunction.call(e.target);
}, 1000);
};
var _stopHoldEvent = function() {
clearInterval(_timeoutId );
};
$('#myElement').on('mousedown', _startHoldEvent).on('mouseup mouseleave', _stopHoldEvent);
Here's my current implementation:
$.liveClickHold = function(selector, fn) {
$(selector).live("mousedown", function(evt) {
var $this = $(this).data("mousedown", true);
setTimeout(function() {
if ($this.data("mousedown") === true) {
fn(evt);
}
}, 500);
});
$(selector).live("mouseup", function(evt) {
$(this).data("mousedown", false);
});
}
I wrote some code to make it easy
//Add custom event listener
$(':root').on('mousedown', '*', function() {
var el = $(this),
events = $._data(this, 'events');
if (events && events.clickHold) {
el.data(
'clickHoldTimer',
setTimeout(
function() {
el.trigger('clickHold')
},
el.data('clickHoldTimeout')
)
);
}
}).on('mouseup mouseleave mousemove', '*', function() {
clearTimeout($(this).data('clickHoldTimer'));
});
//Attach it to the element
$('#HoldListener').data('clickHoldTimeout', 2000); //Time to hold
$('#HoldListener').on('clickHold', function() {
console.log('Worked!');
});
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<img src="http://lorempixel.com/400/200/" id="HoldListener">
See on JSFiddle
Now you need just to set the time of holding and add clickHold event on your element
Try this:
var thumbnailHold;
$(".image_thumb").mousedown(function() {
thumbnailHold = setTimeout(function(){
checkboxOn(); // Your action Here
} , 1000);
return false;
});
$(".image_thumb").mouseup(function() {
clearTimeout(thumbnailHold);
});

Categories

Resources