|
156 | 156 | if (e1Attributes.length != e2Attributes.length) { |
157 | 157 | return false; |
158 | 158 | } |
159 | | - if (!e1Attributes.every(function(attribute){ |
160 | | - if (e1.attributes[attribute] !== e2.attributes[attribute]) { |
161 | | - return false; |
162 | | - } |
163 | | - })) { |
| 159 | + if (!e1Attributes.every(function(attribute) { |
| 160 | + if (e1.attributes[attribute] !== e2.attributes[attribute]) { |
| 161 | + return false; |
| 162 | + } |
| 163 | + })) { |
164 | 164 | return false; |
165 | 165 | } |
166 | 166 | } |
|
561 | 561 | } |
562 | 562 | } |
563 | 563 | diffs = this.findNextDiff(t1, t2, []); |
564 | | - if (diffs.length === 0 || !diffs) { |
| 564 | + if (diffs.length === 0) { |
565 | 565 | // Last check if the elements really are the same now. |
566 | 566 | // If not, remove all info about being done and start over. |
567 | 567 | // Somtimes a node can be marked as done, but the creation of subsequent diffs means that it has to be changed anyway. |
568 | 568 | if (!isEqual(t1, t2)) { |
569 | 569 | removeDone(t1); |
570 | | - diffs = this.findNextDiff(t1, t2, []); |
| 570 | + diffs = this.findNextDiff(t1, t2, []); |
571 | 571 | } |
572 | 572 | } |
573 | 573 |
|
574 | 574 | if (diffs.length > 0) { |
575 | 575 | this.tracker.add(diffs); |
576 | 576 | this.applyVirtual(t1, diffs); |
577 | 577 | } |
578 | | - } while (diffs); |
| 578 | + } while (diffs.length > 0); |
579 | 579 | return this.tracker.list; |
580 | 580 | }, |
581 | 581 | findNextDiff: function(t1, t2, route) { |
|
617 | 617 | } |
618 | 618 |
|
619 | 619 | // no differences |
620 | | - return false; |
| 620 | + return []; |
621 | 621 | }, |
622 | 622 | findOuterDiff: function(t1, t2, route) { |
623 | 623 |
|
624 | | - var diffs = [], attr1, attr2; |
| 624 | + var diffs = [], |
| 625 | + attr1, attr2; |
625 | 626 |
|
626 | 627 | if (t1.nodeName !== t2.nodeName) { |
627 | 628 | return [new Diff({ |
|
635 | 636 | if (t1.data !== t2.data) { |
636 | 637 | // Comment or text node. |
637 | 638 | if (t1.nodeName === '#text') { |
638 | | - return [new Diff({ |
639 | | - action: 'modifyComment', |
640 | | - route: route, |
641 | | - oldValue: t1.data, |
642 | | - newValue: t2.data |
643 | | - })]; |
| 639 | + return [new Diff({ |
| 640 | + action: 'modifyComment', |
| 641 | + route: route, |
| 642 | + oldValue: t1.data, |
| 643 | + newValue: t2.data |
| 644 | + })]; |
644 | 645 | } else { |
645 | | - return [new Diff({ |
646 | | - action: 'modifyTextElement', |
647 | | - route: route, |
648 | | - oldValue: t1.data, |
649 | | - newValue: t2.data |
650 | | - })]; |
| 646 | + return [new Diff({ |
| 647 | + action: 'modifyTextElement', |
| 648 | + route: route, |
| 649 | + oldValue: t1.data, |
| 650 | + newValue: t2.data |
| 651 | + })]; |
651 | 652 | } |
652 | 653 |
|
653 | 654 | } |
|
698 | 699 | var subtrees = (t1.childNodes && t2.childNodes) ? markSubTrees(t1, t2) : [], |
699 | 700 | t1_child_nodes = t1.childNodes ? t1.childNodes : [], |
700 | 701 | t2_child_nodes = t2.childNodes ? t2.childNodes : [], |
701 | | - childNodesLengthDifference, diffs, i, last, e1, e2; |
| 702 | + childNodesLengthDifference, diffs = [], |
| 703 | + i, last, e1, e2; |
702 | 704 |
|
703 | 705 | if (subtrees.length > 1) { |
704 | 706 | /* Two or more groups have been identified among the childnodes of t1 |
705 | | - * and t2. |
706 | | - */ |
| 707 | + * and t2. |
| 708 | + */ |
707 | 709 | return this.attemptGroupRelocation(t1, t2, subtrees, route); |
708 | 710 | } |
709 | 711 |
|
710 | | - /* 0 or 1 groups of similar child nodes have been found |
711 | | - * for t1 and t2. 1 If there is 1, it could be a sign that the |
712 | | - * contents are the same. When the number of groups is below 2, |
713 | | - * t1 and t2 are made to have the same length and each of the |
714 | | - * pairs of child nodes are diffed. |
715 | | - */ |
716 | | - |
717 | | - /* if (subtrees.length === 0) { |
718 | | - // No subtrees - could text nodes as they won't have any childNodes. |
719 | | - // |
720 | | - if (t1.nodeName === '#text' && t2.nodeName === '#text' && t1.data !== t2.data) { |
721 | | - return [new Diff({ |
722 | | - action: 'modiFyTextElement', |
723 | | - oldValue: t1.data, |
724 | | - newValue: t2.data, |
725 | | - route: route |
726 | | - })]; |
727 | | - } |
728 | | - } */ |
| 712 | + /* 0 or 1 groups of similar child nodes have been found |
| 713 | + * for t1 and t2. 1 If there is 1, it could be a sign that the |
| 714 | + * contents are the same. When the number of groups is below 2, |
| 715 | + * t1 and t2 are made to have the same length and each of the |
| 716 | + * pairs of child nodes are diffed. |
| 717 | + */ |
729 | 718 |
|
730 | 719 |
|
731 | | - last = Math.max(t1_child_nodes.length, t2_child_nodes.length); |
732 | | - if (t1_child_nodes.length !== t2_child_nodes.length) { |
733 | | - childNodesLengthDifference = true; |
734 | | - } |
735 | | - |
736 | | - for (i = 0; i < last; i += 1) { |
737 | | - e1 = t1_child_nodes[i]; |
738 | | - e2 = t2_child_nodes[i]; |
| 720 | + last = Math.max(t1_child_nodes.length, t2_child_nodes.length); |
| 721 | + if (t1_child_nodes.length !== t2_child_nodes.length) { |
| 722 | + childNodesLengthDifference = true; |
| 723 | + } |
739 | 724 |
|
740 | | - if (childNodesLengthDifference) { |
741 | | - /* t1 and t2 have different amounts of childNodes. Add |
742 | | - * and remove as necessary to obtain the same length */ |
743 | | - if (e1 && !e2) { |
744 | | - if (e1.nodeName === '#text') { |
745 | | - return [new Diff({ |
746 | | - action: 'removeTextElement', |
747 | | - route: route.concat(i), |
748 | | - value: e1.data |
749 | | - })]; |
750 | | - } |
751 | | - return [new Diff({ |
752 | | - action: 'removeElement', |
| 725 | + for (i = 0; i < last; i += 1) { |
| 726 | + e1 = t1_child_nodes[i]; |
| 727 | + e2 = t2_child_nodes[i]; |
| 728 | + |
| 729 | + if (childNodesLengthDifference) { |
| 730 | + /* t1 and t2 have different amounts of childNodes. Add |
| 731 | + * and remove as necessary to obtain the same length */ |
| 732 | + if (e1 && !e2) { |
| 733 | + if (e1.nodeName === '#text') { |
| 734 | + diffs.push(new Diff({ |
| 735 | + action: 'removeTextElement', |
753 | 736 | route: route.concat(i), |
754 | | - element: cloneObj(e1) |
755 | | - })]; |
| 737 | + value: e1.data |
| 738 | + })); |
| 739 | + return diffs; |
756 | 740 | } |
757 | | - if (e2 && !e1) { |
758 | | - if (e2.nodeName === '#text') { |
759 | | - return [new Diff({ |
760 | | - action: 'addTextElement', |
761 | | - route: route.concat(i), |
762 | | - value: e2.data |
763 | | - })]; |
764 | | - } |
765 | | - return [new Diff({ |
766 | | - action: 'addElement', |
| 741 | + diffs.push(new Diff({ |
| 742 | + action: 'removeElement', |
| 743 | + route: route.concat(i), |
| 744 | + element: cloneObj(e1) |
| 745 | + })); |
| 746 | + return diffs; |
| 747 | + } |
| 748 | + if (e2 && !e1) { |
| 749 | + if (e2.nodeName === '#text') { |
| 750 | + diffs.push(new Diff({ |
| 751 | + action: 'addTextElement', |
767 | 752 | route: route.concat(i), |
768 | | - element: cloneObj(e2) |
769 | | - })]; |
| 753 | + value: e2.data |
| 754 | + })); |
| 755 | + return diffs; |
770 | 756 | } |
771 | | - } |
772 | | - /* We are now guaranteed that childNodes e1 and e2 exist, |
773 | | - * and that they can be diffed. |
774 | | - */ |
775 | | - |
776 | | - diffs = this.findNextDiff(e1, e2, route.concat(i)); |
777 | | - if (diffs && diffs.length > 0) { |
| 757 | + diffs.push(new Diff({ |
| 758 | + action: 'addElement', |
| 759 | + route: route.concat(i), |
| 760 | + element: cloneObj(e2) |
| 761 | + })); |
778 | 762 | return diffs; |
779 | 763 | } |
780 | | - |
781 | 764 | } |
| 765 | + /* We are now guaranteed that childNodes e1 and e2 exist, |
| 766 | + * and that they can be diffed. |
| 767 | + */ |
| 768 | + diffs = diffs.concat(this.findNextDiff(e1, e2, route.concat(i))); |
782 | 769 |
|
783 | | - return []; |
| 770 | + /* Diffs in child nodes should not affect the parent node, |
| 771 | + * so we let these diffs be submitted together with other |
| 772 | + * diffs. |
| 773 | + */ |
| 774 | + |
| 775 | + } |
| 776 | + |
| 777 | + return diffs; |
784 | 778 |
|
785 | 779 | }, |
786 | 780 |
|
787 | 781 | attemptGroupRelocation: function(t1, t2, subtrees, route) { |
788 | 782 | /* Either t1.childNodes and t2.childNodes have the same length, or |
789 | | - * there are at least two groups of similar elements can be found. |
790 | | - * attempts are made at equalizing t1 with t2. First all initial |
791 | | - * elements with no group affiliation (gaps=true) are removed (if |
792 | | - * only in t1) or added (if only in t2). Then the creation of a group |
793 | | - * relocation diff is attempted. |
794 | | - */ |
| 783 | + * there are at least two groups of similar elements can be found. |
| 784 | + * attempts are made at equalizing t1 with t2. First all initial |
| 785 | + * elements with no group affiliation (gaps=true) are removed (if |
| 786 | + * only in t1) or added (if only in t2). Then the creation of a group |
| 787 | + * relocation diff is attempted. |
| 788 | + */ |
795 | 789 |
|
796 | 790 | var gapInformation = getGapInformation(t1, t2, subtrees), |
797 | 791 | gaps1 = gapInformation.gaps1, |
|
920 | 914 | return true; |
921 | 915 | } |
922 | 916 | diffs.forEach(function(diff) { |
923 | | -// console.log(JSON.stringify(diff)); |
924 | | -// console.log(JSON.stringify(tree)); |
925 | | -// console.log(objToNode(tree).outerHTML); |
| 917 | + // console.log(JSON.stringify(diff)); |
| 918 | + // console.log(JSON.stringify(tree)); |
| 919 | + // console.log(objToNode(tree).outerHTML); |
926 | 920 | dobj.applyVirtualDiff(tree, diff); |
927 | | -// console.log(JSON.stringify(tree)); |
928 | | -// console.log(objToNode(tree).outerHTML); |
| 921 | + // console.log(JSON.stringify(tree)); |
| 922 | + // console.log(objToNode(tree).outerHTML); |
929 | 923 | }); |
930 | 924 | return true; |
931 | 925 | }, |
|
1023 | 1017 | break; |
1024 | 1018 | case 'relocateGroup': |
1025 | 1019 | node.childNodes.splice(diff.from, diff.groupLength).reverse() |
1026 | | - .forEach(function(movedNode){ |
| 1020 | + .forEach(function(movedNode) { |
1027 | 1021 | node.childNodes.splice(diff.to, 0, movedNode); |
1028 | | - }); |
| 1022 | + }); |
1029 | 1023 | break; |
1030 | 1024 | case 'removeElement': |
1031 | 1025 | parentNode.childNodes.splice(nodeIndex, 1); |
|
1171 | 1165 | case 'relocateGroup': |
1172 | 1166 | Array.apply(null, new Array(diff.groupLength)).map(function() { |
1173 | 1167 | return node.removeChild(node.childNodes[diff.from]); |
1174 | | - }).forEach(function(childNode, index){ |
1175 | | - if(index===0) { |
| 1168 | + }).forEach(function(childNode, index) { |
| 1169 | + if (index === 0) { |
1176 | 1170 | reference = node.childNodes[diff.to]; |
1177 | 1171 | } |
1178 | | - node.insertBefore(childNode,reference); |
| 1172 | + node.insertBefore(childNode, reference); |
1179 | 1173 | }); |
1180 | 1174 | break; |
1181 | 1175 | case 'removeElement': |
|
0 commit comments