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>
Related
i have e video that i am scrolling with my mousewheel.
Everything is working fine but i would like to check if the user is still scrolling and if it is not so after 10 seconds i would like the video/scrollposition to set-back to zero.
The set-back is working but it is not happing after the "Interval". It is jumping back immediately.
This is my code so far:
const action = document.querySelector(".action");
const video = action.querySelector("video");
//Scroll Magic scenes
const controller = new ScrollMagic.Controller();
let scene = new ScrollMagic.Scene({
duration: 200000, //64000
triggerElement: action,
triggerHook: 0
})
.addIndicators()
.setPin(action)
.addTo(controller);
//Scroll Magic video animation
let accelAmount = 0.1;
let scrollpos = 0;
let currentTime = video.currentTime;
let lastcurrentTime;
let delay = 0;
scene.on("update", e => {
scrollpos = e.scrollPos / 3000; //the higher the number, the slower
});
//Move
setInterval(() => {
delay += (scrollpos - delay) * accelAmount;
video.currentTime = delay;
console.log(video.currentTime + " reading");
lastcurrentTime = video.currentTime;
}, 33.3);
//check if is still scrolling after x seconds
setInterval(checkTime, 10000);
//funktion to execute the check
function checkTime() {
console.log("waiting for new reading");
console.log(video.currentTime + " newreading");
currentTime = video.currentTime;
if (currentTime === lastcurrentTime) {
//is not scrolling -- go to start
//video.currentTime = 0;
window.scrollTo(0, 0);
}
}
You are updating the lastcurrentTime every 33.3ms and you're calling checkTime every 10s. So almost every time you call the checkTime, the lastcurrentTime will be synced with the video.currentTime.
I think that I would try something like this:
let setbackTimeout
scene.on("update", e => {
clearTimeout(setbackTimeout);
scrollpos = e.scrollPos / 3000; //the higher the number, the slower
setbackTimeout = setTimeout(checkTime, 10000);
});
every time you get an update you clear the countdown to setback and create another that you execute 10s later.
Listen to the scroll event listener. With a debounce-like function you can start a timeout that will run whenever the use stops scrolling.
The example below uses the aformentioned technique and shows a message whenever the user stops scrolling for 1 second.
function scrollTracker(delay, callback) {
let timeout = null;
return function(...args) {
if (timeout !== null) {
clearTimeout(timeout);
timeout = null;
}
timeout = setTimeout(callback, delay, ...args)
};
}
const tracker = scrollTracker(1000, () => {
console.log('User stopped scrolling. Handle your video here');
});
window.addEventListener('scroll', tracker);
#page {
height: 20000px;
}
<div id="page"></div>
I think your concept is wrong. I made a little demo how to implement it. It will print the message after 4 sec "inactivity" on button.
const btn = document.querySelector("button")
let myInterval = setInterval(myPrint, 4000)
btn.addEventListener("click", () => {
clearInterval(myInterval)
myInterval = setInterval(myPrint, 4000)
})
function myPrint(){
clearInterval(myInterval)
console.log("programming <3")
}
<button>Click me!</button>
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>
Having issues of removing an interval within the same function.
The code I have set up is as follow:
let $start = document.querySelector('#start');
let $stop = document.querySelector('#stop');
function myFn() {
let t = event.target.id;
let logsetInterval = setInterval(() => {
console.log('interval running');
}, 2000);
if (t === "stop") {
clearInterval(logsetInterval);
}
}
$stop.addEventListener('click', function() {
myFn()
});
$start.addEventListener('click', function() {
myFn()
});
<button id="start">start</button>
<button id="stop">stop</button>
I need it to be within the same function...
What am I doing wrong here.
Your problem sounds like coming from the scope of your function and the global mechanics around it
Every time you call your function myFn a new interval is created, either it's a start or a stop. And it only clear when it's a stop one.
You should probably set your interval as a global variable and only then modify it.
let $start = document.querySelector('#start');
let $stop = document.querySelector('#stop');
let logsetInterval;
function myFn() {
let t = event.target.id;
if (logsetInterval) clearInterval(logsetInterval); // if interval already exists, clean it
logsetInterval = setInterval(() => {
console.log('interval running');
}, 2000);
if (t === "stop") {
clearInterval(logsetInterval);
}
}
$stop.addEventListener('click', function() {
myFn()
});
$start.addEventListener('click', function() {
myFn()
});
Hope I understood your problem right
This code should run for 10 seconds before ending, however if you are running the function again before the 10 seconds are finished, it should clear theTimeout and start the 10 seconds over again
function start() {
let counter = 0;
let timeUp = true;
let hello;
setInterval(()=> {
counter++
console.log(counter)
},1000);
if (timeUp == false) {
clearTimeout(hello)
timeUp = true
console.log('should run again with new clock')
start()
} else {
console.log('new clock started')
timeUp = false;
hello = setTimeout(() => {
timeUp = true
console.log('end clock')
}, 10000);
};
};
When you call start() again, this new function has no reference to hello or timeUp
Try it like this:
let hello
let timeUp = true
function start() {
let counter = 0;
//let timeUp = true;
//let hello;
setInterval(()=> {
counter++
console.log(counter)
},1000);
if (timeUp == false) {
clearTimeout(hello)
timeUp = true
console.log('should run again with new clock')
start()
} else {
console.log('new clock started')
timeUp = false;
hello = setTimeout(() => {
timeUp = true
console.log('end clock')
}, 10000);
};
};
window.start = start
Inside your function start, timeUp is always set to true, and thus clearTimeout will never be called. The way you're doing things, you should make timeUp a global variable so the function has "memory" of if the time has been reached or not.
But why do you need to set two intervals? You're already keeping track of the number of seconds that have passed, so we can make use of that interval to determine when 10 seconds have passed. This simplifies things quite a bit, and allows us to get rid of the timeUp variable as well:
let interval;
function start() {
let counter = 0;
clearInterval(interval); // clear the previous interval
interval = setInterval(() => { // set a new interval
counter++;
if (counter == 10) {
console.log('end of clock');
clearInterval(interval);
}
console.log(counter);
}, 1000);
}
This achieves exactly what you want. Whenever start is called, it cancels the previous interval and creates a new one. Once 10 seconds have passed, it clears the interval.
Your approach is kind of misleading. I think a better approach would be to have a Timer Object that you can start:
function Timer() {
var self = {
// Declare a function to start it for a certain duration
start: function(duration){
self.counter = 0;
self.duration = duration;
clearTimeout(self.timeout); // Reset previous timeout if there is one
console.log("New counter starting.");
self.count();
},
// A function to count 1 by 1
count: function(){
console.log(self.counter);
self.counter++;
if(self.counter > self.duration){
console.log('Time is up.');
} else {
self.timeout = setTimeout(self.count, 1000); // not over yet
}
}
// and other functions like stop, pause, etc if needed
};
return self;
}
// Declare your Timer
var myTimer = new Timer();
// Start it on click
document.getElementById('start-btn').addEventListener('click', function(){
myTimer.start(10);
}, true);
<button id="start-btn">Start the timer</button>
I'm trying to create a simple countdown timer. It counts down from the number entered.
However, I'm trying to clear the interval when the counter gets to 0. At the moment it seems to acknowledge the if statement, but not clearInterval().
http://jsfiddle.net/tmyie/cf3Hd/
$('.click').click(function () {
$('input').empty();
var rawAmount = $('input').val();
var cleanAmount = parseInt(rawAmount) + 1;
var timer = function () {
cleanAmount--;
if (cleanAmount == 0) {
clearInterval(timer);
}
$('p').text(cleanAmount);
};
setInterval(timer, 500);
})
You're not saving the return value of the call to setInterval, which is the value that needs to be passed to clearInterval. Passing the timer handler does no good.
var timer, timerHandler = function () {
cleanAmount--;
if (cleanAmount == 0) {
clearInterval(timer);
}
$('p').text(cleanAmount);
};
timer = setInterval(timerHandler, 500);