1

I have page A that issues an ajax call and brings in snipped B. This snippet is being added into the DOM and all the scripts in that snipper are eval-ed. In that snippet, I have 2 script tags as such:

<script type="text/javascript">
function doOptions(){
   alert('doOptions');
}
</script>
<script type="text/javascript">
   X = { 
      x : function(x) {
           alert('x');
      }
      
      
   }
</script>

Then the JS that is declared in the above script tags is being used on within snippet B as such:

  <button type="button" onclick="doOptions();"> options </button>       
  <button type="button" onclick="X.x();"> XX </button>

Clicking on the XX button work, but clicking on the options button, does not. Both Firefox and IE tell me that doOptions is not defined. Why?

Also, what category of JavaScript knowledge is this? Meaning, if I want to

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
ssm
  • 113
  • 4
  • You don't have to use `
    ` tags. Just indent your code by four spaces and then you can also post HTML as code. Should also be mentioned in the hints next to question textbox.
    – Felix Kling Jul 29 '10 at 19:29
  • What are you using for ajax and what library are you using to eval those scripts? – Gordon Tucker Jul 29 '10 at 19:37
  • YUI for ajax, to complete the async request. Once I get th response back, it is custom code to inject it into the dom via element.innerHTML and then calling a function on this element to query all the scripts blocks that are in the html and eval them one after another. Per my other comment, I now that both script blocks are being evaled. So my question is, why, after apperently successful evel, calling the function that is declared by itself fails, but calling a functionn inside an object works. – ssm Jul 29 '10 at 20:24

2 Answers2

1

This snippet is being added into the DOM and all the scripts in that snipper are eval-ed.

If you are using innerHTML to insert the script, it will not work - the script content will not be parsed. There are methods to get it working with Internet Explorer, but you'll never have a cross browser solution. You should look at returning the data from the AJAX request in a different format (as text, for example) and then creating and appending the script element using DOM functions. For example:

// Create the script element
var script = document.createElement("script");
script.type = "text/javascript";

// Set the source as the location of the ajax service
script.src = "http://path.to/myajaxhandler.php?ajaxopt=2&anotheropt=5";

// Add the script element
document.getElementsByTagName("head")[0].appendChild(script);

Either that or parse out the text content from the script elements returned in the AJAX call, but that gets more complicated because you'll need to use regular expressions (which aren't ideal for parsing HTML, but might be ok if the content returned isn't too complex).

Community
  • 1
  • 1
Andy E
  • 338,112
  • 86
  • 474
  • 445
  • I have a custom function that evals the scripts. It does a decent job dealing with diferent browsers. The snippets are definitelly getting evaled since the second one works. I can see that in Firebug that eval is being called on both snippets. I guess my question is what is the difference between the two snippets such that after an eval, the function is not available, but the function inside an object is? – ssm Jul 29 '10 at 20:21
  • I meant to say that the script blocks are definitely being evaled. – ssm Jul 29 '10 at 20:22
0

If my guess is right and your problem falls this case, this might be useful. The problem could be due to the reason that the evals are executed in the calling environments context.

I executed the following test:

function test() {
    eval('x={bar:function(){alert("bar");}}');
    eval('function foo(){alert("foo")}')


}
test();
x.bar(); //succeeds
foo(); //fails.

Here the call foo() fails because it is local to the test() function whereas the variable 'x' is a global variable(since 'var' is not specified) hence the call to bar() on x succeeds;

If you want to make 'foo' function available outside,

function test() {
    eval('x={bar:function(){alert("bar");}}');
    eval('foo = function(){alert("foo")}')


}
test();
x.bar();
foo();

Now we are assigning the function to a global variable ('var' not specified). Now you can call foo() function outside.

Hope this helps.

Marimuthu Madasamy
  • 13,126
  • 4
  • 30
  • 52
  • You nailed it on the head. You were testing exactly the scenario I was trying to describe. My only question is this: In your case, I can see how foo() is local to the test() function. In my case, my function is not declared inside of any other function, but in its own script block. Shouldn't this make it global? – ssm Jul 29 '10 at 20:29
  • Your functions are in its own script block but only when you call eval(), they are made available and there comes the "calling environment's context". If your call to eval() is not wrapped inside any function, the functions evaluated will be global otherwise the function definitions are local to the function(in your case, this function might be the Ajax success callback) which calls eval. – Marimuthu Madasamy Jul 29 '10 at 20:48