1

I need to include several HTML files inside my main index.html file and execute some code when the included HTML elements are finished loading. I am using the following code to load the HTML files:

function includeHTML() {
  var z, i, elmnt, file, xhttp;
  /* Loop through a collection of all HTML elements: */
  z = document.getElementsByTagName("*");
  for (i = 0; i < z.length; i++) {
    elmnt = z[i];
    /*search for elements with a certain atrribute:*/
    file = elmnt.getAttribute("include-html");
    if (file) {
      /* Make an HTTP request using the attribute value as the file name: */
      xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function () {
        if (this.readyState == 4) {
          if (this.status == 200) {
            elmnt.innerHTML = this.responseText;
          }
          if (this.status == 404) {
            elmnt.innerHTML = "Page not found.";
          }
          /* Remove the attribute, and call this function once more: */
          elmnt.removeAttribute("include-html");
          includeHTML();
        }
      };
      xhttp.open("GET", file, true);
      xhttp.send();
      /* Exit the function: */
      console.log("FILENAME: " + file);
      console.log("Finished html loader IF FILE");
      return;
    }
  }
}

As this function is loading my files recursive I can't use window.onload or respective jquery to trigger after my DOM is finished loading. The supposed behavior should be this way (The script is at the bottom of the body tag):

<script type="text/javascript">
  includeHTML();

  window.onload = function () {
    console.log("DOM loaded");
    // Do stuff after includeHTML is done and all DOM Elements can be retrieved with
    // document.getElementById();
  };
</script>

Right now if I am running js code to be executed the XHTML Requests are still not finished loading all my DOM Content but the js code is executed anyway, I need to make sure that all HTML Content is available before continuing my work.

tanmay_garg
  • 377
  • 1
  • 13
NJ85
  • 23
  • 1
  • 4
  • Perhaps putting the `script` where you call `includeHTML()` in the `` tag might help. – tanmay_garg May 25 '20 at 13:45
  • Hey the problem while putting the HTML Inclusion inside the is that the page is not loaded yet and the include statements cannot be found. If i defer the script inside the header the script is still executed "too late". – NJ85 May 25 '20 at 14:40
  • Is this what you are looking for? https://stackoverflow.com/questions/21518381/proper-way-to-wait-for-one-function-to-finish-before-continuing – tanmay_garg May 25 '20 at 16:04
  • Also, @NJ85 an alternate approach to loading the elements could be using jquery's `.load()` function: https://api.jquery.com/load/. It might be faster and could solve your problem. I'm not sure. Try it out. – tanmay_garg May 26 '20 at 09:01
  • Working it out with jquery Did the thing thank you very much @tanmay-garg . Another plus is i can get rid of the recursive behavior. – NJ85 May 26 '20 at 10:29
  • Yes you can get rid of the recursion! I'll add it as an answer... – tanmay_garg May 26 '20 at 10:30
  • I have posted my answer. Do have a look at the P.S. part too once. That might be the error in your code. If the answer solves your problem, please upvote and mark it as accepted (click the tick)! Thanks. – tanmay_garg May 26 '20 at 11:03

1 Answers1

0

I think your code is basically having problems dealing with the synchronous nature of JavaScript >> When is JavaScript synchronous?

So, I don't know you can make function async so that your code doesn't execute in parallel. Perhaps the answers at Proper way to wait for one function to finish before continuing? might shed some light on it though.

But, an alternative and simpler approach to this could be using jquery's .load() function as such:

function includeHTML() {
  var z, i, elmnt, file;

  /* Loop through a collection of all HTML elements: */
  z = document.getElementsByTagName("*");

  for (i = 0; i < z.length; i++) {
    elmnt = z[i];
    file = elmnt.getAttribute("include-html");

    /* only use elements having this attribute: */
    if (file) {
      elmnt.load(file);
      elmnt.removeAttribute("include-html");
    }
  }
}

P.S. The code you are using is an implementation of How to Include HTML | W3Schools. So, that code works for w3-include-html as an attribute and I guess it should work for include-html instead too. But, W3 is only loading one div whereas you are doing many, and thus removing the return might work.

tanmay_garg
  • 377
  • 1
  • 13
  • @NJ85 please tell me if this solves your problem and mark it as accepted if it does. If not, tell me what issue you're facing. – tanmay_garg May 27 '20 at 07:21