Cardio app: clear timer for interval located in function scope - javascript

Here is Cardio app on CodePen.
http://codepen.io/Mahmoud-Zakaria/pen/vxWzxW?editors=1010
When I want to stop the cardio by stop btn and clear its interval which its refernce in function scope, It doesn't stop/clear.
(function() {
//States
let i = 5;
let play = true;
//DOM
let cardioSec = document.getElementById('cardio-sec');
let cardioStart = document.getElementById('cardio-start');
let cardioStop = document.getElementById('cardio-stop');
//Render
function render(el) {
el.innerHTML = i
};
//Audio
let audio = new Audio("https://raw.githubusercontent.com/mahmoudZakaria90/myCodePenStuff/master/audio/Bepp-beep.mp3");
//Setup
function setInterVals(times, callback) {
i = times;
let timer = setInterval(function() {
console.log(i) //RENDER
render(cardioSec)
i--;
if (i < 1) {
clearInterval(timer);
audio.play();
callback();
}
}, 1000)
return timer;
}
function start() {
setInterVals(5, cardio);
}
function cardio() {
setInterVals(30, rest);
}
function rest() {
setInterVals(15, cardio);
}
function stopCardio() {
clearInterval(setInterVals())
}
cardioStart.onclick = start
cardioStop.onclick = stopCardio
})();

Done:
http://codepen.io/anon/pen/gmdLMr?editors=1010
The "timer" variable was out of the scope, by declaring it as global, you wont have problems ^^

Related

How to use setTimeout without using setTimeout function

Is there a way to use setTimeout without using setTimeout inbuilt function?
I don't want to use setInterval or clearInterval either or window.use. I have gone through multiple blogs, but all those use window, setInterval or clearInterval.
For example, the below code works, but I dont want to have window.
const setTimeouts = [];
function customSetTimeout(cb, interval) {
const now = window.performance.now();
const index = setTimeouts.length;
setTimeouts[index] = () => {
cb();
};
setTimeouts[index].active = true;
const handleMessage = (evt) => {
if (evt.data === index) {
if (window.performance.now() - now >= interval) {
window.removeEventListener('message', handleMessage);
if (setTimeouts[index].active) {
setTimeouts[index]();
}
} else {
window.postMessage(index, '*');
}
}
};
window.addEventListener('message', handleMessage);
window.postMessage(index, '*');
return index;
}
const setIntervals = [];
function customSetInterval(cb, interval) {
const intervalId = setIntervals.length;
setIntervals[intervalId] = function () {
if (setIntervals[intervalId].active) {
cb();
customSetTimeout(setIntervals[intervalId], interval);
}
};
setIntervals[intervalId].active = true;
customSetTimeout(setIntervals[intervalId], interval);
return intervalId;
}
function customClearInterval(intervalId) {
if (setIntervals[intervalId]) {
setIntervals[intervalId].active = false;
}
}
console.log("1");
customSetTimeout(function() {
console.log('3s');
}, 3000);
console.log("2");
=======================================
Alternate solution:
But here, again i dont want to use clearInterval and setInterval
var setMyTimeOut = function(foo,timeOut){
console.log('inside time out');
var timer;
var currentTime = new Date().getTime();
var blah=()=>{
if (new Date().getTime() >= currentTime + timeOut) {
console.log('clear interval if');
clearInterval(timer);
foo()
}
console.log('clear interval else');
}
timer= setInterval(blah, 100);
}
console.log("1");
setMyTimeOut(function() {
console.log('3s');
}, 3000);
console.log("2");
Is there way to achieve the same but without the use setInterval and clearInterval?
I use here the requestAnimationFrame with performance.now().
Its not super exact (well setTimeout neither), but it do the work.
function sleep(delay, cb) {
function check(time, delay) {
if(time >= delay) {
cb("done");
return;
}
time = performance.now();
requestAnimationFrame(check.bind(null, time,delay))
}
check(performance.now(), delay + performance.now());
}
sleep(4000, ()=> {
console.log("sleep done");
})
console.log("i do not block the main thread");
You can use a while loop which checks a set time against the current time:
const startTime = new Date().getTime() + 3000;
let currentTime = new Date().getTime();
function customTimeout() {
while (startTime > currentTime) {
currentTime = new Date().getTime();
}
return console.log('3 Seconds')
};
customTimeout();

how can I re-call this function? not experienced with ES6

I don't know how to call counter() a second time after it runs on page load
I made a new "instance" of the counter, I think. And this does work but there must be a correct way. I need to call it in replay()
/**
* #fileoverview demo
*/
class ReVideo {
constructor() {
this.time = 5;
...
this.timer = document.getElementById("update");
this.counter = setInterval(() => this.countdown(), 1000);
this.fader = fader();
this.counter2 = "";
...
this.retry.addEventListener('click', () => this.replay());
...
}
countdown() {
this.time--;
if (this.time > -1) {
this.timer.innerHTML = "seconds remaining: " + this.time;
} else {
this.timer.innerHTML = "You Lose!";
this.watch.style.display = "block";
this.retry.style.display = "block";
clearInterval(this.counter);
clearInterval(this.counter2);
this.coins++;
this.coinCount.innerHTML = "Coins: " + this.coins;
}
this.notice.style.visibility = "visible";
this.notice.innerHTML = "Loaded";
}
...
replay() {
this.time = 5;
this.watch.style.display = "none";
this.notice.style.visibility = "hidden";
fader("Loaded");
this.retry.style.display = "none";
this.counter2 = setInterval(() => this.countdown(), 1000);
this.counter2;
}
...
}
new ReVideo();
It does not run if i say counter();
You could have a helper counter function to return the intervalID like:
counter () {
const interval = setInterval(() => this.countdown(), 1000);
return interval;
}
and in your constructor, you could assign the intervalID to some variable like:
this.interval = counter();
Then you can stop the counter by passing the variable holding the intervalID like clearInterval(this.interval);

How to decrement given time

I am getting an output of 00:20:00 which is correct but my problem now is its not decrementing even when I have subtracted it am i missing something?
$duration=0;
$startime=date('Y-m-d H:i:s');
$end_time=$end_time=date('Y-m-d H:i:s',
strtotime('+'.$duration.'minutes',strtotime($startime)));
$timefirst=strtotime($startime);
$timesecond=strtotime($end_time);
$differenceinseconds=$timesecond-$timefirst;
echo gmdate("H:i:s", $differenceinseconds);
my script
<div id='response'></div>
<script type="text/javascript">
setInterval(function(){
var xmlhttp=new XMLHttpRequest();
xmlhttp.open("GET",'responseTime.php',false);
xmlhttp.send(null);
document.getElementById('response').innerHTML=xmlhttp.responseText;
},1000);
</script>
As RiggsFolly mentioned why waste servers time running a timer.
Here is what you can do in javascript,
<div id="stopwatch"></div>
<script>
var Stopwatch = function (elem, target, options) {
var timer = createTimer(),
offset,
clock,
interval;
// default options
options = options || {};
options.delay = options.delay || 1;
// append elements
elem.appendChild(timer);
// initialize
reset();
// private functions
function createTimer() {
var interval = 20 ; // 20 seconds
var element = document.createElement("progress");
element.setAttribute("max",interval);
return element;
}
function start() {
if (!interval) {
offset = Date.now();
interval = setInterval(update, options.delay);
}
}
function stop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function reset() {
clock = 0;
render();
}
function update() {
clock += delta();
render();
}
function render() {
timer.value = parseInt(clock / 1000);
if(timer.value==interval){
// This is the point where timer ends, put your further code in here.
}
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
// public API
this.start = start;
this.stop = stop;
this.reset = reset;
};
var elem = document.getElementById("stopwatch");
var timer = new Stopwatch(elem, {delay: 10});
timer.start();
</script>

Stopping a Javascript setInterval that is delayed by a setTimeout

I'm having issue with this jsfiddle snippet:
http://jsfiddle.net/y45jN/7/
var mainFunction = function() {
this.text;
this.repeater;
}
var repeatEvery = function(func, interval) {
var now = new Date();
var delay = interval - now % interval;
function start() {
var intervalID = setInterval(func, interval);
func(intervalID);
}
setTimeout(start, delay);
};
mainFunction.prototype.start = function(printText) {
this.text = printText;
var self = this;
var func = function(intervalID) {
if(intervalID){
this.repeater = intervalID;
}
document.getElementById('test').innerHTML += this.text + '<br/>';
};
repeatEvery(_.bind(func, this),1000);
}
mainFunction.prototype.stop = function() {
clearInterval(this.repeater);
}
var test = new mainFunction();
test.start('hello');
setTimeout(test.stop,10000);
My goal is to call the stop function and stop the Interval that has been set by the start function.
You need to do
setTimeout(function(){ test.stop()}, 10000)
or
setTimeout(test.stop.bind(test), 10000); //Bind method is not available in IE8 though
instead of
setTimeout(test.stop, 10000);
The reason for this is that Javascript loses track of the "this" when you pass a callback to a function.

how to clear all javascript Timeouts?

i have a loop function that in first 5 seconds it runs social1() and in second 5 seconds it runs social2() then loop ...
i have 2 hover functions too
i need clear all active timeouts because when i hover on images (.social1 & .social2), i can see that multiple timeouts are running
how to fix this?
function social1() {
$('.social1').fadeTo(500, 1);
$('.social2').fadeTo(500, 0.5);
timeout = setTimeout(function() {
social2();
}, 5000);
}
function social2() {
$('.social1').fadeTo(500, 0.5);
$('.social2').fadeTo(500, 1);
timeout = setTimeout(function() {
social1();
}, 5000);
}
$(document).ready(function ()
{
social1();
$('.social1').hover(
function () {
window.clearTimeout(timeout);
social1();
},
function () {
timeout = setTimeout(function() {
social2();
}, 5000);
}
);
$('.social2').hover(
function () {
window.clearTimeout(timeout);
social2();
},
function () {
timeout = setTimeout(function() {
social1();
}, 5000);
}
);
__EDIT__
To manage a collection of timeouts (and intervals), you could use following snippet.
This will allow to clear any timeouts or intervals set anywhere in code, although, you have to set this snippet before setting any timeout or interval. Basically, before processing any javascript code or external script which uses timeout/interval.
JS:
;(function () {
window.timeouts = {},
window.intervals = {},
window.osetTimeout = window.setTimeout,
window.osetInterval = window.setInterval,
window.oclearTimeout = window.clearTimeout,
window.oclearInterval = window.clearInterval,
window.setTimeout = function () {
var args = _parseArgs('timeouts', arguments),
timeout = window.osetTimeout.apply(this, args.args);
window.timeouts[args.ns].push(timeout);
return timeout;
},
window.setInterval = function () {
var args = _parseArgs('intervals', arguments),
interval = window.osetInterval.apply(this, args.args);
window.intervals[args.ns].push(interval);
return interval;
},
window.clearTimeout = function () {
_removeTimer('timeouts', arguments);
},
window.clearInterval = function () {
_removeTimer('intervals', arguments);
},
window.clearAllTimeout = function () {
_clearAllTimer('timeouts', arguments[0]);
},
window.clearAllInterval = function () {
_clearAllTimer('intervals', arguments[0]);
};
function _parseArgs(type, args) {
var ns = typeof args[0] === "function" ? "no_ns" : args[0];
if (ns !== "no_ns")[].splice.call(args, 0, 1);
if (!window[type][ns]) window[type][ns] = [];
return {
ns: ns,
args: args
};
}
function _removeTimer(type, args) {
var fnToCall = type === "timeouts" ? "oclearTimeout" : "oclearInterval",
timerId = args[0];
window[fnToCall].apply(this, args);
for (var k in window[type]) {
for (var i = 0, z = window[type][k].length; i < z; i++) {
if (window[type][k][i] === timerId) {
window[type][k].splice(i, 1);
if (!window[type][k].length) delete window[type][k];
return;
}
}
}
}
function _clearAllTimer(type, ns) {
var timersToClear = ns ? window[type][ns] : (function () {
var timers = [];
for (var k in window[type]) {
timers = timers.concat(window[type][k]);
}
return timers;
}());
for (var i = 0, z = timersToClear.length; i < z; i++) {
_removeTimer(type, [timersToClear[i]]);
}
}
}());
How to use it:
Set timeout(s)/interval(s) as usual:
var test1 = setTimeout(function(){/**/, 1000);
var test2 = setTimeout(function(){/**/, 1000);
Then you could use to clear both:
clearAllTimeout(); // clearAllInterval(); for intervals
This will clear both timeouts (test1 & test2)
You can use some namespaces to clear only specific timers, e.g:
// first (optional) parameter for setTimeout/setInterval is namespace
var test1 = setTimeout('myNamespace', function(){/**/, 1000); // 'myNamespace' is current namespace used for test1 timeout
var test2 = setTimeout(function(){/**/, 1000); // no namespace used for test2 timeout
Again, clearAllTimeout(); will clear both timeouts. To clear only namespaced one, you can use:
clearAllTimeout('myNamespace'); // clearAllInterval('myNamespace'); for namespaced intervals
This will clear only test1 timeout
You could for some reason wish to delete non namespaced timeouts only. You could then use:
clearAllTimeout('no_ns'); // clearAllInterval('no_ns'); for non namespaced intervals only
This will clear only test2 timeout in this example
See jsFiddle DEMO
__END of EDIT__
Old post specific to opening question here:
You could try that:
var timeouts = [];
timeouts.push(setTimeout(function() {
social2();
}, 5000));
timeouts.push(setTimeout(function() {
social1();
}, 5000));
//etc...
function clearAllTimeouts(){
for(var i = 0, z = timeouts.length; i < z; i++)
clearTimeout(timeouts[i]);
timeouts = [];
}
UPDATED following David Thomas comment
var timeouts = {'social' : [], 'antisocial' : []};
//a social timeout
timeouts.social.push(setTimeout(function() {
social1();
}, 5000));
//an anti-social timeout
timeouts.antisocial.push(setTimeout(function() {
antisocial1();
}, 5000));
function clearTimeouts(namespace){
for(var i = 0, z = timeouts[namespace].length; i < z; i++)
clearTimeout(timeouts[namespace][i]);
timeouts[namespace] = [];
}
//usage e.g
clearTimeouts("social");
//Incase if you are looking for full fledged code
var dict = {};
function checkForIntervals(id){
var index = index;
var result = findOrAddProperty(id);
if(result.length != 0){
clearTimeoutsFor(id);
}
dict[id].push(setTimeout(function(){alertFunc(id,index);}, 60000));
};
// to clear specific area timeout
function clearTimeoutsFor(namespace){
for(var i = 0, z = dict[namespace].length; i < z; i++)
clearTimeout(dict[namespace][i]);
dict[namespace] = [];
}
to clear all timeouts
function clearAllTimeOuts(){
for (key in dict) {
for(var i = 0, z = dict[key].length; i < z; i++)
clearTimeout(dict[key][i]);
dict[key] =[];
}
};
function findOrAddProperty(str){
var temp = [];
for (key in dict) {
if(key == str){
if (dict.hasOwnProperty(key)) {
temp = dict[key];
break;
}
}
}
if(temp.length == 0){
dict[str] = [];
}
return temp;
};
function alertFunc(id,index) {
jQuery(document).ready(function($) {
do the ajax call here after 1 min
});
};

Categories

Resources