开发者

How to handle events in jQuery UI widgets

开发者 https://www.devze.com 2023-01-22 12:44 出处:网络
I\'m trying to write a jQuery widget following the model given here. Here is a snapshot of the widget:

I'm trying to write a jQuery widget following the model given here. Here is a snapshot of the widget:

(function ($) {
    $.widget("ui.notification", {
        _create: function () {
            if (!this.element.hasClass("ntfn")) {
                this.element.addClass("ntfn");
            }

            this.elTitle = this.element.append("<div class='ntfn-title'>Notifications</div>");

            this.elTitle.click(this._titleClick)
        },
        _titleClick: function () {
            console.log(this);
        }
    });
})(jQuery);
开发者_运维技巧

Here the problem is with the scope of "this" inside the _titleClick method, inside the method this points to the title element. But I need it to point to the widget element.

I think one way of doing it will be to use a wrapper class like

var that = this;
this.elTitle.click(function() {
    that._titleClick.apply(that, arguments);
});

Is this the best way to solve this problem or is there any general pattern to solve this issue?


Use the this._on() method to bind the handler. This method is provided by the jQuery UI widget factory and will make sure that within the handler function, this always refers to the widget instance.

_create: function () {
    ...
    this._on(this.elTitle, {
        click: "_titleClick" // Note: function name must be passed as a string!
    });
},
_titleClick: function (event) {
    console.log(this);       // 'this' is now the widget instance.
},


You should look to jQuery.proxy() http://api.jquery.com/jQuery.proxy/

el.bind('evenname', $.proxy(function () {
   this.isMyScope.doSomething();
}, scope));


I wrote a method my own to solve this issue

_wrapCallback : function(callback) {
    var scope = this;
    return function(eventObject) {
        callback.call(scope, this, eventObject);
    };
}


In your create, init (or somewhere in your instance) function do this:

        _create: function() {

        ...

        // Add events, you will notice a call to $.proxy in here. Without this, when using the 'this'
        // property in the callback we will get the object clicked, e.g the tag holding the buttons image
        // rather than this widgets class instance, the $.proxy call says, use this objects context for the the 'this'
        // pointer in the event. Makes it super easy to call methods on this widget after the call.
        $('#some_tag_reference').click($.proxy(this._myevent, this));

        ...

        },

Now define your objects event hander like this:

        _myevent: function(event) {

            // use the this ptr to access the instance of your widget
            this.options.whatever;
        },


define var scope=this, and use scope in event handler.

    _create: function () {           
        var scope = this;
        $(".btn-toggle", this.element).click(function () {
            var panel = $(this).closest(".panel");
            $(this).toggleClass("collapsed");
            var collapsed = $(this).is(".collapsed");
            scope.showBrief(collapsed);
        });
    },


Another way to do the same thing without using closure, is to pass the widget as a part of the event data like so:

// using click in jQuery version 1.4.3+.
var eventData = { 'widget': this };

// this will attach a data object to the event,
// which is passed as the first param to the callback.
this.elTitle.click(eventData, this._titleClick);

// Then in your click function, you can retrieve it like so:
_titleClick: function (evt) {
    // This will still equal the element.
    console.log(this);
    // But this will be the widget instance.
    console.log(evt.data.widget);
};


It used to be via the jquery bind method now on is favoured.

As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document. For earlier versions, the .bind() method is used for attaching an event handler directly to elements. Handlers are attached to the currently selected elements in the jQuery object, so those elements must exist at the point the call to .bind() occurs. For more flexible event binding, see the discussion of event delegation in .on() or .delegate().

_create: function () {
   var that = this; 
   ...
   elTitle.on("click", function (event) {
             event.widget = that;   // dynamically assign a ref (not necessary)
             that._titleClick(event);
    });
},
_titleClick: function (event) {
    console.log(this);             // 'this' now refers to the widget instance.
    console.log(event.widget);     // so does event.widget (not necessary)
    console.log(event.target);     // the original element `elTitle`
},
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号