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
    Responsive Images: The Ultimate Guide

    Chances are that any Web designers using our Ghostlab browser testing app, which allows seamless testing across all devices simultaneously, will have worked with responsive design in some shape or form. And as today's websites and devices become ever more varied, a plethora of responsive images...

  • By
    Creating Scrolling Parallax Effects with CSS

    Introduction For quite a long time now websites with the so called "parallax" effect have been really popular. In case you have not heard of this effect, it basically includes different layers of images that are moving in different directions or with different speed. This leads to a...

Incredible Demos

  • By
    Create a Brilliant Sprited, CSS-Powered Firefox Animation

    Mozilla recently formally announced Firefox OS and its partners at Mobile World Congress and I couldn't be more excited.  Firefox OS is going to change the lives of people in developing countries, hopefully making a name for itself in the US as well.  The...

  • By
    The Simple Intro to SVG Animation

    This article serves as a first step toward mastering SVG element animation. Included within are links to key resources for diving deeper, so bookmark this page and refer back to it throughout your journey toward SVG mastery. An SVG element is a special type of DOM element...

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!