var domLookupCache = {}; var templatePathCache = {}; function getTemplateEl(id) { if (!domLookupCache[id]) { domLookupCache[id] = document.getElementById(id); } return domLookupCache[id]; } function collectElements(paths, rootElement) { var result = {}; for (var i = 0; i < paths.length; ++i) { var path = paths[i]; var current = rootElement; for (var j = 0; j < path[1].length; ++j) { current = current.children[path[1][j]]; } result[path[0]] = current; } return result; } function getTemplatePaths(id, rootElement) { if (!templatePathCache[id]) { var paths = []; paths.push(["root", []]); function descend(path, el) { for (var i = 0; i < el.children.length; ++i) { var child = el.children[i]; var childPath = path.concat([i]); var tmplName = child.getAttribute("data-tmpl"); if (tmplName) { paths.push([tmplName, childPath]); } if (child.children.length > 0) { descend(childPath, child); } } } descend([], rootElement); templatePathCache[id] = paths; } return templatePathCache[id]; } function makeTemplateCloner(id) { return function() { var templateEl = getTemplateEl(id); if (templateEl === null) { throw new Error(`Couldn\'t find template with ID '${id}'`); } var root = templateEl.content.cloneNode(true); var paths = getTemplatePaths(id, root); var result = collectElements(paths, root); return result; }; } function emptyElement(el) { var newEl = el.cloneNode(false); el.parentElement.insertBefore(newEl, el); el.parentElement.removeChild(el); return newEl; }