wm-html-include.js

Pleasures of HTML include while W3C HTML Import was still a draft

View project on GitHub

How the problem arose

One customer asked me for some additions to his Web page.
It had to be small, compact HTML insertions, with their own styles and behavior and interaction with the rest of the page (some event handling and data exchange).
At the same time, the customer would be able to change styles of these "widgets" along with the main theme of the page, and to change/add some interaction in the future.
How could I do this?
IFrame based solution is heavyweight and associated with surplus difficulties to overcome the "impermeability".
Web components are not supported yet everywhere, and it's too "unusual" for my customer.
And ...drumroll...
the Solution was found!

wm-html-include.js

is a small script to include external HTML page(s) into comprising HTML page.
A part of Wamer project

When to use it

If you need to compose a Web page on client-side, but either iframes or HTML Imports are not suitable to the case.
One most likely may need it to:
quickly sew Web page from some existing or newly developed small parts (components);
patch existing Web page not changing significantly its content.

How to use it

Static links

<!-- Any tag with reference to another HTML, may be another... -->
<div data-wi-src="http://another.domain/component-1.html"> </div>
<!-- ... -->
<!-- ... or the same domain -->
<span data-wi-src="component-2.html"> </span>
<!-- ... -->
<!-- It may even looks almost like W3C "import" -->
<link data-wi-src="component-3.html" />
<!-- ... -->
<!-- Somewhere below -->
<script src="wm-html-include.js"> </script>

The script includes all the pages referenced by data-wi-src attribute into the comprising HTML page.
Note!: the script entirely removes the target element replacing it with referenced content. So if you need any additional styles for included part you should wrap target with some container. Example:

<div style="width: 300px; height: 200px; background: silver;">
    <link data-wi-src="component.html" />
</div>

Dynamic links

Use wmHtmlInclude() function of the script interface.

<div id="place-here">
</div>
<!-- ... -->
<script src="wm-html-include.js"> </script>
<script>
    var link = document.createElement ('link');
    link.setAttribute ('data-wi-src', 'new-component.html');
    document.getElementById ('place-here').appendChild (link);

    // now do the thing
    window.wmHtmlInclude();
</script>

How it works

The script finds all the tags with data-wi-src attribute.
Then, for each such tag it gets the referred HTML page,
merges all it's style, link[rel="stylesheet"] to the target page,
replaces target element with source's body,
loads and runs source's script elements.

It circumvents the same-origin restrictions by YQL and works with any CORS enabled browser.

There are a few cases when the css or script is NOT loaded from the include:

  1. link or script with src attribute. The script checks if corresponding resource with the same url value already exists in the target document. In this case the resource is not loaded;
  2. You can define the loading condition explicitly by data-wi-loadchk attribute in included resources
<link href="https://code.jquery.com/ui/1.11.2/themes/redmond/jquery-ui.min.css" rel="stylesheet"
        data-wi-loadchk="jQuery.ui" />
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"
        data-wi-loadchk="jQuery.fn.scrollspy.noConflict" />
<!-- ... -->
<script src="https://code.jquery.com/ui/1.11.2/jquery-ui.min.js"
        data-wi-loadchk="jQuery.ui">
</script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"
        data-wi-loadchk="jQuery.fn.scrollspy.noConflict">
</script>

The script evaluates the condition pointed out by data-wi-loadchk and does NOT load the resource if the condition is true.
In the example above, the jQuery.ui and Bootstrap libraries are checked to prevent the second loading.

Some restrictions (not arduous)

In order to properly display the page, and due to the loading and processing strategy, it's required that included pages

More restrictions (significant)

Don't even try insecure (HTTP) includes on secure (HTTPS) page.
Normally, browser will block that.
And it will be right.

Examples

Acknowledgments

  • Thank @Matthew-Dove for the starting idea
  • Thank jQuery team for the great work, the Encyclopedia of cross-browser solutions.
  • Thank IE for sleepless night)) I like challenging puzzles)) I look forward to 12th series of this quest-thriller))