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;
});
}
Related
I want to click on a point and delete it, but when i press my mouse button down for 3 seconds, i want to do something else with this point. My problem is, that the code doesnt clear the timer, it just deletes the point after 3 seconds, no matter how long i clicked it on the point.
Im working with setTimeout and clearTimeout.
function click(event,d){
timer= setTimeout(function(){
/* do something */
},3000)
}
function clickRelease(timer){
clearTimeout(timer)
}
divMag1=d3.selectAll(".scatterlayer .trace .points path ")
divMag1.on("mousedown", click)
divMag1.on("mouseup",clickRelease)```
V3 - I think you're deleting the target before you can execute what you want.
Note that setTimout may take more than 3 seconds to execute.
Try:
function click(event) {
const currentTarget = event.currentTarget; // for some reason event.target is null in the timer handler, this fixes it 🤷
const timer = setTimeout(() => {
currentTarget.removeEventListener('mouseup', deleteTarget);
console.log('stuff');
// do stuff
}, 3000);
function deleteTarget() {
clearTimeout(timer);
console.log('deleted');
currentTarget.removeEventListener('mouseup', deleteTarget); // not required if you're actually deleting the target
// remove target
}
currentTarget.addEventListener('mouseup', deleteTarget);
}
document.querySelector('#but').addEventListener('mousedown', click)
<button id="but">Click</button>
V1:
let timer;
function click(event,d){
timer= setTimeout(function(){
/* do something */
},3000);
}
function clickRelease(){
clearTimeout(timer)
}
divMag1=d3.selectAll(".scatterlayer .trace .points path ")
divMag1.on("mousedown", click)
divMag1.on("mouseup",clickRelease)
You should first declare timer variable. Then to make your mouseup event works on you should wrap clickRelease to event funtion again or use it simply:
...
.addEventListener("mouseup", function() { clearTimeout(timer) })
Working example with button:
var timer
function click(event, d) {
timer = setTimeout(function () {
console.log('do something')
}, 1000)
}
function clickRelease(timer){
clearTimeout(timer)
}
var divMag1 = document.querySelector('#but')
divMag1.addEventListener("mousedown", click)
document.addEventListener("mouseup", function() { clickRelease(timer) })
<button id="but">Click</button>
If you want event to doing something repeatedly while button is down you need to use setInterval not setTimeout like this:
var timer
function click(event, d) {
timer = setInterval(function () {
console.log('do something')
}, 1000)
}
var divMag1 = document.querySelector('#but')
divMag1.addEventListener("mousedown", click)
document.addEventListener("mouseup", function() { clearInterval(timer) })
Note for clearing interval uses clearInterval not clearTimeout. Also the mouseup event handler attached on whole document in my solution not on button.
I am chaging the background of the page using mousewheel. I only want to trigger the mousewheel event once 1000ms, so for that I am using a debounce function.
Before I added the debounce function and used e.preventDefault() it prevented the scroll from working. However, now that I have added the debounce function this no longer works and the user can scroll the page again.
Please see code below.
$(document).ready(function() {
$(document).on('mousewheel DOMMouseScroll',debounce(function(e){
e.preventDefault();
//code to change the background image
}, 1000))
});
function debounce(fn, delay) {
var timer = null;
return function () {
var context = this, args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
};
then build it like this:
$(document).ready(function() {
var changeBackground = debounce(function(e){
//code to change the background image
}, 1000)
$(document).on('mousewheel DOMMouseScroll',debounce(function(e){
e.preventDefault();
changeBackground(e);
})
});
Here is my code:
var mouseDown = false;
document.body.onmousedown = function() {
console.log("MOUSE DOWN");
mouseDown = true;
increaseRad();
}
document.body.onmouseup = function() {
console.log("MOUSE UP");
mouseDown = false;
}
function increaseRad(){
rad = 0;
while(mouseDown){
console.log("mouse is still down");
rad++;
console.log(rad)
}
}
When I press down, increaseRad is run, but the while loop inside never ends.
Any idea why?
The problem here is that your code runs as a blocking loop.
while(mouseDown){
console.log("mouse is still down");
rad++;
console.log(rad)
}
The browser evaluates Javascript in a single thread and this loop will never pause to let the browser process those event handlers.
Instead you can use just use asynchronous functions to listen for mousedown events, then start a timer. If the mouse is still down when the timer finishes, then you can count it as a long click.
var mouseIsDown = false;
window.addEventListener('mousedown', function() {
mouseIsDown = true;
setTimeout(function() {
if(mouseIsDown) {
// mouse was held down for > 2 seconds
}
}, 2000);
});
window.addEventListener('mouseup', function() {
mouseIsDown = false;
});
These asynchronous actions (addEventListener, setTimeout) won't block the main thread.
If you click serveral times in a row, you get a wrong click & hold. Better solution is...
var mouseIsDown = false;
var idTimeout;
window.addEventListener('mousedown', function() {
mouseIsDown = true;
idTimeout = setTimeout(function() {
if(mouseIsDown) {
// mouse was held down for > 2 seconds
}
}, 2000);
});
window.addEventListener('mouseup', function() {
clearTimeout(idTimeout);
mouseIsDown = false;
});
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);
});
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);
};