Nimbrod
Nimbrod

Reputation: 57

Passing anonymous functions through jQuery event call without eventData

Given an <input id="foo"> element, I want to call an existing function on blur and pass an anonymous callback to it.

Case 1, simple function call:

function bar(){
    alert("I am");
}

$("#foo").blur(bar); //Works fine

Case 2, passing arguments/function:

$("#foo").bind("blur", {func: function(){console.log("I am apple")}}, bar);

function bar(event){
    event.data.func(); //Works fine
};  

Problem with case 2 is that I'd like to have bar() as a generic function called by more than blur, in which case I would be passing anonymous function directly, not "baked" into a data object. So ideally like this:

function bar(callback){
    //Do stuff
    callback();
}

bar(function(){console.log("Hello Earth")}); //Works

$("#foo").blur(bar(function(){console.log("Hello world")})); //Doesn't work

Last line doesn't work as function gets executed directly, but it's an example of what I would like to achieve. I guess I possibly could make some typeof checks in bar() to determine what I am receiving, but I wanted to ask if there's a cleaner way to pass anonymous function on blur, instead of changing bar().

Upvotes: 2

Views: 76

Answers (5)

Piyush.kapoor
Piyush.kapoor

Reputation: 6803

function bar(callback){
    //Do stuff
    callback();
}

bar(function(){console.log("Hello Earth")}); //Works

$("#foo").blur(bar.bind(this,function(){console.log("Hello world")})); //Will work

Upvotes: 2

T.J. Crowder
T.J. Crowder

Reputation: 1074365

...I wanted to ask if there's a cleaner way to pass anonymous function on blur, instead of changing bar().

Not sure quite what you mean by that, you will have to either change bar or wrap bar.

Changing it:

Make bar a handler generator rather than a direct handler:

function bar(callback) {
    return function(e) {
        // You could use `e` (the event) here and/or pass it on to the callback
        callback();
        // You might use the callback's return, e.g.:
        // return callback();
        // ...if you wanted it to be able to `return false`
    };
}

Now, bar returns an event handler that will call the callback (in addition, presumably, to doing something of its own; otherwise, it's a bit pointless and you'd just pass the callback directly).

Usage:

$("#foo").blur(bar(function(){console.log("Hello world")}));

Wrapping it

If you literally mean you don't want to change bar, you'll need to wrap it:

function wrap(f, callback) {
    return function() {
        // You could call `callback` here instead of later if you like

        // Call the original function passing along the `this` and
        // arguments we received (`arguments` isn't pseudo-code, it's
        // a pseudo-array JavaScript creates for you), get its return value
        var retval = f.apply(this, arguments);

        // Call the callback
        callback();

        // Return the original function's return value
        return retval;
    };
}

If you want to avoid letting errors thrown by callback to make it to the event mechanism, you can wrap it in a try/catch.

Usage:

$("#foo").blur(wrap(bar, function(){console.log("Hello world")}));

Upvotes: 4

fdomn-m
fdomn-m

Reputation: 28611

Last line doesn't work as function gets executed directly

$("#foo").blur(bar(function(){console.log("Hello world")}));

On the last line you're passing the result of bar to the blur() function, not bar itself, it's the same as:

var result = bar(function(){console.log("Hello world")});
$("#foo").blur(result);

The standard method is to wrap this in an anon function:

$("#foo").blur(function() { bar(function(){console.log("Hello world")}) });

This means there are no changes to your other existing functions, as per the question requirement: "instead of changing bar()"

Upvotes: 0

Vanya Avchyan
Vanya Avchyan

Reputation: 880

function bar(){
    alert("I am blur");
}

$("#foo").bind('blur',bar);

Upvotes: 0

eisbehr
eisbehr

Reputation: 12452

Wrap it and return it as an anonymous function:

function bar(callback){
    return function() {
        callback();
    }
}

// direct
bar(function(){console.log("Hello Earth")})();

// as callback
$("#foo").blur(bar(function(){console.log("Hello world")}));

Upvotes: 0

Related Questions