how to avoid call to postmessage - javascript

In my application I have Count down functionality which uses setInterval as follows :
this.timer = window.setInterval(() => {
const time_delta = (this.target_date - new Date() ) / 1000
if (time_delta > 0) {
this.days = time_delta / (24 * 3600)
this.hour = time_delta % (24 * 3600) / (3600)
this.minute = (time_delta % (24 * 3600) % (3600)) / 60
this.second = time_delta % 60
} else {
this.days = 0
this.hour = 0
this.minute = 0
this.second = 0
}
if(time_delta <= 1 && time_delta > 0 ){
clearInterval(this.timer);
location.reload();
}
},10000)
Now there is another functionality which has completely different functionality and it inherits postmessage
(function (window, undefined) {
function MessageChannel(group, targetWindow, origin) {
this._msgNo = 1;
this._group = group;
this._origin = '*' || origin;
this._requestHandler = {};
this._messageQueue = {};
this._targetWindow = targetWindow || window.parent;
window.addEventListener('message', receiveMessage.bind(this), false);
}
MessageChannel.prototype.subscribeRequestMessage = function (msg, callback) {
// Some logic
};
MessageChannel.prototype.unsubscribeRequestMessage = function (msg, callback) {
// Some logic
};
MessageChannel.prototype.postMessage = function (msg, data, timeout) {
// Some logic
};
function receiveMessage(event) {
// Some logic
}
window.Granite = window.Granite || {};
window.Granite.author = window.Granite.author || {};
window.Granite.author.MessageChannel = MessageChannel;
}(this));
The problem I have is that whenever the setInterval executes in every seconds in the Count down timer then the MessageChannel.prototype.postMessage function also executes.
The Count down timer is a component present within an iFrame of a html page and this page also have the code of MessageChannel.prototype.postMessage and its available globally by the framework/tool I am using to build my page. Whenever there is a change in the component then MessageChannel.prototype.postMessage is triggered by the framework. In this case the timer value changes which triggers postMessage call.
I do not want MessageChannel.prototype.postMessage code to execute. How can I avoid this?

Related

Why can't I change this global variable from function? (JavaScript)

Simple countdown project.
Desired outcome:
global variable determines default time.
then slider value overrides that variable.
PROBLEM: slider value changes locally but global value stays the same.
I've watched tutorials all day on variable scopes and still don't see what's wrong because:
Global is declared with "var" outside function: var initialMinutes = 5
attempt to update value inside function looks like this:
const change = slider.addEventListener('change', setMins)
function setMins() {
initialMinutes = slider.value
}
I have also tried with window.variable here and there to no avail.
I hope someone can help. This is becoming difficult to scope with.
const countdown = document.getElementById('countdown')
const slider = document.getElementById('slider')
const startBtn = document.getElementById('btn-startStop')
const resetBtn = document.getElementById('btn-reset')
// Event Listeners
const change = slider.addEventListener('change', setMins)
const start = startBtn.addEventListener('click', startStop)
const reset = resetBtn.addEventListener('click', resetApp)
// Time
var initialMinutes = 15
countdown.innerHTML = initialMinutes+':00'
const initialDuration = initialMinutes * 60
let time = initialMinutes * 60
let interval = null
let status = 'stopped'
function updateCountdown() {
const minutes = Math.floor(time / 60)
let seconds = time % 60
seconds = seconds < 10 ? '0'+ seconds : seconds
if( time < 1) {
clearInterval(interval)
startBtn.innerHTML = 'START'
status = 'stopped'
countdown.innerHTML = `00:00`
} else {
countdown.innerHTML = `${minutes}:${seconds}`
time--;
}
}
function startStop() {
if(status === 'stopped') {
interval = setInterval(updateCountdown, 50)
startBtn.innerHTML = 'STOP'
status = 'running'
} else {
clearInterval(interval)
startBtn.innerHTML = 'START'
status = 'stopped'
}
}
function setMins() {
initialMinutes = slider.value
countdown.innerHTML = slider.value+':00'
}
function resetApp() {
clearInterval(interval);
document.getElementById('countdown').innerHTML = '00:00'
startBtn.innerHTML = 'START'
status = 'stopped'
}
Codepen link included for clarity:
https://codepen.io/donseverino/pen/YzWBJYV
Got it! It was not a problem of scope but of variable assignment.
updateCountdown() uses time and time = initialMinutes * 60
I thought changing initialMinutes would automatically change its value inside time but it doesn't.
Reassigning time inside the function solves it.
function setMins() {
initialMinutes = slider.value
time = initialMinutes * 60
}

How does one refactor best this timer/stopwatch code-base towards a better code-reuse following the OOP paradigm and the DRY principle?

I am having trouble with following OOP in javascript.
How can I make this code more Object-oriented and reusable?
I tried reading up on OOP concepts in JS but couldn't figure a way around making this code be one. Any suggestions?
PS: This is the code for making a stopwatch
//Define variables to hold time values
let seconds = 0;
let minutes = 0;
let hours = 0;
//Define variable to hold "display" value
let interval = null;
//Define variable to hold the clock status
let status = "paused";
//Clock function ( logic to determine when to increment next value, etc.)
function clock() {
seconds++;
//Logic to determine when to increment next value
if (seconds >= 60) {
seconds = 0;
minutes++;
if (minutes >= 60) {
minutes = 0;
hours++;
}
}
//Display updated time values to user
document.getElementById("display").innerHTML =
//If seconds/minutes/hours are only one digit, add a leading 0 to the value
`${hours ? (hours > 9 ? hours : `0${hours}`) : "00"}:${minutes ? (minutes > 9 ? minutes : `0${minutes}`) : "00"}:${seconds > 9 ? seconds : `0${seconds}`}`;
}
function startPause() {
if (status === "paused") {
//Start the stopwatch (by calling the setInterval() function)
interval = window.setInterval(clock, 1000);
document.getElementById("startPause").innerHTML = "Pause";
status = "started";
} else {
window.clearInterval(interval);
document.getElementById("startPause").innerHTML = "Resume";
status = "paused";
}
}
//Function to reset the stopwatch
function reset() {
seconds = 0;
minutes = 0;
hours = 0;
document.getElementById("display").innerHTML = "00:00:00";
document.getElementById("startPause").innerHTML = "Start";
window.clearInterval(interval);
status = "paused";
}
One could use kind of a "component based" approach. The provided example code is pretty straightforward. The constructor does assign all the needed references as public properties to a Stopwatch instance. Getters and setters for reading and writing the component's UI(/DOM) part are implemented as prototypal methods. Helper methods (interval handling, time measure computations) do not need to be part of the class implementation itself, but will be residents of the Stopwatch module scope ...
// module scope of e.g. 'Stopwatch.js' file.
const MEASURE_STATE_RUNNING = 'running';
const MEASURE_STATE_STOPPED = 'stopped';
const UPDATE_CYCLE_MINIMUM = 100; // any value in msec.
const UPDATE_CYCLE_DEFAULT = 200; //
const UPDATE_CYCLE_MAXIMUM = 1000; //
function getDisplayNumber(value) {
return ((String(value).length === 1) && `0${ value }`) || value;
}
function getMeasureInMilliseconds(measure) {
return (((measure.hours * 3600) + (measure.minutes * 60) + measure.seconds) * 1000);
}
function getMeasureFromMilliseconds(value) {
let hours = (value / 3600000);
let minutes = ((hours - Math.floor(hours)) * 60);
let seconds = ((minutes - Math.floor(minutes)) * 60);
hours = Math.floor(hours);
minutes = Math.floor(minutes);
seconds = Math.floor(seconds + 0.001);
seconds = ((seconds < 60) && seconds) || 0;
minutes = ((minutes < 60) && minutes) || 0;
hours = ((hours < 100) && hours) || 0;
return { hours, minutes, seconds };
}
function handleStartStopForBoundStopwatch(/* evt */) {
const stopwatch = this;
if (stopwatch.measureState === MEASURE_STATE_STOPPED) {
stopwatch.startMeasure();
} else {
stopwatch.stopMeasure();
}
}
function updateStopwatchMeasure(stopwatch) {
const dateNow = Date.now();
// has at least one second past since the last measure update?
const isUpdateMeasure = (Math.floor((dateNow - stopwatch.updateTimestamp) / 1000) >= 1);
if (isUpdateMeasure) {
stopwatch.updateTimestamp = dateNow;
// time differences in milliseconds since measuring has been started the last time.
const timePassed = (dateNow - stopwatch.measureTimestamp);
const messureValue = (timePassed + stopwatch.lastMeasuredMSecs);
Object.assign(stopwatch.measure, getMeasureFromMilliseconds(messureValue));
stopwatch.setComponentMeasure();
}
}
class Stopwatch {
constructor(node) {
this.node = node;
this.timerId = null;
this.updateCycle = this.getComponentUpdateCycle();
// for synchronizing display values of a running measure.
this.lastMeasuredMSecs = null;
this.measureTimestamp = null;
this.updateTimestamp = null;
this.measure = this.getComponentMeasure();
this.measureState = this.getComponentMeasureState();
// synchronize component data initially.
this.setComponentMeasure();
this.setComponentMeasureState();
if (this.measureState === MEASURE_STATE_RUNNING) {
this.startMeasure();
}
this.startStopHandler = handleStartStopForBoundStopwatch.bind(this);
node.addEventListener('click', this.startStopHandler);
}
destroy() {
if (this.node) {
this.node.removeEventListener('click', this.startStopHandler);
this.node.remove();
this.node = null;
delete this.node;
}
this.timerId = this.updateCycle = this.lastMeasuredMSecs = null;
this.measureTimestamp = this.updateTimestamp = null;
this.measure = this.measureState = this.startStopHandler = null;
delete this.timerId;
delete this.updateCycle;
delete this.lastMeasuredMSecs;
delete this.measureTimestamp;
delete this.updateTimestamp;
delete this.measure;
delete this.measureState;
delete this.startStopHandler;
}
getComponentMeasure() {
const result =
(/^(?<hours>\d{1,2})\:(?<minutes>\d{1,2})\:(?<seconds>\d{1,2})$/)
.exec(
this.node.dateTime
);
const {
hours,
minutes,
seconds
} = (result && result.groups) || { hours: 0, minutes: 0, seconds: 0 };
return {
hours: parseInt(hours, 10),
minutes: parseInt(minutes, 10),
seconds: parseInt(seconds, 10)
};
}
setComponentMeasure() {
const { hours, minutes, seconds } = this.measure;
const value = [
getDisplayNumber(hours),
getDisplayNumber(minutes),
getDisplayNumber(seconds)
].join(':');
this.node.dateTime = value;
this.node.innerText = value;
}
getComponentMeasureState() {
return (
((this.node.dataset.measureState || '').trim() === 'running')
&& MEASURE_STATE_RUNNING
|| MEASURE_STATE_STOPPED
);
}
setComponentMeasureState() {
this.node.dataset.measureState = this.measureState;
if (this.measureState === MEASURE_STATE_RUNNING) {
this.node.classList.add(MEASURE_STATE_RUNNING);
this.node.classList.remove(MEASURE_STATE_STOPPED);
} else {
this.node.classList.add(MEASURE_STATE_STOPPED);
this.node.classList.remove(MEASURE_STATE_RUNNING);
}
}
getComponentUpdateCycle() {
let value = parseInt(this.node.dataset.updateCycle, 10);
value = (Number.isNaN(value) && UPDATE_CYCLE_DEFAULT) || value;
return Math.max(UPDATE_CYCLE_MINIMUM, Math.min(UPDATE_CYCLE_MAXIMUM, value));
}
startMeasure() {
this.measureTimestamp = this.updateTimestamp = Date.now();
this.lastMeasuredMSecs = getMeasureInMilliseconds(this.measure);
this.timerId = setInterval(
updateStopwatchMeasure,
this.updateCycle,
this
);
this.measureState = MEASURE_STATE_RUNNING;
this.setComponentMeasureState();
}
stopMeasure() {
clearInterval(this.timerId);
this.lastMeasuredMSecs = null;
this.measureTimestamp = null;
this.updateTimestamp = null;
this.measureState = MEASURE_STATE_STOPPED;
this.setComponentMeasureState();
}/*
resetMeasure() {
Object.assign(this.measure, {
hours: 0,
minutes: 0,
seconds: 0
});
this.setComponentMeasure();
}*/
static initialize(node) {
return new Stopwatch(node);
}
}
/*export default*/function initialize() {
return Array
.from(document.body.querySelectorAll('.stopwatch-component'))
.map(Stopwatch.initialize);
}
/**
* usage
*/
const timerList = initialize();
// console.log('timerList :', timerList);
dd {
margin-bottom: 6px;
}
.stopwatch-component {
font-family: monospace;
font-size: x-large;
cursor: pointer;
}
.stopwatch-component.stopped {
text-decoration: line-through solid #999;
}
<dl>
<dt>
1st time measurement
</dt>
<dd>
<time
class="stopwatch-component"
datetime="0:0:0"
data-update-cycle="100"
data-measure-state="running">0:0:0</time>
</dd>
<dt>
2nd time measurement
</dt>
<dd>
<time
class="stopwatch-component"
datetime="99:59:33"
data-update-cycle="1000">99:59:33</time>
</dd>
<dt>
3rd time measurement
</dt>
<dd>
<time
class="stopwatch-component"
datetime="07:11:55"
data-update-cycle="500"
data-measure-state="stopped">7:11:55</time>
</dd>
</dl>
<p>Click each time measure separately for toggling its pause/proceed state.</p>
Note:
In order to keep the (re)rendering of seconds (minutes, hours) that have been passed in sync, one needs another timer approach than the one provided by the OP.
The examples run with different configurable update cycles defined by the value of the data-update-cycle attribute of a <time class="stopwatch-component"/> element. An update interval of 500msec or just 1sec is not suitable for this kind of measure task, due to setInterval being not precise enough. The running example does demonstrate exactly that.
One has to keep the displayed data in sync by constantly comparing the timestamp from starting a measure process with the timestamp from the current update process. The (re)rendering of a displayed value of cause takes place only if at least a second has passed since the last (re)rendering. But the update cycles which constantly (but not permanently) triggers the (re)rendering has to be run at a higher frequency.

HTML 5 Audio Player remaining time show delay

I have a problem with an audio player, when users press play the start-time timer is showing instantly, but remaining-time timer shows with a delay. I'm relatively new to JS, so I can not identify the problem on my own.
Can someone can help me with synching timers (start and remaining) show on play event?
CodePen
var isSeeking = false;
var seek = document.getElementById("seekObj");
var player = document.getElementById("player");
SetSeekColor();
function calculateTotalValue(length) {
var minutes = Math.floor(length / 60),
seconds_int = length - minutes * 60,
seconds_str = seconds_int.toString(),
seconds = seconds_str.split(".")[0],
temp_min = minutes.toString().length === 1 ? "0" + minutes : minutes,
temp_sec = seconds.toString().length === 1 ? "0" + seconds : seconds;
return temp_min + ":" + temp_sec;
}
function calculateCurrentValue(_seconds) {
function padTime(t) {
return t < 10 ? "0" + t : t;
}
if (typeof _seconds !== "number") return "";
if (_seconds < 0) {
_seconds = Math.abs(_seconds);
//console.log(_seconds);
}
var hours = Math.floor(_seconds / 3600),
minutes = Math.floor((_seconds % 3600) / 60),
seconds = Math.floor(_seconds % 60);
var hour = hours > 0 ? padTime(hours) + ":" : "";
return hour + padTime(minutes) + ":" + padTime(seconds);
}
function setupSeek() {
seek.max = player.duration;
}
function seekAudio() {
isSeeking = true;
player.currentTime = seek.value;
isSeeking = false;
}
var prevcurrentime = 0;
function initProgressBar() {
if (!isSeeking) {
seek.value = player.currentTime;
}
var length = player.duration;
var current_time = player.currentTime;
// calculate total length of value
var totalLength = calculateTotalValue(length);
// calculate current value time
var currentTime = calculateCurrentValue(current_time);
if (player.readyState === 4) {
jQuery(".end-time").html(totalLength);
jQuery(".start-time").html(currentTime);
}
//checking if the current time is bigger than the previous or else there will be sync different between remaining and current
if (currentTime > prevcurrentime) {
//calculate the remaining time
var rem_time = length - current_time;
jQuery(".rem-time").html(calculateCurrentValue(rem_time));
}
//setting the previouscurrent time to this current time
prevcurrentime = currentTime;
if (player.currentTime == player.duration) {
$("#play-btn").removeClass("pause");
}
}
function initPlayers(num) {
// pass num in if there are multiple audio players e.g 'player' + i
for (var i = 0; i < num; i++) {
(function() {
// Variables
// ----------------------------------------------------------
// audio embed object
var playerContainer = document.getElementById("player-container"),
player = document.getElementById("player"),
isPlaying = false,
playBtn = document.getElementById("play-btn");
// Controls Listeners
// ----------------------------------------------------------
if (playBtn != null) {
playBtn.addEventListener("click", function() {
togglePlay();
});
}
// Controls & Sounds Methods
// ----------------------------------------------------------
function togglePlay() {
if (player.paused === false) {
player.pause();
isPlaying = false;
$("#play-btn").removeClass("pause");
} else {
$(".start-time").html("");
player.play();
$("#play-btn").addClass("pause");
isPlaying = true;
}
}
})();
}
}
looking good, this is an error in the html. In this piece of code just replace the class rem-time by end-time.
<small style="float: right; position: relative; right: 21px;" class="end-time" onclick="showhideRemaining(this)"></small>
I think the root of your problem lies within the performance of your code. I can't see a big time difference between the two counters, but here are some suggested improvements:
You have the padTime function, so use it (see point 2)!
function padTime(t) {
return t < 10 ? "0" + t : t;
}
no unnecessary or early conversion to strings:
function calculateTotalValue(length) {
var minutes = Math.floor(length / 60);
var seconds = Math.floor(length - minutes * 60);
// use the padTime function here with numbers
return padTime(minutes) + ":" + padTime(seconds);
}
do not query the elements over and over again:
if (player.readyState === 4) {
jQuery(".end-time").html(totalLength);
jQuery(".start-time").html(currentTime);
}
Here, instead of querying the elements (jQuery(".end-time")) every time in your ontimeupdate callback, save the references in variables outside of the callback function.
limit color updates.
setInterval(function() {
SetSeekColor();
}, 34);
Updating the color every millisecond is just overkill. 34 milliseconds should equal something around 30fps.
I noticed you have are planning to have multiple players on one page (initPlayers(num)). Here a few thoughts:
When you initialise the players, save each single player with its UI elements in an Object
initPlayers(jQuery("#player-container").length);: IDs are (must be) unique in an entire HTML Document. This wont work, change it to a class.

Javascript call function at each "X" minutes by clock

Ok, so I have:
function show_popup() {
alert('Ha');
}
Now, what I want is to call this function at each X minutes BUT giving as reference the clock (the real time).
If X is 5, then the next function works properly:
setInterval(function(){
var date = new Date();
var minutes = date.getMinutes().toString();
var minutes = minutes.slice(-1); // Get last number
if(minutes == 0 || minutes == 5)
{
show_popup(); // This will show the popup at 00:00, 00:05, 00:10 and so on
}
}, 1000);
How can I make this function to work if I change 5 minutes to 4, or to 3, or to 20 ?
I must mention that I can't change the timer from setinterval, cause this it will mean that the popup will trigger only if you are on page AFTER passing X minutes. I don't want that. I want to show the popup at specific minutes giving the reference the clock.
You need to find the multiples of X
To do that, you can use modulo operation, so:
if(minutes % X === 0) {
show_popup();
}
The modulo operation will return the rest of division between a and b, if thats 0, thats means b is multiple of a.
For example, if you want to show every 3 minutes:
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0 //show
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0 //show
And so on...
two ways, just run the code to see results(in chrome browser)
1.use timer and you can change period when next tick comes, timer is not that precise
class MyInterval {
constructor(defaultInterval, callback) {
this.interval = defaultInterval
this.callback = callback
this._timeout = null
this.tick()
}
tick() {
const {
interval,
callback
} = this
this._timeout = setTimeout(() => {
callback()
this.tick()
}, interval)
}
stop() {
clearTimeout(this._timeout)
}
changeInterval(interval) {
this.interval = interval
}
}
const myInterval = new MyInterval(1000, () => console.log(new Date()))
setTimeout(() => {
myInterval.changeInterval(2000)
}, 3500)
setTimeout(() => {
myInterval.stop(2000)
}, 13500)
2.use a minimal interval, more quick to react, has a minimal limit, may cost more
class MyInterval {
constructor(minimal, defaultInterval, callback) {
this.minimal = minimal
this.interval = defaultInterval
this.callback = callback
this._current = 0
this._timeout = setInterval(() => {
this._current++
if (this._current >= this.interval) {
this._current = 0
callback()
}
}, minimal)
}
stop() {
clearInterval(this._timeout)
}
changeInterval(interval) {
this.interval = interval
}
}
const myInterval = new MyInterval(1000, 1, () => console.log(new Date()))
setTimeout(() => {
myInterval.changeInterval(2)
}, 3500)
setTimeout(() => {
myInterval.stop()
}, 13500)

Countdown Timer Objects - Javascript

I would like to create a simple timer in Javascript that counts down from a given time until it hits 0. I found this tutorial which worked perfectly. My problem is that I need to place multiple timers on the same page. This tutorial obviously won't do that because it uses global variables (I'm new to JS/Programming so I might not be using the right terms). I tried to re-create the same thing only creating each timer as it's own Object so that they don't interfere with eachother. This is what I have.
function taskTimer(name, startTime) {
this.timer = name;
this.totalSeconds = startTime;
this.tick = function() {
if (this.totalSeconds <= 0) {
return;
}
this.totalSeconds -= 1;
this.updateTimer();
// window.setTimeout("this.tick()", 1000);
};
this.updateTimer = function(){
this.seconds = this.totalSeconds;
this.hours = Math.floor(this.seconds / 3600);
this.seconds -= this.hours * (3600);
this.minutes = Math.floor(this.seconds / 60);
this.seconds -= this.minutes * (60);
this.timeString = this.leadingZero(this.hours) + ":" + this.leadingZero(this.minutes) + ":" + this.leadingZero(this.seconds);
return this.timeString;
};
this.leadingZero = function(time){
return (time < 10) ? "0" + time : + time;
};
}
var testTimer = new taskTimer("timer", 30);
testTimer.tick();
I created one at the end there. Running
testTimer.updateTimer(); returns 00:00:30 which is correct, but running testTimer.tick(); returns no value. There is obviously something wrong with that part of the code I just can't figure it out.
You've got a few problems.
You're calling updateTimer() inside of your tick method, so it
won't ever reach outside of there unless you return it.
With your current setup, you'd have to call tick manually every time you wanted to update the clock, and if you don't do that precisely every one second the timer will be inaccurate.
To go with #2, you shouldn't decrement totalSeconds like you are because it isn't guaranteed that it will be exactly one second between triggers of your timeout. Use dates instead.
Here's what I would do: http://jsfiddle.net/R4hnE/3/
// I added optional callbacks. This could be setup better, but the details of that are negligible.
function TaskTimer(name, durationInSeconds, onEnd, onTick) {
var endTime,
self = this, // store a reference to this since the context of window.setTimeout is always window
running = false;
this.name = name;
this.totalSeconds = durationInSeconds;
var go = (function tick() {
var now = new Date().getTime();
if (now >= endTime) {
if (typeof onEnd === "function") onEnd.call(self);
return;
}
self.totalSeconds = Math.round((endTime - now) / 1000); // update totalSeconds placeholder
if (typeof onTick === "function") onTick.call(self);
window.setTimeout(tick, 1000 / 12); // you can increase the denominator for greater accuracy.
});
// this is an instance method to start the timer
this.start = function() {
if (running) return; // prevent multiple calls to start
running = true;
endTime = new Date().getTime() + durationInSeconds * 1000; // this is when the timer should be done (with current functionality. If you want the ability to pause the timer, the logic would need to be updated)
go();
};
}
// no reason to make this an instance method :)
TaskTimer.prototype.toTimeString = function() {
var hrs = Math.floor(this.totalSeconds / 60 / 60),
min = Math.floor(this.totalSeconds / 60 - hrs * 60),
sec = this.totalSeconds % 60;
return [hrs.padLeft("0", 2), min.padLeft("0", 2), sec.padLeft("0", 2)].join(" : ");
};
var task = new TaskTimer("task1", 30, function() {
document.body.innerHTML = this.toTimeString();
alert('done');
}, function() {
document.body.innerHTML = this.toTimeString();
});
I always have problems with this and in one instance, within the function, I had to redefine it:
this.tick = function() {
self=this;
if (self.totalSeconds <= 0) {
return;
}
self.totalSeconds -= 1;
self.updateTimer();
// window.setTimeout("self.tick()", 1000);
};
Here is another post about that: var self = this?
My version, you can see at:
http://fiddle.jshell.net/hmariod/N7haK/4/
var tmArray = new Array();
var timerRef, timerId=0;
function newTimer(){
try{
if(tmArray.length > 4) throw "Too much timers";
var countDown = parseInt(document.getElementById("tCountown").value,10);
if(isNaN(countDown)) throw "tCountown is NaN";
var tmName = document.getElementById("tName").value;
var nt = new taskTimer(++timerId, tmName, countDown);
createTmElement(timerId, tmName);
tmArray.push(nt);
if(!timerRef) timerRef = setInterval(timerFn, 1000);
showTimers();
}catch(er){
alert("newTimer:" + er);
}
}
function taskTimer(id, name, tCountown) {
this.id = id;
this.tName = name;
this.tCountown = tCountown;
}
function timerFn(){
try{
var i;
killTimer = true;
for(i = 0; i < tmArray.length; i++){
tmArray[i].tCountown--;
if(tmArray[i].tCountown < 0){
tmArray[i].tCountown = 0;
}else{
killTimer = false;
}
}
if(killTimer) clearInterval(timerRef);
showTimers();
}catch(er){
clearInterval(timerRef);
aler("timerFn: " + er);
}
}

Categories

Resources