diff --git a/src/lit-html.ts b/src/lit-html.ts
index 57b2ba3..35f8a10 100644
--- a/src/lit-html.ts
+++ b/src/lit-html.ts
@@ -266,24 +266,12 @@ export class NodePart extends Part {
}
setValue(value: any): void {
- let node: Node|undefined = undefined;
value = this._getValue(value);
if (value instanceof Node) {
- this.clear();
- node = value;
- this._previousValue = value;
+ this._previousValue = this._setNodeValue(value);
} else if (value instanceof TemplateResult) {
- let instance: TemplateInstance;
- if (this._previousValue && this._previousValue._template === value.template) {
- instance = this._previousValue;
- } else {
- this.clear();
- instance = this.instance._createInstance(value.template);
- node = instance._clone();
- }
- instance.update(value.values);
- this._previousValue = instance;
+ this._previousValue = this._setTemplateResultValue(value);
} else if (value && value.then !== undefined) {
value.then((v: any) => {
if (this._previousValue === value) {
@@ -292,76 +280,103 @@ export class NodePart extends Part {
});
this._previousValue = value;
} else if (value && typeof value !== 'string' && value[Symbol.iterator]) {
- // For an Iterable, we create a new InstancePart per item, then set its
- // value to the item. This is a little bit of overhead for every item in
- // an Iterable, but it lets us recurse easily and update Arrays of
- // TemplateResults that will be commonly returned from expressions like:
- // array.map((i) => html`${i}`)
-
- // We reuse this parts startNode as the first part's startNode, and this
- // parts endNode as the last part's endNode.
-
- let itemStart = this.startNode;
- let itemEnd;
- const values = value[Symbol.iterator]() as Iterator;
-
- const previousParts: NodePart[]|undefined = Array.isArray(this._previousValue) ? this._previousValue : undefined;
- let previousPartsIndex = 0;
- const itemParts = [];
- let current = values.next();
- let next = values.next();
-
- if (current.done) {
- // Empty iterable, just clear
- this.clear();
- }
- while (!current.done) {
- // Reuse a previous part if we can, otherwise create a new one
- let itemPart: NodePart;
- if (previousParts !== undefined && previousPartsIndex < previousParts.length) {
- itemPart = previousParts[previousPartsIndex++];
- if (next.done && itemPart.endNode !== this.endNode) {
- // Since this is the last part we'll use, set it's endNode to the
- // container's endNode. Setting the value of this part will clean
- // up any residual nodes from a previously longer iterable.
-
- // Remove previousSibling, since we want itemPart.endNode to be
- // removed as part of the clear operation.
- this.clear(itemPart.endNode.previousSibling!);
- itemPart.endNode = this.endNode;
- }
- itemEnd = itemPart.endNode;
- } else {
- if (next.done) {
- // on the last item, reuse this part's endNode
- itemEnd = this.endNode;
- } else {
- itemEnd = new Text();
- this.endNode.parentNode!.insertBefore(itemEnd, this.endNode);
- }
- itemPart = new NodePart(this.instance, itemStart, itemEnd);
- }
-
- itemPart.setValue(current.value);
- itemParts.push(itemPart);
-
- current = next;
- next = values.next();
- itemStart = itemEnd;
- }
- this._previousValue = itemParts;
+ this._previousValue = this._setIterableValue(value);
} else if (this.startNode.nextSibling! === this.endNode.previousSibling! &&
this.startNode.nextSibling!.nodeType === Node.TEXT_NODE) {
this.startNode.nextSibling!.textContent = value;
this._previousValue = value;
} else {
+ this._previousValue = this._setTextValue(value);
+ }
+ }
+
+ private _insertNodeBeforeEndNode(node: Node) {
+ this.endNode.parentNode!.insertBefore(node, this.endNode);
+ }
+
+ private _setNodeValue(value: Node): Node {
+ this.clear();
+ this._insertNodeBeforeEndNode(value);
+
+ return value;
+ }
+
+ private _setTextValue(value: string): Node {
+ return this._setNodeValue(new Text(value));
+ }
+
+ private _setTemplateResultValue(value: TemplateResult): TemplateInstance {
+ let instance: TemplateInstance;
+ if (this._previousValue && this._previousValue._template === value.template) {
+ instance = this._previousValue;
+ } else {
+ instance = this.instance._createInstance(value.template);
+ this._setNodeValue(instance._clone());
+ }
+ instance.update(value.values);
+ return instance;
+ }
+
+ private _setIterableValue(value: any): NodePart[] {
+ // For an Iterable, we create a new InstancePart per item, then set its
+ // value to the item. This is a little bit of overhead for every item in
+ // an Iterable, but it lets us recurse easily and update Arrays of
+ // TemplateResults that will be commonly returned from expressions like:
+ // array.map((i) => html`${i}`)
+
+ // We reuse this parts startNode as the first part's startNode, and this
+ // parts endNode as the last part's endNode.
+
+ let itemStart = this.startNode;
+ let itemEnd;
+ const values = value[Symbol.iterator]() as Iterator;
+
+ const previousParts: NodePart[]|undefined = Array.isArray(this._previousValue) ?
+ this._previousValue : undefined;
+ let previousPartsIndex = 0;
+ const itemParts = [];
+ let current = values.next();
+ let next = values.next();
+
+ if (current.done) {
+ // Empty iterable, just clear
this.clear();
- node = new Text(value);
- this._previousValue = value;
}
- if (node !== undefined) {
- this.endNode.parentNode!.insertBefore(node, this.endNode);
+ while (!current.done) {
+ // Reuse a previous part if we can, otherwise create a new one
+ let itemPart: NodePart;
+ if (previousParts !== undefined && previousPartsIndex < previousParts.length) {
+ itemPart = previousParts[previousPartsIndex++];
+ if (next.done && itemPart.endNode !== this.endNode) {
+ // Since this is the last part we'll use, set it's endNode to the
+ // container's endNode. Setting the value of this part will clean
+ // up any residual nodes from a previously longer iterable.
+
+ // Remove previousSibling, since we want itemPart.endNode to be
+ // removed as part of the clear operation.
+ this.clear(itemPart.endNode.previousSibling!);
+ itemPart.endNode = this.endNode;
+ }
+ itemEnd = itemPart.endNode;
+ } else {
+ if (next.done) {
+ // on the last item, reuse this part's endNode
+ itemEnd = this.endNode;
+ } else {
+ itemEnd = new Text();
+ this._insertNodeBeforeEndNode(itemEnd);
+ }
+ itemPart = new NodePart(this.instance, itemStart, itemEnd);
+ }
+
+ itemPart.setValue(current.value);
+ itemParts.push(itemPart);
+
+ current = next;
+ next = values.next();
+ itemStart = itemEnd;
}
+ return itemParts;
}
clear(startNode: Node = this.startNode) {