A Wired.com user account lets you create, edit and comment on Webmonkey articles. You will also be able to contribute to the Wired How-To Wiki and comment on news stories at Wired.com.
It's fast and free.
processing...Retrieve Sign In
Please enter your e-mail address or username below. Your username and password will be sent to the e-mail address you provided us.
processing...Welcome to Webmonkey
- edit articles
- add to the code library
- design and write a tutorial
- comment on any Webmonkey article
Sign In Information Sent
Write Widget-oriented JQuery Apps with Classes
/skill level/
/viewed/
Contents |
Introduction
Some days ago, Jeff Watkins published his [Coherent JS] framework: it is an outstanding new framework which implements Apple Bindings in Javascript. From his first tutorial I got the inspiration to write this article: it could be nice to structure our JQuery apps in widgets, using fast and reusable classes.
What you'll need
You need a text editor, latest JQuery, and boom! =)
Page structure
Think about your page as a set of tools: it's easy to see every part of the page as a widget with its own behaviour attached.
MVC: start building your model
Simply write you XHTML + CSS code, describing your page parts.
For example, if I want to make an image to move (stupid example, I know, but easy to implement and to understand for you ^^) creating a widget I've got to write the following code:
<img id="myImage" src="images/myimage.png" alt="Moving image" />
Separate Code from Presentation
In the head section of my page I'm going to write:
<script src="js/jquery-1.3.2.pack.js" type="text/javascript" charset="utf-8"></script> <script src="js/ImageWidget.js" type="text/javascript" charset="utf-8"></script> <script src="js/Main.js" type="text/javascript" charset="utf-8"></script>
- js/jquery-1.3.2.pack.js is the latest JQuery available today.
- js/ImageWidget.js will be our Widget class.
- js/Main.js will be our initialization class.
Write a Class
We are going to use a particular kind of class pattern, which gives the possibility to have private variables (differently from many plugins and patterns) and reduces the overhead of public functions (differently from the GREAT Module Pattern). That's it:
var MyClass = function(args) {
if (!(this instanceof MyClass)) return new MyClass(args); //prevent the call without 'new' construct
var myPrivateVar = args.MyPrivateVar;
this.myPrivateVar = function() { //getter
return myPrivateVar;
}
this.setMyPrivateVar = function(value) { //setter
myPrivateVar = value;
}
this.publicVar = "My public value";
};
MyClass.prototype.myPublicFunction = function() {
// code ...
};
MyClass.prototype.myStaticVar = "I'm static here";
Write a Widget Class
In a Widget it's important to store the DOM Object which represents the Widget: so pass it to class constructor like this:
var ImageWidget = function(object, args) {
if (!(this instanceof ImageWidget)) return new ImageWidget(object, args); //prevent the call without 'new' construct
this.object = function() { //returns attached object, the object which is controlled from this class
return $(object);
};
...
...
...
That's great because you can use this.object() getter everywhere in your code.
So, let's implement the animation:
ImageWidget.prototype.move = function(duration) {
var self = this; //use the closure!!!
this.object().animate({
left: "+= 200px"
}, {
duration: duration,
complete: function() {
// you can use the closure and call class functions with self.myFunct()
}
});
};
Event delegation
To control all DOM events in your widget you could start observing the DOM in the constructor, delegating one the class to handle all the callbacks.That's possible thanks to bubbling: when an event is triggered, it bubbles towards the top of the DOM tree. For exampe if I have and Image Widget (so, an image, a caption and two navigation buttons - next, prev) you will attach the div to a class and, here, you will observe clicks to contained elements.
//Event delegation in an Image Widget
this.object().bind("click", {self: this}, function(event) {
var tgt = $(event.target); //where event has effectively been triggered
var self = event.data.self;
if ("next" == tgt.attr("id")) {
// next button pressed
}
else if ("prev" == tgt.attr("id")) {
// prev button pressed
}
});
Event propagation permits to structure our JavaScript in a different way, [triggering custom events] and binding them everywhere in the page.
Attaching the Class to Widget: giving a behaviour to our static DOM Objects
And the Main.js??? Here we are! =D
$(function() {
var myWidget = new ImageWidget("#myImage", { }); //no args in this stupid example!
myWidget.move(3000); //3 seconds
});
It initializes and fires methods as DOM is loaded.
Alternate methods
Thousands...
Suggested readings
Google "Coherent JS", "John Resig", "JQuery", "Low Pro", "www.learningjquery.com"...
Special Offer For Webmonkey Users
WIRED magazine:
The first word on how technology is changing our world.
