Extending Objects and Classes with mootools
September 12, 2006
I love the moo libraries. Despite my passion and knowledge of the Prototype JavaScript libary, I’ve never used it in a commercial project. I have used moo.fx (and the included prototype.lite) for actual client work and been very satisfied with the results. The moo libraries are very lightweight, organized and clean. They are well thought-out and extendable, and you won’t find any bloatware within.
Now Valerio Proietti has decided to grace us all with his new library, mootools. mootools is like a cross between Prototype and jQuery, with an emphasis on clean, Object-Oriented code and lean, modular design. The library has the most inspired download feature of all libraries — it allows you to pick and choose modules and automatically figures out the dependencies and compresses the code for you.
In this article we’ll take a look at one of the library’s coolest features: extending JavaScript and the library’s functionality.
Extending objects
On the surface, extending objects in mootools works just like Prototype. There is an Object.extend function that takes two arguments: destination and source.
var test = {hello: 'world'};
Object.extend(test, {animal: 'sloth'});
// test now contains "{hello: 'world', animal: 'sloth'}"
At this point mootools diverges from Prototype and adds some nice functionality to help you extend the libary and JavaScript itself.
Class inheritance
mootools implements a class inheritance scheme that is inspired by Dean Edwards’ wonderful Base class. Creating a class is similar to Prototype, but now you don’t ever have to think about the prototype object when you define the class:
var Shape = new Class({
initialize: function(width, height) {
this.width = width;
this.height = height;
},
draw: function() {
console.log('starting to draw...');
}
});
Now we’ll probably never use the Shape class because it’s abstract, so let’s see how mootools lets us extend the class:
var Square = Shape.extend({
draw: function() {
this.parent();
console.log('drawing square');
}
});
Some of you may be wondering where the extend() method on Shape came from. You can breathe a sigh of relief, because it’s not coming from Object.prototype (whew!). Any class created with new Class() gets an extend method. When you use the extend method to define a child class, the parent class remains untouched. The child class inherits all of its parents’ properties and methods. Each of the child’s methods also has access to the parent’s method of the same name, accessed by calling this.parent() within a method.
To see this in action, let’s instantiate a new Square object:
var square = new Square(150, 150);
square.draw();
// Logs "starting to draw...", then "drawing square" to the console
Finally, an easy way to define classes and inheritance schemes in JavaScript!
Multiple inheritance with Class.implement()
mootools supports multiple inheritance in a Ruby mixin style with the Class.implement() method. Using the implement method of an existing class, that class can inherit methods and properties from another class or object. Unlike Class.extend(), the implement method is called on the class you are modifying, not on the object being copied. This method can be used to support multiple inheritance:
var UsefulGlobalObject = {
inspect: function() {
var results = [];
for (var i in this) {
results.push(i + ': ' + this[i]);
}
return results.join(",n");
}
};
var Circle = Shape.extend({
draw: function() {
this.parent();
console.log('drawing circle');
}
});
Circle.implement(UsefulGlobalObject);
Let’s assume UsefulGlobalObject really is a useful global object. Passing this object to Circle.implement() copies all properites of the object to Circle’s prototype, so any circle object will now have the method inspect(). If we were copying from a parent class instead of an object, the syntax would use the new keyword:
Shape.ThreeDimensional = new Class({
rotate: function(degrees, plane) {
console.log('rotating by ' + degrees + ' on the ' + plane + ' plane');
}
});
var Sphere = Shape.extend({
draw: function() {
this.parent();
console.log('drawing sphere');
}
});
Sphere.implement(new Shape.ThreeDimensional);
Sphere has inherited from both the Shape class and the Shape.ThreeDimensional class.
Extending library classes and native objects
Another use for the implement() method is for modifying a library class in a different code module, or even dynamically adding to a class at runtime. This is similar to Ruby, where you can reopen a class definition at any time to add new methods. We can use the implement() method to add or overwrite any method in a mootools class in our own code so that we don’t have to modify the library itself:
Ajax.implement({
// add a new method
newMethod: function() {
// new method code
},
// overwrite an existing method
request: function() {
// overwrite the original request method
}
});
This code will add a new method newMethod and overwrite the request method for the Ajax object.
One last feature of the mootools library is the concept of Native Objects. String, Function and Array have been turned into mootools native objects, which essentially means their extend() method is an alias for the implement() method. Calling extend() on these objects adds properties and methods to them just like Class.implement() does. It makes the syntax for extending a native object even sweeter:
Array.extend({
map: function(fn) {
for (var i = 0, a = []; i < this.length; i++) {
a[i] = fn(this[i]);
}
return a;
}
});
Any method you extend a JavaScript native object (String, Function, Array) with will have the new methods attached, even if it was created before the call to extend(). Note that the Number object is not a native object in mootools, but you can easily change that by calling Object.Native():
new Object.Native(Number);
Number.extend({
isOdd: function() {
return !!(this % 2);
}
});
mootools also provides the Element and Elements classes as native objects, so they can easily be extended just as JavaScript native objects:
Element.extend({
visible: function() {
return this.style.display != 'none';
},
toggle: function() {
this[this.visible() ? 'hide' : 'show']();
return this;
},
hide: function() {
this.style.display = 'none';
return this;
},
show: function() {
this.style.display = '';
return this;
}
});
The Element class in mootools contains all the methods that get bound onto any DOM node passed through the $() function. Note that if you call Element.extend(), any methods or properties you add to the Element class won’t automatically be added to any elements that have already been run through the $() function. We’ll cover extending DOM nodes in an upcoming post.
Plugin friendly
The mootools library is brand new, but it has a solid codebase that stands on the shoulders of giants like Prototype and Dean Edwards. It provides a lot of great features right out of the box, but it’s also been written to make class inheritance and object extension very simple. This encourages traditional use of class inheritance schemes, as well as adding your own extensions and plugins to the library on an as-needed basis, without having to modify the original source code.
September 13th, 2006 at 4:02 am
Nice article, dude. It’s cool when people use and dig into the stuff you’re working on.
September 15th, 2006 at 5:59 am
Nice article ! Brief, understandable, compact, nice !
Helped a lot for newbies like me !
Thank you very much on the quick article bout this mootols
September 20th, 2006 at 7:22 pm
So, question. We (I work at CNET) have a set cookie class that allows us to specify a domain (because we want to be able to set cookies across sub-domains). So I want to overwrite Cookie.set with our own function.
Cookie doesn’t seem to be an Object.Native (it doesn’t have an extend() function). I can call Object.Native(Cookie), which works and adds .extend() to it, but when I try and extend it, I get a compliant that Cookie.prototype is not defined (in Moo.js: this.prototype[property] = properties[property];)
So is the right way to overwrite the set property to just do Cookie.set = …? That seems not to go along with the implement() functionality as you’ve described it here…
September 24th, 2006 at 4:26 pm
Aaron, Cookie is n’t usual class, but singleton. It’s just an object. So the best way is just Cookie.set.
November 5th, 2006 at 12:14 am
[…] Extending Objects and Classes with mootools | CoryHudson.com I love the moo libraries. Despite my passion and knowledge of the Prototype JavaScript libary, I’ve never used it in a commercial project. I have used moo.fx (and the included prototype.lite) for actual client work and been very satisfied with the resul (tags: howto programming tutorial tutorials mootools moo.fx oop framework ajax) […]
April 3rd, 2007 at 12:16 am
Very useful article. I’ve been playing with mootools and the end part about using Object.Native made my life easier - extending Date via this instead of prototype functions.
April 26th, 2007 at 12:06 pm
I’m not quite understanding what all
this is supposed to be about?
Must be me or something…
May 18th, 2007 at 4:30 am
A good article on mootools, but you must have also mentioned and explained how to utilize the library and add it in the header. Like there is an addon library because many would add all the mootools code which will be nothing but prototype.js
August 3rd, 2007 at 1:10 am
please add delicious button, it`d be easier to bookmark your article for others!
thx
September 22nd, 2007 at 2:53 am
Good article on class inheritance
thanks
September 26th, 2007 at 3:59 am
Good function and coding technique
ratan
india
September 26th, 2007 at 4:00 am
I am new to this tecnology but i find here very good information for me
thanks
pooja
November 3rd, 2007 at 12:04 pm
Lots of people still cannot decide what to use – cash or credit cards. Credit cards give you convenience but cash gives you independence. When you apply for any type of credit card, be sure, you will carry some debt. However smart credit cardholders can use their plastic to advantage. Find your credit card with low rates and best rewards at
fingerhut .com
mc216d
November 13th, 2007 at 9:44 am
renoa without a prescription
renoa without a prescription
November 15th, 2007 at 11:33 am
Serbia vacations: Visit TripAdvisor, your source for the web’s best reviews and travel articles about tourism and vacation packages in Serbia, Europe.
Fishing areas give the basis for Serbia tourism
November 15th, 2007 at 8:24 pm
dodge magnum rental car
dodge magnum rental car
February 8th, 2008 at 10:17 am
[…] The Element class in Mootools has been turned into a native object, so you can extend it to add to the methods that get copied onto all DOM nodes passed through the $ function, just like the Mootools system of extending objects. This is similar to extending a native JavaScript object, with the exception that it only works on DOM nodes passed through $ after calling Element.extend: […]