| /** | |
| * @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 { isTemplatePartActive } from './template.js'; | |
| const walkerNodeFilter = 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */; | |
| /** | |
| * Removes the list of nodes from a Template safely. In addition to removing | |
| * nodes from the Template, the Template part indices are updated to match | |
| * the mutated Template DOM. | |
| * | |
| * As the template is walked the removal state is tracked and | |
| * part indices are adjusted as needed. | |
| * | |
| * div | |
| * div#1 (remove) <-- start removing (removing node is div#1) | |
| * div | |
| * div#2 (remove) <-- continue removing (removing node is still div#1) | |
| * div | |
| * div <-- stop removing since previous sibling is the removing node (div#1, | |
| * removed 4 nodes) | |
| */ | |
| export function removeNodesFromTemplate(template, nodesToRemove) { | |
| const { element: { content }, parts } = template; | |
| const walker = document.createTreeWalker(content, walkerNodeFilter, null, false); | |
| let partIndex = nextActiveIndexInTemplateParts(parts); | |
| let part = parts[partIndex]; | |
| let nodeIndex = -1; | |
| let removeCount = 0; | |
| const nodesToRemoveInTemplate = []; | |
| let currentRemovingNode = null; | |
| while (walker.nextNode()) { | |
| nodeIndex++; | |
| const node = walker.currentNode; | |
| // End removal if stepped past the removing node | |
| if (node.previousSibling === currentRemovingNode) { | |
| currentRemovingNode = null; | |
| } | |
| // A node to remove was found in the template | |
| if (nodesToRemove.has(node)) { | |
| nodesToRemoveInTemplate.push(node); | |
| // Track node we're removing | |
| if (currentRemovingNode === null) { | |
| currentRemovingNode = node; | |
| } | |
| } | |
| // When removing, increment count by which to adjust subsequent part indices | |
| if (currentRemovingNode !== null) { | |
| removeCount++; | |
| } | |
| while (part !== undefined && part.index === nodeIndex) { | |
| // If part is in a removed node deactivate it by setting index to -1 or | |
| // adjust the index as needed. | |
| part.index = currentRemovingNode !== null ? -1 : part.index - removeCount; | |
| // go to the next active part. | |
| partIndex = nextActiveIndexInTemplateParts(parts, partIndex); | |
| part = parts[partIndex]; | |
| } | |
| } | |
| nodesToRemoveInTemplate.forEach((n) => n.parentNode.removeChild(n)); | |
| } | |
| const countNodes = (node) => { | |
| let count = (node.nodeType === 11 /* Node.DOCUMENT_FRAGMENT_NODE */) ? 0 : 1; | |
| const walker = document.createTreeWalker(node, walkerNodeFilter, null, false); | |
| while (walker.nextNode()) { | |
| count++; | |
| } | |
| return count; | |
| }; | |
| const nextActiveIndexInTemplateParts = (parts, startIndex = -1) => { | |
| for (let i = startIndex + 1; i < parts.length; i++) { | |
| const part = parts[i]; | |
| if (isTemplatePartActive(part)) { | |
| return i; | |
| } | |
| } | |
| return -1; | |
| }; | |
| /** | |
| * Inserts the given node into the Template, optionally before the given | |
| * refNode. In addition to inserting the node into the Template, the Template | |
| * part indices are updated to match the mutated Template DOM. | |
| */ | |
| export function insertNodeIntoTemplate(template, node, refNode = null) { | |
| const { element: { content }, parts } = template; | |
| // If there's no refNode, then put node at end of template. | |
| // No part indices need to be shifted in this case. | |
| if (refNode === null || refNode === undefined) { | |
| content.appendChild(node); | |
| return; | |
| } | |
| const walker = document.createTreeWalker(content, walkerNodeFilter, null, false); | |
| let partIndex = nextActiveIndexInTemplateParts(parts); | |
| let insertCount = 0; | |
| let walkerIndex = -1; | |
| while (walker.nextNode()) { | |
| walkerIndex++; | |
| const walkerNode = walker.currentNode; | |
| if (walkerNode === refNode) { | |
| insertCount = countNodes(node); | |
| refNode.parentNode.insertBefore(node, refNode); | |
| } | |
| while (partIndex !== -1 && parts[partIndex].index === walkerIndex) { | |
| // If we've inserted the node, simply adjust all subsequent parts | |
| if (insertCount > 0) { | |
| while (partIndex !== -1) { | |
| parts[partIndex].index += insertCount; | |
| partIndex = nextActiveIndexInTemplateParts(parts, partIndex); | |
| } | |
| return; | |
| } | |
| partIndex = nextActiveIndexInTemplateParts(parts, partIndex); | |
| } | |
| } | |
| } | |
| //# sourceMappingURL=modify-template.js.map |