Extending Element With Your MooTools Class Is Awesome
By Ryan Florence, published 2010-03-16
Part of the issue Migrated Articles From Original Site Structure..
Almost every class that is centered around an element deserves a few element shortcuts. You’ve used them plenty of times already but maybe you haven’t written one. Here’s what I’m talking about.
var el = $('myelement');
// element shortcuts
el.fade('in'); // Fx.Tween
el.load('something_impressive.html'); // Request.HTML
el.makeDraggable(); // Drag.Move
I think the best way to do it is the way that Fx.Tween
does it–and just about all the other -core and -more scripts that deal with an element–which is two-fold:
- Create element properties for your class
- Define element extensions
You can skip number 1 if you want and just do:
Element.implement({
beAwesome: function(options){
return this.store('awesome', new AwesomeClass(this, options));
}
});
// usage
$('element').beAwesome(options);
But you may get more mileage by using step 1.
Create element properties for your class
Element.Properties
is what makes el.set('whatever', arg)
possible. Let’s use Tween
as an example. In order to be able to make el.set('tween', options)
available we have to create the element property tween
with a setter and getter.
Element.Properties.tween = {
set: function(options){
var tween = this.retrieve('tween');
if (tween) tween.cancel();
return this.eliminate('tween').store('tween:options', $extend({link: 'cancel'}, options));
},
get: function(options){
if (options || !this.retrieve('tween')){
if (options || !this.retrieve('tween:options')) this.set('tween', options);
this.store('tween', new Fx.Tween(this, this.retrieve('tween:options')));
}
return this.retrieve('tween');
}
};
I’ll let you check the MooTools docs for the stuff inside there that’s unfamiliar. Essentially it lets you set options for an instance of Fx.Tween
on your element, and get the instance if you need if for something–something like an element shortcut for your class!
These methods, called “getters” and “setters”, make it easy to extend Element
. Fx.Tween
adds a few element methods: tween
, fade
, and highlight
. I’m going to list them all here but split them up to talk a bit.
Element.implement({
tween: function(property, from, to){
this.get('tween').start(arguments);
return this;
},
// ...
See how simple it becomes once you define the Element.Properties
? When you do $('el').tween('height', 300)
it only takes one line of code in the method above to make it all happen. Next up is fade.
// ...
fade: function(how){
var fade = this.get('tween'), o = 'opacity', toggle;
how = $pick(how, 'toggle');
switch (how){
case 'in': fade.start(o, 1); break;
case 'out': fade.start(o, 0); break;
case 'show': fade.set(o, 1); break;
case 'hide': fade.set(o, 0); break;
case 'toggle':
var flag = this.retrieve('fade:flag', this.get('opacity') == 1);
fade.start(o, (flag) ? 0 : 1);
this.store('fade:flag', !flag);
toggle = true;
break;
default: fade.start(o, arguments);
}
if (!toggle) this.eliminate('fade:flag');
return this;
},
// ...
This looks bigger than it is. It simply gets the tween from the element (just like before), sets the property to tween as opacity, and then decides how to fade it with the switch statement. If it weren’t for toggle
this block would only be 10 or 11 lines long. Pretty awesome. Next is highlight
.
// ...
highlight: function(start, end){
if (!end){
end = this.retrieve('highlight:original', this.getStyle('background-color'));
end = (end == 'transparent') ? '#fff' : end;
}
var tween = this.get('tween');
tween.start('background-color', start || '#ffff88', end).chain(function(){
this.setStyle('background-color', this.retrieve('highlight:original'));
tween.callChain();
}.bind(this));
return this;
}
});
If you didn’t know, el.highlight
flashes the background color of an element. This is the most complicated of the three for sure because it has to store the original background color or pick a default (#ffff88) and then clean up camp by putting things back to how they were before. However, it’s still a very basic script that’s easy to implement because Fx.Tween
has all the logic for animating a property, and Element.properties.tween
has all the logic for setting and getting a tween instance for an element. All that’s left to do is come up with a few useful shortcuts and implement them.
Here’s an idea, $('el').grow(100)
.
Element.implement({
grow: function(amount){
var tween = this.get('tween');
var to = this.getSize().y + amount.toInt();
tween.start('height', to);
return this;
}
});
Here’s some homework, edit the example below to include a shrink
method.
Now find one of your classes that is centered around an element and create some element shortcuts.