Many people have asked me, if jQuery is object oriented and how they can use it same way as they use PHP or JAVA. For example:

object1 = new Object();
 
object1.testMethod();

As it appears you can do that too in a jQuery if plugin is properly developed. Of course the nature of the Javascript language is not OOP. Javascript is prototyping language but not OOP. However u can prototype properties and methods to make it look like its OOP.

In jQuery I have created a test plugin for you so it is easier to understand.

<script type="text/javascript">// <![CDATA[
//Lets consider it as our class wrapper
(function( $ ) {
 
	$.fn.testClass = function( initvar ) {
 
		this.testMethod = function(status) {
			this.test = status;
 
			//lets call a method of a class
			this.anotherMethod();
		};
 
		this.anotherMethod = function() {
			alert("anotherMethod is called by object " + this.test);
		};
 
		this.getVars = function() {
			alert("Class var set in testMethod: I am object " + this.test + "\nClass var set in constractor: " + this.class_var);
		};
 
		//lets init some variables here, consider it as a class constractor
		this.class_var = initvar;
 
		//THIS IS VERY IMPORTANT TO KEEP AT THE END
		return this;
	};
 
})( jQuery );
 
 
$(function() {
 
	//Now lets create objects
	var object1 = $(document.body).testClass("1");
	var object2 = $(document.body).testClass("2");
 
	//lets call method testMethod
	object1.testMethod("1");
	object2.testMethod("2");
 
	//lets lets see what we have at the end
	object1.getVars();
	object2.getVars();
 
});
// ]]></script>

Great, hope you have a clue now how to build OOP plugins. Now there is a small trick. The way jQuery works is when you call methods .each, .bind, .click, .trigger and etc on the callback you will appear out of your current class scope and the scope will be scope of a new element.

To see it in action, let’s modify our testClass.testMethod() example above:

...
this.testMethod = function(status) {
	this.test = status;
 
	//lets look for some elements on the page	and assign click event
	$("query").bind('click', function(event){
 
		if(this.anotherMethod) {
			alert('You are in a testClass scope')
		} else {
			alert('Oops..out of testClass scope')
		}
 
	});
 
	//lets loop some elements on the page and assign css		
	$("query").each( function(index, value){
 
		if(this.anotherMethod) {
			alert('You are in a testClass scope')
		} else {
			alert('Oops..out of testClass scope')
		}
 
		$(value).css('backgroundColor', '#ff0000')
 
	});
 
};
...

When you call method ‘object1.testMethod(“1″)’, .each and .bind calls will send you out of the testClass scope. When you work with complex applications you don’t want to do that. I work with object and I want to stay inside this object without doing a $(‘query’) to get back to it. jQuery has a great solution to it – jQuery.proxy.

jQuery.proxy

jQuery.proxy takes a function and returns a new one that will always have a particular scope.
Lest re-write our ‘this.testMethod’ again.

...
this.testMethod = function(status) {
	this.test = status;
 
	//lets look for some elements on the page	and assign click event
	$("query").bind('click', jQuery.proxy(function(event){
 
		if(this.anotherMethod) {
			alert('You are in a testClass scope')
		} else {
			alert('Oops..out of testClass scope')
		}
 
	}, this));
 
	//lets loop some elements on the page and assign css		
	$("query").each( jQuery.proxy(function(index, value){
 
		if(this.anotherMethod) {
			alert('You are in a testClass scope')
		} else {
			alert('Oops..out of testClass scope')
		}
 
		$(value).css('backgroundColor', '#ff0000')
 
	}, this));	
 
};
...

Woolia! Now we are in the ‘testClass’ scope. You can call any class method ‘this.anotherMethod()’ or class ‘this.class_var’.

Using setTimeout and setInterval within the class scope

The setTimeout() method calls a function or evaluates an expression after a specified number of milliseconds. This method is a method of global window object. Anytime you call it from your class it sends you out of the class scope.

...
this.testMethod = function(status) {
	this.test = status;
 
	setTimeout(function(){
		alert(this.anotherMethod); //UNDEFINED, out of class scope
	}, 1000);
 
};
...

Solution? Use a jQuery.proxy!

...
this.testMethod = function(status) {
	this.test = status;
 
	setTimeout(jQuery.proxy(function(){
		alert(this.anotherMethod) //CLASS SCOPE
	}, this), 1000);
 
};
...

Alternative method to jQuery.proxy

While jQuery is not the only framework in this world. Here is an alternative solution to jQuery.proxy, you can use it with jQuery, or any other javascript framework.

Let’s first extend a global javascript object ‘Function’ with method ‘Apply’, for convenience. You can give it any name you think is appropriate:

Function.prototype.Apply = function() {
	var obj = this;var args = arguments;
	var F = function() {
		return obj.apply(args[0], (args[1]) ? args[1] : []); //added [1] not to pass main object
  	};
	return F;
};

Now, we can start using it. Let’s re-write our ‘this.testMethod’ and use ‘Apply’ instead of jQuery.proxy:

...
this.testMethod = function(status) {
	this.test = status;
 
	setTimeout(function(){
		alert(this.anotherMethod); //CLASS SCOPE
	}.Apply(this), 1000);
 
};
...

Dima Svirid

Software architect. Ajax/Javascript, HTML5, Android, iPhone/iPad, JAVA, PHP, Cold Fusion, SQL, Air, Flash, Open source software, Frameworks

More Posts

Follow Me:

Tagged with:
 

One Response to jQuery Object Oriented Plugins

  1. Bernhard Kau says:

    Thanks a lot! With your post I was able to easily migrate my Prototype classes to jQuery plugins that act preatty much the same.

Leave a Reply