0

I have a JavaScript function that gets data and a function statement from PHP via XMLHttpRequest.How do I call the function that the PHP returned? It doesn't seem to exist. I'm totally lost as to how to make this happen. Here are test files that better explain it:

test.html

<!DOCTYPE html>
<html lang="en">
<head>
<script>
function main(){
    var xhttp = new XMLHttpRequest();
    xhttp.open("POST", "/test2.php", true);
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xhttp.send('foo=bar');
    xhttp.onreadystatechange = function(){
        if (xhttp.readyState == 4 && xhttp.status == 200) {
            document.getElementById('testDiv').innerHTML = xhttp.responseText;
            if (typeof injectedJS === "function") {
                console.log('yes');
            }else{
                console.log("no");
            }
        }
    };
};
</script>
</head>
<body onLoad=main()>
<div id="testDiv"></div>
</body>
</html>

test2.php

<?php
echo("<h1>Hello!</h1>");
echo("<script>function injectedJS() {var foo='bar';}</script>");
?>

The "Hello!" text is being displayed but "no" is logged to the console.

Thanks in advance for any help or a steer in the right direction, John

7
  • 1
    How do you expect that injectedJS would be assigned a value? Commented Jun 21, 2022 at 21:38
  • A steer in the right direction would be to eval(xhttp.responseText) into life. Commented Jun 21, 2022 at 21:42
  • @ITgoldman - if it were 2014, sure. Commented Jun 21, 2022 at 23:32
  • script tags injected via ajax (or maybe even through innerHTML?) are not executed ... what you do is find the "injected" script tags, create a new script tag and copy the content into it Commented Jun 21, 2022 at 23:34
  • @Pointy - OP exepcts the added html <script>function injectedJS() {var foo='bar';}</script> would declare function injectedJS Commented Jun 21, 2022 at 23:35

1 Answer 1

1

Adding script tags using innerHTML won't execute those tags

Not even adding them through other methods like using DOMParser works

What you need to do is for each script tag you added, you use document.createElement('script') and duplicate the content, then add it to the DOM

  
const html = `<h1>Hello!</h1>
<scrpt>function injectedJS() {var foo='bar';}</scrpt>`.replaceAll('scrpt', 'script');
// ignore the replaceAll - seems snippets are careful about script tags - this is just dummying up the received data anyway

function main() {

  // this is what you put inside
  //   if (xhttp.readyState == 4 && xhttp.status == 200) {

  const tgt = document.getElementById('testDiv');
  
  // add the html to the target node
  tgt.innerHTML = html;

  // process any script tags in the target node
  tgt.querySelectorAll('script').forEach(scr => {

    // create a new script tag
    const newscript = document.createElement('script');

    // copy the contents to the new script tag
    newscript.textContent = scr.textContent;

    // add new script directly after the current location
    scr.insertAdjacentElement('afterend', newscript);

    // remove old script - not strictly required
    scr.remove();
  });

  if (typeof injectedJS === "function") {
    console.log('yes');
  } else {
    console.log("no");
  }
}
main();
<div>Test</div>
<div id="testDiv"></div>

By the way, instead of

xhttp.onreadystatechange = function(){
    if (xhttp.readyState == 4 && xhttp.status == 200) {
        // your code
    }
}

do

xhttp.onload = function(){
    // your code
}

or better still use fetch for cleaner looking code, but that's just opinion so not important

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Bravo! That worked perfectly in the actual project. I'll look at fetch API for the ajax stuff.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.