Create Namespaced Classes with MooTools

By  on  

MooTools has always gotten a bit of grief for not inherently using and standardizing namespaced-based JavaScript classes like the Dojo Toolkit does.  Many developers create their classes as globals which is generally frowned up.  I mostly disagree with that stance, but each to their own.  In any event, namespaces are technically just nested objects and I recently shared with you how to create and retrieve nested objects with MooTools.  With those utility functions available, I've modified Class so that you can create namespaced classes easily!

The MooTools JavaScript

The technique below is very much like monkey patching:

(function() {
	
	// Keep reference to the original Class
	var klass = Class;
	
	// Redefine class ("that's deep")
	Class = function(name, params, context) {
		// Find out if this is namespaced or the original method
		var namespaced = (arguments.length > 1);
		
		// Add the class name to the param list
		if(namespaced) params.$name = name;
		
		// Create and get the original class
		var original = new klass(namespaced ? params : name);
		
		// If namespaced, set class into namespace
		if(namespaced) Object.place(name, original, context);
		
		// Return this newly created class!
		return original;
	};
	
})();

I keep a reference to the original Class, as I'll be using it within my new Class function.  The new signature allows for a namespaced class name, the usual class properties, and the context which may be passed to the Object.place method.  The first step is analyzing the arguments provided to Class;  if one argument, it's a traditional class;  if more than one argument is provided, we know we're trying to create a namespaced class and will act accordingly.  You'll also notice that I add a $name property to the class prototype, providing the given class name to the class for later use.  I've found the class' declaredClass property incredibly helpful within Dojo.

Here's how you'd use the new Class function:

// Create a namespaced class
var myClass = new Class("davidwalsh.ui.Slider", {
	initialize: function() { 
		// Do stuff!
	},
	doSomething: function(){}
});
// myClass === davidwalsh.ui.Slider!

// Create an instance of the class
var myInstance = new davidwalsh.ui.Slider({
	// props
});

// Get the name of the declared class
var instanceClassName = myInstance.$name; // equals "davidwalsh.ui.Slider"

The first argument becomes the namespace and class name as a string.  The second argument is the traditional parameters argument.  If only one argument is provided to the Class function, the class is created and returned per usual;  in fact, both the namespaced method and traditional method return the newly created class.  The method provided above is completely backward compatible so you wont have rewrite your existing code.

Namespaced classes are probably a good idea, as many would argue that "polluting" the global namespace with numerous objects can lead to problems.  In any event, this namespacing method should help you make the most of my set/get nested object methods and allow you to keep the global namespace as clean as you'd like!

Recent Features

  • By
    Create Namespaced Classes with MooTools

    MooTools has always gotten a bit of grief for not inherently using and standardizing namespaced-based JavaScript classes like the Dojo Toolkit does.  Many developers create their classes as globals which is generally frowned up.  I mostly disagree with that stance, but each to their own.  In any event...

  • By
    6 Things You Didn’t Know About Firefox OS

    Firefox OS is all over the tech news and for good reason:  Mozilla's finally given web developers the platform that they need to create apps the way they've been creating them for years -- with CSS, HTML, and JavaScript.  Firefox OS has been rapidly improving...

Incredible Demos

  • By
    Element Position Swapping Using MooTools 1.2

    We all know that MooTools 1.2 can do some pretty awesome animations. What if we want to quickly make two element swap positions without a lot of fuss? Now you can by implementing a MooTools swap() method. MooTools 1.2 Implementation MooTools 1.2 Usage To call the swap...

  • By
    Highlighter: A MooTools Search & Highlight Plugin

    Searching within the page is a major browser functionality, but what if we could code a search box in JavaScript that would do the same thing? I set out to do that using MooTools and ended up with a pretty decent solution. The MooTools JavaScript Class The...

Discussion

  1. Alexander

    Interesting article !

    I’m not a namespacing expert, so here goes nothing :

    The big advantage of such a style of class naming is that instead of having a global variable holding each class, the globale namespace is instead polluted with the topmost level of each namespaces used (assuming we have some from core, some from more, some from a few other third party sources and so on…). Plus we add the overhead to lookup properties of properties (it has been proven that it takes more time to access object.child1.child2 than just object). So as I understand it, it gives the clearer categorization of classes (which is the idea behind Request.HTML, Request.JSON already) and reducing a bit the amount of polution of the global namespace, right ?

  2. Alexander

    Sorry to spam the post, but I thought about all this again and wonder about something else.

    1) the variable var myClass in your example will be in the global namespace, so how using namespacing will reduce pollution ?

    2) Where is Object.place defined ? it’s not in the Core or More documentation, nor in JS itself ?

    3) How is using this monkey patching snippet you posted different from doing :

    var davidwalsh = {ui: {}};
    
    davidwalsh.ui.Slider = new Class({
      initialize: function() { 
        // Do stuff!
      },
      doSomething: function(){}
    });
    
    
    • 1. I put the “var myClass =” there to prove that the new method returns the created class like the old method does, even if you use a namespace. That’s why I added “// myClass === davidwalsh.ui.Slider!” as a code comment.

      2. That code lives at the following link, which is right at the top of the post: http://davidwalsh.name/mootools-namespace

      3. Creating nested objects is tedious. And what if you want to override a class if it’s there, create it if it’s not? You’d use a bunch of if statements to create the nesting. This is far more efficient.

  3. Phil Carty

    Nice, clever little tutorial. I had been “unconsciously” using the same as Alexander’s #3 solution of simply having nested objects for the sake of namespacing classes… and as you say, it’s cumbersome and doesn’t feel like a very efficient way of doing things while you code.

    Will be using this technique from now on! Thanks.

  4. Phil Carty

    Nice, clever little tutorial. I had been unconsciously using the same as Alexander’s #3 solution of simply having nested objects for the sake of namespacing classes… and as you say, it’s cumbersome and doesn’t feel like a very efficient way of doing things while you code.

    Will be using this technique from now on! Thanks.

  5. Eric C.

    I found this to be very useful when working on an e-commerce site. I’ve organized it as sitename.classes.Checkout or sitename.classes.Default. Where sitename.classes.Checkout contains the class for checkout code and sitename.classes.Default is site-wide functionality.

    My question is, any suggestion on how to organize the instances of the above classes when they are created?

    For example (assuming this lives inside of a domready event):

    //no namespace, just floating out there
    myclass = new sitename.classes.Checkout({});
    var myclass = new sitename.classes.Checkout({});

    //namespaced
    sitename.fn.Checkout = new sitename.classes.Checkout({});

    //or, just forget about it and do
    new sitename.classes.Checkout({});

    Side note, I’m using Class a bit incorrectly here. I could just create an object to be a bit leaner, since it’s unlikely that I’ll be re-using much of this code.

  6. hanishi

    Hi great blog! Did not come to an idea of “monkey patching” until I found this article. I sort of needed method overload feature in MooTools system as I was porting Java library to MooTools and below is what I have achieved so far. It is a derived version of the famous method overload done by John Resig.
    Since you seem to know the internals of MooTools very well, I was wondering and appreciate very much if you can help me correct or give an advise how it is done in the code below will not produce any side effects. I wanted to protect the “overload” method to be called once it is “finalized” so I had to work on the “wrapper” function.

    (function(){
        var overloaded = function() {
            this.$overloaded = true;
            return this;
        };
    
        Function.implement({
    
            overload: function(fn) {
                if (this.$finalized)
                    throw new Error('The method "overload" cannot be called.');
                if (typeOf(fn) !== 'function' || fn.$overloaded)
                    throw new Error('The method "overload" failed');
    
                var prev = this,
                    next = function() {
                        if (fn.length == arguments.length)
                            return fn.apply(this, arguments);
                        else if(typeOf(prev) === 'function')
                            return prev.apply(this, arguments);
                    };
                return overloaded.call(next);
            },
    
            finalize: function() {
                this.$finalized = true;
                return this;
            }
        });
    
        var wrap = function(self, key, method){
            if (method.$origin) method = method.$origin;
            var wrapper = function(){
                if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.');
                var caller = this.caller, current = this.$caller;
                this.caller = current; this.$caller = wrapper;
                var result = method.apply(this, arguments);
                this.$caller = current; this.caller = caller;
    
                return result;
            }.extend({$owner: self, $origin: method, $name: key});
            if (method.$finalized)
                wrapper.finalize();
            return wrapper;
        };
    
        var implement = function(key, value, retain){
            if (Class.Mutators.hasOwnProperty(key)){
                value = Class.Mutators[key].call(this, value);
                if (value == null) return this;
            }
    
            if (typeOf(value) == 'function'){
                if (value.$hidden) return this;
                this.prototype[key] = (retain) ? value : wrap(this, key, value);
            } else {
                Object.merge(this.prototype, key, value);
            }
    
            return this;
        };
    
        Class.implement('implement', implement.overloadSetter());
    })();
  7. Shawn

    My limited insight into this is there should be 4 nests never more than one deep.. shared.basetemplate class.localtemplate class.protectedtemplate class.privatetemplate.. then when you declare and construct/create an object it builds it’s set of properties and functions from all the templates with that class name and from the shared template.. I am not sure how mooTools does it but I would use an array with classnames as key and directly find the definition of each quickly and I lean more to dynamically adding functions to applications and sharing data / classes / functions between them without accidentally calling a function from a different app… so it is likely an app creates it’s objects if they don’t exist in the correct namespace. Not sure how MooTools works, and this may not make sense, but I am working on a configuration that allows apps to work independently in the browser but still share classes, dataobjects and standard server request functions, while maintaining independent functionality. but I do things different, my application would maintain keyed arrays of objects under the appname.object so finding the object should be quick, most of it’s work happens at init time when libraries are checked and loaded and it’s private libs loaded the libs would be the classes it needs as some would be shared classes and other classes would be loaded under its own name, while yet some would be system classes and I find unlikely to check other classes unless user defined classes become available where they are entered by the user during the session, I however don’t find an app would dependent on anything 3rd party but could use as plugin or extra functionality if existed… just thinking

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