sans-serif   serif

«

11 Tips for Creating Great MooTools Plugins

February 16, 2010

Here’s a sort of “best practices” that I follow when creating mootools classes in no particular order whatsoever.

  • Check the forge before starting
  • Extend existing classes
  • Add and remove events with methods named attach & detach
  • Create Elements in methods named build
  • Store the main element(s) as this.element & this.elements
  • Ensure religiously that this always references the class instance
  • Write methods to do one thing only
  • Fire events anytime something awesome happens
  • Create options for things that the class doesn’t need
  • Return this with most methods
  • Name my classes Nouns (capitalized) and my methods verbs

1. Check the forge before starting

Since the release of the forge I check for work others have already done. If there is something similar I’ll fork it on github, make what I consider to be improvements, and then send a pull request to the original author. I did this with StaticScroll. It had most of what I needed, so I forked it, added the features I needed, and then Luke Ehresman incorporated the changes and updated it on the forge.

2. Extend existing classes

When I first started writing classes with mootools I did a lot of:

initialize: function(element){
  this.tween = new Fx.Tween(element,{
    duration: 'some-horrible-hard-coded-options',
    transition: this.namespaced.options.that.are.lame
  });

  // ...

  this.tween.start(0,100);
}

Duh. If I’d just extend Tween then I’d get all of it’s options and methods from the start. More often then not I’m just adding some fun to an existing class like Tween or Request.

var Fx.Tween.Toggle = new Class({
  Extends: Fx.Tween
});

3. Add and remove events with methods named attach & detach

I always name the method where I add events attach and always provide myself a way to remove the events with detach. When you’re working with multiple objects sometimes they can bump into each other and you need to detach some events.

//...
initialize: function(element){
  this.element = document.id(element);
  this.bound = this.someMethod.bind(this);
},

attach:function(){
  this.element.addEvent('click', this.bound);
  return this;
},

detach: function(){
  this.element.removeEvent('click', this.bound);
  return this;
}
//...

4. Create Elements in methods named build

I always name any method that creates new elements build or buildMenu, or whatever. I also try not to do any adding of events here, even though Element supports it quite well.

build: function(){
  this.wrapper = new Element('div').inject(this.element);
  return this;
}

5. Store the main element(s) as this.element & this.elements

I do this to keep my world consistent across all plugins. If the class takes an element I call it this.element, even if it’s a “container” or any other tempting name. I do the same for classes with a handful of elements. Though, with event delegation, I usually just need one element.

initialize: function(element){
  this.element = document.id(element);
}

6. Ensure religiously that this always references the class instance

ALWAYS!

7. Write methods to do one thing only

It makes me sad when I pop open a plugin and it’s got one ginormous method that does everything known to geek. You can’t extend classes that have nothing more than a 200 line initialize method. Look at all the -more plugins (and for that matter, any of Aaron Newton’s stuff on clientcide) and you’ll see how he gets a ton of mileage out of his classes.

I get excited when I pop open a class and see that I can easily extend it because it’s got several single purpose methods. Like, really excited. I yell to my wife “Hey, check out the methods on this class! It’s so extendable!” Unfortunately, she never cares because she has no clue what I’m talking about. “I’ve told you a thousand times I don’t know what a moo tool is and I don’t care.”

8. Fire events anytime something awesome happens

Imagine if you were doing ajax stuff and Request didn’t have onSuccess, what’s the point? A class should usually have a custom event fire every time something awesome happens.

Implements: [Options, Events],
//..
beAwesome: function(){
  this.element.beAwesome();
  this.fireEvent('onAwesomeness');
}

9. Create options for things that the class doesn’t need

It’s sometimes hard for me to decide if something should be an option or an argument for the constructor, or something else. When in doubt, I make it an option. In addition to the options object, I tend to have just one argument for the constructor and get really nervous if I want more than two. Additionally, I next-to-never hard-code in strings and numbers and such.

10. Return this with most methods

If you return this with each method then you can chain the methods of your class. Occasionally a method need to return something else, but most of the time you should return this.

doSomethingAwesome: function(){
  // do cool stuff
  return this;
},

doSomethingImportant: function(){
  // do important stuff
  return this;
}

myInstance.attach().doSomethingImportant().doSomethingAwesome().detach();

11. Name my classes Nouns (capitalized) and my methods verbs

Sometimes when a method returns a value, I’ll make it a noun, but generally it’s a verb like ‘jump’, ‘getSomething’, ‘checkStuff’, etc.

Got some patterns of your own? Let’s hear it in the comments!

Related Posts:

  • No Related Posts

Comments

  • http://mad4milk.net Valerio

    Good stuff! I should follow these advices more often when I create MooTools plugins.

    I only disagree with #9. You can always add options later when users complain…

  • Henrik Hansen

    I’d like to add some more:

    • When possible, use other classes and plug-ins to make you’re plug-in do what it should. This is much like #1 and #2 yet it’s more general and not only about extending and making new plug-ins/classes.

    • Use toElement if it makes sense. Just do it, it’s so helpful.

    • Make the class as general as possible and then build on additional functionality using extends. Doing this gives you cleaner and simpler code that is easier to use and maintain.

  • http://www.luismerino.name Luis Merino

    In addition to your good advices, I’d say “use build more like this”:

    initialize: fu… this.elements.each(this.build, this); …}

    And, if you are going to be using composition “this.element.store(‘instance’, this)”; might be a good idea.

  • http://nicbell.net Nic Bell

    Solid advice especially about returning this and firing events.

  • emehrkay

    Great read! I love number 7. One thing that I do, and it is from using other langs, is try to define the members at the top of the object. I like this as a point of reference to know what is possibly being set and used in the object.

    shown: false, running: false, Implements: [Options, Events], …etc

  • http://www.must-art.de/ Jan Philipp Pietrzyk

    A Question to Number 6:

    Whats against ‘var self = this;’? It looks a lot clearer than binding the hell aut of your Event listeners.

  • Ryan Florence

    @Jan – I use var self = this quite often, actually. My example here, however, follows the patterns set in -core and -more.

blog comments powered by Disqus

Comments RSS