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