MooTools Class Creation Tips

By  on  

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!

Recent Features

  • By
    9 Mind-Blowing Canvas Demos

    The <canvas> element has been a revelation for the visual experts among our ranks.  Canvas provides the means for incredible and efficient animations with the added bonus of no Flash; these developers can flash their awesome JavaScript skills instead.  Here are nine unbelievable canvas demos that...

  • By
    CSS vs. JS Animation: Which is Faster?

    How is it possible that JavaScript-based animation has secretly always been as fast — or faster — than CSS transitions? And, how is it possible that Adobe and Google consistently release media-rich mobile sites that rival the performance of native apps? This article serves as a point-by-point...

Incredible Demos

  • By
    Create a Spinning, Zooming Effect with CSS3

    In case you weren't aware, CSS animations are awesome.  They're smooth, less taxing than JavaScript, and are the future of node animation within browsers.  Dojo's mobile solution, dojox.mobile, uses CSS animations instead of JavaScript to lighten the application's JavaScript footprint.  One of my favorite effects...

  • By
    Create Twitter-Style Dropdowns Using jQuery

    Twitter does some great stuff with JavaScript. What I really appreciate about what they do is that there aren't any epic JS functionalities -- they're all simple touches. One of those simple touches is the "Login" dropdown on their homepage. I've taken...

Discussion

  1. Thanks, this is quite useful. I find that davidwalsh.name has almost become the defacto mootools site ;)

  2. 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.

  3. 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.

  4. var that = this;

    :D

  5. 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.

  6. 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?

  7. MarkD

    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.

  8. chris

    thanks been punching myself dealing with the pitfalls of bind and found this how to, thanks, self rocks@!

  9. 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 as bind(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!!!

    var self = this; // .bind(this) on event functions obviously will not work!
    new Element('li', {
    	html: this.markQuerySelection(r.title),
    	rel: this.liFocus+i,
    	styles: Object.merge({
    		'background-color': (i%2?this.options.listEvenColor:this.options.listOddColor)
    	}, this.options.listItemStyles),
    	events: {
    		mouseover:function(e){
    			this.tween('background-color', '#fffcb0')
    		},
    		mouseout: function(e) {
    			this.tween('background-color', (i%2?self.options.listEvenColor:self.options.listOddColor))
    		}
    	}
    })
  10. OK. Any ideas on this one? This is a snippet from a JS Class. self.fnUpdateMediaValues(); is another method in the same class.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!