JavaScript Object Instantiation!!!

Hallelujah! Finally tackled JavaScript object instances.

I learned JavaScript Object Notation (JSON) a few months ago and it has increased the portability of my JavaScript code. But something I’ve never done with Javascript is the use of the “new” keyword like we do with Java, C++, or PHP with Object oriented programming.

Finally decided to get to the bottom of it when I wanted to quickly write a JavaScript count-down (or count-up) timer display.I wanted to be able to create these counters on the fly, anywhere on the page, by just supplying the DIV id to a function.

Here is the full JavaScript code of the “Class” for the object:

/**
 * JavaScript CountDown
 * usage example:
 * 			var count1 = new jsCounter();
 *			count1.init( string_of_element_ID, start_number, ratePerSecond );
 *
 */
var jsCounter = (
	function(){
		function _class(){

			var _self = this;
			var currentCount, lastUpdate, targDiv, ratePerSecond, digits,
				ratePerSecond, currentCount, lastUpdate;

			var redrawFrequency = 220; // ms
			var digitLength = 14;

			/* Object METHODS */
			this.calcChange = function(){
				var currentMs = new Date().getTime();

				var newCount = _self.currentCount - (( currentMs - _self.lastUpdate ) * _self.ratePerSecond / 1000) ;

				var strNum = padLeft("" + newCount + "", _self.digitLength, '0');
				var max = _self.digits.length;

				// Update Digits
				for(var x=0;x < max; x+=1){
					_self.digits[x].innerHTML = strNum[x];
				}

				_self.redrawCounter();
				_self.lastUpdate = currentMs;
				_self.currentCount = newCount;

				if(newCount > 0){
					setTimeout( _self.calcChange, _self.redrawFrequency);
				}

			}; // end calcChange()

			this.redrawCounter = function(){
				this.digits.each(function(e){
					var i = parseInt(e.innerHTML,10);
					i = Math.max(0,(i * 10) + (i - 0.5));
					e.style.backgroundPosition = "center "+i+"%";
				});
			}; // end redraw()

			/* --- Initialization & Start Method --- */
			this.init = function(targDiv0,initNumber,countPerSecond){
				this.targDiv = targDiv0;

				this.currentCount = parseInt(initNumber);
				this.lastUpdate = new Date().getTime();
				this.ratePerSecond = countPerSecond;

				if(typeof targDiv0 == "string"){
					this.targDiv = $(targDiv0);
				}

				var strNum = padLeft("" + this.currentCount + "", this.digitLength, '0');

				// Insert Digits
				for(var x=0;x<strNum.length; x+=1){
					this.targDiv.insert("<div class='digit'>"+strNum[x]+"</div>");
				}

				this.digits = this.targDiv.childElements();

				this.redrawCounter();

				setTimeout( this.calcChange, this.redrawFrequency);
			}; // end init()

		}; // end _class

		return _class;
	}
)();

Now to create an instance of this object, we use this (Note: I am using Prototype JS to run this code when the page has finished loading):

<script type="text/javascript">
Event.observe(window,'load',function(){
	var count1 = new jsCounter();

	new Ajax.Request('/get_count.php',{
		method:'get',
		onSuccess:function(obj){
			var data = obj.responseText.evalJSON(); // parse JSON data from server
			
			// Initialize the counter object with an initial count, and the countdown speed (in counts per second)
			count1.init('thecountdown', data.current, data.rate);
		}
	});
	
});	
</script>

Put this div somewhere on the page:

<div id="thecountdown"></div>

You can also create multiple different DIVs and create new counter objects to instantiate them.

Explanation of JavaScript Class Code

I admit it is a little weird, being a function inside of a function. The concepts are heavily tied in to the notion of “scopes” where you have to know which variables are global to the page (window) and which are local variables to the class. The outer anonymous function basically creates an instance of an inner function called “_class”, then it returns it, basically assigning a new object complete with its own variables and methods, to your desired variable instance.

Inside of the _class() function we have variables, created with the “var” keyword, which can be thought of as object properties.

It starts getting weird when you see “_self” being used in the “calcChange” method. Note that in other methods, we use the “this” keyword to refer to the object’s properties and methods. But in the “calcChange” method, you see “_self” in place of the “this” keyword. Why? If you look at the end of the init method you’ll see a setTimeout statement, which calls this.calcChange. Because of the way setTimeout works with scopes, when it is ready to fire, it doesn’t know anything about “this” (the object we want to work with). But it DOES know about “_self” — that is because we have assigned “this” to “_self” as a property of the class. When you write setTimeout, it knows about _self so it carries the variable over with it.

Therefore, if you want to act upon an object in a function called with setTimeout or setInterval, you have to make sure to set “var _self = this” before calling the setTimeout function. Then, use _self instead of this to refer to the object methods and properties.