in partnership with mediatemple

Mootools API Basics: getting started programming with mootools

Primer

See also: Mootools Tutorial (the Mootorial) at CNET's Clientside.

Classes

Creating

Class creation is shorter than ever. Instead of the old way of instantiating classes:

var Animal = Class.create();
Animal.prototype = {
    initialize: function(){
        ...
    }
};

We now have:

var Animal = new Class({
    initialize: function(){
        ...
    }
});

If you dont want the initialize method run on instantiation of a class, pass null as a first argument, like this:

var Animal = new Class({
    initialize: function(){
        alert('initializing!');
    }
});
 
var Koala = new Animal(null);

And we'll never see alert from that code. Even if you expect any arguments in initialize method, null will override them.

Extending

Extending a class is also a lot easier. We used to have to do something like this to extend our previously defined classes:

var Mammal = Class.create();
Object.extend(Object.extend(Mammal.prototype, Animal.prototype), {
    initialize: function(){
        ...
    }
});

Now we can forget all those extendings. We just need to do this:

var Mammal = Animal.extend({
    initialize: function(){
        ...
    }
});

What about inheritance? Yes, all the new properties get copied in the new Classes, but what if we override a property and we need the previous one?

Now we can do this:

var Animal = new Class({
    initialize: function(message){
        alert(message);
    }
});

 
var Mammal = Animal.extend({
    initialize: function(message){
        this.parent(message);
    }
});

And by calling new Mammal('hello') we'll be presented with the alert.

Note: parent will always call the method with the same name:

var Cat = Mammal.extend({
    initialize: function(message){
        this.parent(message);
    }
});

It will still alert the message when calling new Cat('meow!'), passing through the Mammal, then the Animal.

Implementing

We now can change how a class behaves without changing the library itself:

Animal.implement({
    initialize: function(message){
        document.write(message);
    }
});

Now, new Mammal will write hello in the document, rather than alerting it. The implement method will copy your object in the class itself.

Native Classes

You can extend native objects by calling their hand-set extend method:

String.extend({
    alert: function(){
        alert(this);
    }
});

The this keyword always refers to the current string:

'hello'.alert();

...will simply greet you with an alert box containing your important message.

You can emulate a native object by calling this function:

new Native(Element);

This is useful if an object/class has to be extendable without assigning it to another variable.

Elements

Basics

With MooTools, you can use the $() function to actually extend an element with the properties you specify

For example:

$('myElement').addClass('className');

Note: We can call the $() function on an element object as well as on an ID string.

Also note: You need to call the $() function on an element only once to 'extend' it:

var el = $('myElement');
 
el.addClass('posting');
el.removeClass('posting');

But its no harm to do this:

$('myElement').addClass('posting');
$('myElement').removeClass('posting');

Chaining

$('myElement').addClass('posting').setStyle('position', 'absolute');

This reduces the verbosity of the code and comes in quite handy many times.

Many built-in methods are chainable. You can easily accomplish this too. Read on and we'll get to that.

Just extend, for example, the Element class with a method/more methods:

Element.extend({
    makeRed: function(){
        this.style.color = 'red';
    },
    
    makeBlue: function(){
        this.style.color = 'blue';
    }
});

The keyword this always refers to the current element.

Call your method on an existing element with the $() function:

$('myElement').makeRed();
//This will make the element red, but you want a color changing rainbow chain

$('myElement').makeRed().makeBlue();
//But this won't work yet, we haven't chainified our methods

To be able to chain your methods, just add return this; at the end of the method.

Element.extend({
    makeRed: function(){
        this.style.color = 'red';
        return this;
    },
    
    makeBlue: function(){
        this.style.color = 'blue';
        return this;
    }
});

What your methods return is then sent further down the chain. May it be a string, an array, or a reference to an element.

In this case we return a reference to the element you called the method on. That's what return this does. It makes sense to do this for most methods.

But we could as well return something else, if useful.

Element.extend({
        makeRed: function(){
                this.style.color = 'red';
                return "Oh no, I've been shot!";
        },

        makePurple: function(){
                this.style.color = 'purple';
                return "Stop choking me!";
        }
});

// The Element methods return strings, so we'll extend the String object
String.extend({
        alert: function(){
                alert(this);
                return this;
        }
});

$('element').makeRed().alert();
$('element').makePurple().alert();

Effects

Element.effects()

This stuff leads to a shorter effects creation. By extending the element this way:

Element.extend({
    
    effect: function(property, options){
        return new Fx.Style(this, property, options);
    }
    
});

...we can now create effects like this:

var myEffect = $('myElement').effect('height', {duration: 1000, transition: Fx.Transitions.Sine.easeOut});

And call its method this way:

myEffect.start(10, 100);

Note: this code will generate a new Fx.Style

The following will set the margiun of 'myElement, insert it before 'myOtherElement', and create and start an opacity effect:

$('myelement').setStyle('margin', '10px').injectBefore($('myOtherElement')).effect('opacity').start(0,1);

Fx.Style

The effects part of the library retains all the previous functionalities, but takes advantage of the element extension model, the new classes implementation and we now have to very useful nuggets at our disposal: **Fx.Style** and **Fx.Styles**.

With **Fx.Style** you can control any css property of an element:

var marginChange = new Fx.Style('myElement', 'margin-top', {duration:500});
marginChange.start(10, 100);

Note: you can use marginTop (camelcase, a few ms faster) instead of margin-top (CSS-rule style).

Fx.Styles

Fx.Styles allows you to animate multiple properties at once. You don't specify the properties you intend to modify at first -- when you call the start method you just pass it the properties as an object: {'property': [from, to], 'otherproperty': [from, to], 'anotherproperty': [to]}

Like this:

var myEffects = new Fx.Styles('myElement', {duration: 1000, transition: Fx.Transitions.Sine.easeOut});
 
myEffects.start({'height': [10, 100], 'width': [900, 300]});

This syntax is a little bit odd, yet very powerful.

Note that you can implement any new methods you like to the styles effect with the new class behavior:

Fx.Styles.implement({
    
    move: function(topTo, leftTo){
        this.start({'top': [this.el.getStyle('top', true), topTo], 'left': [this.el.getStyle('left', true), leftTo]});
    }
    
});

This is how we use our new method:

myEffects.move(100, 200);

Our element will move from the current position (read by getStyle) to the new position, determined by the two arguments.

Wrap Up

Well that's all for now... check out the rest of the resources all over the site for more MooTools greatness!