Javascript click and hold on element using setTimeout
I need to have some functionality in my web app where a specific action occurs when the user clicks and holds on an element. Think of it like the long press on Android.
I have my div:
<div id="myDiv"
onmousedown="press()"
onmouseup="cancel()"
onmouseout="cancel()"
onmousemove="cancel()">Long Click Me</div>
and my javascript:
var down = false;
function press()
{
down = true;
setTimeout(function() { action(); }, 1500);
}
function cancel()
{
down = false; // this doesn't happen when user moves off 开发者_高级运维div while holding mouse down!
}
function action()
{
if (!down)
return; // if the flag is FALSE then do nothing.
alert("Success!");
down = false;
}
This works as long as all I do is press and hold on the element. I have the onmouseout
and onmousemove
events to call cancel() because I want the user to have the option to change their mind and move the mouse off the element before action() starts.
Unfortunately, it seems that my code does not do this. In fact, if the use clicks down for a moment, moves the mouse off the div and releases before the 1.5 sec then action() won't bail out as expected.
Edit: Thanks for your input everyone but it turns out I'm just a little bit special and didn't see that I forgot a capital letter in my HTML in my onmouseout. The sample code I gave above should work exactly as expected.
Of course action() is still called. You didn't actually cancel the setTimeout()
function. I would suspect that maybe in your real code, you have a scoping issue and maybe aren't testing the same version of the done
variable that you think you are.
A better way than using the down
flag would be to keep track of the return value from setTimeout()
and actually cancel the timer in the cancel()
function. Then, action()
will never fire when you don't want it to. I think it's also technically a more correct behavior when you mouseout to cancel any chance of the timer firing.
Also, there is no such thing as:
bool down = false;
in javascript. It would have to be:
var down = false;
I would recommend this code:
var downTimer = null;
function down()
{
cancel();
downTimer = setTimeout(function() { action(); }, 1500);
}
function cancel()
{
if (downTimer)
{
clearTimeout(downTimer);
downTimer = null;
}
}
function action()
{
downTimer = null;
alert("Success!");
}
You also need to clear the timeout in your cancel function - otherwise it will still fire - as you initiated it in the down function.
so..
bool down = false;
//your timeout var
var t;
function down()
{
down = true;
t = setTimeout(function() { action(); }, 1500);
}
function cancel()
{
down = false;
clearTimeout(t);
}
function action()
{
if (!down)
return;
alert("Success!");
down = false;
}
There are several things wrong with your code as I see it.
First
bool down = false;
is not valid JavaScript. It should be
var down = false;
Then you have two variables called down
: the boolean value and the function. The function will overwrite the variable, until as such time that you execute one of the statements that sets down
to true or false.
As others have said: once set, the deferred function will continue to be executed 1.5 seconds later, unless you cancel the timeout. But then again it doesn't matter, since you do check to see if the mouse button is down before doing anything.
So I'd say rename the boolean variable to isMouseDown
or something and try again.
to cancel the timeout in the cancel() function, use
var mytimer = null;
function ondown(){mytimer = setTimeOut('action()', 1500;)}
function cancel(){clearTimeout(mytimer);}
function action(){mytimer=null; alert('success!');}
also note that you used down
first as a variable end then as a function... Calling if(!down)
will always return false because down
refers to a function.
精彩评论