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
    Animated 3D Flipping Menu with CSS

    CSS animations aren't just for basic fades or sliding elements anymore -- CSS animations are capable of much more.  I've showed you how you can create an exploding logo (applied with JavaScript, but all animation is CSS), an animated Photo Stack, a sweet...

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

Incredible Demos

  • By
    Simple Image Lazy Load and Fade

    One of the quickest and easiest website performance optimizations is decreasing image loading.  That means a variety of things, including minifying images with tools like ImageOptim and TinyPNG, using data URIs and sprites, and lazy loading images.  It's a bit jarring when you're lazy loading images and they just...

  • By
    Flexbox Equal Height Columns

    Flexbox was supposed to be the pot of gold at the long, long rainbow of insufficient CSS layout techniques.  And the only disappointment I've experienced with flexbox is that browser vendors took so long to implement it.  I can't also claim to have pushed flexbox's limits, but...

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!