2

Consider the following base code:

(function($) {
    $.fn.myPlugin = function(settings) {
        return this.each(function() {
            //whatever
        });
    };
});

The plugin returns a jQuery object. The question is how am I supposed to write a plugin that returns a custom object so that I can do something like this:

var api = $('div.myelement').myPlugin();
api.onMyEventName(function(e, whateverParam) {
    //whatever
});

It'd be highly appreciated if you could write some lines of code that describes me how to do that, how to call the onMyEventName function on a custom api object...

Thanks.

2
  • 3
    Why can't you just return your object? Commented Apr 1, 2010 at 17:34
  • It might brake the JQuery design contract, better to ask. Commented Feb 18, 2014 at 10:24

2 Answers 2

14
(function($) {
    function MyApi($this, settings) {
        this.$this = $this;
        this.settings = settings;
    };

    MyApi.prototype.output = function (val) {
       // use this.$this to access the original jQuery object

       return this.settings[val];
    };

    $.fn.myPlugin = function(settings) {
        return new MyApi(this, settings);
    };
});

Note that we've passed this from $.fn.myPlugin() into the MyApi constructor; this allows you to access the jQuery object that myPlugin() was originally called on within MyApi methods.

You can also do the same using the object literal syntax:

(function($) {
    $.fn.myPlugin = function(settings) {
        return {
            settings: settings,
            output: function (val) {
                // use this.$this to access the original jQuery object

                return this.settings[val];
            },
            $this: this
        };
    };
});

Then;

var something = $('#something').myPlugin({
   val: 'Lemon'
});

alert(something.output('val')); // Lemon

... again, we've captured the value of this (the jQuery object) into a property $this on the newly constructed objected, to gain access to the original jQuery object.

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

2 Comments

Assuming you are accessing your object through JQuery selectors because they are related to the selected nodes, the $.fn.myPlugin should provide the nodes (this) to the MyApi ctor. Also $.fn.myPlugin should use $.map(this,...) so that all the items matched by the selector would be processed with MyApi...
@VajkHermecz: it was a bit of a contrived example I used, but non-the-less you are right about normally passing this; I've updated the code accordingly. In terms of using map() (infact, each() is more common), I'll leave that to the reader to see whether they need it or not; it depends on the usecase!
0

There is a great article by Hector Virgen detailing a possible solution (also used in bootstrap) to adress this question.

The key moment is basically storing your API object in the data section of the node:

$.fn.myplugin = function() {
    return $.each(function() {
        ...
        myplugin = new MyPlugin(this)
        ...
        $(this).data('myplugin', myplugin);
    }
}

After this, users can easily access the object by:

$(this).data("myplugin")

A possibly useful extension to this solution could be defining a mypluginapi method as a shorthand, for accessing your API object:

$.fn.mypluginapi = function() {
    return $(this).myplugin().data('myplugin')
}

Comments

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.