Jan Turoň
Jan Turoň

Reputation: 32912

eval JS in AJAX loaded contents

I'd like to load this code (1) via XMLHttpRequest in another page

<input type="text" onkeypress="info(event)"/>
<script>
  function info(e) { console.log(e.keyCode); }
</script>

This (2) is the way I tried...

<div id="x"></div>
<script>
  var xhr = new XMLHttpRequest();
  xhr.onload = handleResponse.bind(xhr);
  xhr.open("POST","test.php",true);
  xhr.send();

  function handleResponse() {
    var x = document.getElementById("x");
    x.innerHTML = this.responseText;
    var js = x.getElementsByTagName("script")[0];
    eval(js.innerText);
  }
</script>

...and this is the error I got on keypress:

Uncaught ReferenceError: info is not defined

Why the info() is not found since its definition was eval'd? How to make the info fire on keypress if (2) should be unaware of (1)? No jQuery.

Following Mike's recommendation, I created this question to solve separated problem that leads to explanation of this problem.

Upvotes: 1

Views: 563

Answers (1)

(edited for es202020, because JS has changed drastically since 2013 and the old answer is now an anti-pattern. Don't use eval)


Scope. You didn't eval it on window, you added it to the scope of that function handleResponse so it won't exist outside of handleResponse. Also, in this case you don't really need eval at all, just create a script element and add that:

function handleResponse(evt) {
  const s = document.createElement(`script`);
  s.textContent = evt.responseText;
  document.head.appendChild(s);

}

The browser already knows how to interpret scripts, but you need to add elements to the head if you want them to execute instead of be inserted as inactive DOM nodes after the page has already loaded.

Don't use eval().

Upvotes: 2

Related Questions