I have a script where I disable a button after it was clicked, for like 5 seconds, and then enable it again.
$(document).on('click', 'button', function () {
var htmls = $(this).html();
$(this).prop("disabled", true);
setTimeout(function () {
$(this).prop("disabled", false);
$(this).html(htmls);
}, 5000);
$(this).html('<img src="<?=CDN(' / icons / loading / loading5.gif ')?>" />');
});
Somehow the setTimeout won't end, so the button won't be enabled again. I don't get any error messages.
Save $(this) into variable before setTimeout call, since this keyword inside setTimeout handler refers to window object:
$(document).on("click", "button", function() {
var $this = $(this),
htmls = $this.html();
$this.prop("disabled", true)
.html('<img src="..." />');
setTimeout(function() {
$this.prop("disabled", false)
.html(htmls);
}, 5000);
});
Here does not refer to the DOM element.Try to put into another temarory variable.Because it is outside to setTimeOut
var $this = $(this),
htmls = $this.html();
$this.prop("disabled", true);
setTimeout(function() {
$this.prop("disabled", false).html(htmls);
}, 5000);
Related
What I am trying to do is only run my code when someone has hovered on an element for 1 second.
Here is the code that I am using:
var timer;
$(".homeLinkWrap").mouseenter(function() {
timer = setTimeout(function(){
$(this).find('.homeLinkNfo').removeClass('flipOutY').addClass('flipInY').css({opacity: '1'});
console.log('in');
}, 1000);
}).mouseleave(function() {
$(this).find('.homeLinkNfo').removeClass('flipInY').addClass('flipOutY');
console.log('out');
clearTimeout(timer);
});
The first part (mouseenter) IS NOT functioning and DOESN'T remove the class and then add the new one. The second one (mouseleave) IS functioning properly and DOES remove the class and add the new one.
I am guessing it is because I am targeting $(this) which is the current element being hovered over and since it is in a timer function jQuery doesn't know which element $(this) is referring to.
What can I do to remedy this?
I think it is because you are calling $(this) inside the setTimeout function. You need to do something like this:
$(".homeLinkWrap").mouseenter(function() {
var $self = $(this);
timer = setTimeout(function(){
$self.find('.homeLinkNfo').removeClass('flipOutY').addClass('flipInY').css({opacity: '1'});
console.log('in');
}, 1000);
});
Inside the setTimeout callback, this no longer refers to the jQuery selection. You should either keep a reference to the selection:
$(".homeLinkWrap").mouseenter(function() {
var $this = $(this);
timer = setTimeout(function(){
$this.find('.homeLinkNfo').removeClass('flipOutY').addClass('flipInY').css({opacity: '1'});
console.log('in');
}, 1000);
})
Or use an arrow function (ES2015)
$(".homeLinkWrap").mouseenter(function() {
timer = setTimeout(() => {
$(this).find('.homeLinkNfo').removeClass('flipOutY').addClass('flipInY').css({opacity: '1'});
console.log('in');
}, 1000);
})
The problem here is that the this inside the callback function that you're passing to setTimeout doesn't reference to the same point that the this outside the callback does.
There are some ways of solving your problem, I'll suggest you to use Function.prototype.bind to bind your callback function to the same this you have outside:
var timer;
$(".homeLinkWrap").mouseenter(function() {
timer = setTimeout((function() {
$(this).find('.homeLinkNfo').removeClass('flipOutY').addClass('flipInY').css({ opacity: '1' });
}).bind(this), 1000);
}).mouseleave(function() {
$(this).find('.homeLinkNfo').removeClass('flipInY').addClass('flipOutY');
clearTimeout(timer);
});
I need to show a tooltip when a user hovers over a specific tag on my page. However, I want to do it only if the tag was hovered for at least a second. I tried the code below, but - obviously - setTimeout() will trigger after a second every time, even if the cursor is "long gone".
Is there an easy way in jQuery to achieve this? Not really interested in any plugin-solution.
Fiddle
HTML
<div class="tag-tooltip" id="tooltip-1">Followers: 34</div>
<div class="tag js-tag" data-id="1">Star Wars (hover over me!)</div>
jQuery
$(document).on('mouseenter', '.js-tag', function() {
var $this = $(this);
setTimeout(function() {
$('#tooltip-' + $this.data('id')).show();
}, 2000);
});
$(document).on('mouseleave', '.js-tag', function() {
$('#tooltip-' + $this.data('id')).hide();
});
UPDATE ON SOLUTION
Many good suggestions below, many ways to achieve same thing. I find clearTimeout() solution the cleanest, though. Thanks to everyone who contributed:)
You were almost there, here you go:
http://jsfiddle.net/j21wjtwh/4/
var hoverTimer;
$(document).on('mouseenter', '.js-tag', function() {
var $this = $(this);
hoverTimer = setTimeout(function() {
$('#tooltip-' + $this.data('id')).show();
}, 1000);
});
$(document).on('mouseleave', '.js-tag', function() {
clearTimeout(hoverTimer);
$('#tooltip-' + $(this).data('id')).hide();
});
Use a flag. Set it to false on mouseleave. In mouseenter check if variable is set.
var show = false; // Define var
// ^^^^^^^^^^^^^
$(document).on('mouseenter', '.js-tag', function () {
show = true; // Set to `true`
var $this = $(this);
setTimeout(function () {
if (show) { // Check if true
$('#tooltip-' + $this.data('id')).show();
}
}, 1000);
});
$(document).on('mouseleave', '.js-tag', function () {
$('#tooltip-' + $(this).data('id')).hide();
show = false; // Unset
});
Demo: http://jsfiddle.net/tusharj/j21wjtwh/2/
Here is a Fiddle
Here is a Code
$(document).on('mouseenter', '.js-tag', function() {
var $this = $(this);
setTimeout(function() {
if($('.js-tag').is(":hover"))
{
$('#tooltip-' + $this.data('id')).show();
}
}, 1000);
});
$(document).on('mouseleave', '.js-tag', function() {
$('#tooltip-' + $(this).data('id')).hide();
});
But there is one small bug here, try to hover/unhover fast, and you will see it
EDIT
As for me THIS answer much better. It doesn't contains my bug
Just keep track of whether or not you are currently hovering with a variable.
Set the hovering variable to true on mouse enter, and false on mouseleave.
Then in your setTimeout event, check if you are currently hovering.
Updated Fiddle
var hovering = false;
$('.js-tag').mouseenter(function () {
var $this = $(this);
hovering = true;
setTimeout(function () {
if (hovering) {
$('#tooltip-' + $this.data('id')).show();
}
}, 1000);
});
$('.js-tag').mouseleave(function () {
hovering = false;
$('#tooltip-' + $(this).data('id')).hide();
});
You can store timer handle in variable and clear it using clearTimeout on mouseleave.
Here is jsfiddle for it.
http://jsfiddle.net/Lz9snp9t/3/
Try this:
$('.js-tag').on('mouseover', function() {
var $this = $(this);
if(!$this.data('timeout')) {
$this.data('timeout', setTimeout(function() {
$('#tooltip-' + $this.data('id')).show();
}, 2000);
}
});
$('.js-tag').on('mouseout', function() {
var $this = $(this);
if($this.data('timeout')) {
clearTimeout($this.data('timeout'));
}
$('#tooltip-' + $this.data('id')).hide();
});
As it stands the remove function doesn't work. Any suggestions?
var toggle = new function() {
$(document).on('click', 'img', function () {
$(this).parent().toggle('slide');
})
}
var remove = new function() {
$(document).on('click', 'img',
setTimeout(function () {
$(this).parent().remove();
}, 1000);
)
}
The function your are looking for is .queue(). It will execute a provided callback after the previous animation has finished:
$(document).on('click', 'img', function() {
var $entry = $(this).parent();
$entry.toggle('slide').queue(function(next) {
$entry.remove();
next();
});
});
Working example: http://jsfiddle.net/rbBgS/
$('#test').hover(
function () {
$(this).append('Blah');
}
);
How can I make the jQuery repeatedly append Blah in #test based on how long you are hovering over #test?
For instance, how can I append Blah once every second you are hovering over #test?
You could use setInterval like this :
var myInterval = false;
$('#test').hover(
function(){
$that = $(this);
// need to save $(this) as 'this' will be different within setInterval
myInterval = setInterval(function(){
$that.append('Blah');
}, 100); // repeat every 100 ms
},function() {
clearInterval(myInterval); // clear the interval on hoverOut
}
);
Working example here
(function() {
var intv;
$('#test').hover(
function () {
var $this = $(this);
intv = setInterval(function() {
$this.append('Blah');
}, 1000);
},
function() {
clearInterval(intv);
}
);
}());
I've enclosed all the code inside a anonymous scoped function so to not pollute global scope, and I cached a reference to $(this) to avoid a new evaluation every second, inside the timeout
You can use setInterval to do so:
var appending; //var to store the interval
$('#test').hover(function(){ //on mouseenter
var $this = $(this); //store the context, i.e. the element triggering the hover
appending = setInterval(function(){ //the following function gets executed every second until the interval is cleared
$this.append('<p>Blah</p>'); //append content to context
},1000); //1000 meaning the repetition time in ms
},function(){ //on mouseleave
clearInterval(appending); //clear the interval on mouseleave
});
use setInterval()
$('#test').hover(
function () {
setInterval(function() {
$(this).append('Blah');
},1000)
}
);
Target: Object user will hover over to bring up secondary DOM
Tooltip: Fixed DOM object positioned about 10-15px below target
I have made a jquery "tooltip" plugin. This plugin allows users to hover over a DOM object, and will show the "tooltip". I want users to be able to move their mouse from the target to the tooltip without it disappearing the second their mouse leaves the target.
I have tried this:
var hoverTimeout;
data.target.hover(function(){
$this.tooltip('show');
}, function(){
hoverTimeout = setTimeout(function(){
$this.tooltip('hide');
console.log('hey');
}, 1000);
});
data.tooltip.hover(function(){
data.tooltip('show');
clearTimeout(hoverTimeout);
}, function(){
data.tooltip('hide');
});
However, this seems to stop the Tooltip from hiding. The reason I'd like to do this, is so forms can be used, text can be copied, etc., in the tooltip.
I'm hoping something like a setTimeout and clearTimeout will work as I don't want to use hoverintent plugin.
Thank you so much in advance!
You should use the timer both ways:
var hoverTimeout;
data.target.hover(function()
{
hoverTimeout && clearTimeout(hoverTimeout);
$(this).tooltip('show');
},
function()
{
var $this = $(this);
hoverTimeout = setTimeout(function(){
$this.tooltip('hide');
}, 1000);
});
data.tooltip.hover(function()
{
hoverTimeout && clearTimeout(hoverTimeout);
},
function()
{
var $this = $(this);
hoverTimeout = setTimeout(function(){
$this.tooltip('hide');
}, 1000);
});
You should probably combine the two, since you're anyhow doing the exact same thing on both of them:
var hoverTimeout;
data.target.add( data.tooltip ).hover(function()
{
hoverTimeout && clearTimeout(hoverTimeout);
$(this).tooltip('show');
},
function()
{
var $this = $(this);
hoverTimeout = setTimeout(function(){
$this.tooltip('hide');
}, 1000);
});
var hoverTimeout;
data.target.hover(function()
{
$this.tooltip('show');
clearTimeout(hoverTimeout);
}, function()
{
hoverTimeout = setTimeout(function(){
$this.tooltip('hide');
}, settings.delay);
});
data.tooltip.hover(function()
{
clearTimeout(hoverTimeout);
}, function()
{
hoverTimeout = setTimeout(function(){
$this.tooltip('hide');
}, settings.delay);
});