views:

70

answers:

2

Had a nice PHP/HTML/JS prototype working on my personal Linode, then tried to throw it into a work machine.

The page adds a script tag dynamically with some JavaScript. It's a bunch of Google charts that update based on different timeslices. That code looks something like this:

// jQuery $.post to send the beginning and end timestamps
$.post("channel_functions.php", data_to_post, function(data){
   // the data that's returned is the javascript I want to load
   var script = document.createElement('script');
   var head= document.getElementsByTagName('head')[0];
   var script= document.createElement('script');
   var text = document.createTextNode(data);
   script.type= 'text/javascript';
   script.id = 'chart_data';
   script.appendChild(text);
   // Adding script tag to page
   head.appendChild(script);
   // Call the function I know were present in the script tag
   loadTheCharts();
});

function loadTheCharts() {
   // These are the functions that were loaded dynamically
   // By this point the script tag is supposed be loaded, added and eval'd
   function1();
   function2();
}

Function1() and function2() don't exist until they get added to the dom, but I don't call loadTheCharts() until after the $.post has run so this doesn't seem to be a problem.

I'm one of those dirty PHP coders you mother warned you about, so I'm not well versed in JavaScript beyond what I've read in the typical go-to O'Reilly books. But this code worked fine on my personal dev server, so I'm wondering why it wouldn't work on this new machine.

The only difference in setup, from what I can tell, is that the new machine is running on port 8080, so it's 192.168.blah.blah:8080/index.php instead of nicedomain.com/index.php.

I see the code was indeed added to the dom when I use webmaster tools to "view generated source" but in Firebug I get an error like "function2() is undefined" even though my understanding was that all script tags are eval'ed when added to .

My question: Given what I've laid out, and that the machine is running on :8080, is there a reason anyone can think of as to why a dynamically loaded function like function2() would be defined on the Linode and not on the machine running Apache on 8080?

+1  A: 

Why don't you just eval the responseText? I don't see the need to create a new script node.

Javier Parra
You would need to do this if you wanted to execute code with `function` or `var` statements in global scope. Otherwise they'd be stuck in the caller's local scope. Usually you'd want to avoid this though. (You can of course write to `window.prop` from inside the `eval`.)
bobince
So I can do an alert(data) and see all that JS just fine, so I know it's being returned. Yet when I follow that with a eval(data) the functions still don't seem to go "live." Perplexing!I'm thinking this problem is a scoping issue. Is there any way to run a function off window? Something like window.loadTheCharts()?
editor
@editor: all "global" symbols are really properties of the global object. In browsers, this is `window`, so `window.loadTheCharts()` will work just fine (assuming `loadTheCharts` isn't defined within another function).
outis
instead of declaring the functions as `function2(){}` in the data you should declare them as `function2 = function(){}` and they should be available globally after eval... I think
Javier Parra
Excellent idea. Hopefully that will work (I'll report back). Do you have to do: var function2 = function(){}? How do you execute functions on an object?
editor
No: `var` declares a variable local to the scope you `var`​rd it in, so `var f= function() {}` has the same problem as `function f() {}` here! You can do `f= function() {}` without the `var` but that's a bit naughty (referencing a variable without having `var`​rd it anywhere will be disallowed in ECMA262-5 Strict Mode); it'd probably be better to be explicit about it and say `window.f= function() { ... };`.
bobince
+2  A: 

jQuery supports javascript responses:

$.post("channel_functions.php", data_to_post, 
       function (data, textStatus, xhr) {loadTheCharts()}, 
       'script');

However, a dataType of "script" will turn a cross-domain POST into a GET, as per the documentation.

The main problem with eval is the eval-ed code inherits the scope the eval is in. Instead, you can use jQuery.globalEval. Try something like:

$.post("channel_functions.php", data_to_post, 
       function (data, textStatus, xhr) {
           /* data might have errors, which will cause an exception.
              We'll let the default exception handler catch & log it.
            */
           $.globalEval(data);
           loadTheCharts();
       });
outis