lit-html
Version:
HTML template literals in JavaScript
95 lines • 4 kB
JavaScript
/**
* @license
* Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
* This code may only be used under the BSD style license found at
* http://polymer.github.io/LICENSE.txt
* The complete set of authors may be found at
* http://polymer.github.io/AUTHORS.txt
* The complete set of contributors may be found at
* http://polymer.github.io/CONTRIBUTORS.txt
* Code distributed by Google as part of the polymer project is also
* subject to an additional IP rights grant found at
* http://polymer.github.io/PATENTS.txt
*/
import { isCEPolyfill } from './dom.js';
import { isTemplatePartActive } from './template.js';
/**
* An instance of a `Template` that can be attached to the DOM and updated
* with new values.
*/
export class TemplateInstance {
constructor(template, processor, getTemplate) {
this._parts = [];
this.template = template;
this.processor = processor;
this._getTemplate = getTemplate;
}
update(values) {
let i = 0;
for (const part of this._parts) {
if (part !== undefined) {
part.setValue(values[i]);
}
i++;
}
for (const part of this._parts) {
if (part !== undefined) {
part.commit();
}
}
}
_clone() {
// When using the Custom Elements polyfill, clone the node, rather than
// importing it, to keep the fragment in the template's document. This
// leaves the fragment inert so custom elements won't upgrade and
// potentially modify their contents by creating a polyfilled ShadowRoot
// while we traverse the tree.
const fragment = isCEPolyfill ?
this.template.element.content.cloneNode(true) :
document.importNode(this.template.element.content, true);
const parts = this.template.parts;
let partIndex = 0;
let nodeIndex = 0;
const _prepareInstance = (fragment) => {
// Edge needs all 4 parameters present; IE11 needs 3rd parameter to be
// null
const walker = document.createTreeWalker(fragment, 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */, null, false);
let node = walker.nextNode();
// Loop through all the nodes and parts of a template
while (partIndex < parts.length && node !== null) {
const part = parts[partIndex];
// Consecutive Parts may have the same node index, in the case of
// multiple bound attributes on an element. So each iteration we either
// increment the nodeIndex, if we aren't on a node with a part, or the
// partIndex if we are. By not incrementing the nodeIndex when we find a
// part, we allow for the next part to be associated with the current
// node if neccessasry.
if (!isTemplatePartActive(part)) {
this._parts.push(undefined);
partIndex++;
}
else if (nodeIndex === part.index) {
if (part.type === 'node') {
const part = this.processor.handleTextExpression(this._getTemplate);
part.insertAfterNode(node);
this._parts.push(part);
}
else {
this._parts.push(...this.processor.handleAttributeExpressions(node, part.name, part.strings));
}
partIndex++;
}
else {
nodeIndex++;
if (node.nodeName === 'TEMPLATE') {
_prepareInstance(node.content);
}
node = walker.nextNode();
}
}
};
_prepareInstance(fragment);
return fragment;
}
}
//# sourceMappingURL=template-instance.js.map