Extending MooTools

0
811
7 min read

 

MooTools 1.3 Cookbook

MooTools 1.3 Cookbook

Over 100 highly effective recipes to turbo-charge the user interface of any web-enabled Internet application and web page

        Read more about this book      
Learn Programming & Development with a Packt Subscription

(For more resources on this topic, see here.)

The reader can benefit from the previous article on MooTools: Extending and Implementing Elements.

 

Making a Corvette out of a car-extending the base class

The “base class” is a function, a method, that allows extension. Just what does extending a class entail? Buckle up and let us take a drive.

Getting ready

Just to show the output of our work, create a DIV that will be our canvas.

<div id="mycanvas"></div>

How to do it…

Creating a class from the base class is as rudimentary as this: var Car = new Class();. That is not very instructive, so at the least, we add the constructor method to call at the time of instantiation: initialize.

<script type="text/javascript">
var Car = new Class({
initialize: function(owner) {
this.owner = owner;
}
});

The constructor method takes the form of a property named initialize and must be a function; however, it does not have to be the first property declared in the class.

How it works…

So far in our recipe, we have created an instance of the base class and assigned it to the variable Car. We like things to be sporty, of course. Let’s mutate the Car into a Corvette using Extends and passing it the name of the Class to make a copy of and extend into a new class.

var Corvette = new Class({
Extends: Car,
mfg: 'Chevrolet',
model: 'Corvette',
setColor: function(color) {
this.color = color;
}
});

Our Corvette is ready for purchase. An instantiation of the extended class will provide some new owner happiness for 5 years or 50,000 miles, whichever comes first. Make the author’s red, please.

var little_red = new Corvette('Jay Johnston');
little_red.setColor('red');
$('mycanvas').set('text',little_red.owner+"'s little
"+little_red.color+' '+little_red.model+' made by
'+little_red.mfg);
</script>

There’s more…

This entire example will work identically if Corvette Implements rather than Extends Car.

Whether to Extend or to Implement
Extending a class changes the prototype, creating a copy in which the this.parent property allows for the overridden parent class method to be referenced within the extended class’s current method.
To derive a mutation that takes class properties from multiple classes, we use Implements.

Be sure to place the Extends or Implements property first before all other methods and properties. And if both extending and implementing, the Implements property follows the Extends property.

See also

See how Moo can muster so much class: http://mootools.net/docs/core/Class/Class#Class.

 

Giving a Corvette a supercharger-Implements versus Extends

Be ready to watch for several things in this recipe. Firstly, note how the extended corvette methods can use this.parent. Secondly, note how the implemented corvette, the ZR1, can implement multiple classes.

Getting ready

Create a canvas to display some output.

<h1>Speed Indexes:</h1>
<div id="mycanvas"></div>

How to do it…

Here we create a class to represent a car. This car does not have an engine until it goes through further steps of manufacturing, so if we ask what its speed is, the output is zero. Next, we create a class to represent a sporty engine, which has an arbitrary speed index of 10.

// create two classes from the base Class
var Car = new Class({
showSpeed: function() { return 0; }
});
var SportyEngine = new Class({
speed: 10
});

Now we get to work. First, we begin by manufacturing corvettes, a process which is the extension of Car, they are faster than an empty chassis, of course, so we have them report their speed as an index rating one more than the parent class.

// Extend one, Implement the other
var Corvette = new Class({
Extends: Car,
showSpeed: function() {
// this.parent calls the overridden class
return this.parent()+1;
}
});

Secondly, we implement both Car and SportyEngine simultaneously as ZR1. We cannot use this.parent so we return the speed if asked. Of course, the ZR1 would not have a speed if only a mutation of Car, but since it is also a mutation of SportyEngine it has the speed index of that class.

var ZR1 = new Class({
// multiple classes may be implemented
Implements: [Car, SportyEngine], // yep
showSpeed: function() {
// this.parent is not available
//return this.parent()+1; // nope
return this.speed;
}
});

How it works…

When an instantiation of Corvette is created and its showSpeed() method called, it reports the speed of the parent class, Car, adding 1 to it. This is thanks to the magic Extends provides via this.parent().

var corvette = new Corvette();
var zr1 = new ZR1();

$('mycanvas').set('html',
'<table>'+
'<tr><th>Corvette:</th>'+
'<td>'+corvette.showSpeed()+'</td></tr>'+
'<tr><th>ZR1:</th>'+
'<td>'+zr1.showSpeed()+'</td></tr>'+
'</table>');

And so, the output of this would be:

Corvette: 1

ZR1: 10

An instantiation of ZR1 has the properties of all classes passed to Implements. When showSpeed() is called, the value conjured by this.speed comes from the property defined within SportyEngine.

 

Upgrading some Corvettes—Extends versus Implements

Now that we have reviewed some of the reasons to extend versus implement, we are ready to examine more closely how inheritance within Extends can be useful in our scripting.

Getting ready

Create a display area for the output of our manufacturing plant.

<h1>Speeds Before</h1>
<div id="before"></div>

<h1>Speeds After</h1>
<div id="after"></div>

How to do it…

Create two classes, one that represents all car chassis with no engine and one that represents a fast engine that can be ordered as an upgrade. This section is identical to the last recipe; if necessary, review once more before continuing as the jist will be to alter our instantiations to display how inheritance patterns affect them.

// create two classes from the base Class
var Car = new Class({
showSpeed: function() { return 0; }
});
var SportyEngine = new Class({
speed: 10
});

// Extend one, Implement the other
var Corvette = new Class({
Extends: Car,
speed: 1,
showSpeed: function() {
// this.parent calls the overridden class
return this.parent()+1;
}
});
var ZR1 = new Class({
// multiple classes may be implemented
Implements: [Car, SportyEngine], // yep
showSpeed: function() {
// this.parent is not available
//return this.parent()+1; // nope
return this.speed;
}
});

Note that the output before mutation is identical to the end of the previous recipe.

var corvette = new Corvette();
var zr1 = new ZR1();

$('before').set('html',
'<table>'+
'<tr><th>Corvette:</th>'+
'<td>'+corvette.showSpeed()+'</td></tr>'+
'<tr><th>ZR1</th>'+
'<td>'+zr1.showSpeed()+'</td></tr>'+
'</table>');

Here is what happens when the manufacturing plant decides to start putting engines in the base car chassis. That gives them a speed, where they did not have one previously. Mutate the base class by having it return an index of five rather than zero.

// the mfg changes base Car speed to be +5 faster
Car = Car.implement({
showSpeed: function() {
return 5;
}
});

// but SportyEngine doesn't use the parent method
$('after').set('html',
'<table>'+
'<tr><th>New Corvette:</th>'+
'<td>'+corvette.showSpeed()+'</td></tr>'+
'<tr><th>New ZR1</th>'+
'<td>'+zr1.showSpeed()+'</td></tr>'+
'</table>');

How it works…

The zr1 instantiation did not mutate. The corvette instantiation did. Since zr1 used implements, there is no inheritance that lets it call the parent method.

In our example, this makes perfect sense. The base chassis comes with an engine rated with a speed of five. The ZR1 model, during manufacturing/instantiation is given a completely different engine/a completely different property, so any change/recall of the original chassis would not be applicable to that model.

For the naysayer, the next recipe shows how to effect a manufacturer recall that will alter all Corvettes, even the ZR1s.

There’s more…

There is an interesting syntax used to mutate the new version of Car, Class.implement(). That same syntax is not available to extend elements.

See also

Here is a link to the MooTool documentation for Class.implement(): http://mootools.net/docs/core/Class/Class#Class:implement.

 

NO COMMENTS

LEAVE A REPLY

Please enter your comment!
Please enter your name here