简体   繁体   中英

jQuery plugin callback - jQuery Boilerplate

I'm using jquery boilerplate template for my plugin. I need to deliver some callback from this plugin. This callback need to be some variable with offsets coordinates.

var coordinates = {
    x: x2, y: y2
};

I try to delegate this callback like this:

;(function ($, window, document) {

/* 'use strict'; */

// default options
var name = "plugin",
    defaults = {};

// constructor
function plugin (options, callback) {
    this.settings = $.extend({}, defaults, options);
    this.init();
    this.callback = callback;
}

plugin.prototype = {
    init: function () {
        var offset = $(this).offset(),
            x2 = (e.pageX - offset.left),
            y2 = (e.pageY - offset.top);

        $(document).on('mouseup', function() {
            var coordinates = {
                x: x2, y: y2
            };
            this.callback(coordinates);
        });
    }
};

// initialize
$.fn[name] = function (options, callback) {
    return this.each(function() {
        if (!$.data(this, "plugin_" + name)) {
            $.data(this, "plugin_" + name, new plugin(options, callback));
        }
    });
};

})(jQuery, window, document);

I have an arror that callback is not a method for this object. Can anybody help?

Focus on how and especially where you call your callback:

plugin.prototype = {
    init: function () {
        var offset = $(this).offset(),
            x2 = (e.pageX - offset.left),
            y2 = (e.pageY - offset.top);

        $(document).on('mouseup', function() {
            var coordinates = {
                x: x2, y: y2
            };
            this.callback(coordinates);
        });
    }
};

You are creating an anonymous nested function. Anonymous functions by default have this === window .


Edit: Thanks to KevinB's comment, I noticed that my previous statement wasn't true for all cases, simply because it is possible to change the context of functions by calling .apply() and .call() , which jQuery does in order to allow you to simply use $(this) to access the element which triggered the event.

What I had in mind is that, if anonymous functions are called without these two methods, they, then this === window . But this is also true for methods which are called directly as functions, not as methods. The following won't work either.

var obj = { foo : 'foo', bar : function(){console.log(this.foo);} };
$(document).on('mouseup', obj.bar);

First of all because of the aforementioned change of context that jQuery does when calling the callback, 2nd because of a simple rule of thumb: the context is whatever is to the left of the dot . When calling a callback like this: callback() , nothing is to the left of the dot, ie this === null (don't hit me) which doesn't exist, so it defaults to this === window .


The fix to this is fairly easy: simply introduce a new variable that reference the instance of your plugin. This variable is commonly called that . Minor changes should accomplish your goal:

init: function() {
    var offset = $(this).offset(),
        x2 = (e.pageX - offset.left),
        y2 = (e.pageY - offset.top),
        that = this;

    $(document).on('mouseup', function(){
        var coordinates = {
            x: x2, y: y2
        };
        that.callback(coordinates);
    });
}

But beware: the way your plugin currently works, it will attach a listener to the mouseup event each time it is run . You don't need that many... especially since it will result in lags if you run the plugin a lot. I'd suggest to hook up the event listener once and call all callbacks one by one once the event has been triggered.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM