4

I've been attempting to grasp my mind around a good way to structure a plugin so it can accept method calls with options, just method calls, options on init, and init without options.

So far here is what i have.

(function($) {
    var settings = {};
    var defaults = {
        args : "default args"
    };
    var methods = {
        init : function(options) {
            if(options) {
                settings = $.extend({},defaults,options);
            }
        },
        test : function(arg) {
            alert("test: " + arg.args);
            alert("args: " + settings.args);
        }
    };
    $.fn.dataTable = function(method) {
        var args = arguments;
        var $this = this;
        return this.each(function() {
            if ( methods[method] ) {
                return methods[method].apply( $this, Array.prototype.slice.call( args, 1 ));
            } else if ( typeof method === 'object' || ! method ) {
                return methods.init.apply( $this, args );
            } else {
                $.error( 'Method ' +  method + ' does not exist on jQuery.plugin' );
            }  
        });
    };

})(jQuery);


$(document).ready(function(){
    $(".tbl").dataTable();
    //$(".tbl").dataTable({ args : "hello world" });
    $(".tbl").dataTable("test",{args:"test args passed"});
    //$(".tbl").dataTable("test");
});

however with this I receive

test: test args passed

and

args: undefined

Any help?

1 Answer 1

3
(function($) {
    var defaults = {
        string1 : "hello ",
        string2 : "world!"
    };
    var methods = {
        init : function(options) {
            if(options) {
                $.extend(defaults,options);
            }
            alert(defaults.string1 + defaults.string2);
        },
        test : function(arg) {
            alert("test: " + arg.args);
            alert("args: " + defaults.string1 + defaults.string2);
        }
    };
    $.fn.dataTable = function(method) {
        var args = arguments;
        var $this = this;
        return this.each(function() {
            if ( methods[method] ) {
                return methods[method].apply( $this, Array.prototype.slice.call( args, 1 ));
            } else if ( typeof method === 'object' || ! method ) {
                return methods.init.apply( $this, Array.prototype.slice.call( args, 0 ) );
            } else {
                $.error( 'Method ' +  method + ' does not exist on jQuery.plugin' );
            }  
        });
    };

})(jQuery);


$(document).ready(function(){
    $(".tbl").dataTable();
    //$(".tbl").dataTable({ string1 : "foo", string2 : "bar" });
    $(".tbl").dataTable("test",{args:"test args passed"});
    //$(".tbl").dataTable("test");
});
Sign up to request clarification or add additional context in comments.

4 Comments

my only fear is that this will have complications if i try to initialize two instances of the plugin on one page. var $this = this
I know this is an old post, but thanks! Also, re: your comment, instead of .apply($this...), using .apply($(this)...) at least uses the single element from the .each() function.
Yes, the line must read: return methods[ method ].apply( $( this ), Array.prototype.slice.call( outerArguments, 1 )); to apply the function at one specific element per loop, otherwise for example with $this being an array of 8 matching divs would result in calling the function 64 times (8 loops x 8 elements per loop). The same in the default init section. This means that the $this assignation is not needed and can be removed. -I've named outerArguments instead of args, to make it clean code, but this does not matter for the $(this) issue.
@rlemon: doing with $(this) instead of $this, I am initing 8 independent instances and works well.

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.