问题
It's a follow up to this question - https://stackoverflow.com/a/33430608/3766930 Basically I have a text area and when user starts typing in sth, the counter starts going down from 3 to 0. when it reaches 0 it gets disabled.
Now I want to add a feature of starting over - when user clicks the link start over
, text area goes enabled again and user has 3 seconds (again) to perform the input.
I modified the jquery script:
$('#textArea').on('input propertychange', display30Seconds);
var interval;
function display30Seconds() {
var validTime = 3000;
if (!interval)
interval = setInterval(function () {
$('#counter').html(validTime / 1000);
validTime = validTime - 1000;
if (validTime < 0) {
clearInterval(interval);
alert('Time Up!');
$('#textArea').prop('disabled', true);
$('#counter').html('<a href="#" id="counterIsDone">start over</a>');
$('#counterIsDone').on('click', function(){
$('#textArea').prop('disabled', false);
display30Seconds();
});
}
}, 1000);
}
but I see that I cannot call the method display30Seconds();
again. Or rather I can, but the interval is not set again. How can I fix it?
Seems like I'm not entering the code inside
if (!interval)
because the interval is not visible any more after clearing it (?). So I thought about moving the var interval;
into the body of the method function display30Seconds() {
, but that doesn't bring the expected effect. Is there a way of fixing it?
Here is my updated fiddle: http://jsfiddle.net/jf4ea4nx/3/
回答1:
Set interval=null
after the clearInterval()
call.
What seems to confuse you is the semantics of clearInterval(interval)
. As Patrick Evans points out in his comment, it will not set interval
to a value that evaluates to false
in a condition.
To make it completely clear you could use a boolean variable such as countdownRunning
in addition to the interval
variable to keep track of whether the countdown is active or not.
回答2:
Try this:
$('#textArea').on('input propertychange', display30Seconds);
var interval=false;
function display30Seconds() {
var validTime = 3000;
if (!interval)
interval = setInterval(function () {
$('#counter').html(validTime / 1000);
validTime = validTime - 1000;
if (validTime < 0) {
clearInterval(interval);
alert('Time Up!');
$('#textArea').prop('disabled', true);
$('#counter').html('<a href="#" id="counterIsDone">start over</a>');
$(document).on('click','#counterIsDone', function(){
$('#textArea').prop('disabled', false);
display30Seconds();
});
interval=false;
}
}, 1000);
}
回答3:
You can improve your code by using a conditional recursive call to to your iterative function instead - each call has a one second delay, which makes it slightly more intuitive to use (think of each call as one tick):
var seconds = 3;
$('#textArea').on('input propertychange', setTimeout(timeout.bind(null, seconds), 1000));
function timeout (iterations) {
$('#counter').html(iterations);
if (iterations === 0) {
alert('Time Up!');
$('#textArea').prop('disabled', true);
$('#counter').html('<a href="#" id="counterIsDone">start over</a>');
$('#counterIsDone').on('click', function(){
$('#textArea').prop('disabled', false);
timeout(seconds);
});
}
else {
setTimeout(timeout.bind(null, --iterations), 1000);
}
}
The bind
function simply binds the arguments of the bind
function to the arguments of the timeout
call - the first argument to the bind function declares its this
scope; but don't worry about that too much.
You can modify the duration of the timer by changing the seconds
var. Hope this helps :)
来源:https://stackoverflow.com/questions/33435439/how-can-i-depend-on-the-interval-that-i-just-cleared-in-jquery