Saturday, August 7, 2010

DOM-Wrappers In RightJS 2

Put your tin-foil hats on people, because it's your next brainwashing session about upcoming RightJS 2.

When you heard that RightJS 2 is going to have dom-wrappers instead of direct dom-units access you might think "oh, that's not a big deal, jQuery has dom-wrappers from the very beginning!". And you will be dead wrong! I already touched it a bit in one of my previous articles, now let me show this beauty in details.


DOM-Wrappers == Classes

First of all, dom-wrappers in RightJS are not just a bunch of functions behind a namespace, dom-wrappers in RightJS essentially are normal classes, with inheritance and functionality-injection support. For example you have the basic class Element and two subclasses Form and Input, which means you can say normally call instanceof on them.

$('div') instanceof Element;   // true
$('div') instanceof Input; // false
$('div') instanceof Form; // false

$('form') instanceof Element; // true
$('form') instanceof Input; // false
$('form') instanceof Form; // true

$('input') instanceof Element; // true
$('input') instanceof Input; // true
$('input') instanceof Form; // false

You also can extend them separately and all the methods will follow the inheritance structure principles

Element.include({
global_method: function() {
// this method will appear on all elements
}
});

Input.include({
inputs_only: function() {
// this method will appear on Input elements only
}
});

You can use polymorphism, redefine the meaning of methods, etc. For example the Element#select will search for matching elements by a css-rule, but Input#select will put the focus on the input element and select its content. No problem, you can do that easily.


Define Your Own Wrappers

The usual extending methods like Element#include, Form#include are fine, but in RightJS you are also allowed to define your own wrappers for certain types of elements. For example you can define a tables-sepecific wrapper

Element.Wrappers.TABLE = new Wrapper(Element, {
sortBy: function(column) {
// sort the table body
}
});

Or you could create a textareas wrapper the same way

Element.Wrappers.TEXTAREA = new Wrapper(Input, {
spellcheck: function() {
// spellcheck the content
}
});

NOTE: we inherited the Element and Input classes as you would normally do with any other classes in RigthJS.

Once you've done that, anytime you access a table or a textarea you'll have those new methods available

$('my-table').sortBy('name');

$('my-textarea').spellcheck();

This feature will let you to adjust and completely redefine the framework itself for the needs of your application.

But this is not the most kick-ass thing yet. Because we have much more!


Private DOM-Wrappers

With RightJS 2 you are not limited to the actual dom-nodes and tags. You can define your very own private dom-wrappers that won't be tied to the framework structure in any way. Why would you need that? The answer is simple - widgets.

How do you normally write a widget? You create some class which aggregates some main element and then you have all the headaches with different contexts and bindings, because half of your logic is in your class and half is in your elements

var MyWidget = new Class(Observer, {
initialize: function() {
this.element = $E('div')
.onClick(this.clicked.bind(this));
},

clicked: function() {
// do something about it.
}
});

Then more, you'll have to create several proxy methods to delegate the methods to actually insert the widget on the page and do other normal dom-manipulations and so one and so one. In more or less complicated case those things tend to get quite messy.

Well my friends, you don't have to suffer anymore, because now you can define your widget as a private wrapper and inherit any existing dom-wrapper directly just like that

var MyWidget = new Wrapper(Element, {
initialize: function(widget_id) {
this.$super('div', {
'id': widget_id,
'class': 'my-widget'
});
this.onClick('doSomething');

// build your entire widget over here
},

doSomething: function() {
// do something about the click
}
});

NOTE: now you never leave the actual element context, don't need to worry about bindings, and then, can manipulate with your widget as a usual element on your page.

var widget = new MyWidget('widget-id');
widget.insertTo('some-element', 'after');
widget.addClass('custom-class');

// more of that!
$('widget-id') instanceof MyWidget; // true!

And there is more! You can inherit your private wrappers as any other and create different versions of your widget!

var MySuperWidget = new Wrapper(MyWidget, {
initialize: function(widget_id) {
this.$super(widget_id);

this.onClick('doSuperThing');
},

doSuperThing: function() {
// do the super thing over here!
}
});

You can create abstract widgets, share modules between them, do any sorts of crazy things, the possibilities are endless! And at the end, you still have an Element, which you can toss around the page in the usual way.

---

Oh yes my dear fellas, RightJS 2 will help you to kick some serious ass! The right way!

And this is about it. Come over for the next session, it will be fun!

No comments: