jQuery.Class class
plugin: jquery/class
download: jQuery.Class
test: qunit.html
Class provides simulated inheritance in JavaScript. Use Class to bridgethe gap between jQuery's functional programming style and Object OrientedProgramming. It is based off John Resig's Simple ClassInheritance library. Besides prototypal inheritance, it includes a fewimportant features:
- Static inheritance
- Introspection
- Namespaces
- Setup and initialization methods
- Easy callback function creation
The GetStarted with jQueryMX has a good walkthrough of $.Class.
Static v. Prototype
Before learning about Class, it's important to understand the differencebetween a class's static and prototype properties.
//STATIC
MyClass.staticProperty //sharedproperty
//PROTOTYPE
myclass = new MyClass()
myclass.prototypeMethod() //instance method
A static (or class) property is on the Class constructor function itselfand can be thought of being shared by all instances of the Class. Prototypepropertes are available only on instances of the Class.
A Basic Class
The following creates a Monster class with a name (for introspection),static, and prototype members. Every time a monster instance is created, thestatic count is incremented.
$.Class('Monster',
/* @static */
{
count: 0
},
/* @prototype */
{
init: function( name ) {
// savesname on the monster instance
this.name = name;
// sets thehealth
this.health = 10;
//increments count
this.constructor.count++;
},
eat: function( smallChildren ){
this.health += smallChildren;
},
fight: function() {
this.health -= 2;
}
});
hydra = new Monster('hydra');
dragon = new Monster('dragon');
hydra.name // -> hydra
Monster.count // -> 2
Monster.shortName // -> 'Monster'
hydra.eat(2); // health = 12
dragon.fight(); // health =8
Notice that the prototype init function is called when a newinstance of Monster is created.
Inheritance
When a class is extended, all static and prototype properties areavailable on the new class. If you overwrite a function, you can call the baseclass's function by calling this._super. Lets create a SeaMonsterclass. SeaMonsters are less efficient at eating small children, but morepowerful fighters.
Monster("SeaMonster",{
eat: function( smallChildren ) {
this._super(smallChildren / 2);
},
fight: function() {
this.health -= 1;
}
});
lockNess = new SeaMonster('Lock Ness');
lockNess.eat(4); //health = 12
lockNess.fight(); //health =11
Static property inheritance
You can also inherit static properties in the same way:
$.Class("First",
{
staticMethod: function() { return 1;}
},{})
First("Second",{
staticMethod: function() { return this._super()+1;}
},{})
Second.staticMethod() // -> 2
Namespaces
Namespaces are a good idea! We encourage you to namespace all of yourcode. It makes it possible to drop your code into another app without problems.Making a namespaced class is easy:
$.Class("MyNamespace.MyClass",{},{});
new MyNamespace.MyClass()
Introspection
Often, it's nice to create classes whose name helps determine functionality.Ruby on Rails's ActiveRecordORM class is a great example of this. Unfortunately, JavaScript doesn't have away of determining an object's name, so the developer must provide a name.Class fixes this by taking a String name for the class.
$.Class("MyOrg.MyClass",{},{})
MyOrg.MyClass.shortName //-> 'MyClass'
MyOrg.MyClass.fullName //-> 'MyOrg.MyClass'
The fullName (with namespaces) and the shortName (without namespaces) areadded to the Class's static properties.
Setup and initialization methods
Class provides static and prototype initialization functions. These comein two flavors - setup and init. Setup is called before init and can be used to'normalize' init's arguments.
PRO TIP: Typically, you don't need setup methods in yourclasses. Use Init instead. Reserve setup methods for when you need to docomplex pre-processing of your class before init is called.
$.Class("MyClass",
{
setup: function() {} //static setup
init: function() {} //static constructor
},
{
setup: function() {} //prototype setup
init: function() {} //prototype constructor
})
Setup
Setup functions are called before init functions. Static setup functionsare passed the base class followed by arguments passed to the extend function.Prototype static functions are passed the Class constructor function arguments.
If a setup function returns an array, that array will be used as thearguments for the following init method. This provides setup functions theability to normalize arguments passed to the init constructors. They are alsoexcellent places to put setup code you want to almost always run.
The following is similar to how jQuery.Controller.prototype.setupmakes sure init is always called with a jQuery element and merged options evenif it is passed a raw HTMLElement and no second parameter.
$.Class("jQuery.Controller",{
...
},{
setup: function( el, options ) {
...
return [$(el),
$.extend(true,
this.Class.defaults,
options || {} ) ]
}
})
Typically, you won't need to make or overwrite setup functions.
Init
Init functions are called after setup functions. Typically, they receivethe same arguments as their preceding setup function. The Foo class's init method gets called in the following example:
$.Class("Foo", {
init: function( arg1, arg2, arg3 ) {
this.sum = arg1+arg2+arg3;
}
})
var foo = new Foo(1,2,3);
foo.sum //-> 6
Proxies
Similar to jQuery's proxy method, Class provides a proxyfunction that returns a callback to a method that will always have this set to the class or instance of the class.
The following example uses this.proxy to make sure this.name is available in show.
$.Class("Todo",{
init: function( name ) {
this.name = name
},
get: function() {
$.get("/stuff",this.proxy('show'))
},
show: function( txt ) {
alert(this.name+txt)
}
})
new Todo("Trash").get()
Callback is available as a static and prototype method.
Demo
Demo
HTML
<h2>Basic Tabs</h2>
<ul id="tabs1" class="ui-helper-clearfix"'="">
<li><ahref="#tab1">Tab 1</a></li>
<li><ahref="#tab2">Tab 2</a></li>
<li><ahref="#tab3">Tab 3</a></li>
</ul>
<div id="tab1" class="tab">Tab 1 Content</div>
<div id="tab2" class="tab">Tab 2 Content</div>
<div id="tab3" class="tab">Tab 3 Content</div>
<h2>History Tabs</h2>
<ul id="tabs2" class="ui-helper-clearfix"'="">
<li><ahref="#tab4">Tab 4</a></li>
<li><ahref="#tab5">Tab 5</a></li>
<li><ahref="#tab6">Tab 6</a></li>
</ul>
<div id="tab4" class="tab">Tab 4 Content</div>
<div id="tab5" class="tab">Tab 5 Content</div>
<div id="tab6" class="tab">Tab 6 Content</div>
Source
steal('jquery/controller').then(function(){
$.Controller("Tabs",{
init : function(){
this.element.children("li:first").addClass('active')
var tab = this.tab;
this.element.children("li:gt(0)").each(function(){
tab($(this)).hide()
})
},
tab : function(li){
return $(li.find("a").attr("href"))
},
"li click" : function(el, ev){
ev.preventDefault();
this.activate(el)
},
activate : function(el){
this.tab(this.find('.active').removeClass('active')).hide()
this.tab(el.addClass('active')).show();
}
})
//inherit from tabs
Tabs("HistoryTabs",{
// ignore clicks
"li click" : function(){},
// listen for history changes
"{window} hashchange" : function(ev){
var hash = window.location.hash;
this.activate(hash === '' || hash === '#' ?
this.element.find("li:first") :
this.element.find("a[href="+hash+"]").parent()
)
}
})
//adds the controller to the element
$("#tabs1").tabs();
$("#tabs2").history_tabs();
})
Constructor
To create a Class call:
$.Class( [NAME , STATIC,]PROTOTYPE ) -> Class
NAME{optional:String}
If provided, this sets the shortName and fullName of the class and adds itand any necessary namespaces to the window object.
STATIC{optional:Object}
If provided, this creates static properties and methods on the class.
PROTOTYPE{Object}
Creates prototype methods on the class.
When a Class is created, the static setupand [jQuery.Class.static.init init] methods are called.
To create an instance of a Class, call:
new Class([args ... ]) -> instance
The created instance will have all the prototype properties and methodsdefined by the PROTOTYPE object.
When an instance is created, the prototype setupand initmethods are called.
new $.Class() -> jquery.class
returns {jquery.class}
jQuery.Class.prototype.constructor attribute
A reference to the Class (or constructor function). This allows you toaccess a class's static properties from an instance.
Quick Example
// a class with a static property
$.Class("MyClass", {staticProperty : true}, {});
// a new instance of myClass
var mc1 = new MyClass();
// read the static property from the instance:
mc1.constructor.staticProperty //-> true
jQuery.Class.prototype.init function
If an init method is provided, it gets called when a new instanceis created. Init gets called after setup,typically with the same arguments passed to the Class constructor: ( new Class( arguments ... )).
$.Class("MyClass",
{
init: function( val ) {
this.val = val;
}
})
var mc = new MyClass(1)
mc.val //-> 1
Setupis able to modify the arguments passed to init. Read about it there.
API
class.init()
jQuery.Class.prototype.proxy function
Returns a method that sets 'this' to the current instance. This does thesame thing as and is described better in jQuery.Class.static.proxy.The only difference is this proxy works on a instance instead of a class.
API
class.proxy(fname) -> Function
fname {String|Array}
If a string, it represents the function to be called.
If it is an array, it will call each function in order and pass the returnvalue of the prior function to the next function.
returns {Function}
the callback function
jQuery.Class.prototype.setup function
If a setup method is provided, it is called when a new instances iscreated. It gets passed the same arguments that were given to the Classconstructor function ( new Class( arguments ... )).
$.Class("MyClass",
{
setup: function( val ) {
this.val = val;
}
})
var mc = new MyClass("CheckCheck")
mc.val //-> 'Check Check'
Setup is called before init.If setup return an array, those arguments will be used for init.
$.Class("jQuery.Controller",{
setup : function(htmlElement,rawOptions){
return [$(htmlElement),
$.extend({}, this.Class.defaults,rawOptions )]
}
})
PRO TIP: Setup functions are used to normalizeconstructor arguments and provide a place for setup code that extending classesdon't have to remember to call _super to run.
Setup is not defined on $.Class itself, so calling super in inhertingclasses will break. Don't do the following:
$.Class("Thing",{
setup : function(){
this._super(); // breaks!
}
})
API
class.setup() ->Array|undefined
returns {Array|undefined}
If an array is return, jQuery.Class.prototype.initis called with those arguments; otherwise, the original arguments are used.
jQuery.Class.static.extend function
Extends a class with new static and prototype functions. There are avariety of ways to use extend:
// with className, static and prototype functions
$.Class('Task',{ STATIC},{ PROTOTYPE })
// with just classname and prototype functions
$.Class('Task',{PROTOTYPE })
// with just a className
$.Class('Task')
You no longer have to use .extend. Instead, you can pass thoseoptions directly to $.Class (and any inheriting classes):
// with className, static and prototype functions
$.Class('Task',{ STATIC},{ PROTOTYPE })
// with just classname and prototype functions
$.Class('Task',{PROTOTYPE })
// with just a className
$.Class('Task')
API
$.Class.extend(fullName, klass,proto) -> jQuery.Class
fullName {optional:String}
the classes name (used for classes w/ introspection)
klass {optional:Object}
the new classes static/class functions
proto {optional:Object}
the new classes prototype functions
returns {jQuery.Class}
returns the new class
jQuery.Class.static.fullName attribute
The full name of the class, including namespace, provided forintrospection purposes.
$.Class("MyOrg.MyClass",{},{})
MyOrg.MyClass.shortName //-> 'MyClass'
MyOrg.MyClass.fullName //-> 'MyOrg.MyClass'
jQuery.Class.static.namespace attribute
The namespaces object
$.Class("MyOrg.MyClass",{},{})
MyOrg.MyClass.namespace //-> MyOrg
jQuery.Class.static.newInstance function
Creates a new instance of the class. This method is useful for creatingnew instances with arbitrary parameters.
Example
$.Class("MyClass",{},{})
var mc = MyClass.newInstance.apply(null, newArray(parseInt(Math.random()*10,10))
API
$.Class.newInstance() -> class
jQuery.Class.static.proxy function
Returns a callback function for a function on this Class. Proxy ensuresthat 'this' is set appropriately.
$.Class("MyClass",{
getData: function() {
this.showing = null;
$.get("data.json",this.proxy('gotData'),'json')
},
gotData: function( data ) {
this.showing =data;
}
},{});
MyClass.showData();
Currying Arguments
Additional arguments to proxy will fill in arguments onthe returning function.
$.Class("MyClass",{
getData: function( callback ) {
$.get("data.json",this.proxy('process',callback),'json');
},
process: function( callback, jsonData ) { //callback is added asfirst argument
jsonData.processed = true;
callback(jsonData);
}
},{});
MyClass.getData(showDataFunc)
Nesting Functions
Proxy can take an array of functions to call as the firstargument. When the returned callback function is called each function in thearray is passed the return value of the prior function. This is often used toeliminate currying initial arguments.
$.Class("MyClass",{
getData: function( callback ) {
//callsprocess, then callback with value from process
$.get("data.json",this.proxy(['process2',callback]),'json')
},
process2: function( type,jsonData ) {
jsonData.processed = true;
return[jsonData];
}
},{});
MyClass.getData(showDataFunc);
API
$.Class.proxy(funcs, fname) ->Function
funcs {}
fname {String|Array}
If a string, it represents the function to be called.
If it is an array, it will call each function in order and pass the returnvalue of the prior function to the next function.
returns {Function}
the callback function.
jQuery.Class.static.setup function
Setup gets called on the inherting class with the base class followed bythe inheriting class's raw properties.
Setup will deeply extend a static defaults property on the base class withproperties on the base class. For example:
$.Class("MyBase",{
defaults : {
foo: 'bar'
}
},{})
MyBase("Inheriting",{
defaults : {
newProp : 'newVal'
}
},{}
Inheriting.defaults -> {foo: 'bar', 'newProp': 'newVal'}
API
$.Class.setup(baseClass,fullName, staticProps, protoProps) -> undefined
baseClass {Object}
the base class that is being inherited from
fullName {String}
the name of the new class
staticProps {Object}
the static properties of the new class
protoProps {Object}
the prototype properties of the new class
returns {undefined}
jQuery.Class.static.shortName attribute
The name of the class without its namespace, provided for introspectionpurposes.
$.Class("MyOrg.MyClass",{},{})
MyOrg.MyClass.shortName //-> 'MyClass'
MyOrg.MyClass.fullName //-> 'MyOrg.MyClass'