patternjavascriptMinor
Stopwatch app using Dojo
Viewed 0 times
stopwatchdojousingapp
Problem
Here is the link to fiddle. This is my first app using Dojo. Any comments/feedback is highly appreciated.
```
dojoConfig = {parseOnLoad: true};
resetStopwatch();
require(["dijit/form/ToggleButton", "dijit/form/Button", "dojo/dom", "dojo/dom-attr", "dojo/domReady!"], function(ToggleButton, Button, dom, domAttr){
var timeUpdate;
var toggleButton = new ToggleButton({
showLabel: true,
checked: false,
label: "Start",
onChange: function() {
if (this.get('label') == "Start") {
this.set('label', 'Stop');
var milliseconds = seconds = minutes = hours = 0;
timeUpdate = updateTime(domAttr, 0, 0, 0, 0);
}
else if (this.get('label') == "Resume") {
this.set('label', 'Stop');
// fetch current time in the stopwatch
prev_milliseconds = parseInt(domAttr.get("milliseconds", "innerHTML"));
prev_seconds = parseInt(domAttr.get("seconds", "innerHTML"));
prev_minutes = parseInt(domAttr.get("minutes", "innerHTML"));
prev_hours = parseInt(domAttr.get("hours", "innerHTML"));
timeUpdate = updateTime(domAttr, prev_hours, prev_minutes, prev_seconds, prev_milliseconds);
}
else if (this.get('label') == "Stop"){
this.set('label', 'Resume');
clearInterval(timeUpdate);
}
}
}, "start_stop_resume");
var resetButton = new Button({
label: "Reset",
onClick: function(){
toggleButton.set('label', "Start");
clearInterval(timeUpdate);
resetStopwatch();
resumeFlag = false;
}
}, "reset");
});
function updateTime(domAttr, prev_hours, prev_minutes, prev_seconds, prev_milliseconds){
var startTime = new Date();
timeUpdate = setInterval(function(){
var timeElapsed = new Date().
```
dojoConfig = {parseOnLoad: true};
resetStopwatch();
require(["dijit/form/ToggleButton", "dijit/form/Button", "dojo/dom", "dojo/dom-attr", "dojo/domReady!"], function(ToggleButton, Button, dom, domAttr){
var timeUpdate;
var toggleButton = new ToggleButton({
showLabel: true,
checked: false,
label: "Start",
onChange: function() {
if (this.get('label') == "Start") {
this.set('label', 'Stop');
var milliseconds = seconds = minutes = hours = 0;
timeUpdate = updateTime(domAttr, 0, 0, 0, 0);
}
else if (this.get('label') == "Resume") {
this.set('label', 'Stop');
// fetch current time in the stopwatch
prev_milliseconds = parseInt(domAttr.get("milliseconds", "innerHTML"));
prev_seconds = parseInt(domAttr.get("seconds", "innerHTML"));
prev_minutes = parseInt(domAttr.get("minutes", "innerHTML"));
prev_hours = parseInt(domAttr.get("hours", "innerHTML"));
timeUpdate = updateTime(domAttr, prev_hours, prev_minutes, prev_seconds, prev_milliseconds);
}
else if (this.get('label') == "Stop"){
this.set('label', 'Resume');
clearInterval(timeUpdate);
}
}
}, "start_stop_resume");
var resetButton = new Button({
label: "Reset",
onClick: function(){
toggleButton.set('label', "Start");
clearInterval(timeUpdate);
resetStopwatch();
resumeFlag = false;
}
}, "reset");
});
function updateTime(domAttr, prev_hours, prev_minutes, prev_seconds, prev_milliseconds){
var startTime = new Date();
timeUpdate = setInterval(function(){
var timeElapsed = new Date().
Solution
I tinkered a bit with the fiddle, I have the following observations:
-
If you were to place the colons in the HTML, then you would no longer need to concatenate the colons into the time fields:
-
You could generalize
or a more Golfic version which calculates the amount of zeroes that will be required:
-
-
Your code would be much cleaner if you split out time calculations from prettyfying the numbers.
You could have a function that is dedicated to time calculations:
and a function that just updates the DOM:
-
A very minor nitpicking, but the
-
Another nitpicking is that you trust the DOM as your data model (you retrieve the values from the labels when you hit Resume), that is a bad practice in general, but acceptable for a timer project.
You can check the end result here.
-
If you were to place the colons in the HTML, then you would no longer need to concatenate the colons into the time fields:
:
:
::
-
You could generalize
prependZero so that it works for both seconds and milliseconds by passing the requested length:function prependZero( time, length ){
time = time + "";
while( time.length < length ){
time = '0' + time;
}
return time;
}or a more Golfic version which calculates the amount of zeroes that will be required:
function prependZero2( time, length ){
time = time + "";
return new Array( Math.max( length - time.length + 1 , 0 ) ).join("0") + time;
}-
if(minutes > 60) minutes = minutes % 60; is the same as minutes = minutes % 60; is the same as minutes %= 60;.-
Your code would be much cleaner if you split out time calculations from prettyfying the numbers.
You could have a function that is dedicated to time calculations:
function updateTime(domAttr, prev_hours, prev_minutes, prev_seconds, prev_milliseconds){
var startTime = new Date();
timeUpdate = setInterval(function(){
var timeElapsed = new Date().getTime() - startTime.getTime();
// calculate hours
hours = parseInt(timeElapsed/1000/60/60) + prev_hours;
// calculate minutes
minutes = parseInt(timeElapsed/1000/60) + prev_minutes;
minutes %= 60;
// calculate seconds
seconds = parseInt(timeElapsed/1000) + prev_seconds;
seconds %= 60;
// calculate milliseconds
milliseconds = timeElapsed + prev_milliseconds;
milliseconds %= 1000;
setStopwatch( hours , minutes , seconds , milliseconds );
},25); // update time in stopwatch after every 25ms
return timeUpdate;
}and a function that just updates the DOM:
function setStopwatch( hours , minutes , seconds , milliseconds ){
require(["dojo/dom-attr"], function(domAttr){
domAttr.set("hours" , "innerHTML", prependZero( hours, 2 ) );
domAttr.set("minutes" , "innerHTML", prependZero( minutes, 2 ) );
domAttr.set("seconds" , "innerHTML", prependZero( seconds, 2 ) );
domAttr.set("milliseconds", "innerHTML", prependZero( milliseconds, 3 ) );
});
}resetStopwatch then becomes as simple as function resetStopwatch(){
setStopwatch( 0, 0, 0, 0 );
}-
A very minor nitpicking, but the
require array is hard to read, you should figure out how Dojo proposes you should indent that array.-
Another nitpicking is that you trust the DOM as your data model (you retrieve the values from the labels when you hit Resume), that is a bad practice in general, but acceptable for a timer project.
You can check the end result here.
Code Snippets
<div id="stopwatch">
<span id="hours"></span>:
<span id="minutes"></span>:
<span id="seconds"></span>::
<span id="milliseconds"></span>
</div>function prependZero( time, length ){
time = time + "";
while( time.length < length ){
time = '0' + time;
}
return time;
}function prependZero2( time, length ){
time = time + "";
return new Array( Math.max( length - time.length + 1 , 0 ) ).join("0") + time;
}function updateTime(domAttr, prev_hours, prev_minutes, prev_seconds, prev_milliseconds){
var startTime = new Date();
timeUpdate = setInterval(function(){
var timeElapsed = new Date().getTime() - startTime.getTime();
// calculate hours
hours = parseInt(timeElapsed/1000/60/60) + prev_hours;
// calculate minutes
minutes = parseInt(timeElapsed/1000/60) + prev_minutes;
minutes %= 60;
// calculate seconds
seconds = parseInt(timeElapsed/1000) + prev_seconds;
seconds %= 60;
// calculate milliseconds
milliseconds = timeElapsed + prev_milliseconds;
milliseconds %= 1000;
setStopwatch( hours , minutes , seconds , milliseconds );
},25); // update time in stopwatch after every 25ms
return timeUpdate;
}function setStopwatch( hours , minutes , seconds , milliseconds ){
require(["dojo/dom-attr"], function(domAttr){
domAttr.set("hours" , "innerHTML", prependZero( hours, 2 ) );
domAttr.set("minutes" , "innerHTML", prependZero( minutes, 2 ) );
domAttr.set("seconds" , "innerHTML", prependZero( seconds, 2 ) );
domAttr.set("milliseconds", "innerHTML", prependZero( milliseconds, 3 ) );
});
}Context
StackExchange Code Review Q#40339, answer score: 3
Revisions (0)
No revisions yet.