1

Okay I am working with some jquery creating dynamic popups. However, periodically the response will be the name of a function that I need to call instead of actual data and I am trying to figure out how to do this..

success: function(response) {
                                var obj = $.parseJSON(response);
                                if (obj.response == 'false') {
                                    $('#popuperrDisplay').html(obj.msg);
                                    $('#popuperrors').show();
                                } else {
                                    if (obj.response == 'redirect') {
                                        window.location.href = obj.msg; 
                                    } else if (obj.response == 'function') {
                                        call obj
                                    } else {
                                        $(this).dialog('close');
                                    }
                                }
                            }

This is the current portion of my jquery. I need to figure out how I can send the name of a JS function through json_encode and have JS actually call that function

Justin
  • 2,131
  • 4
  • 24
  • 41

3 Answers3

5

If the function is defined globally (on the window object), you could simply invoke it like so:

if (obj.response === 'function' &&            // 1
    typeof window[obj.msg] !== 'undefined') { // 2

    window[obj.msg]();                        // 3
    // or...
    window[obj.msg].apply(null, obj.args);    // 4
}
  1. checks whether the type of the response is a function.
  2. checks if there is a function with the given name defined on the window object.
  3. calls that function.
  4. calls that function and provides it with an array of arguments.

Edit: (window[] syntax)

To further clarify, window['showPopup'] accesses the showPopup member of the window object. It's the same as doing window.showPopup. Only, the [] syntax has the advantage of receiving a string instead of actual code.

window['showPopup'] will return an object (if defined); let it be a function for our particular example.

We then call that function object by using the () operator, like so: window['showPopup'](). Once again, this is the same as doing this: window.showPopup().

Edit 2: (invoke with arguments)

If the function has to be invoked with an array of arguments, we can use apply. Invoking the function would then look like:

window['showPopup'].apply(null, arrayOfArgs);

Where arrayOfArgs is an array containing the arguments.

Bryan Menard
  • 13,234
  • 4
  • 31
  • 47
  • the function itself is in a functions.js file that is loaded into the head of every page. But the name of the function will be coming from the json return from the initial php script that it queries. A case I may need a function would be if I add something from a popup, and then need to update the list on the current page. Makes sense to be able to pass a function name dynamically so I ran: if (obj.response == 'function') { obj.msg(); } should work? – Justin Aug 28 '11 at 06:06
  • 1
    @Justin, No, `obj.msg()` is not correct. The type of `obj.msg` is "string" because it came from parsing JSON. You can't call a string. – Ray Toal Aug 28 '11 at 06:10
  • You cannot transmit a function in a JSON payload. You could always resort to using `eval()` if you absolutely need to return actual JavaScript code in your response. But it should be avoided whenever possible. – Bryan Menard Aug 28 '11 at 06:12
  • I won't be returning actual JS in my response, only the name of the function itself... The names of the functions will be set by me the programmer, and so there is no worry that something will cause issues with running non-functions or someone trying to do anything harmful. now, say in the same function i have in my json attributes such as: id=1, using the window[] method how do I parse those attributes? and last, say I have multiple attributes I want to pass that come from json - how to create say obj.attribs to pass back as an 'array' to pass into the function? – Justin Aug 28 '11 at 06:18
  • Edited my answer to take into account an array of arguments. – Bryan Menard Aug 28 '11 at 06:34
  • Okay so I have to use .apply, but the arrayofArgs would be returned via JSON as well.. so it would be something like obj.attribs but from php it'll look like: $data['attribs'] = array('id' => '1', 'p_id' => '2'); for however many there are... all of that would be before json_encode, so how do i take the encoded stuff and port back the attributes into var arrayofArgs? – Justin Aug 28 '11 at 06:39
  • Simply put an array in your JSON payload. The array will be serialized in JSON just fine, if done properly in php. Using `obj.attribs` in lieu of `arrayOfArgs` should work just fine. – Bryan Menard Aug 28 '11 at 06:44
  • I'm rather new to jquery and json especially -- as in about 7 days.. so putting an array in JSON payload i have no clue what that means or how to... but if i do obj.attribs, then in the function that is called -- how would I handle those attributes to again be transferred in the data: of the ajax in the new function? – Justin Aug 28 '11 at 06:48
0

If you have a function in a variable named x and you want to call that function, there are several ways you can do that.

function doAlert(msg) {
    alert(msg);
}

var x = doAlert;

x("hi");
x.call(this, "hi");
x.apply(this, arrayOfArguments);

See here for more info on .call(). See here for more info on .apply().

If you have a string that represents a function name and you want to call the corresponding global function with that name, you can do so via the window object.

function doAlert(msg) {
    alert(msg);
}

var name = "doAlert";
window[name]("hi");

It is also possible, though not generally recommended, to use eval:

function doAlert(msg) {
    alert(msg);
}

var name = "doAlert";
eval(name + '("hi");');

You asked this question in a comment:

Say i have a function inside functions.js named updateAll that has no parameters... in my php, my json would be $data['function_name'] = 'updateAll'; which would get encoded with json_encode()... turning that into obj.function_name so could I not just call: obj.function_name(); and have it work?

Here's my answer to that new question:

I'm not sure I fully understand your question, but I'll try to describe various possible aspects of your question.

If function_name is a variable, you can't use obj.function_name(). That syntax only works for string constants (not variables).

If you have a method name in a variable, you can always do the same thing as the dot notation by using [] like this: obj[function_name]();

If the function name is in $data['function_name'] = 'updateAll' and that function name is actually a method on the obj object, such that what you want to call is `obj.updateAll', then the way you could do that would like this:

obj[$data['function_name']]();

Remember that in Javascript, anywhere that you would use the .x reference for a name that was known ahead of time, you can use the [x] reference for a name that is in a variable.

If (as you posted in a comment), your JSON looked like this:

{"response":"function","msg":"someFunction","attribs":{"id":"1","p_id":"2"}}

and that JSON meant that you wanted to call the function someFunction() and pass it the parameters in attribs, then there are a couple ways to do that depending upon how you want the arguments passed to the function. If you want the args passed as the attribs object, you'd do it like this:

var data = {"response":"function","msg":"someFunction","attribs":{"id":"1","p_id":"2"}};
if (data.response == "function") {
    data.msg(data.attribs);
}

If you wanted the arguments passed as normal parameters with the id parameter first and the p_id parameter second, you'd do it like this:

var data = {"response":"function","msg":"someFunction","attribs":{"id":"1","p_id":"2"}};
if (data.response == "function") {
    data.msg(data.attribs.id, data.attribs.p_id);
}
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • say i have a function inside functions.js named updateAll that has no parameters... in my php, my json would be $data['function_name'] = 'updateAll'; which would get encoded with json_encode()... turning that into obj.function_name so could I not just call: obj.function_name(); and have it work? – Justin Aug 28 '11 at 06:11
  • I tried to address your new question by adding new info to my answer. – jfriend00 Aug 28 '11 at 06:20
  • Okay so based on your code... I would do something like this in my php: $data['function_name'] = 'updateAll'; echo json_encode($data); then in my JS I would do: var obj = $.parseJSON(response); which to call the function i would do window[obj.function_name](); and if I need to pass any variables to that function, I would do that in the ()'s.. – Justin Aug 28 '11 at 06:33
  • now say I have in my php $data['attribs'] = array('id' => '1', 'p_id' => '2'); before the json_encode how would I port that into the function to be called? – Justin Aug 28 '11 at 06:35
  • You've lost me a bit. I'd have to see the generated JSON to know how to read it. – jfriend00 Aug 28 '11 at 06:58
  • `{"response":"function","msg":"someFunction","attribs":{"id":"1","p_id":"2"}}` that's the basic's of how it might look... I'll also need to know how to handle it inside the function to be written, to tie it onto the ajax data: set for the next query that'll take place.. – Justin Aug 28 '11 at 07:54
  • I added more to my answer on how to call someFunction with the arguments based on that JSON. – jfriend00 Aug 28 '11 at 19:58
0

If I understand the question correctly, the server is sending back objects in one of the forms:

{"response":"false", "msg":"some message"}

{"response":"redirect", "msg":"some message"}

{"response":"function", "msg":"functionName"}

and the parsed string will become an object called obj.

In the latter case I am assuming the value of msg is the name of the function to call. You could invoke this with

window[obj.msg]()

Best to check that it is a function with typeof first (see Bryan's answer).

Also make sure the name of the function that the server is sending back is a function you expect it to send back. You don't want to call anything blindly. At least it appears you are expecting it to send back function names and not arbitrary code, but still, be safe!

Ray Toal
  • 86,166
  • 18
  • 182
  • 232
  • what is the window[]? I've seen that in all 3 answers, but I have no clue what it is, does or whatever as I have never seen it aside from window.location – Justin Aug 28 '11 at 06:13
  • `window` is the name of the global object in browser-based JS environments. All global variables are properties of this object. Assuming that `obj.msg` evaluated to a string which was the name of a global function, this function would be a property of this global object and would be accessible as `window[obj.msg]`. Note that you have to use brackets. *not the dot notation*, to get this property, because the function name is computed via an expression, and not given directly. – Ray Toal Aug 28 '11 at 06:30