John
John

Reputation: 245

Javascript not executing when loaded via XMLHttpRequest but does when loaded with jQuery.load

While converting a script to not require jQuery, I've discovered that if I load my content (a partial html page with html and javascript) via XMLHttpRequest, the javascript in the partial page does not work. But if I load the partial using jQuery.load, it does work.

I've tried digging through jQuery's load function to see if it's doing anything special and nothing jumped out at me. I've been banging my head against the wall and searching for an answer for a couple of days now to no avail.

What am I doing wrong/how can I make it work like it does when loaded with jQuery.load?

EDIT

I got the XMLHttpRequest method to work by splitting out out my javascript from the html in the fragment and loading the javascript using the suggested technique here: https://stackoverflow.com/a/11695198/362958. However, that still does not provide an explanation of why jQuery.load works. Is jQuery umtimately parsing the HTML and doing the same thing for any scripts it finds within the content it loads?

I've set up a plunker (https://plnkr.co/edit/wE9RuULx251C5ARnUbCh) with the following code that demonstrates the issue. Note: once you load the fragment with jQuery, it will continue to work and you'll have to restart the plunk for the XMLHttpRequest method to fail again.

index.html:

<!DOCTYPE html>
<html>

  <head>
    <script data-require="jquery@*" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>

  <h3>Buttons</h3>  
    <div>
      <input type="button" value="Load with XMLHttpRequest" onclick="loadXMLDoc('ajaxContentDiv', 'fragmentToLoad.html');">  (Links do not work if loaded this way... Script from fragmentToLoad.html not loaded in DOM?) <br/><br/>
      <input type="button" value="Load with JQuery" onclick="jQuery('#ajaxContentDiv').load('fragmentToLoad.html');">  (Links will work if loaded this way)
    </div>
<br/>
<br/>
<br/>
<div id="ajaxContentDiv">Content will load here...</div>

  </body>

</html>

script.js:

function loadXMLDoc(targetDivName, url) {

  var xmlhttp = new XMLHttpRequest();
  xmlhttp.open("GET", url, true);
  xmlhttp.onreadystatechange = function () {
      if (xmlhttp.readyState == XMLHttpRequest.DONE) {
          if (xmlhttp.status == 200) {
              document.getElementById(targetDivName).innerHTML = xmlhttp.responseText;
          }
      }
  };
  xmlhttp.send();
}

fragmentToLoad.html:

<div id="divToBeUpdated">
  <span id="stringBox">String here</span>
</div>
<br/>
<h3>Links</h3>
<div>
  <a href="#" onclick="updateDiv('Hello World 1');">Link 1</a><br>
  <a href="#" onclick="updateDiv('Hello World 2');">Link 2</a><br>
  <a href="#" onclick="updateDiv('Hello World 3');">Link 3</a><br>
</div>

<script>
  function updateDiv(string){
    var stringBox = document.getElementById('stringBox');
    stringBox.innerHTML = string;
  }
</script>

Upvotes: 5

Views: 6909

Answers (1)

guest271314
guest271314

Reputation: 1

You can use single .html file, and you are on the correct track by splitting the html content - though you can also split the html content of a single file, rather than requesting two files. @Barmar explains the functionality of jQuery's .load() method at this comment.

script.js

function loadXMLDoc(targetDivName, url) {

  var xmlhttp = new XMLHttpRequest();
  xmlhttp.open("GET", url, true);
  xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == XMLHttpRequest.DONE) {
      if (xmlhttp.status == 200) {
        // create a `div` elemenent, append response to `div` element
        // get specific elements by `id`, append `script` element to `document.body`
        var content = document.createElement("div");
        content.innerHTML = xmlhttp.responseText
        var div = content.querySelector("#htmlContent");
        var contentScript = content.querySelector("#contentScript");
        var script = document.createElement("script");
        script.textContent = contentScript.textContent;
        document.getElementById(targetDivName).innerHTML = div.innerHTML;
        document.body.appendChild(script);
      }
    }
  };
  xmlhttp.send();
}

fragmentToLoad.html

<div id="htmlContent">
  <div id="divToBeUpdated">
    <span id="stringBox">String here</span>
  </div>
  <br/>
  <h3>Links</h3>
  <div class="links">
    <a href="#">Link 1</a>
    <br>
    <a href="#">Link 2</a>
    <br>
    <a href="#">Link 3</a>
    <br>
  </div>
</div>
<script type="text/javascript" id="contentScript">
  function updateDiv(string) {
    var stringBox = document.getElementById('stringBox');
    stringBox.innerHTML = string;
  }
  // attach `click` event to `.link a` elements here
  var links = document.querySelectorAll(".links a");
  for (var i = 0; i < links.length; i++) {
    (function(link, i) {
      console.log(i)
      link.addEventListener("click", function(e) {
        e.preventDefault();
        updateDiv("Hello World " + i)
      })
    })(links[i], i)
  }
</script>

plnkr https://plnkr.co/edit/7fLtGRSV7WlH2enLbwSW?p=preview

Upvotes: 3

Related Questions