views:

55

answers:

4

I'm not sure how best to describe this problem... In short, I want to use object literal to allow me to pass a random amount of variables in any order to a function. Whilst this is not big deal in theory, in my code, this object literal is passed to a second function call on_change.

on_change works comparing an element inner HTML to a string. if it is the same, it sets a time out of to call the function again (this is sort of/almost recursive, but the function dose actually get to end before it is called again). if the elements inner HTML is different from the string, then the third parameter is executed. this will either be a function or a string. either way it will execute. I have tested this function plenty and used it for a while now.

how ever, it cannot seem to get the object literal to flow through the function calls...

var params = { xpos:'false'};
on_change('window_3_cont_buffer','','
if(Window_manager.windows[3].window_cont_buffer.getElementsByTagName(\'content\')[0].getElementsByTagName(\'p\')[0].innerHTML == \'ERROR\'){
alert(Window_manager.windows[3].window_cont_buffer.getElementsByTagName(\'content\')[0].getElementsByTagName(\'p\')[1].innerHTML);
return false;
} else { 
Window_manager.windows[3].load_xml(\'location/view.php?location_ID=3\', \'\', ' + params + ' ); }
');

I call this as part of the form submission. after this line, I then call a function to load some content via ajax, which works fine and will trigger the code from the on_change function.

I have tested load_xml function it is able to call alert(param.xpos) and get the correct response. I can even added in a check for being undefined so that rest of the times I cam load_xml I don't get swamped with alerts.

The load_xml function first set up the on_change function, then calls the function to load the content to a hidden div. Once the AJAX request has updated that DIV, the on_change function should now call the parse_xml function. This pulls out the information from the xml file. How ever... The idea of this object literal param is that it can tell this parse_xml function to ignore certain things.

on_change("window_" + this.id + "_cont_buffer", "", "Window_manager.windows[" + this.id + "].parse_xml('" + param + "')");

this is part of load_xml. it works perfectly fine, even with the param bit in there. except, parse_xml dose not seem to be able to use that parameter.

I have been able to get it to a point where parse_xml can alert(param) and give [object object] which I would of thought meant that the object litteral had been passed through, but when I try and call alert(param.xpos) I get undefined.

I know this is a pig of a problem, and I could get around it by just having the function take a zillion boolean parameters, but its just not practical or elegant.

I'm sure you will need to ask me plenty more questions before I can solve this. I will post more complete code, I just cut it down to what is actually going on.

Thanks

+2  A: 

In effect, what you have is this:

var params = {param: "value"};
foo("bar('one', 'two', 'three');");

...where foo uses eval on that string, something like:

function foo(codestring) {
    eval(codestring);
}

...and you're looking for how to embed params in that.

You could do this by serializing the object literal as a string so that when you combine it with the other string, and the total string is evaluated, it gets evaluated. Browsers are slowly getting JSON serialization built in, but for now you want to use jQuery, Prototype, or (if you just want this part) json2.js from Crockford, which offers JSON.stringify for turning objects that can be turned into JSON strings, into JSON strings. So:

var params = {param: "value"};
foo("bar(" + JSON.stringify(params) + ");");

But what you really want to do is refactor so that all of that logic is expressed as code, not code within a string. Then you could pass the literal directly, plus a whole raft of other benefits, including modularization, debugging, etc.

var params = {param: "value"};
function callBar() {
   bar(params);
}
foo(callBar);

...changing foo so that it calls a function rather than evaling a string. (eval is to be avoided whenever possible, and to paraphrase the Dalai Lama, it's [almost] always possible.) My sample foo changes to:

function foo(func) {
    func();
}

If foo needs to include additional information for bar (and if callBar is set up to handle those extra arguments), it can use Function#call or Function#apply to do that. (Those links are to MDC, but don't worry, they're not Firefox-specific, they've been in the ECMA spec for years and are nearly universally supported.)

T.J. Crowder
+1  A: 

You can't put an object inside a string. You would have to serialise the object, add it into the string, then parse it back into a structured object on the other side. The simplest way to do that would be to use JSON (via JSON.stringify or a library fallback for older browsers that don't have it), since JSON evaluates as simple JavaScript.

Note that you wouldn't get the exact same object back, but a new one with the same attributes and properties, and it only works for simple types, so you can't include a function in the object or anything.

However, in any case, passing JavaScript code around in strings is an anti-pattern to be strenuously avoided. Instead use inline functions, and you don't have to worry about what you can and can't put in a string, and you can get rid of all that unreadable wrapping and \-escaping:

var params = {xpos: 'false'};
on_change('window_3_cont_buffer', '', function() {
    var w= Window_manager.windows[3];
    var ps= w.window_cont_buffer.getElementsByTagName('content')[0].getElementsByTagName('p');
    if (ps[0].innerHTML==='ERROR') {
        alert(ps[1].innerHTML);
        return false;
    } else { 
        w.load_xml('location/view.php?location_ID=3', '', params);
    }
});
bobince
Admittedly the in line function is something that I never though about... even though I went to the effort of making sure that on_change can handle a function.And that should mean that when I pass params (which I could even just put directly in place) it should be picked up as it is. Thanks!
thecoshman
A: 

Some general techniques which may be helpful for you:

// Example of calling function objects given as arguments:

function on_change(foo, callback1, callback2) {
    if (foo)
        callback1();
    else
        callback2.call(available_as_this);
}

on_change(foo, function() { your code }, function() { another code });


// Example of function taking arbitrary number of arguments:

function any_params() {
    console.log('I got ' + arguments.length + 'arguments!');
    console.log('First argument: ' + arguments[0]);
}

any_params('one', 'two', 'three', [], null, {});

See arguments variable and call().

jholster
A: 

I want to use object literal to allow me to pass a random amount of variables in any order to a function.

Why oh why don't you just create an object which contains the parameters and functions, and pass that around? The receiving funtion can just test to see if a property of the object is set before trying to use it.

slugster