Comparing version 2.3.1 to 2.4.0
189
diffDOM.js
@@ -18,3 +18,3 @@ (function(root, factory) { | ||
var diffcount; | ||
var diffcount, foundAll = false; | ||
@@ -44,18 +44,3 @@ var Diff = function(options) { | ||
var SubsetMapping = function SubsetMapping(a, b) { | ||
this.oldValue = a; | ||
this.newValue = b; | ||
}; | ||
SubsetMapping.prototype = { | ||
contains: function contains(subset) { | ||
if (subset.length < this.length) { | ||
return subset.newValue >= this.newValue && subset.newValue < this.newValue + this.length; | ||
} | ||
return false; | ||
}, | ||
toString: function toString() { | ||
return this.length + " element subset, first mapping: old " + this.oldValue + " → new " + this.newValue; | ||
} | ||
}; | ||
@@ -155,3 +140,2 @@ var elementDescriptors = function(el) { | ||
} | ||
if (e1.attributes) { | ||
@@ -168,2 +152,3 @@ e1Attributes = Object.keys(e1.attributes); | ||
} | ||
return true; | ||
})) { | ||
@@ -173,3 +158,2 @@ return false; | ||
} | ||
if (e1.childNodes) { | ||
@@ -327,7 +311,8 @@ if (e1.childNodes.length !== e2.childNodes.length) { | ||
} | ||
origin = [index[0] - lcsSize, index[1] - lcsSize]; | ||
ret = new SubsetMapping(origin[0], origin[1]); | ||
ret.length = lcsSize; | ||
return ret; | ||
return { | ||
oldValue: index[0] - lcsSize, | ||
newValue: index[1] - lcsSize, | ||
length: lcsSize | ||
}; | ||
}; | ||
@@ -423,2 +408,5 @@ | ||
} | ||
oldTree.subsets = subsets; | ||
oldTree.subsetsAge = 100; | ||
return subsets; | ||
@@ -459,2 +447,4 @@ }; | ||
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. | ||
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. | ||
maxChildDiffCount: 3, // Numeral. See maxChildCount. | ||
valueDiffing: true, // Whether to take into consideration the values of forms that differ from auto assigned values (when a user fills out a form). | ||
@@ -566,13 +556,20 @@ // syntax: textDiff: function (node, currentValue, expectedValue, newValue) | ||
diffs = this.findNextDiff(t1, t2, []); | ||
if (diffs.length === 0) { | ||
// Last check if the elements really are the same now. | ||
// If not, remove all info about being done and start over. | ||
// Somtimes a node can be marked as done, but the creation of subsequent diffs means that it has to be changed anyway. | ||
// Sometimes a node can be marked as done, but the creation of subsequent diffs means that it has to be changed again. | ||
if (!isEqual(t1, t2)) { | ||
removeDone(t1); | ||
diffs = this.findNextDiff(t1, t2, []); | ||
if (foundAll) { | ||
console.error('Could not find remaining diffs!'); | ||
console.log({t1, t2}); | ||
} else { | ||
foundAll = true; | ||
removeDone(t1); | ||
diffs = this.findNextDiff(t1, t2, []); | ||
} | ||
} | ||
} | ||
if (diffs.length > 0) { | ||
foundAll = false | ||
this.tracker.add(diffs); | ||
@@ -644,2 +641,20 @@ this.applyVirtual(t1, diffs); | ||
if (route.length && this.maxChildCount && t1.childNodes && t2.childNodes && t1.childNodes.length > this.maxChildCount && t2.childNodes.length > this.maxChildCount) { | ||
var childNodesLength = t1.childNodes.length < t2.childNodes.length ? t1.childNodes.length : t2.childNodes.length, childDiffCount = 0, j = 0; | ||
while (childDiffCount < this.maxChildDiffCount && j < childNodesLength) { | ||
if (!isEqual(t1.childNodes[j], t2.childNodes[j])) { | ||
childDiffCount++; | ||
} | ||
j++; | ||
} | ||
if (childDiffCount === this.maxChildDiffCount) { | ||
return [new Diff() | ||
.setValue(t._const.action, t._const.replaceElement) | ||
.setValue(t._const.oldValue, cloneObj(t1)) | ||
.setValue(t._const.newValue, cloneObj(t2)) | ||
.setValue(t._const.route, route) | ||
]; | ||
} | ||
} | ||
if (t1.data !== t2.data) { | ||
@@ -796,8 +811,9 @@ // Comment or text node. | ||
findInnerDiff: function(t1, t2, route) { | ||
var t = this; | ||
var subtrees = (t1.childNodes && t2.childNodes) ? markSubTrees(t1, t2) : [], | ||
var oldSubsets = t1.subsets; | ||
//var subtrees = (t1.childNodes && t2.childNodes) ? markSubTrees(t1, t2) : [], | ||
var subtrees = t1.subsets && t1.subsetsAge-- ? t1.subsets : (t1.childNodes && t2.childNodes) ? markSubTrees(t1, t2) : [], | ||
t1ChildNodes = t1.childNodes ? t1.childNodes : [], | ||
t2ChildNodes = t2.childNodes ? t2.childNodes : [], | ||
childNodesLengthDifference, diffs = [], | ||
index = 0, | ||
index = 0, t = this, | ||
last, e1, e2, i; | ||
@@ -1075,2 +1091,3 @@ | ||
nodeIndex = routeInfo.nodeIndex, | ||
newSubsets = [], splitLength, | ||
newNode, movedNode, nodeArray, route, length, c, i; | ||
@@ -1158,5 +1175,59 @@ | ||
} | ||
if (node.subsets) { | ||
node.subsets.forEach(function(map) { | ||
if (diff[t._const.from] < diff[t._const.to] && map.oldValue <= diff[t._const.to] && map.oldValue > diff[t._const.from]) { | ||
map.oldValue -= diff.groupLength; | ||
splitLength = map.oldValue + map.length - diff[t._const.to]; | ||
if (splitLength > 0) { | ||
// new insertion splits map. | ||
newSubsets.push({ | ||
oldValue: diff[t._const.to] + diff.groupLength, | ||
newValue: map.newValue + map.length - splitLength, | ||
length: splitLength | ||
}) | ||
map.length -= splitLength; | ||
} | ||
} else if (diff[t._const.from] > diff[t._const.to] && map.oldValue > diff[t._const.to] && map.oldValue < diff[t._const.from]) { | ||
map.oldValue += diff.groupLength; | ||
splitLength = map.oldValue + map.length - diff[t._const.to]; | ||
if (splitLength > 0) { | ||
// new insertion splits map. | ||
newSubsets.push({ | ||
oldValue: diff[t._const.to] + diff.groupLength, | ||
newValue: map.newValue + map.length - splitLength, | ||
length: splitLength | ||
}) | ||
map.length -= splitLength; | ||
} | ||
} else if (map.oldValue === diff[t._const.from]) { | ||
map.oldValue = diff[t._const.to]; | ||
} | ||
}); | ||
} | ||
break; | ||
case this._const.removeElement: | ||
parentNode.childNodes.splice(nodeIndex, 1); | ||
if (parentNode.subsets) { | ||
parentNode.subsets.forEach(function(map) { | ||
if (map.oldValue > nodeIndex) { | ||
map.oldValue -= 1; | ||
} else if (map.oldValue === nodeIndex) { | ||
map.delete = true; | ||
} else if (map.oldValue < nodeIndex && (map.oldValue + map.length) > nodeIndex) { | ||
if (map.oldValue + map.length - 1 === nodeIndex) { | ||
map.length--; | ||
} else { | ||
newSubsets.push({ | ||
newValue: map.newValue + nodeIndex - map.oldValue, | ||
oldValue: nodeIndex, | ||
length: map.length - nodeIndex + map.oldValue - 1 | ||
}) | ||
map.length = nodeIndex - map.oldValue | ||
} | ||
} | ||
}); | ||
} | ||
node = parentNode; | ||
break; | ||
@@ -1181,2 +1252,17 @@ case this._const.addElement: | ||
} | ||
if (node.subsets) { | ||
node.subsets.forEach(function(map) { | ||
if (map.oldValue >= c) { | ||
map.oldValue += 1; | ||
} else if (map.oldValue < c && (map.oldValue + map.length) > c) { | ||
splitLength = map.oldValue + map.length - c | ||
newSubsets.push({ | ||
newValue: map.newValue + map.length - splitLength, | ||
oldValue: c + 1, | ||
length: splitLength | ||
}) | ||
map.length -= splitLength | ||
} | ||
}); | ||
} | ||
break; | ||
@@ -1188,2 +1274,23 @@ case this._const.removeTextElement: | ||
} | ||
if (parentNode.subsets) { | ||
parentNode.subsets.forEach(function(map) { | ||
if (map.oldValue > nodeIndex) { | ||
map.oldValue -= 1; | ||
} else if (map.oldValue === nodeIndex) { | ||
map.delete = true; | ||
} else if (map.oldValue < nodeIndex && (map.oldValue + map.length) > nodeIndex) { | ||
if (map.oldValue + map.length - 1 === nodeIndex) { | ||
map.length--; | ||
} else { | ||
newSubsets.push({ | ||
newValue: map.newValue + nodeIndex - map.oldValue, | ||
oldValue: nodeIndex, | ||
length: map.length - nodeIndex + map.oldValue - 1 | ||
}) | ||
map.length = nodeIndex - map.oldValue | ||
} | ||
} | ||
}); | ||
} | ||
node = parentNode; | ||
break; | ||
@@ -1209,2 +1316,17 @@ case this._const.addTextElement: | ||
} | ||
if (node.subsets) { | ||
node.subsets.forEach(function(map) { | ||
if (map.oldValue >= c) { | ||
map.oldValue += 1; | ||
} if (map.oldValue < c && (map.oldValue + map.length) > c) { | ||
splitLength = map.oldValue + map.length - c | ||
newSubsets.push({ | ||
newValue: map.newValue + map.length - splitLength, | ||
oldValue: c + 1, | ||
length: splitLength | ||
}) | ||
map.length -= splitLength | ||
} | ||
}); | ||
} | ||
break; | ||
@@ -1215,2 +1337,11 @@ default: | ||
if (node.subsets) { | ||
node.subsets = node.subsets.filter(function(map) { | ||
return !map.delete && map.oldValue !== map.newValue; | ||
}); | ||
if (newSubsets.length) { | ||
node.subsets = node.subsets.concat(newSubsets); | ||
} | ||
} | ||
// capture newNode for the callback | ||
@@ -1217,0 +1348,0 @@ info.newNode = newNode; |
{ | ||
"name": "diff-dom", | ||
"version": "2.3.1", | ||
"version": "2.4.0", | ||
"description": "A diff for DOM elements, as client-side JavaScript code. Gets all modifications, insertions and removals between two DOM fragments.", | ||
@@ -5,0 +5,0 @@ "main": "diffDOM.js", |
Sorry, the diff of this file is not supported yet
338022
19
1541