JavaScript: How to pass multiple arguments to a callback function inside an object's member?
Asked Answered
A

3

4

When working with plugins I sometimes stumble upon one that has something like this:

  • It will take constructor arguments.
  • Some of the parameters resolve to functions.
  • Some of those will take multiple arguements.

like this:

{
    color: function (someData, moreData) {
        return someData + moreData;
    }
}

How do I pass two arguments to that function?

Note: I am unable to change the plugin, so moving the second argument to another constructor argument is not an option.

Sample JavaScript:

(function ($) {
    $.fn.greenify = function (options) {
        var settings = $.extend({
            color: function (someData, moreData) { // <-- THIS TAKES 2 ARGUMENTS!
                return someData + moreData;
            },
        }, options);
        return this.css({
            color: settings.color,
        });
    };
}(jQuery));

$("#target1").greenify({
    color: "blue"
});

$("#target2").greenify({
    color: ["bl", "ue"]   // <-- In your answer only this should be changed
});

My targets:

<div id="target1">My Thing</div>   // <-- will be blue
<div id="target2">My Thing2</div>  // <-- will be black but should be blue

FIDDLE DEMO


UPDATE: I fell for a major misconception that this code

$("#target1").greenify({
    color: "blue"
});

would hand the value "blue" over to function (someData, moreData) as first parameter someData. This is false! What actually happens is that the default callback (function (someData, moreData)) is completely replaced by the string "blue"!

Adebayo answered 3/6, 2013 at 13:50 Comment(5)
You actually don't have to change the constructor (demo), but you'll have to update the plugin body anyway, I suppose.Engulf
I guess you didn't show us the actual plugin since what you posted doesn't make much sense (but may be a fault of the plugin coder). If so, please link to the real source code.Mi
@Bergi: Here is the actual plugin which rose this question to me. But my question is not about a design decision. I am curious as of the capabilities of JS.Adebayo
The relevant line is here - it calls the method with the given name with multiple arguments (e.g. $(…).select2("data", someValues, true)). Is that what you wanted? Or do you want to know more about how to design jQuery plugins and about using .apply?Mi
Thank you. This is a good solution to the initial problem. Aside from that I am still curious about ways to handle the above sample.Adebayo
M
3

How do I pass two arguments to that function?

You don't. jQuery does. It's a callback function to determine the color property dynamically in the .css() method - see the docs.

So actually, that default function doesn't make any sense as it should return a css color value but returns the old value prefixed by the index of the element - which is definitely not a color.

So just use $("#target2").greenify({color: "black"}).

If you want to pass a function, that is also possible - but it will overwrite, not call that default function. An example:

$("div").greenify({
    color: function(index, prevColor) {
        return ["blue", "black"][index % 2];
    }
});
Mi answered 3/6, 2013 at 14:8 Comment(3)
Will this actually override the function (someData, moreData) {...} or will it only pass it's return value to the first argument someData in the original function?Adebayo
Yes, it will replace it on the settings object. It's impossible to call that function as you cannot access it from outside (without using some ugly hacks, like compromising $.extend)Mi
I'll accept this as the answer as this is the closest fit (pointing at the last part) - basically the question incorporates a design flaw, that no plugin will actually ever have.Adebayo
L
0
var settings = $.extend({}, options);
if($.isArray(options.color)) {
    settings.color = function () {
        return options.color.join('');
    };
}

fiddle: http://jsfiddle.net/2QBGm/

Levity answered 3/6, 2013 at 14:9 Comment(1)
OP said he is unable to change the plugin!Mi
T
0

See this jsFiddle

I have made some changes to your code and it's now working as you want it.

I used the options object to get the arguments:

color: function () {
    return options.color[0] + options.color[1];
}
Terzetto answered 3/6, 2013 at 14:33 Comment(2)
OP said he is unable to change the plugin!Mi
@Mi thanks for the notice. I thought plugin is something else. I didn't understand the question fully. My bad, sorryTerzetto

© 2022 - 2024 — McMap. All rights reserved.