UNPKG

es5-lit-html

Version:
168 lines (137 loc) 5.14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.removeNodesFromTemplate = removeNodesFromTemplate; exports.insertNodeIntoTemplate = insertNodeIntoTemplate; var _template = require("./template.js"); /** * @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 */ /** * @module shady-render */ var 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) */ function removeNodesFromTemplate(template, nodesToRemove) { var content = template.element.content, parts = template.parts; var walker = document.createTreeWalker(content, walkerNodeFilter, null, false); var partIndex = nextActiveIndexInTemplateParts(parts); var part = parts[partIndex]; var nodeIndex = -1; var removeCount = 0; var nodesToRemoveInTemplate = []; var currentRemovingNode = null; while (walker.nextNode()) { nodeIndex++; var 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(function (n) { return n.parentNode.removeChild(n); }); } var countNodes = function countNodes(node) { var count = node.nodeType === 11 /* Node.DOCUMENT_FRAGMENT_NODE */ ? 0 : 1; var walker = document.createTreeWalker(node, walkerNodeFilter, null, false); while (walker.nextNode()) { count++; } return count; }; var nextActiveIndexInTemplateParts = function nextActiveIndexInTemplateParts(parts) { var startIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; for (var i = startIndex + 1; i < parts.length; i++) { var part = parts[i]; if ((0, _template.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. */ function insertNodeIntoTemplate(template, node) { var refNode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var content = template.element.content, parts = template.parts; // 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; } var walker = document.createTreeWalker(content, walkerNodeFilter, null, false); var partIndex = nextActiveIndexInTemplateParts(parts); var insertCount = 0; var walkerIndex = -1; while (walker.nextNode()) { walkerIndex++; var 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); } } }