Index: trunk/parsers/wikidom/lib/es/es.ListBlockItem.js |
— | — | @@ -105,4 +105,4 @@ |
106 | 106 | }; |
107 | 107 | |
108 | 108 | es.extend( es.ListBlockItem, es.EventEmitter ); |
109 | | -es.extend( es.ListBlockItem, es.Container ); |
\ No newline at end of file |
| 109 | +es.extend( es.ListBlockItem, es.Container ); |
Index: trunk/parsers/wikidom/lib/es/es.Content.js |
— | — | @@ -265,23 +265,22 @@ |
266 | 266 | * TODO: Implement render option, which will allow annotations to influence output, such as an |
267 | 267 | * image outputing it's URL |
268 | 268 | * |
| 269 | + * @param range {es.Range} Range of text to get |
269 | 270 | * @param start {Integer} Optional beginning of range, if omitted range will begin at 0 |
270 | 271 | * @param end {Integer} Optional end of range, if omitted range will end a this.data.length |
271 | 272 | * @param render {Boolean} If annotations should have any influence on output |
272 | 273 | * @return {String} Plain text within given range |
273 | 274 | */ |
274 | | -es.Content.prototype.getText = function( start, end, render ) { |
275 | | - // Wrap values |
276 | | - start = Math.max( 0, start || 0 ); |
277 | | - if ( end === undefined ) { |
278 | | - end = this.data.length; |
| 275 | +es.Content.prototype.getText = function( range, render ) { |
| 276 | + if ( !range ) { |
| 277 | + range = new es.Range( 0, this.data.length ); |
279 | 278 | } else { |
280 | | - end = Math.min( this.data.length, end ); |
| 279 | + range.normalize(); |
281 | 280 | } |
282 | 281 | // Copy characters |
283 | 282 | var text = ''; |
284 | 283 | var i; |
285 | | - for ( i = start; i < end; i++ ) { |
| 284 | + for ( i = range.start; i < range.end; i++ ) { |
286 | 285 | // If not using in IE6 or IE7 (which do not support array access for strings) use this.. |
287 | 286 | // text += this.data[i][0]; |
288 | 287 | // Otherwise use this... |
— | — | @@ -295,12 +294,16 @@ |
296 | 295 | * |
297 | 296 | * Range arguments (start and end) are clamped if out of range. |
298 | 297 | * |
299 | | - * @param start {Integer} Optional beginning of range, if omitted range will begin at 0 |
300 | | - * @param end {Integer} Optional end of range, if omitted range will end a this.data.length |
| 298 | + * @param range {es.Range} Range of content to get |
301 | 299 | * @return {es.Content} New content object |
302 | 300 | */ |
303 | | -es.Content.prototype.slice = function( start, end ) { |
304 | | - return new es.Content( this.data.slice( start, end ) ); |
| 301 | +es.Content.prototype.getContent = function( range ) { |
| 302 | + if ( !range ) { |
| 303 | + range = new es.Range( 0, this.data.length ); |
| 304 | + } else { |
| 305 | + range.normalize(); |
| 306 | + } |
| 307 | + return new es.Content( this.data.slice( range.start, range.end ) ); |
305 | 308 | }; |
306 | 309 | |
307 | 310 | /** |
— | — | @@ -335,14 +338,13 @@ |
336 | 339 | /** |
337 | 340 | * Removes content data within a specific range. |
338 | 341 | * |
339 | | - * @param start {Integer} Beginning of range |
340 | | - * @param end {Integer} End of range |
| 342 | + * @param range {Range} Range of content to remove |
341 | 343 | */ |
342 | | -es.Content.prototype.remove = function( start, end ) { |
343 | | - this.data.splice( start, end - start ); |
| 344 | +es.Content.prototype.remove = function( range ) { |
| 345 | + range.normalize(); |
| 346 | + this.data.splice( range.start, range.getLength() ); |
344 | 347 | this.emit( 'remove', { |
345 | | - 'start': start, |
346 | | - 'end': end |
| 348 | + 'range': range |
347 | 349 | } ); |
348 | 350 | this.emit( 'change', { 'type': 'remove' } ); |
349 | 351 | }; |
— | — | @@ -362,16 +364,15 @@ |
363 | 365 | * Strict coverage may be used to compare not only annotation types, but also their data. Since new |
364 | 366 | * line characters are never annotated, they are always considered covered. |
365 | 367 | * |
366 | | - * @param start {Integer} Beginning of range |
367 | | - * @param end {Integer} End of range |
| 368 | + * @param range {es.Range} Range of content to analyze |
368 | 369 | * @param annotation {Object} Annotation to compare with |
369 | 370 | * @param strict {Boolean} Optionally compare annotation data as well as type |
370 | 371 | * @return {Array} List of indexes of covered characters within content data |
371 | 372 | */ |
372 | | -es.Content.prototype.coverageOfAnnotation = function( start, end, annotation, strict ) { |
| 373 | +es.Content.prototype.coverageOfAnnotation = function( range, annotation, strict ) { |
373 | 374 | var coverage = []; |
374 | 375 | var i, index; |
375 | | - for ( i = start; i < end; i++ ) { |
| 376 | + for ( i = range.start; i < range.end; i++ ) { |
376 | 377 | index = this.indexOfAnnotation( i, annotation ); |
377 | 378 | if ( typeof this.data[i] !== 'string' && index !== -1 ) { |
378 | 379 | if ( strict ) { |
— | — | @@ -427,18 +428,19 @@ |
428 | 429 | * |
429 | 430 | * @param method {String} Way to apply annotation ("toggle", "add" or "remove") |
430 | 431 | * @param annotation {Object} Annotation to apply |
431 | | - * @param start {Integer} Offset to begin annotating from |
432 | | - * @param end {Integer} Offset to stop annotating to |
| 432 | + * @param range {es.Range} Range of content to annotate |
433 | 433 | */ |
434 | | -es.Content.prototype.annotate = function( method, annotation, start, end ) { |
| 434 | +es.Content.prototype.annotate = function( method, annotation, range ) { |
| 435 | + if ( !range ) { |
| 436 | + range = new es.Range( 0, this.data.length ); |
| 437 | + } else { |
| 438 | + range.normalize(); |
| 439 | + } |
435 | 440 | var i; |
436 | | - |
437 | | - start = Math.max( start, 0 ); |
438 | | - end = Math.min( end, this.data.length ); |
439 | 441 | if ( method === 'toggle' ) { |
440 | | - var coverage = this.coverageOfAnnotation( start, end, annotation, false ); |
441 | | - if ( coverage.length === end - start ) { |
442 | | - var strictCoverage = this.coverageOfAnnotation( start, end, annotation, true ); |
| 442 | + var coverage = this.coverageOfAnnotation( range, annotation, false ); |
| 443 | + if ( coverage.length === range.getLength() ) { |
| 444 | + var strictCoverage = this.coverageOfAnnotation( range, annotation, true ); |
443 | 445 | method = strictCoverage.length === coverage.length ? 'remove' : 'add'; |
444 | 446 | } else { |
445 | 447 | method = 'add'; |
— | — | @@ -446,7 +448,7 @@ |
447 | 449 | } |
448 | 450 | if ( method === 'add' ) { |
449 | 451 | var duplicate; |
450 | | - for ( i = start; i < end; i++ ) { |
| 452 | + for ( i = range.start; i < range.end; i++ ) { |
451 | 453 | duplicate = -1; |
452 | 454 | if ( typeof this.data[i] === 'string' ) { |
453 | 455 | // Never annotate new lines |
— | — | @@ -468,7 +470,7 @@ |
469 | 471 | } |
470 | 472 | } |
471 | 473 | } else if ( method === 'remove' ) { |
472 | | - for ( i = start; i < end; i++ ) { |
| 474 | + for ( i = range.start; i < range.end; i++ ) { |
473 | 475 | if ( typeof this.data[i] !== 'string' ) { |
474 | 476 | if ( annotation.type === 'all' ) { |
475 | 477 | // Remove all annotations by converting the annotated character to a plain |
— | — | @@ -486,8 +488,7 @@ |
487 | 489 | this.emit( 'annotate', { |
488 | 490 | 'method': method, |
489 | 491 | 'annotation': annotation, |
490 | | - 'start': start, |
491 | | - 'end': end |
| 492 | + 'range': range |
492 | 493 | } ); |
493 | 494 | this.emit( 'change', { 'type': 'annotate' } ); |
494 | 495 | }; |
— | — | @@ -499,9 +500,9 @@ |
500 | 501 | * @param end {Integer} End of range |
501 | 502 | * @param {String} Rendered HTML of content data |
502 | 503 | */ |
503 | | -es.Content.prototype.render = function( start, end ) { |
504 | | - if ( start || end ) { |
505 | | - return this.slice( start, end ).render(); |
| 504 | +es.Content.prototype.render = function( range ) { |
| 505 | + if ( range ) { |
| 506 | + return this.getContent( range ).render(); |
506 | 507 | } |
507 | 508 | var out = '', |
508 | 509 | left = '', |
— | — | @@ -584,20 +585,16 @@ |
585 | 586 | line, |
586 | 587 | offset = 0, |
587 | 588 | i, j, k; |
588 | | - |
589 | 589 | for ( i = 0; i < this.data.length; i++ ) { |
590 | | - |
591 | 590 | if ( line == null ) { |
592 | 591 | line = { |
593 | 592 | text : '', |
594 | 593 | annotations : [] |
595 | 594 | }; |
596 | 595 | } |
597 | | - |
598 | 596 | right = this.data[i]; |
599 | 597 | leftPlain = typeof left === 'string'; |
600 | 598 | rightPlain = typeof right === 'string'; |
601 | | - |
602 | 599 | if ( rightPlain && right == "\n" ) { |
603 | 600 | lines.push(line); |
604 | 601 | line = null; |
— | — | @@ -605,7 +602,6 @@ |
606 | 603 | left = ''; |
607 | 604 | continue; |
608 | 605 | } |
609 | | - |
610 | 606 | if ( !leftPlain ) { |
611 | 607 | for ( j = 1; j < left.length; j++ ) { |
612 | 608 | for ( k = line.annotations.length - 1; k >= 0; k-- ) { |
— | — | @@ -618,7 +614,6 @@ |
619 | 615 | } |
620 | 616 | } |
621 | 617 | } |
622 | | - |
623 | 618 | if ( !rightPlain ) { |
624 | 619 | for ( j = 1; j < right.length; j++ ) { |
625 | 620 | if ( leftPlain || this.indexOfAnnotation( i - 1, right[j], true ) === -1 ) { |
— | — | @@ -631,16 +626,12 @@ |
632 | 627 | } |
633 | 628 | } |
634 | 629 | } |
635 | | - |
636 | 630 | line.text += rightPlain ? right : right[0]; |
637 | | - |
638 | 631 | left = right; |
639 | 632 | } |
640 | | - |
641 | 633 | if ( line != null ) { |
642 | 634 | lines.push(line); |
643 | 635 | } |
644 | | - |
645 | 636 | return lines; |
646 | 637 | }; |
647 | 638 | |
Index: trunk/parsers/wikidom/lib/es/es.TextFlow.js |
— | — | @@ -90,10 +90,10 @@ |
91 | 91 | */ |
92 | 92 | var $ruler = $( '<div class="editSurface-ruler"></div>' ).appendTo( this.$ ), |
93 | 93 | ruler = $ruler[0], |
94 | | - fit = this.fitCharacters( line.start, line.end, ruler, position.left ); |
95 | | - ruler.innerHTML = this.content.render( line.start, fit.end ); |
| 94 | + fit = this.fitCharacters( line.range, ruler, position.left ); |
| 95 | + ruler.innerHTML = this.content.render( new es.Range( line.range.start, fit.end ) ); |
96 | 96 | var left = ruler.clientWidth; |
97 | | - ruler.innerHTML = this.content.render( line.start, fit.end + 1 ); |
| 97 | + ruler.innerHTML = this.content.render( new es.Range( line.range.start, fit.end + 1 ) ); |
98 | 98 | var right = ruler.clientWidth; |
99 | 99 | var center = Math.round( left + ( ( right - left ) / 2 ) ); |
100 | 100 | $ruler.remove(); |
— | — | @@ -103,7 +103,7 @@ |
104 | 104 | // If the position is right of the center of the character it's on top of, increment offset |
105 | 105 | fit.end + ( position.left >= center ? 1 : 0 ), |
106 | 106 | // If the line ends in a non-boundary character, decrement offset |
107 | | - line.end + ( this.boundaryTest.exec( line.text.substr( -1 ) ) ? -1 : 0 ) |
| 107 | + line.range.end + ( this.boundaryTest.exec( line.text.substr( -1 ) ) ? -1 : 0 ) |
108 | 108 | ); |
109 | 109 | }; |
110 | 110 | |
— | — | @@ -147,7 +147,7 @@ |
148 | 148 | }; |
149 | 149 | while ( position.line < lineCount ) { |
150 | 150 | line = this.lines[position.line]; |
151 | | - if ( offset >= line.start && offset < line.end ) { |
| 151 | + if ( offset >= line.range.start && offset < line.range.end ) { |
152 | 152 | position.bottom = position.top + line.height; |
153 | 153 | break; |
154 | 154 | } |
— | — | @@ -174,10 +174,10 @@ |
175 | 175 | * Since the left position will be zero for the first character in the line, so we can skip |
176 | 176 | * measuring for those cases. |
177 | 177 | */ |
178 | | - if ( line.start < offset ) { |
| 178 | + if ( line.range.start < offset ) { |
179 | 179 | var $ruler = $( '<div class="editSurface-ruler"></div>' ).appendTo( this.$ ), |
180 | 180 | ruler = $ruler[0]; |
181 | | - ruler.innerHTML = this.content.render( line.start, offset ); |
| 181 | + ruler.innerHTML = this.content.render( new es.Range( line.range.start, offset ) ); |
182 | 182 | position.left = ruler.clientWidth; |
183 | 183 | $ruler.remove(); |
184 | 184 | } |
— | — | @@ -240,7 +240,7 @@ |
241 | 241 | charFit = null, |
242 | 242 | wordCount = this.boundaries.length; |
243 | 243 | while ( ++iteration <= limit && rs.wordOffset < wordCount - 1 ) { |
244 | | - wordFit = this.fitWords( rs.wordOffset, wordCount - 1, rs.ruler, rs.width ); |
| 244 | + wordFit = this.fitWords( new es.Range( rs.wordOffset, wordCount - 1 ), rs.ruler, rs.width ); |
245 | 245 | fractional = false; |
246 | 246 | if ( wordFit.width > rs.width ) { |
247 | 247 | // The first word didn't fit, we need to split it up |
— | — | @@ -249,12 +249,16 @@ |
250 | 250 | rs.wordOffset++; |
251 | 251 | lineEnd = this.boundaries[rs.wordOffset]; |
252 | 252 | do { |
253 | | - charFit = this.fitCharacters( charOffset, lineEnd, rs.ruler, rs.width ); |
| 253 | + charFit = this.fitCharacters( |
| 254 | + new es.Range( charOffset, lineEnd ), rs.ruler, rs.width |
| 255 | + ); |
254 | 256 | // If we were able to get the rest of the characters on the line OK |
255 | 257 | if ( charFit.end === lineEnd) { |
256 | 258 | // Try to fit more words on the line |
257 | 259 | wordFit = this.fitWords( |
258 | | - rs.wordOffset, wordCount - 1, rs.ruler, rs.width - charFit.width |
| 260 | + new es.Range( rs.wordOffset, wordCount - 1 ), |
| 261 | + rs.ruler, |
| 262 | + rs.width - charFit.width |
259 | 263 | ); |
260 | 264 | if ( wordFit.end > rs.wordOffset ) { |
261 | 265 | lineOffset = rs.wordOffset; |
— | — | @@ -262,7 +266,7 @@ |
263 | 267 | charFit.end = lineEnd = this.boundaries[rs.wordOffset]; |
264 | 268 | } |
265 | 269 | } |
266 | | - this.appendLine( charOffset, charFit.end, lineOffset, fractional ); |
| 270 | + this.appendLine( new es.Range( charOffset, charFit.end ), lineOffset, fractional ); |
267 | 271 | // Move on to another line |
268 | 272 | charOffset = charFit.end; |
269 | 273 | // Mark the next line as fractional |
— | — | @@ -270,7 +274,7 @@ |
271 | 275 | } while ( charOffset < lineEnd ); |
272 | 276 | } else { |
273 | 277 | lineEnd = this.boundaries[wordFit.end]; |
274 | | - this.appendLine( lineStart, lineEnd, rs.wordOffset, fractional ); |
| 278 | + this.appendLine( new es.Range( lineStart, lineEnd ), rs.wordOffset, fractional ); |
275 | 279 | rs.wordOffset = wordFit.end; |
276 | 280 | } |
277 | 281 | lineStart = lineEnd; |
— | — | @@ -344,10 +348,10 @@ |
345 | 349 | currentLine = this.lines.length - 1; |
346 | 350 | for ( var i = this.lines.length - 1; i >= 0; i-- ) { |
347 | 351 | var line = this.lines[i]; |
348 | | - if ( line.start < offset && line.end > offset ) { |
| 352 | + if ( line.range.start < offset && line.range.end > offset ) { |
349 | 353 | currentLine = i; |
350 | 354 | } |
351 | | - if ( ( line.end < offset && !line.fractional ) || i === 0 ) { |
| 355 | + if ( ( line.range.end < offset && !line.fractional ) || i === 0 ) { |
352 | 356 | rs.lines = this.lines.slice( 0, i ); |
353 | 357 | rs.wordOffset = line.wordOffset; |
354 | 358 | gap = currentLine - i; |
— | — | @@ -365,12 +369,13 @@ |
366 | 370 | /** |
367 | 371 | * Adds a line containing a given range of text to the end of the DOM and the "lines" array. |
368 | 372 | * |
| 373 | + * @param range {es.Range} Range of content to append |
369 | 374 | * @param start {Integer} Beginning of text range for line |
370 | 375 | * @param end {Integer} Ending of text range for line |
371 | 376 | * @param wordOffset {Integer} Index within this.words which the line begins with |
372 | 377 | * @param fractional {Boolean} If the line begins in the middle of a word |
373 | 378 | */ |
374 | | -es.TextFlow.prototype.appendLine = function( start, end, wordOffset, fractional ) { |
| 379 | +es.TextFlow.prototype.appendLine = function( range, wordOffset, fractional ) { |
375 | 380 | var rs = this.renderState, |
376 | 381 | lineCount = rs.lines.length; |
377 | 382 | $line = this.$.find( '.editSurface-line[line-index=' + lineCount + ']' ); |
— | — | @@ -378,12 +383,11 @@ |
379 | 384 | $line = $( '<div class="editSurface-line" line-index="' + lineCount + '"></div>' ) |
380 | 385 | .appendTo( this.$ ); |
381 | 386 | } |
382 | | - $line[0].innerHTML = this.content.render( start, end ); |
| 387 | + $line[0].innerHTML = this.content.render( range ); |
383 | 388 | // Collect line information |
384 | 389 | rs.lines.push({ |
385 | | - 'text': this.content.getText( start, end ), |
386 | | - 'start': start, |
387 | | - 'end': end, |
| 390 | + 'text': this.content.getText( range ), |
| 391 | + 'range': range, |
388 | 392 | 'width': $line.outerWidth(), |
389 | 393 | 'height': $line.outerHeight(), |
390 | 394 | 'wordOffset': wordOffset, |
— | — | @@ -415,14 +419,15 @@ |
416 | 420 | * starting with [offset .. limit], which usually results in reducing the end position in all but |
417 | 421 | * the last line, and in most cases more than 3 times, before changing directions. |
418 | 422 | * |
419 | | - * @param start {Integer} Index within "words" to begin fitting from |
420 | | - * @param end {Integer} Index within "words" to stop fitting to |
| 423 | + * @param range {es.Range} Range of content to try to fit |
421 | 424 | * @param ruler {HTMLElement} Element to take measurements with |
422 | 425 | * @param width {Integer} Maximum width to allow the line to extend to |
423 | 426 | * @return {Integer} Last index within "words" that contains a word that fits |
424 | 427 | */ |
425 | | -es.TextFlow.prototype.fitWords = function( start, end, ruler, width ) { |
426 | | - var offset = start, |
| 428 | +es.TextFlow.prototype.fitWords = function( range, ruler, width ) { |
| 429 | + var offset = range.start, |
| 430 | + start = range.start, |
| 431 | + end = range.end, |
427 | 432 | charOffset = this.boundaries[offset], |
428 | 433 | middle, |
429 | 434 | lineWidth, |
— | — | @@ -435,7 +440,7 @@ |
436 | 441 | // Measure and cache width of substring |
437 | 442 | cacheKey = charOffset + ':' + charMiddle; |
438 | 443 | // Prepare the line for measurement using pre-escaped HTML |
439 | | - ruler.innerHTML = this.content.render( charOffset, charMiddle ); |
| 444 | + ruler.innerHTML = this.content.render( new es.Range( charOffset, charMiddle ) ); |
440 | 445 | // Test for over/under using width of the rendered line |
441 | 446 | this.widthCache[cacheKey] = lineWidth = ruler.clientWidth; |
442 | 447 | |
— | — | @@ -457,7 +462,7 @@ |
458 | 463 | if ( end === middle - 1 ) { |
459 | 464 | // A final measurement is required |
460 | 465 | var charStart = this.boundaries[start]; |
461 | | - ruler.innerHTML = this.content.render( charOffset, charStart ); |
| 466 | + ruler.innerHTML = this.content.render( new es.Range( charOffset, charStart ) ); |
462 | 467 | lineWidth = this.widthCache[charOffset + ':' + charStart] = ruler.clientWidth; |
463 | 468 | } |
464 | 469 | return { 'end': start, 'width': lineWidth }; |
— | — | @@ -470,14 +475,15 @@ |
471 | 476 | * used to detect when the first character was too long to fit on a line. In such cases the result |
472 | 477 | * will contain the index of the first character and it's width. |
473 | 478 | * |
474 | | - * @param start {Integer} Index within "text" to begin fitting from |
475 | | - * @param end {Integer} Index within "text" to stop fitting to |
| 479 | + * @param range {es.Range} Range of content to try to fit |
476 | 480 | * @param ruler {HTMLElement} Element to take measurements with |
477 | 481 | * @param width {Integer} Maximum width to allow the line to extend to |
478 | 482 | * @return {Integer} Last index within "text" that contains a character that fits |
479 | 483 | */ |
480 | | -es.TextFlow.prototype.fitCharacters = function( start, end, ruler, width ) { |
481 | | - var offset = start, |
| 484 | +es.TextFlow.prototype.fitCharacters = function( range, ruler, width ) { |
| 485 | + var offset = range.start, |
| 486 | + start = range.start, |
| 487 | + end = range.end, |
482 | 488 | middle, |
483 | 489 | lineWidth, |
484 | 490 | cacheKey; |
— | — | @@ -491,7 +497,7 @@ |
492 | 498 | lineWidth = this.widthCache[cacheKey]; |
493 | 499 | } else { |
494 | 500 | // Fill the line with a portion of the text, escaped as HTML |
495 | | - ruler.innerHTML = this.content.render( offset, middle ); |
| 501 | + ruler.innerHTML = this.content.render( new es.Range( offset, middle ) ); |
496 | 502 | // Test for over/under using width of the rendered line |
497 | 503 | this.widthCache[cacheKey] = lineWidth = ruler.clientWidth; |
498 | 504 | } |
— | — | @@ -517,7 +523,7 @@ |
518 | 524 | lineWidth = this.widthCache[cacheKey]; |
519 | 525 | } else { |
520 | 526 | // A final measurement is required |
521 | | - ruler.innerHTML = this.content.render( offset, start ); |
| 527 | + ruler.innerHTML = this.content.render( new es.Range( offset, start ) ); |
522 | 528 | lineWidth = this.widthCache[cacheKey] = ruler.clientWidth; |
523 | 529 | } |
524 | 530 | } |
Index: trunk/parsers/wikidom/lib/es/es.ParagraphBlock.js |
— | — | @@ -46,17 +46,10 @@ |
47 | 47 | /** |
48 | 48 | * Deletes content in a block within a range. |
49 | 49 | * |
50 | | - * @param start {Integer} Offset to start removing content from |
51 | | - * @param end {Integer} Offset to start removing content to |
| 50 | + * @param range {es.Range} Range of content to remove |
52 | 51 | */ |
53 | | -es.ParagraphBlock.prototype.deleteContent = function( start, end ) { |
54 | | - // Normalize start/end |
55 | | - if ( end < start ) { |
56 | | - var tmp = end; |
57 | | - end = start; |
58 | | - start = tmp; |
59 | | - } |
60 | | - this.content.remove( start, end ); |
| 52 | +es.ParagraphBlock.prototype.deleteContent = function( range ) { |
| 53 | + this.content.remove( range ); |
61 | 54 | }; |
62 | 55 | |
63 | 56 | /** |
— | — | @@ -66,11 +59,10 @@ |
67 | 60 | * |
68 | 61 | * @param method {String} Way to apply annotation ("toggle", "add" or "remove") |
69 | 62 | * @param annotation {Object} Annotation to apply |
70 | | - * @param start {Integer} Offset to begin annotating from |
71 | | - * @param end {Integer} Offset to stop annotating to |
| 63 | + * @param range {es.Range} Range of content to annotate |
72 | 64 | */ |
73 | | -es.ParagraphBlock.prototype.annotateContent = function( method, annotation, start, end ) { |
74 | | - this.content.annotate( method, annotation, start, end ); |
| 65 | +es.ParagraphBlock.prototype.annotateContent = function( method, annotation, range ) { |
| 66 | + this.content.annotate( method, annotation, range ); |
75 | 67 | }; |
76 | 68 | |
77 | 69 | /** |
— | — | @@ -79,19 +71,18 @@ |
80 | 72 | * @param start {Integer} Offset to get content from |
81 | 73 | * @param end {Integer} Offset to get content to |
82 | 74 | */ |
83 | | -es.Block.prototype.getContent = function( start, end ) { |
84 | | - return this.content.slice( start, end ); |
| 75 | +es.Block.prototype.getContent = function( range ) { |
| 76 | + return this.content.getContent( range ); |
85 | 77 | }; |
86 | 78 | |
87 | 79 | /** |
88 | 80 | * Gets content as plain text within a range. |
89 | 81 | * |
90 | | - * @param start {Integer} Offset to start get text from |
91 | | - * @param end {Integer} Offset to start get text to |
| 82 | + * @param range {es.Range} Range of text to get |
92 | 83 | * @param render {Boolean} If annotations should have any influence on output |
93 | 84 | */ |
94 | | -es.Block.prototype.getText = function( start, end, render ) { |
95 | | - return this.content.getText( start, end, render ); |
| 85 | +es.Block.prototype.getText = function( range, render ) { |
| 86 | + return this.content.getText( range, render ); |
96 | 87 | }; |
97 | 88 | |
98 | 89 | /** |
— | — | @@ -146,6 +137,6 @@ |
147 | 138 | /** |
148 | 139 | * Extend es.Block to support paragraph block creation with es.Block.newFromWikidom |
149 | 140 | */ |
150 | | -es.Block.models.paragraph = es.ParagraphBlock; |
| 141 | +es.Block.models.paragraph = es.ParagraphBlock; |
151 | 142 | |
152 | 143 | es.extend( es.ParagraphBlock, es.Block ); |
Index: trunk/parsers/wikidom/lib/es/es.ListBlockList.js |
— | — | @@ -73,4 +73,4 @@ |
74 | 74 | }; |
75 | 75 | |
76 | 76 | es.extend( es.ListBlockList, es.EventEmitter ); |
77 | | -es.extend( es.ListBlockList, es.Container ); |
\ No newline at end of file |
| 77 | +es.extend( es.ListBlockList, es.Container ); |
Index: trunk/parsers/wikidom/lib/es/es.ListBlock.js |
— | — | @@ -49,18 +49,14 @@ |
50 | 50 | /** |
51 | 51 | * Deletes content in a block within a range. |
52 | 52 | * |
53 | | - * @param offset {Integer} Offset to start removing content from |
54 | | - * @param length {Integer} Offset to start removing content to |
| 53 | + * @param range {es.Range} Range of content to remove |
55 | 54 | */ |
56 | | -es.ListBlock.prototype.deleteContent = function( start, end ) { |
57 | | - // Normalize start/end |
58 | | - if ( end < start ) { |
59 | | - var tmp = end; |
60 | | - end = start; |
61 | | - start = tmp; |
62 | | - } |
63 | | - var location = this.list.getLocationFromOffset( start ); |
64 | | - location.item.flow.content.remove( location.offset, location.offset + end - start ); |
| 55 | +es.ListBlock.prototype.deleteContent = function( range ) { |
| 56 | + range.normalize(); |
| 57 | + var location = this.list.getLocationFromOffset( range.start ); |
| 58 | + location.item.flow.content.remove( |
| 59 | + new es.Range( location.offset, location.offset + range.getLength() ) |
| 60 | + ); |
65 | 61 | }; |
66 | 62 | |
67 | 63 | /** |
— | — | @@ -70,22 +66,23 @@ |
71 | 67 | * |
72 | 68 | * @param method {String} Way to apply annotation ("toggle", "add" or "remove") |
73 | 69 | * @param annotation {Object} Annotation to apply |
74 | | - * @param start {Integer} Offset to begin annotating from |
75 | | - * @param end {Integer} Offset to stop annotating to |
| 70 | + * @param range {es.Range} Range of content to annotate |
76 | 71 | */ |
77 | | -es.ListBlock.prototype.annotateContent = function( method, annotation, start, end ) { |
| 72 | +es.ListBlock.prototype.annotateContent = function( method, annotation, range ) { |
| 73 | + range.normalize(); |
78 | 74 | // TODO: Support annotating multiple items at once |
79 | | - var location = this.list.getLocationFromOffset( start ); |
80 | | - location.item.content.annotate( method, annotation, location.offset, location.offset + end - start ); |
| 75 | + var location = this.list.getLocationFromOffset( range.start ); |
| 76 | + location.item.content.annotate( |
| 77 | + method, annotation, new es.Range( location.offset, location.offset + range.getLength() ) |
| 78 | + ); |
81 | 79 | }; |
82 | 80 | |
83 | 81 | /** |
84 | 82 | * Gets content within a range. |
85 | 83 | * |
86 | | - * @param start {Integer} Offset to get content from |
87 | | - * @param end {Integer} Offset to get content to |
| 84 | + * @param range {es.Range} Range of content to get |
88 | 85 | */ |
89 | | -es.ListBlock.prototype.getContent = function() { |
| 86 | +es.ListBlock.prototype.getContent = function( range ) { |
90 | 87 | // TODO: Implement me! |
91 | 88 | return new Content(); |
92 | 89 | }; |
— | — | @@ -93,11 +90,10 @@ |
94 | 91 | /** |
95 | 92 | * Gets content as plain text within a range. |
96 | 93 | * |
97 | | - * @param start {Integer} Offset to start get text from |
98 | | - * @param end {Integer} Offset to start get text to |
| 94 | + * @param range {Range} Range of text to get |
99 | 95 | * @param render {Boolean} If annotations should have any influence on output |
100 | 96 | */ |
101 | | -es.ListBlock.prototype.getText = function() { |
| 97 | +es.ListBlock.prototype.getText = function( range ) { |
102 | 98 | // TODO: Implement me! |
103 | 99 | return ''; |
104 | 100 | }; |
Index: trunk/parsers/wikidom/lib/es/es.Surface.js |
— | — | @@ -18,7 +18,7 @@ |
19 | 19 | 'clickDelay': 500, |
20 | 20 | 'clickTimeout': null, |
21 | 21 | 'clickPosition': null, |
22 | | - 'hotSpotRadius': 2 |
| 22 | + 'hotSpotRadius': 1 |
23 | 23 | }; |
24 | 24 | this.keyboard = { |
25 | 25 | 'selecting': false, |
— | — | @@ -452,7 +452,9 @@ |
453 | 453 | this.$rangeFill.hide(); |
454 | 454 | } |
455 | 455 | } |
456 | | - text += from.location.block.getText( from.location.offset, to.location.offset ); |
| 456 | + text += from.location.block.getText( |
| 457 | + new es.Range( from.location.offset, to.location.offset ) |
| 458 | + ); |
457 | 459 | } else { |
458 | 460 | // Multiple block selection |
459 | 461 | blockWidth = Math.max( |
— | — | @@ -499,7 +501,7 @@ |
500 | 502 | }; |
501 | 503 | |
502 | 504 | /** |
503 | | - * Sets the selection to a new range. |
| 505 | + * Sets the selection to a new es.Range. |
504 | 506 | * |
505 | 507 | * @param from {es.Selection} Selection to apply |
506 | 508 | */ |
— | — | @@ -653,7 +655,7 @@ |
654 | 656 | to = selection.end; |
655 | 657 | if ( from.block === to.block ) { |
656 | 658 | // Single block deletion |
657 | | - from.block.deleteContent( from.offset, to.offset ); |
| 659 | + from.block.deleteContent( new es.Range( from.offset, to.offset ) ); |
658 | 660 | } else { |
659 | 661 | // Multiple block deletion |
660 | 662 | var block; |
— | — | @@ -661,13 +663,13 @@ |
662 | 664 | block = this.doc.blocks[i]; |
663 | 665 | if ( block === from.block ) { |
664 | 666 | // From offset to length |
665 | | - block.deleteContent( from.offset, block.getLength() ); |
| 667 | + block.deleteContent( new es.Range( from.offset, block.getLength() ) ); |
666 | 668 | } else if ( block === to.block ) { |
667 | 669 | // From 0 to offset |
668 | | - block.deleteContent( 0, to.offset ); |
| 670 | + block.deleteContent( new es.Range( 0, to.offset ) ); |
669 | 671 | } else { |
670 | 672 | // Full coverage |
671 | | - block.deleteContent( 0, block.getLength() ); |
| 673 | + block.deleteContent( new es.Range( 0, block.getLength() ) ); |
672 | 674 | } |
673 | 675 | } |
674 | 676 | } |
— | — | @@ -696,7 +698,7 @@ |
697 | 699 | to = selection.end; |
698 | 700 | if ( from.block === to.block ) { |
699 | 701 | // Single block annotation |
700 | | - from.block.annotateContent( method, annotation, from.offset, to.offset ); |
| 702 | + from.block.annotateContent( method, annotation, new es.Range( from.offset, to.offset ) ); |
701 | 703 | } else { |
702 | 704 | // Multiple block annotation |
703 | 705 | var block; |
— | — | @@ -704,13 +706,15 @@ |
705 | 707 | block = this.doc.blocks[i]; |
706 | 708 | if ( block === from.block ) { |
707 | 709 | // From offset to length |
708 | | - block.annotateContent( method, annotation, from.offset, block.getLength() ); |
| 710 | + block.annotateContent( |
| 711 | + method, annotation, new es.Range( from.offset, block.getLength() ) |
| 712 | + ); |
709 | 713 | } else if ( block === to.block ) { |
710 | 714 | // From 0 to offset |
711 | | - block.annotateContent( method, annotation, 0, to.offset ); |
| 715 | + block.annotateContent( method, annotation, new es.Range( 0, to.offset ) ); |
712 | 716 | } else { |
713 | 717 | // Full coverage |
714 | | - block.annotateContent( method, annotation, 0, block.getLength() ); |
| 718 | + block.annotateContent( method, annotation, new es.Range( 0, block.getLength() ) ); |
715 | 719 | } |
716 | 720 | } |
717 | 721 | } |
Index: trunk/parsers/wikidom/lib/es/es.Block.js |
— | — | @@ -88,10 +88,9 @@ |
89 | 89 | /** |
90 | 90 | * Deletes content in a block within a range. |
91 | 91 | * |
92 | | - * @param offset {Integer} Offset to start removing content from |
93 | | - * @param length {Integer} Offset to start removing content to |
| 92 | + * @param range {es.Range} Range of content to remove |
94 | 93 | */ |
95 | | -es.Block.prototype.deleteContent = function( start, end ) { |
| 94 | +es.Block.prototype.deleteContent = function( range ) { |
96 | 95 | throw 'Block.deleteContent not implemented in this subclass.'; |
97 | 96 | }; |
98 | 97 | |
— | — | @@ -102,31 +101,28 @@ |
103 | 102 | * |
104 | 103 | * @param method {String} Way to apply annotation ("toggle", "add" or "remove") |
105 | 104 | * @param annotation {Object} Annotation to apply |
106 | | - * @param start {Integer} Offset to begin annotating from |
107 | | - * @param end {Integer} Offset to stop annotating to |
| 105 | + * @param range {es.Range} Range of content to annotate |
108 | 106 | */ |
109 | | -es.Block.prototype.annotateContent = function( method, annotation, start, end ) { |
| 107 | +es.Block.prototype.annotateContent = function( method, annotation, range ) { |
110 | 108 | throw 'Block.annotateContent not implemented in this subclass.'; |
111 | 109 | }; |
112 | 110 | |
113 | 111 | /** |
114 | 112 | * Gets content within a range. |
115 | 113 | * |
116 | | - * @param start {Integer} Offset to get content from |
117 | | - * @param end {Integer} Offset to get content to |
| 114 | + * @param range {es.Range} Range of content to get |
118 | 115 | */ |
119 | | -es.Block.prototype.getContent = function( start, end ) { |
| 116 | +es.Block.prototype.getContent = function( range) { |
120 | 117 | throw 'Block.getContent not implemented in this subclass.'; |
121 | 118 | }; |
122 | 119 | |
123 | 120 | /** |
124 | 121 | * Gets content as plain text within a range. |
125 | 122 | * |
126 | | - * @param start {Integer} Offset to start get text from |
127 | | - * @param end {Integer} Offset to start get text to |
| 123 | + * @param range {es.Range} Range of text to get |
128 | 124 | * @param render {Boolean} If annotations should have any influence on output |
129 | 125 | */ |
130 | | -es.Block.prototype.getText = function( start, end, render ) { |
| 126 | +es.Block.prototype.getText = function( range, render ) { |
131 | 127 | throw 'Block.getText not implemented in this subclass.'; |
132 | 128 | }; |
133 | 129 | |
Index: trunk/parsers/wikidom/lib/es/es.Range.js |
— | — | @@ -10,14 +10,10 @@ |
11 | 11 | * @property end {Integer} |
12 | 12 | */ |
13 | 13 | es.Range = function( from, to ) { |
14 | | - this.set( from, to ); |
15 | | -}; |
16 | | - |
17 | | -es.Range.prototype.set = function( from, to ) { |
18 | 14 | this.from = from || 0; |
19 | 15 | this.to = to || from; |
20 | 16 | this.normalize(); |
21 | | -} |
| 17 | +}; |
22 | 18 | |
23 | 19 | es.Range.prototype.getLength = function() { |
24 | 20 | return Math.abs( this.from - this.to ); |