Commit b588b1cbc0c0e85d0288a7fa484660bf8225a915
html-element: new algorithm for replacing nodes, takes existing nodes into account
Matt McKegg committed on 7/27/2016, 4:41:35 AMParent: 3bfb6e65a932b5fb11b3c2260c7582699eb17ae5
Files changed
html-element.js | changed |
html-element.js | |||
---|---|---|---|
@@ -111,29 +111,42 @@ | |||
111 | 111 … | } | |
112 | 112 … | }) | |
113 | 113 … | } | |
114 | 114 … | ||
115 … | +function indexOf (target, item) { | ||
116 … | + return Array.prototype.indexOf.call(target, item) | ||
117 … | +} | ||
118 … | + | ||
115 | 119 … | function replace (oldNodes, newNodes) { | |
116 | - // TODO: optmize to not reinsert nodes that are already in correct position! | ||
117 | 120 … | var parent = oldNodes[oldNodes.length - 1].parentNode | |
118 | - var marker = oldNodes[oldNodes.length - 1].nextSibling | ||
121 … | + var nodes = parent.childNodes | ||
122 … | + var startIndex = indexOf(nodes, oldNodes[0]) | ||
123 … | + | ||
124 … | + // avoid reinserting nodes that are already in correct position! | ||
125 … | + for (var i = 0; i < newNodes.length; i++) { | ||
126 … | + if (nodes[i + startIndex] === newNodes[i]) { | ||
127 … | + continue | ||
128 … | + } else if (nodes[i + startIndex + 1] === newNodes[i]) { | ||
129 … | + parent.removeChild(nodes[i + startIndex]) | ||
130 … | + continue | ||
131 … | + } else if (nodes[i + startIndex] === newNodes[i + 1] && newNodes[i + 1]) { | ||
132 … | + parent.insertBefore(newNodes[i], nodes[i + startIndex]) | ||
133 … | + } else if (nodes[i + startIndex]) { | ||
134 … | + parent.insertBefore(newNodes[i], nodes[i + startIndex]) | ||
135 … | + } else { | ||
136 … | + parent.appendChild(newNodes[i]) | ||
137 … | + } | ||
138 … | + walk(newNodes[i], rebind) | ||
139 … | + } | ||
140 … | + | ||
119 | 141 … | oldNodes.filter(function (node) { | |
120 | 142 … | return !~newNodes.indexOf(node) | |
121 | 143 … | }).forEach(function (node) { | |
122 | - parent.removeChild(node) | ||
144 … | + if (node.parentNode) { | ||
145 … | + parent.removeChild(node) | ||
146 … | + } | ||
123 | 147 … | walk(node, unbind) | |
124 | 148 … | }) | |
125 | - if (marker) { | ||
126 | - newNodes.forEach(function (node) { | ||
127 | - parent.insertBefore(node, marker) | ||
128 | - walk(node, rebind) | ||
129 | - }) | ||
130 | - } else { | ||
131 | - newNodes.forEach(function (node) { | ||
132 | - parent.appendChild(node) | ||
133 | - walk(node, rebind) | ||
134 | - }) | ||
135 | - } | ||
136 | 149 … | } | |
137 | 150 … | ||
138 | 151 … | function isText (value) { | |
139 | 152 … | return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' | |
@@ -152,15 +165,16 @@ | |||
152 | 165 … | function getNodes (document, nodeOrNodes) { | |
153 | 166 … | if (Array.isArray(nodeOrNodes)) { | |
154 | 167 … | if (nodeOrNodes.length) { | |
155 | 168 … | var result = [] | |
156 | - nodeOrNodes.forEach(function (item) { | ||
169 … | + for (var i = 0; i < nodeOrNodes.length; i++) { | ||
170 … | + var item = nodeOrNodes[i] | ||
157 | 171 … | if (Array.isArray(item)) { | |
158 | 172 … | getNodes(document, item).forEach(push, result) | |
159 | 173 … | } else { | |
160 | 174 … | result.push(getNode(document, item)) | |
161 | 175 … | } | |
162 | - }) | ||
176 … | + } | ||
163 | 177 … | return result.map(getNode.bind(this, document)) | |
164 | 178 … | } else { | |
165 | 179 … | return [getNode(document, null)] | |
166 | 180 … | } |
Built with git-ssb-web