6

Suffice it to say, I'm wanting to branch my plugin writing a bit, and decided I want to be able to "namespace" them. So far, rewriting the $.method ones to $.namespace.method has been easy.

The problem I'm having is making Element Methods such as $('element').method(), but to use a namespace; for example $('element').namespace.method(). I've tried a few workarounds and can create $.fn.namespace.method, however, when I call this from within that method, I only get $.fn.namespace and not the 'element' that I'd like to get.

Example: If i call $('body').namespace.test(), then inside method test, I want this to be the element <body></body>

Any help figuring out how to pull this off much appreciated. Probably just over-thinking things as usual.

Currently trying possible work-arounds for something like $('body').namespace().method(), thus far, not working so well ... :P

8
  • +1 - I don't think this is possible in JavaScript. You should just prefix your method names (e.g. namespaceTest). If real namespacing is so important to you, then I'm afraid you can't use jQuery's prototype. Commented Jul 17, 2013 at 15:37
  • I may be missing your point, but are you just looking for $.fn.myMethod(/* function code */); which you then call like $("div").myMethod()? Commented Jul 17, 2013 at 15:41
  • 1
    @JosephSilber It's JavaScript! I'm sure there's a way! LoL, after all, this is the "freest" language out there! Commented Jul 17, 2013 at 15:42
  • @Archer No, as I mentioned, I want $("div").myNameSpace.myMethod(); Commented Jul 17, 2013 at 15:42
  • Okay - I was going off the comment "The problem I'm having is making Element Methods such as $('element').method()" Commented Jul 17, 2013 at 15:43

4 Answers 4

3

If you don't need to be compatible with IE8, you may use Object.defineProperty.

Working example :

 Object.defineProperty($.fn, 'namespace', {
  get: function(){
    var t = this;
    return {
      lowercasehtml: function(){
         return t.html(function(_,h){ return h.toLowerCase() }); 
      }
    }
  }
});

$('#a').namespace.lowercasehtml(); // changes the html of #a to lowercase (yes, it's stupid, I know)

Demonstration

But I'm not convinced it's a good idea to namespace like this. I would have simply defined

$.fn.namespace_lowercasehtml = function() ...

That's what I personally do for my application specific extensions to jQuery.

Sign up to request clarification or add additional context in comments.

2 Comments

nice suggestion, I'll try it right after lunch, any thought on IE8 work around?
To be honest I think my second suggestion, even if not fancy, is the best one.
2

While I don't recommend it, you can generate a new object for every call to namespace():

(function($){

    var plugin = {
        test: function (){
            console.log(this);
        }
    };

    var methods = Object.keys( plugin );

    $.fn.namespace = function (){

        var self = this,
            localMethods = {};

        $.each(methods, function () {
            localMethods[ this ] = plugin[ this ].bind(self);
        });

        return localMethods;
    };

}(jQuery));

Here's the fiddle: http://jsfiddle.net/WaXzL/


You can either polyfill Object.keys for older browsers, or just create the methods array manually.

Same goes for bind: either polyfill it, or call it manually.

Here's a version that would work in older browsers:

(function($){

    var plugin = {
        test: function (){
            console.log(this);
        }
    };

    var methods = [];

    for ( var i in plugin ) {
        if ( plugin.hasOwnProperty(i) ) {
            methods.push(i);
        }
    }

    $.fn.namespace = function (){

        var self = this,
            localMethods = {};

        $.each(methods, function (i, method) {
            localMethods[ method ] = function () {
                plugin[ method ].call( self );
            };
        });

        return localMethods;
    };

}(jQuery));

And here's the fiddle: http://jsfiddle.net/WaXzL/1/

1 Comment

Thanks for your suggestion. I added support for passing arguments to any local method: jsfiddle.net/WaXzL/2
2

How about instead of doing:

$('element').namespace.method()

you simplify it and do

$('element').namespace('method')

instead? This is much simpler:

(function($){
    var methods = {
        test: function(a, b){
            console.log(this, a, b);
        }
    };

    $.fn.namespace = function(method){
        var params = Array.prototype.slice.call(arguments, 1);
        return methods[method].apply(this, params);
    };
}(jQuery));

Then you'd do something like: $('body').namespace('test', 1, 2);

2 Comments

because my intellisense in my IDE will read $('ele').namespace.method() but it won't read a method name passed as string param
@SpYk3HH: I was trying to keep it simple. I don't use a "fancy" IDE.
2

A better solution is to just have one main method, and pass the method name as a string:

(function($){

    var plugin = {
        test: function (){
            console.log(this);
        },
        otherTest: function (){
            console.log(this);
        }
    };

    $.fn.namespace = function (method){
        var args = Array.prototype.slice.call(arguments, 1);
        return plugin[ method ].call(this, args);
    };

}(jQuery));

Here's the fiddle: http://jsfiddle.net/yYNDH/

1 Comment

@dystroy - Yeah. I had gone over to JSFiddle to create the fiddle before I posted, and when I came back, I didn't realize that he had already posted it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.