Index: trunk/parsers/wikidom/lib/es/es.Surface.js |
— | — | @@ -67,16 +67,31 @@ |
68 | 68 | |
69 | 69 | Surface.prototype.onMouseDown = function( e ) { |
70 | 70 | var $target = $( e.target ); |
71 | | - $block = $target.is( '.editSurface-block' ) ? $target : $target.closest( '.editSurface-block' ), |
72 | | - block = $block.data( 'block' ); |
73 | | - |
74 | | - if( !block ) { |
75 | | - return false; |
| 71 | + $block = $target.is( '.editSurface-block' ) |
| 72 | + ? $target : $target.closest( '.editSurface-block' ); |
| 73 | + // Not a block or child of a block? Find the nearest block... |
| 74 | + if( !$block.length ) { |
| 75 | + var minDistance; |
| 76 | + this.$.find( '> .editSurface-document .editSurface-block' ).each( function() { |
| 77 | + var top = $(this).offset().top, |
| 78 | + bottom = top + $(this).height(); |
| 79 | + // Inside test |
| 80 | + if ( e.pageY >= top && e.pageY < bottom ) { |
| 81 | + $block = $(this); |
| 82 | + return false; |
| 83 | + } |
| 84 | + // Distance test |
| 85 | + var distance = Math.abs( e.pageY - top ); |
| 86 | + if ( typeof minDistance === 'undefined' || distance < minDistance ) { |
| 87 | + minDistance = distance; |
| 88 | + $block = $(this); |
| 89 | + } |
| 90 | + } ); |
76 | 91 | } |
77 | | - |
78 | | - var position = new Position( e.pageX - $block.offset().left, |
79 | | - e.pageY - $block.offset().top ); |
80 | | - var offset = block.flow.getOffset( position ); |
| 92 | + var block = $block.data( 'block' ) |
| 93 | + blockOffset = $block.offset() |
| 94 | + position = new Position( e.pageX - blockOffset.left, e.pageY - blockOffset.top ) |
| 95 | + offset = block.flow.getOffset( position ); |
81 | 96 | this.cursor.show( new Location( block, offset ) ); |
82 | 97 | this.$input.focus(); |
83 | 98 | return false; |
Index: trunk/parsers/wikidom/lib/es/es.TextFlow.js |
— | — | @@ -15,6 +15,7 @@ |
16 | 16 | if ( text !== undefined ) { |
17 | 17 | this.setText( text ); |
18 | 18 | } |
| 19 | + this.boundaryTest = /([ \.\,\;\:\-\t\r\n\f])/g; |
19 | 20 | } |
20 | 21 | |
21 | 22 | /** |
— | — | @@ -87,7 +88,12 @@ |
88 | 89 | var right = ruler.clientWidth; |
89 | 90 | var center = Math.round( left + ( ( right - left ) / 2 ) ); |
90 | 91 | $ruler.remove(); |
91 | | - return fit.end + ( position.x >= center ? 1 : 0 ); |
| 92 | + // Reset RegExp object's state |
| 93 | + this.boundaryTest.lastIndex = 0; |
| 94 | + var virtual = line < this.lines.length - 1 |
| 95 | + && this.boundaryTest( this.lines[line].text.substr( -1, 1 ) ) |
| 96 | + ? -1 : 0; |
| 97 | + return Math.min( fit.end + ( position.x >= center ? 1 : 0 ), this.lines[line].end + virtual ); |
92 | 98 | }; |
93 | 99 | |
94 | 100 | /** |
— | — | @@ -127,7 +133,7 @@ |
128 | 134 | position.top += this.lines[line].height; |
129 | 135 | line++; |
130 | 136 | }; |
131 | | - |
| 137 | + |
132 | 138 | /* |
133 | 139 | * Virtual n+1 position |
134 | 140 | * |
— | — | @@ -135,17 +141,15 @@ |
136 | 142 | * line, a virtual n+1 position is supported. Offsets beyond this virtual position will cause |
137 | 143 | * an exception to be thrown. |
138 | 144 | */ |
139 | | -/* |
140 | 145 | if ( line === lineCount ) { |
141 | | - if ( offset !== lines[line].end + 1 ) { |
| 146 | + if ( offset !== this.lines[line - 1].end + 1 ) { |
142 | 147 | line--; |
143 | 148 | position.bottom = position.top; |
144 | | - position.top -= lines[line].height; |
| 149 | + position.top -= this.lines[line].height; |
145 | 150 | } else { |
146 | 151 | throw 'Out of range error. Offset is expected to be less than or equal to text length.'; |
147 | 152 | } |
148 | 153 | } |
149 | | -*/ |
150 | 154 | |
151 | 155 | /* |
152 | 156 | * Offset measuring |
— | — | @@ -186,12 +190,13 @@ |
187 | 191 | // Purge "boundaries" and "words" arrays |
188 | 192 | this.boundaries = []; |
189 | 193 | this.words = []; |
| 194 | + // Reset RegExp object's state |
| 195 | + this.boundaryTest.lastIndex = 0; |
190 | 196 | // Iterate over each word+boundary sequence, capturing offsets and encoding text as we go |
191 | | - var boundary = /([ \.\,\;\:\-\t\r\n\f])/g, |
192 | | - match, |
| 197 | + var match, |
193 | 198 | start = 0, |
194 | 199 | end; |
195 | | - while ( match = boundary.exec( text ) ) { |
| 200 | + while ( match = this.boundaryTest.exec( text ) ) { |
196 | 201 | // Include the boundary character in the range |
197 | 202 | end = match.index + 1; |
198 | 203 | // Store the boundary offset |
— | — | @@ -387,7 +392,7 @@ |
388 | 393 | if ( ruler.clientWidth > width ) { |
389 | 394 | // Detect impossible fit (the first character won't fit by itself) |
390 | 395 | if (middle - offset === 1) { |
391 | | - start = middle; |
| 396 | + start = middle - 1; |
392 | 397 | break; |
393 | 398 | } |
394 | 399 | // Words after "middle" won't fit |