MooTools Class Creation Tips
Writing MooTools classes can be a daunting task, even for a novice MooTools developer. Here are a few tips I've picked up along the way that will take your Moo plugin / class development to the next level.
self = this
Using the this keyword is essential in MooTools but can become annoying when you need to use binding frequently. For example:
/* dreadful use of bind instead of "self" */ //more class code above }, someMethod: function() { this.elements.each(function(element) { if(element.value == this.options.defaultValue) { element.set('value',''); } },this); var request = new Request({ method: 'get', url: 'page.php', data: { ajax: 1 }, onRequest: function() { this.options.textIndicator.set('text','Updating ' + this.elements.length + ' element...'); }.bind(this), onSuccess: function() { this.options.textIndicator.set('text','Update successful. ' + this.elements.length + ' elements updated.'); }.bind(this), onFailure: function() { this.options.textIndicator.set('text','Failed to update ' + this.elements.length + ' elements.'); }.bind(this) }).send(); }, //more class code below
Instead of binding everything under the sun, set a self var that is equal to the this to avoid that mess:
/* better */ //more class code above }, someMethod: function() { var self = this; self.elements.each(function(element) { if(element.value == self.options.defaultValue) { element.set('value',''); } }); var request = new Request({ method: 'get', url: 'page.php', data: { ajax: 1 }, onRequest: function() { self.options.textIndicator.set('text','Updating ' + self.elements.length + ' element...'); }, onSuccess: function() { self.options.textIndicator.set('text','Update successful. ' + self.elements.length + ' elements updated.'); }, onFailure: function() { self.options.textIndicator.set('text','Failed to update ' + self.elements.length + ' elements.'); } }).send(); }, //more class code below
Classes that use self references include Function, Native, and Swiff.
this.____ = $(this.options.element);
Modifying the class options from inside the class is generally poor practice. Instead of this:
this.options.element = $(this.target.element);
...use this:
this.element = $(this.target.element);
Your class will become shorter and you may accept both strings and Elements as values.
No $/$$ as Default Values
Since your MooTools class is likely not inside the domready() function, assigning default setting values to $('something') or $$('.somethings) is not wise:
var myClass = new Class({ Implements: [Options], options: { elements: $$('a') }, initialize: function() { }, //more down here });
Instead, set them to a string and extend the elements inside the initialize() method:
var myClass = new Class({ Implements: [Options], options: { elements: 'a' }, initialize: function() { this.elements: $$(this.options.elements); }, //more down here });
Step Back: Less Specificity
When creating a MooTools class, take a step back and think "what can I take out of this class to make it more flexible?" The less specific a plugin is, the more flexible and usable the class can be. For that specific use, extend your scaled-back class.
Less Dependencies, More Use
One advantage of using MooTools is that it's highly extensible. While MooTools implements numerous helper functions on native JavaScript objects, if you can avoid using the functionality of another MooTools class that's only use a few times, do it. Less dependencies can make your class more stable and modular.
Hopefully this list of tips can make your future plugin creation more fruitful, clean, and functional!
Thanks, this is quite useful. I find that davidwalsh.name has almost become the defacto mootools site ;)
David,
those are some great tips! I just found myself in a situation when writing a class where I used bind(this) but also needed to reference the element returned in the .each loop. Using self would have really made that easier.
Good tips. I like the “self” idea, but it seems like “self” could be a bad choice of names since it could be confused with the self/window object. I’ve seen other people use a variable called “that” instead. As long as it’s declared with the var keyword, it shouldn’t be a problem, but it’s still potentially confusing.
var that = this;
:D
While this is very useful, keep in mind, that you only should use this where you need it, so on the first level, ‘outside’ an inner function using self in unnecessary.
So what’s the best choice of doing things?
– using bind (or the Binds mutator)
or …
– self (with the additional bonus you have access to “this” too)?
The fundamental difference I think is that the self technique uses closures and the bind uses method encapsulation… so in theory the self is more performent…
@kow: I am not sure I understand what you mean? Maybe you can give an example to clarify? If I understand correctly binding to this wouldn’t be usefull outside of the “first level” either?
Isn’t this closure solution (‘.self’ ) considered bad practice because of possible memory leaks escpecially in our good old friend ie6? Closures can be very powerful but they are quit tricky to handle.
For example you have to clean up the references yourself onBeforeUnload to prevent leaks?
Moo takes care of that when you use their method.
thanks been punching myself dealing with the pitfalls of bind and found this how to, thanks, self rocks@!
Have written dozens of classes over the last few years and today I was spinning my wheels while creating a new element and trying to access
this
as a reference to the element as well asbind(this)
to access class methods and options….Thanks David for posting this have not used the self method in awhile and it was exactly what I was looking for!!!
OK. Any ideas on this one? This is a snippet from a JS Class.
self.fnUpdateMediaValues();
is another method in the same class.