Index: trunk/parsers/wikidom/tests/hype/es.DocumentModel.test.js |
— | — | @@ -215,6 +215,47 @@ |
216 | 216 | deepEqual( documentModel.slice( 0 ), tree, 'Nodes in the model tree contain correct lengths' ); |
217 | 217 | } ); |
218 | 218 | |
| 219 | +test( 'es.DocumentModel.getRelativeContentOffset', 6, function() { |
| 220 | + var documentModel = es.DocumentModel.newFromPlainObject( obj ); |
| 221 | + |
| 222 | + // Test 1 |
| 223 | + equal( |
| 224 | + documentModel.getRelativeContentOffset( 1, 1 ), |
| 225 | + 2, |
| 226 | + 'getRelativeContentOffset advances forwards through the inside of elements' |
| 227 | + ); |
| 228 | + // Test 2 |
| 229 | + equal( |
| 230 | + documentModel.getRelativeContentOffset( 2, -1 ), |
| 231 | + 1, |
| 232 | + 'getRelativeContentOffset advances backwards through the inside of elements' |
| 233 | + ); |
| 234 | + // Test 3 |
| 235 | + equal( |
| 236 | + documentModel.getRelativeContentOffset( 1, -1 ), |
| 237 | + 1, |
| 238 | + 'getRelativeContentOffset treats the begining a document as a non-content offset' |
| 239 | + ); |
| 240 | + // Test 4 |
| 241 | + equal( |
| 242 | + documentModel.getRelativeContentOffset( 26, 1 ), |
| 243 | + 26, |
| 244 | + 'getRelativeContentOffset treats the end a document as a non-content offset' |
| 245 | + ); |
| 246 | + // Test 5 |
| 247 | + equal( |
| 248 | + documentModel.getRelativeContentOffset( 3, 1 ), |
| 249 | + 9, |
| 250 | + 'getRelativeContentOffset advances forwards between elements' |
| 251 | + ); |
| 252 | + // Test 6 |
| 253 | + equal( |
| 254 | + documentModel.getRelativeContentOffset( 26, -1 ), |
| 255 | + 19, |
| 256 | + 'getRelativeContentOffset advances backwards between elements' |
| 257 | + ); |
| 258 | +} ); |
| 259 | + |
219 | 260 | test( 'es.DocumentModel.getContent', 6, function() { |
220 | 261 | var documentModel = es.DocumentModel.newFromPlainObject( obj ); |
221 | 262 | |
Index: trunk/parsers/wikidom/lib/hype/models/es.DocumentModel.js |
— | — | @@ -748,6 +748,38 @@ |
749 | 749 | }; |
750 | 750 | |
751 | 751 | /** |
| 752 | + * Gets a content offset a given distance forwards or backwards from another. |
| 753 | + * |
| 754 | + * @method |
| 755 | + * @param {Integer} offset Offset to start from |
| 756 | + * @param {Integer} distance Number of content offsets to move |
| 757 | + * @param {Integer} Offset a given distance from the given offset |
| 758 | + */ |
| 759 | +es.DocumentModel.prototype.getRelativeContentOffset = function( offset, distance ) { |
| 760 | + if ( !es.DocumentModel.isContentOffset( this.data, offset ) ) { |
| 761 | + throw 'Invalid offset error. Can not get relative content offset from non-content offset.'; |
| 762 | + } |
| 763 | + if ( distance === 0 ) { |
| 764 | + return offset; |
| 765 | + } |
| 766 | + var direction = distance > 0 ? 1 : -1, |
| 767 | + i = offset + direction, |
| 768 | + steps = 0; |
| 769 | + distance = Math.abs( distance ); |
| 770 | + while ( i > 0 && i < this.data.length - 1 ) { |
| 771 | + if ( typeof this.data[i] === 'string' || es.isArray( this.data[i] ) ) { |
| 772 | + steps++; |
| 773 | + offset = i; |
| 774 | + if ( distance === steps ) { |
| 775 | + return offset; |
| 776 | + } |
| 777 | + } |
| 778 | + i += direction; |
| 779 | + } |
| 780 | + return offset; |
| 781 | +}; |
| 782 | + |
| 783 | +/** |
752 | 784 | * Generates a transaction which inserts data at a given offset. |
753 | 785 | * |
754 | 786 | * @method |