Anupheaus
Anupheaus

Reputation: 3801

Test to see if variable is instance of jQuery.Callbacks

Anyone know of an easy way to test a variable to see if it is an object of type jQuery.Callbacks.

Background: I've got some jquery widgets I've created, and they each have events managed using jQuery.Callbacks. Some of my widgets use other widgets and will pass along the configuration given to itself to the sub-widget, and this includes events. So if my parent widget initialises an event, I don't want the child widget to initialise it again, or i'll lose any existing subscriptions.

For Example:

var notCallbackHandler1='';
var notCallbackHandler2={ add: function(something) { } };
var callbackHandler=$.Callbacks();

function isVariableACallbackHandler(variable) {
    // <-- What goes here?
}

isVariableACallbackHandler(notCallbackHandler1); // Should return false
isVariableACallbackHandler(notCallbackHandler2); // Should return false
isVariableACallbackHandler(callbackHandler); // Should return true

Upvotes: 0

Views: 150

Answers (2)

Seimen
Seimen

Reputation: 7250

Well you can check if the passed argument has a method which is specific for jQuery.Callbacks(). Like this for example:

var $callbacks = $.Callbacks(),
    $noCallbacks = $('div'),
    checkIfCallbacks = function(callback) {
        var checkFun = 'fireWith';
        return typeof callback[checkFun] == 'function';
    };

checkIfCallbacks($callbacks); // true
checkIfCallbacks($noCallbacks); // false

Update: checking for typeof suffices.

Update: Here would be an improved version of your code, just don't use for...in loops and avoid jQuery functions if possible if you want better performance.

var $callbacksProto = $.Callbacks();

$.isCallbacks = function (object) {
    // first check if we even have an object
    // this can already save a lot of comparison time
    if (typeof object == 'object') {
        var prop, i;

        for (i = 0; i < $callbacksProto.length; i++) {
            prop = $callbacksProto[i];

            // check if the property name of the original $callbacksProto is a function in our object
            // because every $callbacksProto property is a function
            if (typeof object[prop] != 'function') {
                return false;
            }
        }

    } else {
        return false;
    }

    // if no error occurred return true
    return true;
};

Upvotes: 2

Anupheaus
Anupheaus

Reputation: 3801

Here is what I ended up using:

var tempCallbacksObject=$.Callbacks();
$.isCallbacks = function (variable) {
    for (var propertyName in tempCallbacksObject) {
        if (variable[propertyName] == undefined) { return false; }
        if ($.type(tempCallbacksObject[propertyName]) != $.type(variable[propertyName])) { return false; }
    }
    return true;
};

I created a tempCallbacksObject so that I wouldn't have to keep creating a Callbacks object each time I wanted to compare. I also compared every member of the callbacks object so that it is much less likely that an object with a member or two with the same name causes a false positive.

I still don't like it though because it requires a loop and that always takes time, especially since it is likely to be used to check each event handler on each widget I create. Oh well, if someone finally does come up with something better (or an improved version of this) then I've only got the one place to change it.

Upvotes: 0

Related Questions