Wondering how you can make .off() only happen for a specific period of time. I have a div which once clicked i want to disable the click event for 2 seconds, and then be allowed to click again. At the moment all I have is the div can be clicked, then once clicked it is off.
Here is a brief example of what I am asking:
$('.test').on('click', function() {
// *do stuff*
$('.test').off('click'); *for a certain perdiod of time*
});
It's a much simpler task to use a boolean variable as a flag to state whether the click handler should be executed, instead of attaching/detaching events from multiple elements. Try this:
var clickEnabled = true;
$('div').click(function() {
clickEnabled = false;
setTimeout(function() {
clickEnabled = true;
}, 2000);
});
$('.test').on('click', function(e) {
if (!clickEnabled) {
e.preventDefault();
} else {
// do stuff...
}
});
Note that you should also make the fact that .test is disabled visible in the UI, otherwise you'll just confuse and annoy your visitors when they click an element expecting an action, but nothing happens.
What about activate on after a certain period of time?
function myFunction() {
...do stuff
$('.test').off('click'); for a certain perdiod of time
setTimeout(function(){ $('.test').on('click', myFunction)}, 2000);
}
Using the setTimeout you may do something like:
var enabled = true;
var timeoutSeconds = 2;
$(function () {
$('.test').on('click', function(e) {
if (enabled) {
// *do stuff*
enabled = false;
window.setTimeout(function() {
enabled = true;
}, timeoutSeconds * 1000);
} else {
e.preventDefault();
}
});
});
You could do it like this.
function onClick() {
// do stuff here
$('.test').off('click');
setTimeout(function(){
$('.test').on('click', onClick);
}, 2000)
}
$('.test').on('click', onClick);
Or you can do it with css and toggleClass
// css
.disabled {
pointer-events: none;
}
// js
$('.test').on('click', function(){
// do stuff here
$('.test').addClass('disabled');
setTimeout(function(){
$('.test').removeClass('disabled');
}, 2000);
});
Related
I have a button group of three buttons. The relevant haml code is:
.btn-group#refresh-buttons
%button.btn.btn-default#refresh-5-sec 5 sec
%button.btn.btn-default#refresh-30-sec 30 sec
%button.btn.btn-default#refresh-60-sec 60 sec
I'm trying to build an adjustable refresh-rate feature. The first click registers and sets the refresh rate correctly (I inspected the event object) but subsequent clicks on any button thereafter do not register, they do not create an event object. My JS code is below:
$(document).ready(function() {
var intervalId = window.setInterval(function(){
$('.container').load('/dashboard/index .container');
}, 60000);
console.log(intervalId);
$("#refresh-buttons").on("click", "button", function(event) {
if(event.target.id === "refresh-5-sec") {
clearInterval(intervalId);
setInterval(function(){
$('.container').load('/dashboard/index .container');
}, 5000);
}
else if(event.target.id === "refresh-30-sec") {
clearInterval(intervalId);
setInterval(function(){
$('.container').load('/dashboard/index .container');
}, 10000);
}
else if(event.target.id === "refresh-60-sec") {
clearInterval(intervalId);
setInterval(function(){
$('.container').load('/dashboard/index .container');
}, 15000);
}
});
});
Thanks.
As already mentioned, if the .container element contains the button group then you need to use event delegation. There was another issue in the code, however. You were not setting intervalId each time you changed the refresh rate, so you would end up with multiple instances of setInterval() running.
I also tidied up a little as there was some code duplication going on...
$(document).ready(function() {
var intervalId = window.setInterval(function(){
$('.container').load('/dashboard/index .container');
}, 60000);
console.log(intervalId);
$(document).on("click", "#refresh-buttons button", function(event) {
var interval = 0;
switch(event.target.id) {
case: "refresh-5-sec" {
interval = 5000;
break;
}
case: "refresh-30-sec" {
interval = 30000;
break;
}
case: "refresh-60-sec" {
interval = 60000;
break;
}
}
if (interval != 0)
{
clearInterval(intervalId);
intervalId = setInterval(function(){
$('.container').load('/dashboard/index .container');
}, interval);
}
}
});
You should really change the click event handler so it's not attached to document. That example will work no matter how you change your page, but it's advisable to use the closest selector to the buttons as possible, that does not change when you do a load().
As #adeneo points out in his comment above, the #refresh-buttons element can't be inside the .container element, because you overwrite it on load() and therefore remove the event handler you attached.
If the #refresh-buttons element is inside the .container element, you have to use a delegate on a non-changing parent element, like this:
$(".container").on("click", "#refresh-buttons button", function(event) {...});
The idea is simple: I have buttons which refer to another website. Whenever the user has clicked more than two links I want to refresh some content (through Ajax). For that to work I need to detect if my window is active or not, since I only want the event to start when the user is BACK on my page.
Without further ado this is my code:
$(document).on("click", "a", function() {
numberOfClicks += 1;
if (numberOfClicks >= 2)
{
userOnWebsiteOrNot();
numberOfClicks = 0;
}
});
function userOnWebsiteOrNot()
{
if (focusedOrNot == 0)
{
$('#resultaat').hide().fadeIn(5000);
}
}
window.addEventListener('focus', function() {
document.title = 'focused';
focusedOrNot = 0;
});
window.addEventListener('blur', function() {
document.title = 'not focused';
focusedOrNot = 1;
});
It DOES detect whenever the user is on the page or not, but somehow the fade always happens.
Could anybody explain me what I'm doing wrong or give me any ideas?
Thanks
Yenthe
ANSWER:
I needed a setTimeOut on three functions because they would otherwise check too fast. Thank you for that help Romo! ;) All credit goes to Romo to be honest.
$(document).on("click", "a", function() {
numberOfClicks += 1;
if (numberOfClicks >= 2)
{
haallinks();
setTimeout(function() {
userOnWebsiteOrNot();
}, 2000);
numberOfClicks = 0;
}
});
function userOnWebsiteOrNot()
{
if (focusedOrNot === 0)
{
$('#resultaat').hide().fadeIn(5000);
}
else
{
controlerenActiefOfNiet();
}
}
function controlerenActiefOfNiet()
{
setTimeout(function() {
userOnWebsiteOrNot();
}, 2000);
}
window.addEventListener('focus', function() {
setTimeout(function() {
focusedOrNot = 0;
}, 0);
});
window.addEventListener('blur', function() {
setTimeout(function() {
focusedOrNot = 1;
}, 1000);
});
I think the problem is that when you click a link the second time the window will always be focused. JS runs pretty fast. To overcome this, I think you should do a setTimeout() and delay it 200ms or so to give the window time to "lose" focus
setTimeout(function() {userOnWebsiteOrNot(); },2000);
http://jsfiddle.net/xVHgE/
Edit: Adding delay to event listener. I don't think you can "delay" an event though, just the function it runs.
window.addEventListener('focus', function() {
setTimeout( function() {
$('#test').html('focus');
focusedOrNot = 0;
} , 5000);
});
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);
};
When mouse is over a product number (focus) then show some product information.
When user is not longer over a product number (blur), then wait 3 seconds, then hide details.
$('.productNumber').live('blur', function() {
setTimeout(function(){
var divToPutData = $(this);
divToPutData.hide();
}, 3000);
});
Now user says that if user moves mouse back within those 5 seconds to stop the count down, until a blur event fires again. No sure how to do this with setTimeout.
Use clearTimeout()
var myTimeout = null;
$('.productNumber').live('mouseover', function() {
//If timeout is still active, clear
if(myTimeout != null)
clearTimeout(myTimeout);
});
$('.productNumber').live('blur', function() {
//Store the ID returned by setTimeout
myTimout = setTimeout(function(){ divToPutData.hide(); }, 3000);
});
Use the function clearTimeout.
setTimeout returns a numeric id, you can store it in a variable, and then pass it to the clearTimeout function:
var myTimeout = setTimeout ( function(){alert(2);}, 1000);
clearTimeout(myTimeout);
var t;
$('.productNumber').live('mouseover', function() {
clearTimeout(t);
});
$('.productNumber').live('mouseout', function() {
t = setTimeout(function(){
divToPutData.hide();
}, 3000);
});
have the setTimeout assigned to a variable, so you can cancel it on hover again
var hideTimeout;
$('.productNumber').live('blur',function() {
hideTimeout = setTimeout(function() {
divToPutData.hide();
}, 3000);
});
$('.productNumber').live('mouseover',function() {
clearTimeout(hideTimeout);
// Do the show stuff
}
jQuery is not my strongest language, so you may need to modify this slightly, but this is the general approach to this scenario.
Use the jQuery stop() to abort any ongoing animation
Test it here: http://jsfiddle.net/T7kRr/1/
jQuery
$(".productNumber").hover(
function () {
$(this).find(".productDesc:last").stop(true, true).show();
},
function () {
$(this).find(".productDesc:last").delay(3000).fadeOut();
}
);
HTML
<div class="productNumber">1001<span class="productDesc" style="display:none">iPhone</span></div>
<div class="productNumber">2001<span class="productDesc" style="display:none">iPad</span></div>
<div class="productNumber">3333<span class="productDesc" style="display:none">TV</span></div>
<div class="productNumber">9999<span class="productDesc" style="display:none">HiFi</span></div>
I need a function that executes a function while a button is pressed and stops executing when the button is let go
$('#button').--while being held down--(function() {
//execute continuously
});
I believe something like this would work:
var timeout, clicker = $('#clicker');
clicker.mousedown(function(){
timeout = setInterval(function(){
// Do something continuously
}, 500);
return false;
});
$(document).mouseup(function(){
clearInterval(timeout);
return false;
});
See this demo: http://jsfiddle.net/8FmRd/
A small modification to the original answer:
$('#Clicker').mousedown(function () {
//do something here
timeout = setInterval(function () {
//do same thing here again
}, 500);
return false;
});
$('#Clicker').mouseup(function () {
clearInterval(timeout);
return false;
});
$('#Clicker').mouseout(function () {
clearInterval(timeout);
return false;
});
With the mouseout event on the Clicker it stops when you move your mouse out of the click area.
The reason why I suggest to do the same thing twice is to get a smoother effect. If you don't do it once before the timeout is set it will be a delay of, in this case, 500ms before something happens.
Here's a pure JavaScript implementation of the supplied solutions which has extended support for touch screens. You supply the id, action to perform (function(){}) and the interval (ms) to repeat the action. Note that this implementation will also execute the action immediately, rather than waiting for the interval to lapse.
// Configures an element to execute a function periodically whilst it holds the user's attention via a mouse press and hold.
function assertPeriodicPress(id, action, interval) {
// Listen for the MouseDown event.
document.getElementById(id).addEventListener('mousedown', function(ev) { action(); timeout = setInterval(action, interval); return false; }, false);
// Listen for mouse up events.
document.getElementById(id).addEventListener('mouseup', function(ev) { clearInterval(timeout); return false; }, false);
// Listen out for touch end events.
document.getElementById(id).addEventListener('touchend', function(ev) { clearInterval(timeout); return false; }, false);
}
$.fn.click2=function(cb,interval){
var timeout;
if(!interval) interval=100;
$(this).mousedown(function () {
var target=this;
timeout = setInterval(function(){
cb.apply(target);
}, interval);
return false;
}).mouseup(function () {
clearInterval(timeout);
return false;
}).mouseout(function () {
clearInterval(timeout);
return false;
});
}