Instead of listening for click, do this:
- Listen for
mousedown and mouseup.
- On
mousedown, perform the action and set a timer to perform it again in a moment via setTimeout. Remember the timer handle (the return value).
- When the timer goes off and you do the action again, schedule it to happen again in a moment, again via
setTimeout, again remembering the handle.
- When you see
mouseup, cancel the outstanding timer using the handle with clearTimeout.
Example:
var pos = 1;
var handle = 0;
function move(delta) {
$('.box').css({'left': pos += delta });
}
function moveRight() {
move(1);
clearTimeout(handle); // Just in case
handle = setTimeout(moveRight, 50);
}
function moveLeft() {
move(-1);
clearTimeout(handle); // Just in case
handle = setTimeout(moveLeft, 50);
}
$('.right').on("mousedown", moveRight);
$('.left').on("mousedown", moveLeft);
$('.left, .right').on("mouseup", function() {
clearTimeout(handle);
handle = 0;
});
.box{
background-color: gray;
height:20px;
width: 20px;
left: 0;
position: relative;
margin-top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<button class="left" button-held>Left</button>
<button class="right" button-held>Right</button>
<div class="box"></div>
In a comment you've said:
I just noticed a bug within this, if I leave one of the buttons pressed, and then slide out of it while still keeping it pressed and then releasing it, it move the box indefinitely until you press again one of the buttons, do you maybe know why this is happening?
It's because we're only listening for mouseup on the button, so when you release it, we don't get that event. Silly mistake on my part. :-)
Two solutions:
Either listen for mouseup on document, or
Listen for mouseleave on the button as well as mouseup.
I think #1 is probably best, especially since when I just tried it on Chrome, it even gracefully handled the case where I pressed the mouse down over the button, then slid it right out of the browser window entirely (!) and released it. Chrome still gave us the mouseup on `document. :-)
Implementing #1 is just a matter of hooking mouseup on document instead of .left, .right:
var pos = 1;
var handle = 0;
function move(delta) {
$('.box').css({'left': pos += delta });
}
function moveRight() {
move(1);
clearTimeout(handle); // Just in case
handle = setTimeout(moveRight, 50);
}
function moveLeft() {
move(-1);
clearTimeout(handle); // Just in case
handle = setTimeout(moveLeft, 50);
}
$('.right').on("mousedown", moveRight);
$('.left').on("mousedown", moveLeft);
// ONLY CHANGE is on the next line
$(document).on("mouseup", function() {
clearTimeout(handle);
handle = 0;
});
.box{
background-color: gray;
height:20px;
width: 20px;
left: 0;
position: relative;
margin-top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<button class="left" button-held>Left</button>
<button class="right" button-held>Right</button>
<div class="box"></div>
Implementing #2 is just a matter of adding mouseleave to the mouseout handler; but note that the button retains its "pushed" appearance even though we stop doing the movement as soon as the mouse leaves the button:
var pos = 1;
var handle = 0;
function move(delta) {
$('.box').css({'left': pos += delta });
}
function moveRight() {
move(1);
clearTimeout(handle); // Just in case
handle = setTimeout(moveRight, 50);
}
function moveLeft() {
move(-1);
clearTimeout(handle); // Just in case
handle = setTimeout(moveLeft, 50);
}
$('.right').on("mousedown", moveRight);
$('.left').on("mousedown", moveLeft);
// ONLY CHANGE is on the next line
$('.left, .right').on("mouseup mouseleave", function() {
clearTimeout(handle);
handle = 0;
});
.box{
background-color: gray;
height:20px;
width: 20px;
left: 0;
position: relative;
margin-top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<button class="left" button-held>Left</button>
<button class="right" button-held>Right</button>
<div class="box"></div>