HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Stopwatch app using Dojo

Submitted by: @import:stackexchange-codereview··
0
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().

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 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.