crush
crush

Reputation: 17033

jQuery plugin scope issue

I'm overlooking something here with scope resolution in this jQuery plugin. Here is a simplified example of what I'm trying to achieve:

(function($) {
    $.fn.dashboard = function(options) {
        this.onClick = function(e) {
            alert("do something");
            return false;
        };

        var createButton(parent) {
            //This should call the onClick method defined above when the link is clicked.
            var button = $('<a href="#">Reply</a>').click(this.onClick);
            parent.append(button);
        };

        return this.each(function() {
            var doc = $('body');
            createButton(doc);
        });
    };
})(jQuery);

The issue is that onClick never gets called. Definitely seems to be some manner of scope issue.

Upvotes: 0

Views: 138

Answers (3)

ShankarSangoli
ShankarSangoli

Reputation: 69915

Inside the plugin this points to jQuery object. The issue in your code is with this.onClick which is just added a new property onClick to jQuery object.

Try this.

(function($) {
    $.fn.dashboard = function(options) {
        var doSomething = function(){
            alert("do something");
            return false;
        };

        var createButton(parent) {
            parent.append($('<a href="#">Reply</a>').click(doSomething));
        };

        return this.each(function() {
            var doc = $('body');
            createButton(doc);
        });
    };
})(jQuery);

Upvotes: 2

Sam Sehnert
Sam Sehnert

Reputation: 2943

In your example, 'this' in the createButton method is actually referring to the createButton function itself, NOT the jQuery collection passed to the plugin.

To make this work, simply assign 'this' to a variable in the plugin method, and use that variable in your createButton (and other) functions.

(function($) {
    $.fn.dashboard = function(options) {

        var $this = this;

        this.onClick = function(e) {
            alert("do something");
            return false;
        };

        var createButton = function(parent) {
            //This should call the onClick method defined above when the link is clicked.
            var button = $('<a href="#">Reply</a>').click($this.onClick);
            parent.append(button);
        };

        return this.each(function() {
            var doc = $('body');
            createButton(doc);
        });
    };
})(jQuery);

Note that this answer only deals with the scope resolution, and in fact, as this answer mentions, you should probably assign the click function directly.

Upvotes: 1

user229044
user229044

Reputation: 239581

this is going to be a jQuery object wrapping the set of matched elements. You can either iterate over the set and assign to onClick, or (more correctly) you use jQuery's click event handler instead of assigning directly to onClick:

$.fn.dashboard = function(options) {
    this.each(function () {
        $(this).click(function(e) {

        });
    });
}

You should read the jQuery page Plugins/Authoring.

Upvotes: 1

Related Questions