Reputation: 495
I have a javascript function that goes like this:
$(document).keydown(function(e) {
switch(e.which) {
case 38:
moveUp();
break;
case 40:
moveDown();
break;
}
});
function moveDown() {
$('element').animate({top: "100%"}, {duration: 1000 });
}
function moveUp() {
$('element').animate({top: "-100%"}, {duration: 1000 });
}
My question is how would I create a delay in the keydown
function that tells it that it has to wait until the function moveUp()/movedown()
is finished before calling the function again without creating a queue?
Thank you for all the advise, by the way, I cant use setTimeout
because it would cause a delay on every initial function.
Upvotes: 2
Views: 395
Reputation: 42044
I may suggest you to set a data attribute.
The animate has a complete callback. So before starting the animation you may set the attribute to false and when the animation is completed you may reset to true this attribute.
This attribute can be tested in the keydown event to decide if it's right to continue.
$(function () {
// set the data attribute to true
$(document).data('isAnimateCompleted', true);
$(document).keydown(function(e) {
// if false return
if ($(document).data('isAnimateCompleted') == false) {
return;
}
switch(e.which) {
case 38:
moveUp();
break;
case 40:
moveDown();
break;
}
});
function moveDown() {
// before starting set to false
$(document).data('isAnimateCompleted', false);
$('#element').animate({top: "100px"}, 1000, function() {
// when completed set to true
$(document).data('isAnimateCompleted', true);
});
}
function moveUp() {
$(document).data('isAnimateCompleted', false);
$('#element').animate({top: "0px"}, 1000, function() {
$(document).data('isAnimateCompleted', true);
});
}
});
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<div id="element" style="position: fixed;top: auto;">This is an element</div>
Another possibility is to use the jQuery animated selector to test if the animation is in progress avoiding at all global variables.
Upvotes: 0
Reputation: 6433
Here's easy solution.
var flag = true;
$(document).keydown(function(e) {
if(flag == true){
switch (e.which) {
case 38:
moveUp();
break;
case 40:
moveDown();
break;
}
}
});
function moveDown() {
$('#elem').animate({
top: "100px"
}, {
duration: 1000,
start: function(){ flag=false; },
complete: function(){flag=true; }
});
}
function moveUp() {
$('#elem').animate({
top: "0px"
}, {
duration: 1000,
start: function(){ flag=false; },
complete: function(){flag=true; }
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="background: green; width: 100px; height: 100px; position:absolute;" id="elem">
</div>
Upvotes: 3
Reputation: 60143
Assuming you want keypresses to have no effect at all while an animation is in progress, this should help. When the animation is about to start, I set a variable called inProgress
to true
. I set it back to false
in the completed handler for the animation. In the keydown handler, I check that flag, and if an animation is in progress, I ignore the key.
var position = 50;
var inProgress = false;
function move() {
inProgress = true;
$('#box').animate({ top: position + 'px', duration: 1000 }, function () {
inProgress = false;
});
}
$(document).keydown(function(e) {
if (inProgress) {
return;
}
switch(e.which) {
case 38:
e.preventDefault();
position -= 10;
move();
break;
case 40:
e.preventDefault();
position += 10;
move();
break;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box" style="position:absolute;top:50px;background-color:blue;width:50px;height:50px"></div>
Upvotes: 3
Reputation: 974
This should help you, I used the complete function of the animate to execute the next action as soon as it's finish animating.
var isAnimating = false;
var callAfterFinish = undifined;
$(document).keydown(function(e) {
switch(e.which) {
case 38:
moveUp();
break;
case 40:
moveDown();
break;
}
});
function moveDown() {
if(!isAnimating){
$('element').animate({top: "100%"}, {duration: 1000 },function(){
if(!callAfterFinish) {
callAfterFinish();
callAfterFinish = undifined;
}
isAnimating = false;
});
isAnimating = true;
} else if(!callAfterFinish) {
callAfterFinish = moveDown;
}
}
function moveUp() {
if(!isAnimating){
$('element').animate({top: "-100%"}, {duration: 1000 },function(){
if(!callAfterFinish) {
callAfterFinish();
callAfterFinish = undifined;
}
isAnimating = false;
});
isAnimating = true;
} else if(!callAfterFinish) {
callAfterFinish = moveUp;
}
}
Upvotes: 3