I wrote a timer code via JavaScript. I want to stop this timer when I click on a button, and restart it by double clicking the same button, however, it currently only works once.
Here is the code:
let pElement = document.createElement('p');
document.body.appendChild(pElement);
let liveTimer = () => {
let date = new Date();
let onlineTime = date.toLocaleTimeString();
pElement.innerHTML = onlineTime;
};
let setI = setInterval(liveTimer, 1000);
function stopTime() {
clearInterval(setI);
}
function startTimer() {
setInterval(liveTimer, 1000);
}
<button onclick="stopTime()" ondblclick="startTimer()">click me</button>
You forgot to set the interval-Id the second time you are calling setInterval inside the startTimer function.
Just because you set the value here let setI= setInterval(liveTimer,1000);, doesn't mean that the value will get refreshed when you do setInterval(liveTimer,1000);. This will return a different value that you need to store inside a variable.
let pElement = document.createElement('p');
document.body.appendChild(pElement);
let liveTimer = () => {
let date = new Date();
let onlineTime = date.toLocaleTimeString();
pElement.innerHTML = onlineTime;
};
let setI = setInterval(liveTimer, 1000);
function stopTime() {
clearInterval(setI);
}
function startTimer() {
setI = setInterval(liveTimer, 1000);
}
<button onclick="stopTime()" ondblclick="startTimer()">click me</button>
Related
I want to build a stopWatch. You can start and pause. My approach. I start a setInterval and when pause is clicked, I delete the intervalID and set intervalID (global) to zero. However, the interval is not deleted. What am I doing wrong? I suspect that I am assuming something wrong. I expect the interval ID after clear and restart to be the same and not the next higher number. I use Firefox on OS.
My code:
const o = document.querySelector("div");
const b = document.querySelector("button");
let intervalID = null;
let timer;
b.addEventListener("click", () => {
if (intervalID !== null) {
console.log("instance already running lets clear Interval by IntervalIdD");
clearInterval(intervalID);
console.log("interval_cleared",intervalID);
intervalID = null;
return;
}
intervalID = setInterval(function() {
console.log(123)
}, 1000);
console.log("interval",intervalID);
})
<div>0</div>
<button>Start / Stop</button>
Since your interval is globally defined and you are able to clear it. I do not think there will any intervals running in the background.
Though, you might see different results if its not defined globally, example in react's useEffect method.
Below is the modified example for timer, let me know what you think.
const o = document.querySelector("div");
const b = document.querySelector("button");
let intervalID = null;
let count = 0;
b.addEventListener("click", () => {
if (!intervalID ) {
intervalID = setInterval(function() {
o.innerText = count++;
}, 1000);
return;
}
console.log("instance already running lets clear Interval by IntervalIdD");
console.log("interval_cleared", intervalID );
clearInterval(intervalID );
intervalID = null;
})
<div>0</div>
<button>Start / Stop</button>
Here I'm trying to update working inside the setTimeout it gets updated but the addEventListener still has its old value.
const button = document.getElementById('button');
var working = true;
button.addEventListener('click', function() {
const p = document.getElementById('paragraph');
p.innerText = "Im working on something that you guys can't see";
setTimeout(() => {
working = false
}, 5000);
while (working) {
console.log(working) // This one remains true always.
}
p.textContent = "Im done";
});
The timeout is simply not able to execute due to the while hogging the browser.
Use setInterval for the console.log to see it
const button = document.getElementById('button');
const p = document.getElementById('paragraph');
let working = true;
button.addEventListener('click', function() {
p.innerText = "I'm working on something that you guys can't see";
setTimeout(() => {
working = false
}, 5000);
let tId = setInterval(() => {
console.log(working)
if (!working) {
p.textContent = "I'm done";
clearInterval(tId)
}
},100);
});
<button id="button">Click</button>
<p id="paragraph"></p>
To hog on purpose for a time, test in the hogging loop
const button = document.getElementById('button');
const p = document.getElementById('paragraph');
button.addEventListener('click', function() {
p.textContent = "I'm working on something that you guys can't see";
setTimeout(() => {
let endTime = new Date()
endTime.setSeconds(endTime.getSeconds() + 5)
while (true) {
let now = new Date()
if (now.getTime() - endTime.getTime() >= 5000) {
p.textContent = "I'm done";
break;
}
}
}, 10)
});
<button id="button">Click</button>
<p id="paragraph"></p>
when i click my button, a timer is supposed to display a countdown timer. But the button does not work.
let timerCounter = document.getElementById("timer-counter");
let timer;
let timerCount;
function startTimer() {
timer = setInterval(function() {
timerCount--;
timerElement.textContent = "Time; " + timerCount;
if (timerCount === 0) {
clearInterval(timer);
}
});
}
startButton.addEventListener("click", startTimer);
This is what I found so far:
You are decrementing the timerCount, need to specify the initial value for it to work.
You're using timerElement instead of timerCounter that you've declared.
You must pass the second args to the setInterval which is delay.
const timerCounter = document.getElementById('timer-counter');
const startButton = document.getElementById('start-button');
let timer;
let timerCount = 30;
startButton.addEventListener('click', startTimer);
function startTimer() {
timer = setInterval(function () {
timerCount--;
timerCounter.textContent = 'Time; ' + timerCount;
if (timerCount === 0) {
clearInterval(timer);
}
}, 1000);
}
<div id="timer-counter"></div>
<button id="start-button">Start</button>
Here's a slightly different approach that avoids some of the problems with global variables. The function the listener calls initialises the count, and then returns a new function (a closure) that is called when the button is clicked. It also uses setTimeout which I find more easy to understand.
// Cache your elements
const counter = document.querySelector('#counter');
const startButton = document.querySelector('button');
// Initialise your count variable
function startTimer(count = 30) {
// Return a function that is called from
// the listener
return function loop () {
// Disabled the button once it's been clicked
if(!startButton.disabled) startButton.disabled = true;
counter.textContent = `Time: ${count}`;
if (count > 0) {
setTimeout(loop, 500, --count);
}
}
loop();
}
// Call startTimer to initialise the count, and return
// a new function that is used as the listener
startButton.addEventListener('click', startTimer(), false);
<div id="counter"></div>
<button>Start</button>
I'm sure this could be improved.
In this example we don't go below 0.
We don't allow timeout collisions ( timeouts don't stack causing weird counting speeds ).
We can reset to the original number when on 0.
const c = document.getElementById('timer-counter')
const b = document.getElementById('start-button')
let timer = false
let timerCount = 30
b.addEventListener('click', start)
function decrement() {
if(timerCount < 0) {
timerCount = 30
timer = false
return
}
c.innerText = `Count: ${timerCount}`
timerCount--
timer = setTimeout(decrement, 200)
}
function start() {
if(timer) return
decrement()
}
<div id="timer-counter"></div>
<button id="start-button">Start</button>
I am working on a HTML customelement, but when I run it in the browser, I get a very interesting error. This is the code:
class clock extends HTMLElement {
constructor() {
super()
this.time = new Date(this.getAttribute('time'));
this.span = document.createElement('span')
this.appendChild(this.span)
}
Timer() {
let Now = this.time;
let Seconds = Now.getSeconds();
let Minutes = Now.getMinutes();
let Hours = Now.getHours();
Minutes = Minutes < 10 ? "0" + Minutes : Minutes;
document.getElementById("digitalClock").textContent = Hours + ":" + Minutes;
}
connectedCallback(){
this.span.innerHTML = `...<span id="digitalClock"></span>`;
this.Timer();
this.myClockTimer = setInterval(this.Timer, 5000);
}
disconnectedCallback(){
clearInterval(this.myClockTimer);
}
}
customElements.define('worktime-clock', clock)
When I run this, the Timer function runs well when calling with this.Timer() in the connectedCallback function, but one line after, when it gets into a cycle, it says that Now is undefined in Timer function. It seems like there is a problem about calling it in setinterval, however, the function is definitely running again and again as expected. Does someone know what is the problem?
You lose the correct this context by passing the Timer function as a callback. As a result this (within the callback) now points to window instead. You can use bind to set the this-context:
this.myClockTimer = setInterval(this.Timer.bind(this), 5000);
This accomplishes the same thing:
var that = this;
this.myClockTimer = setInterval(function() { that.Timer(); }, 5000);
Another alternative:
this.myClockTimer = setInterval(function() { this.Timer(); }.bind(this), 5000);
Or an arrow function
<script>
customElements.define('worktime-clock', class extends HTMLElement {
updateTime() {
let Now = new Date();
const pad = x => String(x).padStart(2,'0');
const H = pad(Now.getHours());
const M = pad(Now.getMinutes());
const S = pad(Now.getSeconds());
this.innerHTML = `${H}:${M}:${S}`;
}
connectedCallback() {
this.myClockTimer = setInterval(() => {
this.updateTime();
}, 1e3);
}
})
</script>
<worktime-clock>21:22:23</worktime-clock>
Or for a code-golf competition
<script>
customElements.define('worktime-clock', class extends HTMLElement {
connectedCallback() {
setInterval(() => {
this.innerHTML = new Date().toString().split` `[4];
}, 1e3);
}
})
</script>
<worktime-clock>21:22:23</worktime-clock>
I am new to OOP in Javascript or jQuery, I am trying to clear the interval and stop any methods inside the interval, it seems not working with what I did below.
function Timer() {
var sec = $('.timer #second');
this.runTimer = function(_currentime) {
var currentTimeing = parseInt($(_currentime).text());
this.timeInterval = setInterval(function() {
$('.projects li span.second').text(currentTimeing++)
}, 1000);
$("#stop").click(function() {
// clear interval
clearInterval(this.timeInterval);
})
}
}
var play = new Timer();
$("#start").click(function(){
//console.log(this.runTimer())
play.runTimer('#second');
})
You are using this in context of different functions, that's why it's not working fine. Try:
function Timer() {
var sec = $('.timer #second');
this.runTimer = function(_currentime) {
var currentTimeing = parseInt($(_currentime).text()), that = this;
that.timeInterval = setInterval(function(){
$('.projects li span.second').text(currentTimeing ++)
}, 1000);
$("#stop").click(function(){
// clear interval
clearInterval(that.timeInterval);
})
}
}
var play = new Timer();
$("#start").click(function(){
//console.log(this.runTimer())
play.runTimer('#second');
})
I'm simply saving reference to correct this in that variable, so I can later use it to clear interval.
function Timer() {
var sec = $('.timer #second');
var timeinterval; // declare timeinterval variable here
this.runTimer = function(_currentime) {
var currentTimeing = parseInt($(_currentime).text());
timeInterval = setInterval(function(){
$('.projects li span.second').text(currentTimeing ++)
}, 1000);
$("#stop").click(function(){
// clear interval
clearInterval(timeInterval);
})
}
}
var play = new Timer();
$("#start").click(function(){
//console.log(this.runTimer())
play.runTimer('#second');
})