Failed to start countdown for the second time during operation - javascript

I am using the following code and giving a second click to the same start countdown button not clean the first process, so there are two counts at the same time. How do I stop the first process when the second start?
Thank you very much in advance.
function countdown(element, minutes, seconds) {
// Fetch the display element
var el = document.getElementById(element);
// Set the timer
var interval = setInterval(function() {
if(seconds == 0) {
if(minutes == 0) {
(el.innerHTML = "STOP!");
clearInterval(interval);
return;
} else {
minutes--;
seconds = 60;
}
}
if(minutes > 0) {
var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
} else {
var minute_text = '';
}
var second_text = seconds > 1 ? '' : '';
el.innerHTML = minute_text + ' ' + seconds + ' ' + second_text + '';
seconds--;
}, 1000);
}
//Start as many timers as you want
var start1 = document.getElementById('timer1');
var start2 = document.getElementById('timer2');
start1.onclick = function() {
countdown('countdown1', 0, 15);
}
start2.onclick = function() {
countdown('countdown2', 0, 10);
}
//extra button and counter
<div id='countdown1'></div>
<div id='countdown2'></div>
<input id="timer1" type="button" value="Start timer 1" />
<input id="timer2" type="button" value="Start timer 2" />

You could save the interval variable as an attribute of the countdown element. Then, at the beginning of the countdown function, check if the interval attribute has been defined for that element. If so, call clearInterval on it before starting a new interval.

clearInterval(intervalvalue)
will be helpful to .
Working code here

Related

How to end my countdown timer when a button is clicked?

I'm trying to create a function that will end a countdown timer, or automatically make the minutes and seconds part of the countdown timer === 0; however, it seems that using clearInterval(time) doesn't seem to work! Could anyone point out how I might be able to achieve what I'm trying to do!
Note that I've made startingMinutes = 1 just for my ease.
Below is the countdown function and HTML:
// FUNCTION - countDown function that counts down from 8 minutes
const startingMinutes = 1;
let time = startingMinutes * 60;
function updateCountDown() {
const minutes = Math.floor(time / 60);
let seconds = time % 60;
seconds = seconds < 1 ? '0' + seconds : seconds;
document.getElementById("countdown").innerHTML = `${minutes}:${seconds}`;
time--;
time = time < 0 ? 0 : time;
if (minutes == 0 && seconds == 0) {
document.getElementById('tableStyle').style.display = "block";
document.getElementById('wordsIncluded').style.display = "block";
document.getElementById('show_header_one').style.display = "block";
recognition.abort(); //speech recognition stops when countdown timer ends
isListening = false;
}
//my attempt at clearing the countdowntimer!
window.addEventListener('DOMContentLoaded', function() {
document.getElementById("submit_button").addEventListener("click", function() {
clearInterval(time);
})});
HTML:
//where the countdown timer is displayed
<div id="circle"><p id="countdown">8:00</p></div>
//Click the below button and the countdown timer will end (minutes === 0 and seconds === 0)
<button id="submit_button" type="submit">Click to Submit</button>
To use clearInterval you need to pass it the value returned by setInterval
I have an example below using your code, where I pass the value from "setInterval" which I call "interval" to a function "stop" which calls "clearInterval" to stop the timer, and runs the code you were running.
let isListening = true;
const recognition = { abort: () => console.log('aborted') };
function updateCountDown(time) {
const minutes = Math.floor(time / 60);
const seconds = time % 60;
const timer = document.getElementById("countdown");
timer.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
function start(time) {
const interval = setInterval(() => {
if (--time) updateCountDown(time);
else stop(interval);
}, 1000);
document.getElementById("submit_button")
.addEventListener("click", () => stop(interval))
}
function stop(interval) {
updateCountDown(0); // This line sets time to 0
clearInterval(interval);
foo()
}
// I assume you want this to happen when the timer runs down or the button is clicked
function foo() {
document.getElementById('tableStyle').style.display = "block";
document.getElementById('wordsIncluded').style.display = "block";
document.getElementById('show_header_one').style.display = "block";
recognition.abort(); //speech recognition stops when countdown timer ends
isListening = false;
}
start(8*60)
#tableStyle, #wordsIncluded, #show_header_one { display: none; }
<p id="tableStyle">Table Style</p>
<p id="wordsIncluded">Words Included</p>
<p id="show_header_one">Show Header One</p>
<div id="circle">
<p id="countdown">8:00</p>
</div>
<button id="submit_button" type="submit">Click to Submit</button>
const startingMinutes = 1;
let time = startingMinutes * 60;
var abort_count_down = true;
function updateCountDown() {
if (abort_count_down) {
const minutes = Math.floor(time / 60);
let seconds = time % 60;
seconds = seconds < 1 ? '0' + seconds : seconds;
document.getElementById("countdown").innerHTML = `${minutes}:${seconds}`;
time--;
time = time < 0 ? 0 : time;
if (minutes == 0 && seconds == 0) {
document.getElementById('tableStyle').style.display = "block";
document.getElementById('wordsIncluded').style.display = "block";
document.getElementById('show_header_one').style.display = "block";
recognition.abort(); //speech recognition stops when countdown timer ends
isListening = false;
}
};
//my attempt at clearing the countdowntimer!
window.addEventListener('DOMContentLoaded', function() {
document.getElementById("submit_button").addEventListener("click", function() {
abort_count_down = false;
})});

Why does enabling timer to auto start disable my stop and reset buttons?

Thanks for any help here, not sure what's going on - but when I enable the timer(); line in order to automatically start the timer when the page is loaded, it disables the stop and reset buttons. I tried to only include relevant code here. Can anyone shed some light on why this is happening? Thank you in advance!
const startstop = () => {};
var clicks = 0;
function onClick() {
clicks += 1;
document.getElementById("clicks").innerHTML = clicks;
};
const input = parseInt(prompt("Enter a SAMS number: "));
var SAMSINPUT = input;
//console.log(SAMSINPUT);
document.getElementById('output').innerHTML = SAMSINPUT;
var goal = 0;
//var SAMSINPUTtest = parseInt(document.getElementById("input"));
//setInterval(function doIncrement() {
// goal += 1;
//}, SAMSINPUT * 1000); // *1000 to convert from seconds to milliseconds
var output2 = document.getElementById('output2');
setInterval(function doIncrement() {
goal += 1;
output2.innerHTML = goal.toString();
}, SAMSINPUT * 1000)
var timerDiv = document.getElementById('timerValue'),
start = document.getElementById('start'),
stop = document.getElementById('stop'),
reset = document.getElementById('reset'),
t;
// Get time from cookie
var cookieTime = null; //getCookie('time'); // for test
// If timer value is saved in the cookie
if (cookieTime != null && cookieTime != '00:00:00') {
var savedCookie = cookieTime;
var initialSegments = savedCookie.split('|');
var savedTimer = initialSegments[0];
var timerSegments = savedTimer.split(':');
var seconds = parseInt(timerSegments[2]),
minutes = parseInt(timerSegments[1]),
hours = parseInt(timerSegments[0]);
timer();
document.getElementById('timerValue').textContent = savedTimer;
$('#stop').removeAttr('disabled');
$('#reset').removeAttr('disabled');
} else {
var seconds = 0,
minutes = 0,
hours = 0;
timerDiv.textContent = "00:00:00";
}
// New Date object for the expire time
var curdate = new Date();
var exp = new Date();
// Set the expire time
exp.setTime(exp + 2592000000);
function add() {
seconds++;
if (seconds >= 60) {
seconds = 0;
minutes++;
if (minutes >= 60) {
minutes = 0;
hours++;
}
}
timerDiv.textContent = (hours ? (hours > 9 ? hours : "0" + hours) : "00") +
":" + (minutes ? (minutes > 9 ? minutes : "0" + minutes) : "00") +
":" + (seconds > 9 ? seconds : "0" + seconds);
// Set a 'time' cookie with the current timer time and expire time object.
var timerTime = timerDiv.textContent.replace("%3A", ":");
//console.log('timerTime', timerTime);
//setCookie('time', timerTime + '|' + curdate, exp);
timer();
}
function timer() {
t = setTimeout(add, 1000);
}
timer(); // autostart timer
/* Start button */
start.onclick = timer;
/* Stop button */
stop.onclick = function() {
clearTimeout(t);
}
/* Clear button */
reset.onclick = function() {
timerDiv.textContent = "00:00:00";
seconds = 0;
minutes = 0;
hours = 0;
//setCookie('time', "00:00:00", exp);
}
/**
* Javascript Stopwatch: Button Functionality
*
*/
$('#start').on('click', function() {
$('#stop').removeAttr('disabled');
$('#reset').removeAttr('disabled');
});
$('#stop').on('click', function() {
$(this).prop('disabled', 'disabled');
});
$('#reset').on('click', function() {
$(this).prop('disabled', 'disabled');
});
/**
* Javascript Stopwatch: Cookie Functionality
*
*/
function setCookie(name, value, expires) {
document.cookie = name + "=" + value + "; path=/" + ((expires == null) ? "" : "; expires=" + expires.toGMTString());
}
function getCookie(name) {
var cname = name + "=";
var dc = document.cookie;
if (dc.length > 0) {
begin = dc.indexOf(cname);
if (begin != -1) {
begin += cname.length;
end = dc.indexOf(";", begin);
if (end == -1) end = dc.length;
return unescape(dc.substring(begin, end));
}
}
return null;
}
body {
background-color: powderblue;
}
p {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body onload="startstop();">
<p> SAMS VALUE:
<a id="output"></a>
</p>
<p> GOAL:
<a id="output2"></a>
</p>
<button style="background-color:green" type="button" onClick="onClick()">ACTUAL</button>
<p>Actual Count: <a id="clicks">0</a></p>
<div class="container">
<div class="row">
<div class="col-sm-4"></div>
<div class="col-sm-4">
<div id="timeContainer" class="well well-sm">
<time id="timerValue"></time>
</div>
<div id="timerButtons">
<button id="start" class="btn btn-success">START</button>
<button id="stop" class="btn btn-danger" disabled="disabled">STOP</button>
<button id="reset" class="btn btn-default" disabled="disabled">RESET</button>
</div>
<div class="col-sm-4 col-sm-4 col-md-4"></div>
</div>
</div>
</div>
</body>

How can I modify my function to be able to cancel the interval from anywhere in the controller

I am trying to create a countdown and I want to be able to cancel the interval not only when reach 0 but with clicking of a button as well.How can I modify my function to be able to cancel the interval from anywhere in the controller.
function countDown(total) {
total = total * 60;
var interval = $interval(function () {
var minutes = Math.floor(total / 60);
var seconds = total - minutes * 60;
if (minutes < 1)
{
minutes = '0:';
}
else
{
minutes = minutes + ':';
}
if (seconds < 10)
{
seconds = '0' + seconds;
}
self.remainingTime = "Remaining time: " + minutes + seconds;
total--;
if(minutes === '0:' && seconds === '00')
{
$interval.cancel(interval);
}
}, 1000);
}
As suggested by other users, you should make interval global in the controller. Then on the other functions you want to cancel the interval you can call it safely.
Take a look at the below sample:
angular.module('app', [])
.controller('ctrl', function($interval) {
var self = this;
var interval;
self.wizard = {
startInterval: startInterval,
cancelInterval: cancelInterval
};
startInterval();
return self.wizard;
function startInterval() {
countDown(24);
}
function cancelInterval() {
$interval.cancel(interval);
}
function countDown(total) {
cancelInterval();
total = total * 60;
interval = $interval(function() {
var minutes = Math.floor(total / 60);
var seconds = total - minutes * 60;
if (minutes < 1) {
minutes = '0:';
} else {
minutes = minutes + ':';
}
if (seconds < 10) {
seconds = '0' + seconds;
}
self.wizard.remainingTime = "Remaining time: " + minutes + seconds;
total--;
if (minutes === '0:' && seconds === '00') {
$interval.cancel(interval);
}
}, 1000);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<span ng-app="app" ng-controller="ctrl as ctrl">
<span ng-bind="ctrl.remainingTime"> </span>
<br/>
Cancel Interval
<br/>
Start Interval
</span>
I created an example using self instead of $scope like you are in your snippet above. As others mentioned moving the interval var to the global scope fixes this. I also added a stop and start function to test the issue you mentioned in the example above.
UPDATED - I added some code to the stop interval to reset the interval to undefined. I found an example of this usage on Angular's site so it might be worth a try to see if it fixes your other issue.
var app = angular.module('app', []);
app.controller('BaseController', function($interval) {
var self = this;
var interval;
function countDown(total) {
total = total * 60;
interval = $interval(function() {
var minutes = Math.floor(total / 60);
var seconds = total - minutes * 60;
if (minutes < 1) {
minutes = '0:';
} else {
minutes = minutes + ':';
}
if (seconds < 10) {
seconds = '0' + seconds;
}
self.remainingTime = "Remaining time: " + minutes + seconds;
total--;
if (minutes === '0:' && seconds === '00') {
$interval.cancel(interval);
}
}, 1000);
}
self.stopInterval = function(){
if (angular.isDefined(interval)) {
$interval.cancel(interval);
interval = undefined;
}
}
self.startInterval = function(){
countDown(10);
}
});
Then in the html I added a button to start and stop the interval like so:
<body ng-app="app">
<div ng-controller="BaseController as baseCtrl">
{{ baseCtrl.remainingTime }}
<div>
<button ng-click="baseCtrl.startInterval()">Start Countdown</button>
<button ng-click="baseCtrl.stopInterval()">Stop Countdown</button>
</div>
</div>
</body>
You can view the codepen example here

how to set the same id for multiple element in html

I want to use countdown timer for 10 element that creating at run time. each element has expire time so I want to show user how much time of of the expiration is remained.so I use a jquery file to do this .so I must use an id for a tag to show the remained time .when I use it for one element it works fine but when I use it for multiple element it just works for first element.how can I solve this problem to show the remained time for all elements
Jquery file
//var count = 1000;
//var counter = setInterval(timer, 1000);
//function timer() {
// count -= 1;
// if (count==1000) {
// clearInterval(counter);
// }
// document.getElementById("num").innerHTML = count;
//}
function CountDown() {
this.start_time = "02:00:00:23";
this.target_id = "#timer";
this.name = "timer";
}
CountDown.prototype.init=function(){
this.reset();
setInterval(this.name+'.tick()',1000);
}
CountDown.prototype.reset=function(){
time = this.start_time.split(":");
this.days = parseInt(time[0]);
this.hours = parseInt(time[1]);
this.minutes=parseInt(time[2]);
this.seconds = parseInt(time[3]);
this.update_target();
}
CountDown.prototype.tick=function(){
if (this.seconds > 0 || this.minutes > 0 || this.hours > 0 ||this.days>0) {
if (this.hours == 0 && this.minutes == 0 && this.seconds == 0) {
this.days = this.days - 1;
this.hours = 23;
this.minutes = 59;
this.seconds = 59;
}
if (this.minutes == 0 && this.seconds==0) {
this.hours = this.hours - 1;
this.minutes = 59;
this.seconds = 59;
}
else if (this.seconds == 0) {
this.minutes = this.minutes - 1;
this.seconds = 59;
}
else {
this.seconds = this.seconds - 1;
}
}
this.update_target();
}
CountDown.prototype.update_target = function () {
seconds = this.seconds;
minutes = this.minutes;
hours = this.hours;
days = this.days;
if (seconds<10)
seconds = "0"+seconds;
if (minutes < 10)
minutes = "0"+ minutes;
if (hours < 10)
hours = "0" + hours;
if (days < 10)
days = "0" + days;
$(this.target_id).val(days+":"+hours+":"+minutes + ":" + seconds)
// $(this.target_id).val(this.minutes+":"+seconds)
}
Html
<script src="~/Scripts/jquery-1.4.4.min.js"></script>
<script src="~/Scripts/countdown.js"></script>
<input type="text" id="timer" value=" " />
<script>
timer = new CountDown();
timer.init();
</script>
Id is unique in html use class instead .. more element can have the same class
$('.yourClass')
instead of
$('#yourId')
.
<script src="~/Scripts/jquery-1.4.4.min.js"></script>
<script src="~/Scripts/countdown.js"></script>
<input type="text" class="timer" value=" " />
<script>
timer = new CountDown();
timer.init();
</script>
function CountDown() {
this.start_time = "02:00:00:23";
this.target_id = ".timer";
this.name = "timer";
}
EDIT :
I've created a JSFiddle for it, can you precise your request ?
See it here
I changed this :
timer = new CountDown("02:00:00:23");
timer.init();
And this function :
function CountDown(start_time) {
this.start_time = start_time;
this.target_id = ".timer";
this.name = "timer";
}
Id's are unique and should only be used once in an html page. Also, and element should only have a single ID. Classes are not unique so multiple elements can have the same class, also, a single element can have multiple classes. Example:
<div class="exampleClass anotherClass"></div>
<div class="exampleClass></div>
<div class="exampleClass></div>
Instead of id="timer" use class="timer" then in your javascript file use $(".timer") to target those classes. So in your case instead of this.target_id = "#timer" use this.target_id =".timer";
Here's a good reference for classes and ids.

Getting different values from a span

I want to create a website with multiple countdowns activated by a click, some of them have different time, others the same. When one finish I need to return it to his original countdown value, so you will be able to click it again.
I have the times (in seconds) inside a span .time, and that's how I get the time for the countdowns, however I don't know how to save the original time, so when one is clicked I get as "original time" always the first span .time.
Here is my code: http://jsfiddle.net/arglab/m19aojmu/16/
Javascript
function timer(selector) {
var description = ["seconds","hour"]
var self = $(selector);
var sec = parseInt(self.find('span.timeout').text());
console.log(sec)
order++;
var actualTime = $('span.timeout').html();
console.log("Original time " + actualTime)
self.addClass('selec').css('order',order+'');
var interval = setInterval(function() {
sec--;
console.log(sec)
if (sec >= 0) {
var hours = Math.floor(sec / 3600);
var min = Math.floor((sec - (hours*3600)) / 60);
var seconds = Math.floor(sec % 60);
var value = seconds;
if(min > 0) {
if(min == 1) {
value = " minute " + value;
} else {
value = " minutes " + value;
}
value = min + value;
}
if(hours > 0) {
if(hours == 1) {
value = " hour " + value;
} else {
value = " hours " + value;
}
value = hours + value;
}
self.find('span.timeout').text(value);
self.find('span.timeout').text(value);
} else if($(this).find('span').text() <= 0) {
console.log(sec)
var text = self.find('span.timeout').text(actualTime);
console.log(actualTime)
clearInterval(interval);
}
$('.element').each(function(){
if($(this).find('span').text() == 0){
$(this).removeClass('selec');
$(this).css('order','0');
}
});
}, 1000);
}
var order = 1;
$("body").on('click', '.element', function() {
timer(this);
});
HTML
<div id="container">
<div class="element" id="el1"><b>element 1</b> <span class="timeout">1000</span> seconds (1000)</div>
<div class="element" id="el2"><b>element 2</b> <span class="timeout">5</span> seconds (5)</div>
<div class="element" id="el3"><b>element 3</b> <span class="timeout">10</span> seconds (10)</div>
<div class="element" id="el4"><b>element 4</b> <span class="timeout">15</span> seconds (15)</div>
<div class="element" id="el5"><b>element 5</b> <span class="timeout">10</span> seconds (10)</div>
</div>
As you can see, if you click a 10 seconds countdown, when it finish his time isn't 10 seconds (as it should be) but, in this case, 1000 (first span .time)
What can I do? Thanks
You need to use self in your timer function.
Find the comments in the below code,
function timer(selector) {
var description = ["seconds", "hour"]
var self = $(selector);
var sec = parseInt(self.find('span.timeout').text());
console.log(sec)
order++;
var actualTime = self.find('span.timeout').html(); // use self.find here
console.log("Original time " + actualTime)
self.addClass('selec').css('order', order + '');
var interval = setInterval(function () {
sec--;
console.log(sec)
if (sec >= 0) {
var hours = Math.floor(sec / 3600);
var min = Math.floor((sec - (hours * 3600)) / 60);
var seconds = Math.floor(sec % 60);
var value = seconds;
if (min > 0) {
if (min == 1) {
value = " minute " + value;
} else {
value = " minutes " + value;
}
value = min + value;
}
if (hours > 0) {
if (hours == 1) {
value = " hour " + value;
} else {
value = " hours " + value;
}
value = hours + value;
}
self.find('span.timeout').text(value);
// remove the below redundant line
//self.find('span.timeout').text(value);
} else if (self.find('span').text() <= 0) { //use self not this
console.log(sec);
var text = self.find('span.timeout').text(actualTime);
console.log(actualTime)
clearInterval(interval);
}
$('.element').each(function () {
if ($(this).find('span').text() == 0) {
$(this).removeClass('selec');
$(this).css('order', '0');
}
});
}, 1000);
}
Live Demo
When registereing your onclick handler, you should pass another object to the timer function:
$("body").on('click', '.element', function(eve) {
timer(eve.target);
});

Categories

Resources