Skip to content

Instantly share code, notes, and snippets.

@alexanderlperez
Created November 1, 2013 03:03
Show Gist options
  • Save alexanderlperez/7260457 to your computer and use it in GitHub Desktop.
Save alexanderlperez/7260457 to your computer and use it in GitHub Desktop.
NOTE: this code is a little stale and *highly* coupled Using the setTimeout family of functions in an Angular.js module: since the JS engine on the browser updates variables outside of the angular event-loop, $apply() is required to update any values changed outside of a controller. You can see the need for $apply() in Timer.prototype.incrementT…
<script>
/*
Timer Ver. 3
The purpose of this series of fiddles is to explore properly dividing the program logic into model and controller
while appropriately executing the Angular.js 'way' of achieving that result
- the model has been moved outside the controller
*/
function timerCtrl($scope) {
$scope.Timer = new Timer($scope);
}
function Timer(scope) {
this.scope = scope;
this.timeElapsed = 0;
this.getTimeElapsed = "00:00";
this.intervalTimer = null;
this.timerStarted = false;
}
Timer.prototype = {
start: function () {
//prevent orphaning intervalTimer - by overwriting it with a
//reference to another timer - every time the start button is
//clicked
if (!this.timerStarted) {
//bind must be used here since, internally, setInterval's this is bound to the global scope
//now we can refer to $scope as 'this' in Timer
this.intervalTimer = setInterval(this.incrementTimer.bind(this.scope), 1000);
this.timerStarted = true;
}
},
pause: function () {
this.timerStarted = false;
clearInterval(this.intervalTimer);
},
reset: function () {
this.timerStarted = false;
this.timeElapsed = 0;
this.getTimeElapsed = "00:00";
clearInterval(this.intervalTimer);
},
incrementTimer: function () {
//convenience function: convert seconds to minutes
function formatElapsedTime(time) {
var minutes = Math.floor(time / 60),
seconds = Math.floor(time % 60);
if (seconds < 10) seconds = "0" + seconds.toString();
else seconds.toString();
if (minutes < 10) minutes = "0" + minutes.toString();
else minutes.toString();
return minutes + ":" + seconds;
}
this.Timer.timeElapsed++;
this.Timer.getTimeElapsed = formatElapsedTime(this.Timer.timeElapsed);
//update Angular's binding process
//Question: why do I need $apply here but not in Timer.reset()?
//Answer: all event callbacks outside of the Angular execution context (effectively its event loop),
// in this case setInterval's event within the normal browser event loop, need $apply() to
// activate the $watch list loop so that Angular knows to check all the expressions in the view
// for any changes, in this case the {{Timer.getTimeElapsed}} expression in the HTMLT
this.$apply();
}
};
</script>
<div ng-app ng-controller="timerCtrl">
<h1>{{Timer.getTimeElapsed}}</h1>
<button type="button" ng-click="Timer.start()">Start</button>
<button type="button" ng-click="Timer.pause()">Pause</button>
<button type="button" ng-click="Timer.reset()">Reset</button>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment