Index: trunk/parsers/wikidom/tests/hype/index.html |
— | — | @@ -18,6 +18,7 @@ |
19 | 19 | <script src="../../lib/hype/bases/es.EventEmitter.js"></script> |
20 | 20 | <script src="../../lib/hype/bases/es.ModelNode.js"></script> |
21 | 21 | <script src="../../lib/hype/bases/es.ViewNode.js"></script> |
| 22 | + <script src="../../lib/hype/bases/es.DocumentNode.js"></script> |
22 | 23 | <script src="../../lib/hype/bases/es.DocumentModelNode.js"></script> |
23 | 24 | <script src="../../lib/hype/models/es.DocumentModel.js"></script> |
24 | 25 | <script src="../../lib/hype/models/es.ListItemModel.js"></script> |
Index: trunk/parsers/wikidom/lib/hype/models/es.DocumentModel.js |
— | — | @@ -589,89 +589,6 @@ |
590 | 590 | }; |
591 | 591 | |
592 | 592 | /** |
593 | | - * Gets the content offset of a node. |
594 | | - * |
595 | | - * This method is pretty expensive. If you need to get different slices of the same content, get |
596 | | - * the content first, then slice it up locally. |
597 | | - * |
598 | | - * @method |
599 | | - * @param {es.DocumentModelNode} node Node to get offset of |
600 | | - * @returns {Integer} Offset of node or -1 of node was not found |
601 | | - */ |
602 | | -es.DocumentModel.prototype.getOffsetFromNode = function( node ) { |
603 | | - var offset = 0, |
604 | | - currentNode, |
605 | | - iteration = [this, 0], |
606 | | - iterations = [iteration]; |
607 | | - while ( iterations[0][0].length < iteration[0][1] ) { |
608 | | - currentNode = iteration[0][iteration[1]]; |
609 | | - if ( currentNode === node ) { |
610 | | - break; |
611 | | - } else { |
612 | | - if ( currentNode.length ) { |
613 | | - // Include opening element when descending |
614 | | - offset++; |
615 | | - // Descend one level down |
616 | | - iterations.push( [currentNode, 0] ); |
617 | | - iteration = iterations[iterations.length - 1]; |
618 | | - } else { |
619 | | - // Include opening and closing when passing over |
620 | | - offset += 2; |
621 | | - } |
622 | | - } |
623 | | - iteration[1]++; |
624 | | - if ( iteration[1] >= iteration[0].length ) { |
625 | | - // Include closing element when ascending |
626 | | - offset++; |
627 | | - // Ascend one level up |
628 | | - iterations.pop(); |
629 | | - iteration = iterations[iterations.length - 1]; |
630 | | - } |
631 | | - } |
632 | | - return offset; |
633 | | -}; |
634 | | - |
635 | | -/** |
636 | | - * Gets the node at a given offset. |
637 | | - * |
638 | | - * This method is pretty expensive. If you need to get different slices of the same content, get |
639 | | - * the content first, then slice it up locally. |
640 | | - * |
641 | | - * TODO: Rewrite this method to not use recursion, because the function call overhead is expensive |
642 | | - * |
643 | | - * @method |
644 | | - * @param {Integer} offset Offset to find node at |
645 | | - * @returns {es.DocumentModelNode} Node at offset |
646 | | - */ |
647 | | -es.DocumentModel.prototype.getNodeFromOffset = function( offset ) { |
648 | | - var nodeOffset = 0, |
649 | | - nodeLength; |
650 | | - for ( var i = 0, length = this.length; i < length; i++ ) { |
651 | | - nodeLength = this[i].getElementLength(); |
652 | | - if ( offset >= nodeOffset && offset < nodeOffset + nodeLength ) { |
653 | | - return this[i].length ? |
654 | | - es.DocumentModel.prototype.getNodeFromOffset.call( this[i], offset - nodeOffset ) : |
655 | | - this[i]; |
656 | | - } |
657 | | - nodeOffset += nodeLength; |
658 | | - } |
659 | | - return this; |
660 | | -}; |
661 | | - |
662 | | -/** |
663 | | - * Gets the affected nodes and the range of data they occupy. |
664 | | - */ |
665 | | -es.DocumentModel.prototype.select = function( range, includeSubRanges ) { |
666 | | - range.normalize(); |
667 | | - var result = { |
668 | | - 'nodes': [], |
669 | | - 'range': new es.Range() |
670 | | - }; |
671 | | - // Add list of highest-common-level nodes that are covered by range to results.nodes |
672 | | - // Set range from beginning of first node to the end of the last node |
673 | | -}; |
674 | | - |
675 | | -/** |
676 | 593 | * Gets the element object of a node. |
677 | 594 | * |
678 | 595 | * @method |
Index: trunk/parsers/wikidom/lib/hype/bases/es.DocumentNode.js |
— | — | @@ -32,46 +32,102 @@ |
33 | 33 | }; |
34 | 34 | |
35 | 35 | /** |
36 | | - * Gets the first offset within this node of a given child node. |
| 36 | + * Gets the content offset of a node. |
37 | 37 | * |
| 38 | + * This method is pretty expensive. If you need to get different slices of the same content, get |
| 39 | + * the content first, then slice it up locally. |
| 40 | + * |
38 | 41 | * @method |
39 | | - * @param {es.ModelNode} node |
| 42 | + * @param {es.DocumentModelNode} node Node to get offset of |
| 43 | + * @param {Boolean} [shallow] Do not iterate into child nodes of child nodes |
| 44 | + * @returns {Integer} Offset of node or -1 of node was not found |
40 | 45 | */ |
41 | | -es.DocumentNode.prototype.getOffsetFromNode = function( node ) { |
42 | | - if ( this.length ) { |
43 | | - var offset = 0; |
44 | | - for( var i = 0; i < this.length; i++ ) { |
45 | | - if ( this[i] === node ) { |
46 | | - return offset; |
| 46 | +es.DocumentNode.prototype.getOffsetFromNode = function( node, shallow ) { |
| 47 | + var offset = 0; |
| 48 | + if ( shallow ) { |
| 49 | + if ( this.length ) { |
| 50 | + for ( var i = 0; i < this.length; i++ ) { |
| 51 | + if ( this[i] === node ) { |
| 52 | + return offset; |
| 53 | + } |
| 54 | + offset += this[i].getElementLength() + 1; |
47 | 55 | } |
48 | | - offset += this[i].getElementLength() + 1; |
49 | 56 | } |
| 57 | + } else { |
| 58 | + var currentNode, |
| 59 | + iteration = [this, 0], |
| 60 | + iterations = [iteration]; |
| 61 | + while ( iterations[0][0].length < iteration[0][1] ) { |
| 62 | + currentNode = iteration[0][iteration[1]]; |
| 63 | + if ( currentNode === node ) { |
| 64 | + break; |
| 65 | + } else { |
| 66 | + if ( currentNode.length ) { |
| 67 | + // Include opening element when descending |
| 68 | + offset++; |
| 69 | + // Descend one level down |
| 70 | + iterations.push( [currentNode, 0] ); |
| 71 | + iteration = iterations[iterations.length - 1]; |
| 72 | + } else { |
| 73 | + // Include opening and closing when passing over |
| 74 | + offset += 2; |
| 75 | + } |
| 76 | + } |
| 77 | + iteration[1]++; |
| 78 | + if ( iteration[1] >= iteration[0].length ) { |
| 79 | + // Include closing element when ascending |
| 80 | + offset++; |
| 81 | + // Ascend one level up |
| 82 | + iterations.pop(); |
| 83 | + iteration = iterations[iterations.length - 1]; |
| 84 | + } |
| 85 | + } |
50 | 86 | } |
51 | | - return null; |
| 87 | + return offset; |
52 | 88 | }; |
53 | 89 | |
54 | 90 | /** |
55 | | - * Gets the node which a given offset is within. |
| 91 | + * Gets the node at a given offset. |
56 | 92 | * |
| 93 | + * This method is pretty expensive. If you need to get different slices of the same content, get |
| 94 | + * the content first, then slice it up locally. |
| 95 | + * |
| 96 | + * TODO: Rewrite this method to not use recursion, because the function call overhead is expensive |
| 97 | + * |
57 | 98 | * @method |
58 | | - * @param {Integer} offset |
| 99 | + * @param {Integer} offset Offset within this node to look for child node in |
| 100 | + * @param {Boolean} [shallow] Do not iterate into child nodes of child nodes |
| 101 | + * @returns {es.DocumentModelNode|null} Node at offset, or null if non was found |
59 | 102 | */ |
60 | | -es.DocumentNode.prototype.getNodeFromOffset = function( offset ) { |
61 | | - if ( this.length ) { |
62 | | - var i = 0, |
63 | | - length = this.length, |
64 | | - left = 0, |
65 | | - right; |
66 | | - while ( i < length ) { |
67 | | - right = left + this[i].getElementLength() + 1; |
68 | | - if ( offset >= left && offset < right ) { |
69 | | - return this[i]; |
| 103 | +es.DocumentNode.prototype.getNodeFromOffset = function( offset, shallow ) { |
| 104 | + var i, |
| 105 | + length; |
| 106 | + if ( shallow ) { |
| 107 | + if ( this.length ) { |
| 108 | + var left = 0, |
| 109 | + right; |
| 110 | + for ( i = 0, length = this.length; i < length; i++ ) { |
| 111 | + right = left + this[i].getElementLength() + 1; |
| 112 | + if ( offset >= left && offset < right ) { |
| 113 | + return this[i]; |
| 114 | + } |
| 115 | + left = right; |
70 | 116 | } |
71 | | - left = right; |
72 | | - i++; |
73 | 117 | } |
| 118 | + return null; |
| 119 | + } else { |
| 120 | + var nodeOffset = 0, |
| 121 | + nodeLength; |
| 122 | + for ( i = 0, length = this.length; i < length; i++ ) { |
| 123 | + nodeLength = this[i].getElementLength(); |
| 124 | + if ( offset >= nodeOffset && offset < nodeOffset + nodeLength ) { |
| 125 | + return this[i].length ? |
| 126 | + this.getNodeFromOffset.call( this[i], offset - nodeOffset ) : this[i]; |
| 127 | + } |
| 128 | + nodeOffset += nodeLength; |
| 129 | + } |
| 130 | + return null; |
74 | 131 | } |
75 | | - return null; |
76 | 132 | }; |
77 | 133 | |
78 | 134 | /** |
Index: trunk/parsers/wikidom/lib/hype/bases/es.DocumentViewBranchNode.js |
— | — | @@ -71,7 +71,8 @@ |
72 | 72 | } |
73 | 73 | node = this.items[i]; |
74 | 74 | } |
75 | | - return node.getParent().getOffsetFromNode( node ) + node.getOffsetFromPosition( position ); |
| 75 | + return node.getParent().getOffsetFromNode( node, true ) + |
| 76 | + node.getOffsetFromPosition( position ); |
76 | 77 | }; |
77 | 78 | |
78 | 79 | /** |
— | — | @@ -82,9 +83,9 @@ |
83 | 84 | * @returns {es.Position} Position of offset |
84 | 85 | */ |
85 | 86 | es.DocumentViewBranchNode.prototype.getRenderedPositionFromOffset = function( offset ) { |
86 | | - var node = this.getNodeFromOffset( offset ); |
| 87 | + var node = this.getNodeFromOffset( offset, true ); |
87 | 88 | if ( node !== null ) { |
88 | | - return node.getRenderedPositionFromOffset( offset - this.getOffsetFromNode( node ) ); |
| 89 | + return node.getRenderedPositionFromOffset( offset - this.getOffsetFromNode( node, true ) ); |
89 | 90 | } |
90 | 91 | return null; |
91 | 92 | }; |