Web Components

HTML Templates

HTML Imports described in the previous article are handy way for linking external HTML to front-end Web pages. Importing is usually accompanied with creating a range of Web components in external resources: for example, an imported HTML file can contain an inert DOM subtree which is employed to build identical fragments in the main document. Implementation of HTML Templates enables the use of the <template> element with a number of child nodes. Such nodes are provided with custom style attributes and event handlers. Templates are parsed "on-demand" when a code snippet selects a <template> and returns its content as an instance of DocumentFragment.

The example below creates a template containing a single image element. The template has inline CSS declarations and attaches a load event handler to the image. The template will be imported to a document displaying an extract dedicated to Java Database Connectivity. A scripting routine in the main document will use the template to decorate three blocks of text. Each image will have identical style and behavior based on the template, but sources of images will vary.

The template declaration starts with the <template> element, then the <img> with its attributes follows:

image-template.html
<template>
 <img src="placeholder.png" width="48" height="48"
  style="float: left; shape-margin: 2px; shape-image-threshold: 0.7;"
  onload="this.style.shapeOutside='url('+this.src+')';">
</template>

The image style is based on the CSS Shapes specification: when a source of the image loads in the main document, the shape contour will be rendered as the outline of the source enclosing all pixels with alpha values greater than 0.7.

The main document contains both markup and text nodes. The first <div> element is introductory. Two child nodes of the next <div> element describe DriverManager and DataSource as mechanisms for establishing a JDBC connection:

main-document.html
. . .
<link rel="import" href="image-template.html">
. . .
<div id="intro">
 The JDBC API . . .
</div>
<div id="api">
 In a typical scenario, a JDBC application will connect to a target data source using one of two mechanisms:
 <div>
  DriverManager . . .
 </div>
 <div>
  DataSource . . .
 </div>
</div>

First of all, the external template is imported to the main document:

a scripting routine in the main document
var imported=document.querySelector("link[rel='import']").import;

Even if an imported document only contains a markup fragment, i.e. HTML without <html>, <head> and <body> elements, it is parsed as an instance of HTMLDocument:

console.log(imported.nodeType); // 9: DOCUMENT_NODE

The next step is to obtain access to the imported template:

var template=imported.querySelector("template"); // HTMLTemplateElement

The content property of the template element returns its child nodes as a DocumentFragment:

var content=template.content; // DocumentFragment

The imported fragment will be inserted before three blocks of text, each time with a different source:

var intro=document.querySelector("#intro");
content.querySelector("img").src="java.png";
intro.insertBefore(content.cloneNode(true), intro.childNodes[0]);

var driverManager=document.querySelector("#api").childNodes[1];
content.querySelector("img").src="green-pin.png";
driverManager.insertBefore(content.cloneNode(true), driverManager.childNodes[0]);

var dataSource=document.querySelector("#api").childNodes[2];
content.querySelector("img").src="blue-pin.png";
dataSource.insertBefore(content.cloneNode(true), dataSource.childNodes[0]);