Index: trunk/extensions/VisualEditor/tests/es/es.DocumentNode.test.js |
— | — | @@ -938,3 +938,81 @@ |
939 | 939 | } |
940 | 940 | } |
941 | 941 | } ); |
| 942 | + |
| 943 | +test( 'es.DocumentBranchNode.traverseLeafNodes', 6, function() { |
| 944 | + var root3 = es.DocumentModel.newFromPlainObject( esTest.obj ); |
| 945 | + |
| 946 | + // Test 1 |
| 947 | + var realLeaves = [], expectedLeaves = [ |
| 948 | + root3.children[0], |
| 949 | + root3.children[1].children[0].children[0].children[0], |
| 950 | + root3.children[1].children[0].children[0].children[1].children[0].children[0], |
| 951 | + root3.children[1].children[0].children[0].children[1].children[1].children[0], |
| 952 | + root3.children[1].children[0].children[0].children[1].children[2].children[0], |
| 953 | + root3.children[2] |
| 954 | + ]; |
| 955 | + root3.traverseLeafNodes( function( node ) { realLeaves.push( node ); } ); |
| 956 | + ok( |
| 957 | + es.compareArrays( realLeaves, expectedLeaves ), |
| 958 | + 'Traversing the entire document returns all leaf nodes' |
| 959 | + ); |
| 960 | + // Test 2 |
| 961 | + realLeaves = []; |
| 962 | + expectedLeaves = expectedLeaves.reverse(); |
| 963 | + root3.traverseLeafNodes( function( node ) { realLeaves.push( node ) }, undefined, true ); |
| 964 | + ok( |
| 965 | + es.compareArrays( realLeaves, expectedLeaves ), |
| 966 | + 'Traversing the entire document returns all leaf nodes (in reverse)' |
| 967 | + ); |
| 968 | + |
| 969 | + // Test 3 |
| 970 | + realLeaves = []; |
| 971 | + expectedLeaves = [ |
| 972 | + root3.children[1].children[0].children[0].children[1].children[1].children[0], |
| 973 | + root3.children[1].children[0].children[0].children[1].children[2].children[0], |
| 974 | + root3.children[2] |
| 975 | + ]; |
| 976 | + root3.traverseLeafNodes( function( node ) { realLeaves.push( node ); }, root3.children[1].children[0].children[0].children[1].children[1].children[0] ); |
| 977 | + ok( |
| 978 | + es.compareArrays( realLeaves, expectedLeaves ), |
| 979 | + 'Starting at a leaf node returns that leaf node and everything after it' |
| 980 | + ); |
| 981 | + // Test 4 |
| 982 | + realLeaves = []; |
| 983 | + expectedLeaves = [ |
| 984 | + root3.children[0], |
| 985 | + root3.children[1].children[0].children[0].children[0], |
| 986 | + root3.children[1].children[0].children[0].children[1].children[0].children[0], |
| 987 | + root3.children[1].children[0].children[0].children[1].children[1].children[0], |
| 988 | + ].reverse(); |
| 989 | + root3.traverseLeafNodes( function( node ) { realLeaves.push( node ); }, root3.children[1].children[0].children[0].children[1].children[1].children[0], true ); |
| 990 | + ok( |
| 991 | + es.compareArrays( realLeaves, expectedLeaves ), |
| 992 | + 'Starting at a leaf node returns that leaf node and everything before it (in reverse)' |
| 993 | + ); |
| 994 | + |
| 995 | + // Test 5 |
| 996 | + realLeaves = []; |
| 997 | + expectedLeaves = [ |
| 998 | + root3.children[1].children[0].children[0].children[0], |
| 999 | + root3.children[1].children[0].children[0].children[1].children[0].children[0], |
| 1000 | + root3.children[1].children[0].children[0].children[1].children[1].children[0], |
| 1001 | + root3.children[1].children[0].children[0].children[1].children[2].children[0], |
| 1002 | + root3.children[2] |
| 1003 | + ]; |
| 1004 | + root3.traverseLeafNodes( function( node ) { realLeaves.push( node ); }, root3.children[1] ); |
| 1005 | + ok( |
| 1006 | + es.compareArrays( realLeaves, expectedLeaves ), |
| 1007 | + 'Starting at a non-leaf node returns all leaf nodes inside and after it' |
| 1008 | + ); |
| 1009 | + // Test 6 |
| 1010 | + realLeaves = []; |
| 1011 | + expectedLeaves = [ |
| 1012 | + root3.children[0] |
| 1013 | + ]; |
| 1014 | + root3.traverseLeafNodes( function( node ) { realLeaves.push( node ); }, root3.children[1], true ); |
| 1015 | + ok( |
| 1016 | + es.compareArrays( realLeaves, expectedLeaves ), |
| 1017 | + 'Starting at a non-leaf node returns all leaf nodes before it and none inside (in reverse)' |
| 1018 | + ); |
| 1019 | +} ); |
\ No newline at end of file |
Index: trunk/extensions/VisualEditor/modules/es/bases/es.DocumentBranchNode.js |
— | — | @@ -41,11 +41,27 @@ |
42 | 42 | * iteration will stop. |
43 | 43 | * |
44 | 44 | * @param {Function} callback Function to execute for each leaf node |
45 | | - * @param {es.DocumentNode} [from] Leaf node to start at |
| 45 | + * @param {es.DocumentNode} [from] Node to start at. Must be a descendant of this node |
46 | 46 | * @param {Boolean} [reverse] Whether to iterate backwards |
47 | 47 | */ |
48 | 48 | es.DocumentBranchNode.prototype.traverseLeafNodes = function( callback, from, reverse ) { |
49 | | - // TODO: Implement me! |
| 49 | + // TODO: Implement from and reverse |
| 50 | + // TODO: We'll need an iterative rather than recursive implementation for from, probably |
| 51 | + var i, childNode, callbackResult; |
| 52 | + for ( i = reverse ? this.children.length - 1 : 0; reverse ? i >= 0 : i < this.children.length; reverse ? i-- : i++ ) { |
| 53 | + childNode = this.children[i]; |
| 54 | + if ( childNode.hasChildren() ) { |
| 55 | + // Recurse |
| 56 | + childNode.traverseLeafNodes( callback, from, reverse ); |
| 57 | + } else { |
| 58 | + // It's a leaf node |
| 59 | + callbackResult = callback( childNode /*, TODO what is index? */ ); |
| 60 | + if ( callbackResult === false ) { |
| 61 | + // The callback is telling us to stop |
| 62 | + return; |
| 63 | + } |
| 64 | + } |
| 65 | + } |
50 | 66 | }; |
51 | 67 | |
52 | 68 | /** |