0

I have a basic plugin written according the jQuery authoring guide. This plugin implements some basic features for a ul of elements (activate, deactivate and search).

jquery.myplugin.core.js

(function($) {
    var methods = {
        init : function(opts){
            var options = $.extend({}, $.fn.list.defaults, opts);
            return this.each(function(i) {
                ...
                methods.search("my search query"));
            });
         },
         deactivate : function(){ ... },
         activate : function(){ ... },
         search : function(query){ ... },
    };
    $.fn.list = function(method){
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.list' );
        }
};
    $.fn.list.defaults = {...};
})(jQuery);

I have numerous lists in my app, each performing different actions - some sharing features. For example; two lists might be considered deleteable such that items can be deleted from them. Is there a way to write these extra feature sets as mixins or extended plugins of a core plugin?

So I would have:

  • jquery.myplugin.core.js
  • jquery.myplugin.editable.js
  • jquery.myplugin.deletable.js
  • ...

I had a look at Best Way to Extend a jQuery Plugin which made me think of:

jquery.myplugin.deletable.js

(function($) { 
    var extensionMethods = {
        delete : function(elem){ console.log("deleting "+elem); }
    };

$.fn.list.deletable = function(){ return $.extend(true, $.fn.list.prototype, extensionMethods); };

})(jQuery);

Which I thought would allow me to do:

>>> $('#list').list.deletable();
>>> $('#list').list.deletable("delete", elem);
>>> $('#list').list.deleteable("search", "some element"); # Method from core

but nothing happens as I'm sure there is something I'm not understanding correctly. Can anyone help me out here?

Community
  • 1
  • 1
Timmy O'Mahony
  • 53,000
  • 18
  • 155
  • 177
  • The biggest problem i see is all of your methods are private, meaning, there is no way to access them outside of the scope that you used to define the plugin. Additionally, using `$(sel).list.deleteable()` will not work because `.deleteable` would not have access to `this`. – Kevin B Mar 08 '12 at 19:03

1 Answers1

0

You could create a plugin that calls the original plugin,

http://jsfiddle.net/JLcrm/

(function($){
    var methods = {
        "delete": function() {
            console.log("delete");
            return this;
        }
    };
    $.fn.deleteable = function(method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return $.fn.list.apply(this,arguments);
        } else {
            try {
                return $.fn.list.apply(this,arguments);
            } catch (e) {
                $.error('Method ' + method + ' does not exist on jQuery.delete');
            }
        }
    };
})(jQuery);

$(document).list().list("search")
$(document).deleteable().deleteable("delete");

There are some typos in your code, I fixed them in the fiddle.

Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • I think this is probably the best solution. I found [a similar post](http://c0d3it.blogspot.com/2011/04/jquery-oop-encapsulation.html) while googl'ing. Why it seemingly so difficult to do something as straight forward as inheritance? – Timmy O'Mahony Mar 08 '12 at 19:22
  • It's all about the way in which the methods are defined. If you instead build the $.fn.list method with inheritance in mind, it wouldn't be so difficult to create a new method that implements all of the methods in the old method plus more. – Kevin B Mar 08 '12 at 20:20