|
40 | 40 | } |
41 | 41 | }; |
42 | 42 |
|
43 | | - var SubsetMapping = function SubsetMapping(a, b) { |
44 | | - this.oldValue = a; |
45 | | - this.newValue = b; |
46 | | - }; |
47 | 43 |
|
48 | | - SubsetMapping.prototype = { |
49 | | - contains: function contains(subset) { |
50 | | - if (subset.length < this.length) { |
51 | | - return subset.newValue >= this.newValue && subset.newValue < this.newValue + this.length; |
52 | | - } |
53 | | - return false; |
54 | | - }, |
55 | | - toString: function toString() { |
56 | | - return this.length + " element subset, first mapping: old " + this.oldValue + " → new " + this.newValue; |
57 | | - } |
58 | | - }; |
59 | 44 |
|
60 | 45 | var elementDescriptors = function(el) { |
61 | 46 | var output = []; |
|
318 | 303 | if (lcsSize === 0) { |
319 | 304 | return false; |
320 | 305 | } |
321 | | - origin = [index[0] - lcsSize, index[1] - lcsSize]; |
322 | | - ret = new SubsetMapping(origin[0], origin[1]); |
323 | | - ret.length = lcsSize; |
324 | 306 |
|
325 | | - return ret; |
| 307 | + return { |
| 308 | + oldValue: index[0] - lcsSize, |
| 309 | + newValue: index[1] - lcsSize, |
| 310 | + length: lcsSize |
| 311 | + }; |
326 | 312 | }; |
327 | 313 |
|
328 | 314 | /** |
|
413 | 399 | } |
414 | 400 | } |
415 | 401 | } |
| 402 | + |
| 403 | + oldTree.subsets = subsets; |
| 404 | + oldTree.subsetsAge = 100; |
416 | 405 | return subsets; |
417 | 406 | }; |
418 | 407 |
|
|
448 | 437 | debug: false, |
449 | 438 | diffcap: 10, // Limit for how many diffs are accepting when debugging. Inactive when debug is false. |
450 | 439 | maxDepth: false, // False or a numeral. If set to a numeral, limits the level of depth that the the diff mechanism looks for differences. If false, goes through the entire tree. |
451 | | - maxChildCount: false, // False or a numeral. If set to a numeral, does not try to diff the contents of nodes with more children if there are more than maxChildCountDiffCount differences among child nodes. |
452 | | - maxChildCountDiffCount: 3, // Numeral. See maxChildCount. |
| 440 | + maxChildCount: 50, // False or a numeral. If set to a numeral, does not try to diff the contents of nodes with more children if there are more than maxChildDiffCount differences among child nodes. |
| 441 | + maxChildDiffCount: 3, // Numeral. See maxChildCount. |
453 | 442 | valueDiffing: true, // Whether to take into consideration the values of forms that differ from auto assigned values (when a user fills out a form). |
454 | 443 | // syntax: textDiff: function (node, currentValue, expectedValue, newValue) |
455 | 444 | textDiff: function() { |
|
640 | 629 | ]; |
641 | 630 | } |
642 | 631 |
|
643 | | - if (this.maxChildCount && t1.childNodes && t2.childNodes && t1.childNodes.length > this.maxChildCount && t2.childNodes.length > this.maxChildCount) { |
| 632 | + if (route.length && this.maxChildCount && t1.childNodes && t2.childNodes && t1.childNodes.length > this.maxChildCount && t2.childNodes.length > this.maxChildCount) { |
644 | 633 | var childNodesLength = t1.childNodes.length < t2.childNodes.length ? t1.childNodes.length : t2.childNodes.length, childDiffCount = 0, j = 0; |
645 | | - while (childDiffCount < this.maxChildCountDiffCount && j < childNodesLength) { |
| 634 | + while (childDiffCount < this.maxChildDiffCount && j < childNodesLength) { |
646 | 635 | if (!isEqual(t1.childNodes[j], t2.childNodes[j])) { |
647 | 636 | childDiffCount++; |
648 | 637 | } |
649 | 638 | j++; |
650 | 639 | } |
651 | | - if (childDiffCount === this.maxChildCountDiffCount) { |
| 640 | + if (childDiffCount === this.maxChildDiffCount) { |
652 | 641 | return [new Diff() |
653 | 642 | .setValue(t._const.action, t._const.replaceElement) |
654 | 643 | .setValue(t._const.oldValue, cloneObj(t1)) |
|
809 | 798 | return node; |
810 | 799 | }, |
811 | 800 | findInnerDiff: function(t1, t2, route) { |
812 | | - var t = this; |
813 | | - var subtrees = (t1.childNodes && t2.childNodes) ? markSubTrees(t1, t2) : [], |
| 801 | + var oldSubsets = t1.subsets; |
| 802 | + //var subtrees = (t1.childNodes && t2.childNodes) ? markSubTrees(t1, t2) : [], |
| 803 | + var subtrees = t1.subsets && t1.subsetsAge-- ? t1.subsets : (t1.childNodes && t2.childNodes) ? markSubTrees(t1, t2) : [], |
814 | 804 | t1ChildNodes = t1.childNodes ? t1.childNodes : [], |
815 | 805 | t2ChildNodes = t2.childNodes ? t2.childNodes : [], |
816 | 806 | childNodesLengthDifference, diffs = [], |
817 | | - index = 0, |
| 807 | + index = 0, t = this, |
818 | 808 | last, e1, e2, i; |
819 | 809 |
|
820 | 810 | if (subtrees.length > 0) { |
|
1087 | 1077 | node = routeInfo.node, |
1088 | 1078 | parentNode = routeInfo.parentNode, |
1089 | 1079 | nodeIndex = routeInfo.nodeIndex, |
| 1080 | + newSubsets = [], splitLength, |
1090 | 1081 | newNode, movedNode, nodeArray, route, length, c, i; |
1091 | 1082 |
|
1092 | 1083 | var t = this; |
|
1169 | 1160 | movedNode = nodeArray[i]; |
1170 | 1161 | node.childNodes.splice(diff[t._const.to], 0, movedNode); |
1171 | 1162 | } |
| 1163 | + if (node.subsets) { |
| 1164 | + |
| 1165 | + node.subsets.forEach(function(map) { |
| 1166 | + if (diff[t._const.from] < diff[t._const.to] && map.oldValue <= diff[t._const.to] && map.oldValue > diff[t._const.from]) { |
| 1167 | + map.oldValue -= diff.groupLength; |
| 1168 | + splitLength = map.oldValue + map.length - diff[t._const.to]; |
| 1169 | + if (splitLength > 0) { |
| 1170 | + // new insertion splits map. |
| 1171 | + newSubsets.push({ |
| 1172 | + oldValue: diff[t._const.to] + diff.groupLength, |
| 1173 | + newValue: map.newValue + map.length - splitLength, |
| 1174 | + length: splitLength |
| 1175 | + }) |
| 1176 | + map.length -= splitLength; |
| 1177 | + } |
| 1178 | + } else if (diff[t._const.from] > diff[t._const.to] && map.oldValue > diff[t._const.to] && map.oldValue < diff[t._const.from]) { |
| 1179 | + map.oldValue += diff.groupLength; |
| 1180 | + splitLength = map.oldValue + map.length - diff[t._const.to]; |
| 1181 | + if (splitLength > 0) { |
| 1182 | + // new insertion splits map. |
| 1183 | + newSubsets.push({ |
| 1184 | + oldValue: diff[t._const.to] + diff.groupLength, |
| 1185 | + newValue: map.newValue + map.length - splitLength, |
| 1186 | + length: splitLength |
| 1187 | + }) |
| 1188 | + map.length -= splitLength; |
| 1189 | + } |
| 1190 | + } else if (map.oldValue === diff[t._const.from]) { |
| 1191 | + map.oldValue = diff[t._const.to]; |
| 1192 | + } |
| 1193 | + }); |
| 1194 | + if (node.subsets && newSubsets.length) { |
| 1195 | + node.subsets = node.subsets.concat(newSubsets); |
| 1196 | + } |
| 1197 | + } |
| 1198 | + |
1172 | 1199 | break; |
1173 | 1200 | case this._const.removeElement: |
1174 | 1201 | parentNode.childNodes.splice(nodeIndex, 1); |
| 1202 | + if (parentNode.subsets) { |
| 1203 | + parentNode.subsets.forEach(function(map) { |
| 1204 | + if (map.oldValue > nodeIndex) { |
| 1205 | + map.oldValue -= 1; |
| 1206 | + } else if (map.oldValue === nodeIndex) { |
| 1207 | + map.delete = true; |
| 1208 | + } else if (map.oldValue < nodeIndex && (map.oldValue + map.length) > nodeIndex) { |
| 1209 | + if (map.oldValue + map.length - 1 === nodeIndex) { |
| 1210 | + map.length--; |
| 1211 | + } else { |
| 1212 | + newSubsets.push({ |
| 1213 | + newValue: map.newValue + nodeIndex - map.oldValue, |
| 1214 | + oldValue: nodeIndex, |
| 1215 | + length: map.length - nodeIndex + map.oldValue - 1 |
| 1216 | + }) |
| 1217 | + map.length = nodeIndex - map.oldValue |
| 1218 | + } |
| 1219 | + } |
| 1220 | + }); |
| 1221 | + parentNode.subsets = parentNode.subsets.filter(function(map) { |
| 1222 | + return !map.delete; |
| 1223 | + }); |
| 1224 | + if (newSubsets.length) { |
| 1225 | + parentNode.subsets = parentNode.subsets.concat(newSubsets); |
| 1226 | + } |
| 1227 | + } |
1175 | 1228 | break; |
1176 | 1229 | case this._const.addElement: |
1177 | 1230 | route = diff[this._const.route].slice(); |
|
1191 | 1244 | } else { |
1192 | 1245 | node.childNodes.splice(c, 0, newNode); |
1193 | 1246 | } |
| 1247 | + if (node.subsets) { |
| 1248 | + node.subsets.forEach(function(map) { |
| 1249 | + if (map.oldValue >= c) { |
| 1250 | + map.oldValue += 1; |
| 1251 | + } if (map.oldValue < c && (map.oldValue + map.length) > c) { |
| 1252 | + splitLength = map.oldValue + map.length - c |
| 1253 | + newSubsets.push({ |
| 1254 | + newValue: map.newValue + map.length - splitLength, |
| 1255 | + oldValue: c + 1, |
| 1256 | + length: splitLength |
| 1257 | + }) |
| 1258 | + map.length -= splitLength |
| 1259 | + } |
| 1260 | + }); |
| 1261 | + } |
1194 | 1262 | break; |
1195 | 1263 | case this._const.removeTextElement: |
1196 | 1264 | parentNode.childNodes.splice(nodeIndex, 1); |
1197 | 1265 | if (parentNode.nodeName === 'TEXTAREA') { |
1198 | 1266 | delete parentNode.value; |
1199 | 1267 | } |
| 1268 | + if (parentNode.subsets) { |
| 1269 | + parentNode.subsets.forEach(function(map) { |
| 1270 | + if (map.oldValue > nodeIndex) { |
| 1271 | + map.oldValue -= 1; |
| 1272 | + } else if (map.oldValue === nodeIndex) { |
| 1273 | + map.delete = true; |
| 1274 | + } else if (map.oldValue < nodeIndex && (map.oldValue + map.length) > nodeIndex) { |
| 1275 | + if (map.oldValue + map.length - 1 === nodeIndex) { |
| 1276 | + map.length--; |
| 1277 | + } else { |
| 1278 | + newSubsets.push({ |
| 1279 | + newValue: map.newValue + nodeIndex - map.oldValue, |
| 1280 | + oldValue: nodeIndex, |
| 1281 | + length: map.length - nodeIndex + map.oldValue - 1 |
| 1282 | + }) |
| 1283 | + map.length = nodeIndex - map.oldValue |
| 1284 | + } |
| 1285 | + } |
| 1286 | + }); |
| 1287 | + parentNode.subsets = parentNode.subsets.filter(function(map) { |
| 1288 | + return !map.delete; |
| 1289 | + }); |
| 1290 | + if (newSubsets.length) { |
| 1291 | + parentNode.subsets = parentNode.subsets.concat(newSubsets); |
| 1292 | + } |
| 1293 | + } |
1200 | 1294 | break; |
1201 | 1295 | case this._const.addTextElement: |
1202 | 1296 | route = diff[this._const.route].slice(); |
|
1217 | 1311 | if (node.nodeName === 'TEXTAREA') { |
1218 | 1312 | node.value = diff[this._const.newValue]; |
1219 | 1313 | } |
| 1314 | + if (node.subsets) { |
| 1315 | + node.subsets.forEach(function(map) { |
| 1316 | + if (map.oldValue >= c) { |
| 1317 | + map.oldValue += 1; |
| 1318 | + } if (map.oldValue < c && (map.oldValue + map.length) > c) { |
| 1319 | + splitLength = map.oldValue + map.length - c |
| 1320 | + newSubsets.push({ |
| 1321 | + newValue: map.newValue + map.length - splitLength, |
| 1322 | + oldValue: c + 1, |
| 1323 | + length: splitLength |
| 1324 | + }) |
| 1325 | + map.length -= splitLength |
| 1326 | + } |
| 1327 | + }); |
| 1328 | + } |
1220 | 1329 | break; |
1221 | 1330 | default: |
1222 | 1331 | console.log('unknown action'); |
|
0 commit comments