|
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