Search code examples
jquerychaining

Is it possible to chain a jQuery object to a custom object method?


I'm wondering how I could use a syntax like $(someSelector).someObj.someMethod() in conjunction with jQuery?

The Idea: I don't want to extend $.fn with a bunch of custom functions. Therefore someObj contains several methods which should resolve this to $(someSelector).

I know that I could use just one custom function which execudes code depending on its argument:

(function( $ ) {
    $.fn.customFunc = function( funcSelector ) {
        if ( funcSelector === "do this") {
            // do this
        }
        if ( funcSelector === "do that" ) {
            // do that
        }
    };
}( jQuery ));

So $(someSelector).customFunc(funcSelector) is a good workaround.

But I'm still curious: Is it possible to achieve chainability between jQuery and custom objects?

Update #1:

I like @jfriend00's approach. See his last edit. It's also based on passing the custom function name as string parameter BUT it allows defining custom functions as real functions, not some code wrapped in an if/switch statement.

Update #2:

See @barmar's custom class approach in the answers.


Solution

  • You can do something like:

    $(someSelector).someObj.someMethod()
    

    by adding a property someObj to jQuery.fn that is an object with it's own methods including someObj.

    jQuery.fn.someObj = {
        someMethod: function() {
            // method code here
        }
    };
    

    But, when you do that and call it like you specified as $(someSelector).someObj.someMethod(), the this value in .someMethod() will be someObj and will NOT be the jQuery object so this is generally not a useful thing to do because you lose access to the jQuery object which is generally the reason for adding jQuery methods.


    If you're concerned about adding too many methods to the jQuery namespace, then you can just use your own prefix on the method names and it will be insignificantly different from what you were asking for originally from a namespace collision point of view (this just uses a _ between parts of a single name instead of . between two names:

    $(someSelector).myUniquePrefix_add();
    $(someSelector).myUniquePrefix_remove();
    $(someSelector).myUniquePrefix_modify();
    

    Any work-arounds that attempt to solve the this issue in the first scheme are messy at best and simply not worth the trouble or the overhead because Javascript just doesn't work that way.

    For example, you could make it work like this:

    jQuery.fn.someObj = function(method /* other args */) {
        var args = [].slice.call(arguments, 1);
        return this.someObj[method].apply(this, args);
    }
    
    jQuery.fn.someObj.someMethod = function() {
        // method code here
    }
    
    // and then call it like this
    $(someSelector).someObj("someMethod", "arg1", "arg2");