Index: trunk/extensions/VisualEditor/modules/es/views/es.SurfaceView.js |
— | — | @@ -139,6 +139,8 @@ |
140 | 140 | es.SurfaceView.prototype.onMouseDown = function( e ) { |
141 | 141 | if ( e.button === 0 ) { // left mouse button |
142 | 142 | |
| 143 | + this.selection.normalize(); |
| 144 | + |
143 | 145 | var offset = this.documentView.getOffsetFromEvent( e ); |
144 | 146 | |
145 | 147 | if ( e.originalEvent.detail === 1 ) { // single click |
— | — | @@ -174,8 +176,14 @@ |
175 | 177 | var node = this.documentView.getNodeFromOffset( offset ), |
176 | 178 | nodeOffset = this.documentView.getOffsetFromNode( node, false ); |
177 | 179 | |
178 | | - this.selection.from = this.documentView.getModel().getRelativeContentOffset( nodeOffset, 1 ); |
179 | | - this.selection.to = this.documentView.getModel().getRelativeContentOffset( nodeOffset + node.getElementLength(), -1 ); |
| 180 | + this.selection.from = this.documentView.getModel().getRelativeContentOffset( |
| 181 | + nodeOffset, |
| 182 | + 1 |
| 183 | + ); |
| 184 | + this.selection.to = this.documentView.getModel().getRelativeContentOffset( |
| 185 | + nodeOffset + node.getElementLength(), |
| 186 | + -1 |
| 187 | + ); |
180 | 188 | this.mouse.selectedRange = this.selection.clone(); |
181 | 189 | } |
182 | 190 | |
— | — | @@ -206,11 +214,11 @@ |
207 | 215 | var wordRange = this.documentView.model.getWordBoundaries( offset ); |
208 | 216 | if ( wordRange ) { |
209 | 217 | if ( wordRange.to <= this.mouse.selectedRange.from ) { |
210 | | - this.selection.to = wordRange.from; |
211 | | - this.selection.from = this.mouse.selectedRange.to; |
| 218 | + this.selection.from = wordRange.from; |
| 219 | + this.selection.to = this.mouse.selectedRange.to; |
212 | 220 | } else { |
213 | | - this.selection.to = wordRange.to; |
214 | 221 | this.selection.from = this.mouse.selectedRange.from; |
| 222 | + this.selection.to = wordRange.to; |
215 | 223 | } |
216 | 224 | } else { |
217 | 225 | this.selection.to = offset; |
— | — | @@ -223,11 +231,17 @@ |
224 | 232 | this.documentView.getNodeFromOffset( offset ) |
225 | 233 | ); |
226 | 234 | if ( nodeRange.to <= this.mouse.selectedRange.from ) { |
227 | | - this.selection.to = this.documentView.getModel().getRelativeContentOffset( nodeRange.from, 1 ); |
228 | | - this.selection.from = this.mouse.selectedRange.to; |
| 235 | + this.selection.from = this.documentView.getModel().getRelativeContentOffset( |
| 236 | + nodeRange.from, |
| 237 | + 1 |
| 238 | + ); |
| 239 | + this.selection.to = this.mouse.selectedRange.to; |
229 | 240 | } else { |
230 | | - this.selection.to = this.documentView.getModel().getRelativeContentOffset( nodeRange.to, -1 ); |
231 | 241 | this.selection.from = this.mouse.selectedRange.from; |
| 242 | + this.selection.to = this.documentView.getModel().getRelativeContentOffset( |
| 243 | + nodeRange.to, |
| 244 | + -1 |
| 245 | + ); |
232 | 246 | } |
233 | 247 | } |
234 | 248 | |
— | — | @@ -323,94 +337,10 @@ |
324 | 338 | } |
325 | 339 | break; |
326 | 340 | case 8: // Backspace |
327 | | - if ( this.selection.from === this.selection.to ) { |
328 | | - var sourceOffset = this.selection.to, |
329 | | - targetOffset = this.documentView.getModel().getRelativeContentOffset( sourceOffset, -1), |
330 | | - sourceNode = this.documentView.getNodeFromOffset( sourceOffset, false ), |
331 | | - targetNode = this.documentView.getNodeFromOffset( targetOffset, false ), |
332 | | - sourceSplitableNode = es.DocumentViewNode.getSplitableNode( sourceNode ), |
333 | | - targetSplitableNode = es.DocumentViewNode.getSplitableNode( targetNode ); |
334 | | - |
335 | | - if ( sourceNode === targetNode || ( sourceNode.model.getElementType() === targetNode.model.getElementType() && sourceSplitableNode.getParent() === targetSplitableNode.getParent() ) ) { |
336 | | - this.selection.from = this.selection.to = targetOffset; |
337 | | - this.showCursor(); |
338 | | - var tx = this.documentView.model.prepareRemoval( |
339 | | - new es.Range( targetOffset, sourceOffset ) |
340 | | - ); |
341 | | - this.documentView.model.commit ( tx ); |
342 | | - } else { |
343 | | - this.selection.from = this.selection.to = targetOffset; |
344 | | - this.showCursor(); |
345 | | - var tx = this.documentView.model.prepareInsertion( |
346 | | - targetOffset, sourceNode.model.getContent() |
347 | | - ); |
348 | | - this.documentView.model.commit( tx ); |
349 | | - |
350 | | - var nodeToDelete = sourceNode; |
351 | | - es.DocumentNode.traverseUpstream( nodeToDelete, function( node ) { |
352 | | - if ( node.getParent().children.length === 1 ) { |
353 | | - nodeToDelete = sourceNode.getParent(); |
354 | | - } else { |
355 | | - return false; |
356 | | - } |
357 | | - } ); |
358 | | - var range = new es.Range(); |
359 | | - range.from = this.documentView.getOffsetFromNode( nodeToDelete, false ); |
360 | | - range.to = range.from + nodeToDelete.getElementLength(); |
361 | | - tx = this.documentView.model.prepareRemoval( range ); |
362 | | - this.documentView.model.commit ( tx ); |
363 | | - } |
364 | | - } else { |
365 | | - var tx = this.documentView.model.prepareRemoval( this.selection ); |
366 | | - this.documentView.model.commit( tx ); |
367 | | - this.documentView.clearSelection(); |
368 | | - this.selection.from = this.selection.to = Math.min( this.selection.from, this.selection.to ); |
369 | | - this.showCursor(); |
370 | | - } |
| 341 | + this.handleDelete( true ); |
371 | 342 | break; |
372 | 343 | case 46: // Delete |
373 | | - if ( this.selection.from === this.selection.to ) { |
374 | | - var sourceOffset = this.documentView.getModel().getRelativeContentOffset( this.selection.to, 1), |
375 | | - targetOffset = this.selection.to, |
376 | | - sourceNode = this.documentView.getNodeFromOffset( sourceOffset, false ), |
377 | | - targetNode = this.documentView.getNodeFromOffset( targetOffset, false ), |
378 | | - sourceSplitableNode = es.DocumentViewNode.getSplitableNode( sourceNode ), |
379 | | - targetSplitableNode = es.DocumentViewNode.getSplitableNode( targetNode ); |
380 | | - |
381 | | - if ( sourceNode === targetNode /*|| ( sourceNode.model.getElementType() === targetNode.model.getElementType() && sourceSplitableNode.getParent() === targetSplitableNode.getParent() ) */) { |
382 | | - var tx = this.documentView.model.prepareRemoval( |
383 | | - new es.Range( targetOffset, sourceOffset ) |
384 | | - ); |
385 | | - this.documentView.model.commit ( tx ); |
386 | | - } else { |
387 | | - this.selection.from = this.selection.to = targetOffset; |
388 | | - this.showCursor(); |
389 | | - var tx = this.documentView.model.prepareInsertion( |
390 | | - targetOffset, sourceNode.model.getContent() |
391 | | - ); |
392 | | - this.documentView.model.commit( tx ); |
393 | | - |
394 | | - var nodeToDelete = sourceNode; |
395 | | - es.DocumentNode.traverseUpstream( nodeToDelete, function( node ) { |
396 | | - if ( node.getParent().children.length === 1 ) { |
397 | | - nodeToDelete = nodeToDelete.getParent(); |
398 | | - } else { |
399 | | - return false; |
400 | | - } |
401 | | - } ); |
402 | | - var range = new es.Range(); |
403 | | - range.from = this.documentView.getOffsetFromNode( nodeToDelete, false ); |
404 | | - range.to = range.from + nodeToDelete.getElementLength(); |
405 | | - tx = this.documentView.model.prepareRemoval( range ); |
406 | | - this.documentView.model.commit ( tx ); |
407 | | - } |
408 | | - } else { |
409 | | - var tx = this.documentView.model.prepareRemoval( this.selection ); |
410 | | - this.documentView.model.commit( tx ); |
411 | | - this.documentView.clearSelection(); |
412 | | - this.selection.from = this.selection.to = Math.min( this.selection.from, this.selection.to ); |
413 | | - this.showCursor(); |
414 | | - } |
| 344 | + this.handleDelete(); |
415 | 345 | break; |
416 | 346 | case 13: // Enter |
417 | 347 | if ( this.selection.from === this.selection.to ) { |
— | — | @@ -477,6 +407,70 @@ |
478 | 408 | return true; |
479 | 409 | }; |
480 | 410 | |
| 411 | +es.SurfaceView.prototype.handleDelete = function( backspace ) { |
| 412 | + if ( this.selection.from === this.selection.to ) { |
| 413 | + if ( backspace ) { |
| 414 | + var sourceOffset = this.selection.to, |
| 415 | + targetOffset = this.documentView.getModel().getRelativeContentOffset( |
| 416 | + sourceOffset, |
| 417 | + -1 |
| 418 | + ); |
| 419 | + } else { |
| 420 | + var sourceOffset = this.documentView.getModel().getRelativeContentOffset( |
| 421 | + this.selection.to, |
| 422 | + 1 |
| 423 | + ), |
| 424 | + targetOffset = this.selection.to; |
| 425 | + } |
| 426 | + |
| 427 | + var sourceNode = this.documentView.getNodeFromOffset( sourceOffset, false ), |
| 428 | + targetNode = this.documentView.getNodeFromOffset( targetOffset, false ); |
| 429 | + |
| 430 | + if ( sourceNode.model.getElementType() === targetNode.model.getElementType() ) { |
| 431 | + var sourceSplitableNode = es.DocumentViewNode.getSplitableNode( sourceNode ), |
| 432 | + targetSplitableNode = es.DocumentViewNode.getSplitableNode( targetNode ); |
| 433 | + } |
| 434 | + |
| 435 | + this.selection.from = this.selection.to = targetOffset; |
| 436 | + this.showCursor(); |
| 437 | + |
| 438 | + if ( sourceNode === targetNode || |
| 439 | + ( typeof sourceSplitableNode !== 'undefined' && |
| 440 | + sourceSplitableNode.getParent() === targetSplitableNode.getParent() ) ) { |
| 441 | + var tx = this.documentView.model.prepareRemoval( |
| 442 | + new es.Range( targetOffset, sourceOffset ) |
| 443 | + ); |
| 444 | + this.documentView.model.commit ( tx ); |
| 445 | + } else { |
| 446 | + var tx = this.documentView.model.prepareInsertion( |
| 447 | + targetOffset, sourceNode.model.getContent() |
| 448 | + ); |
| 449 | + this.documentView.model.commit( tx ); |
| 450 | + |
| 451 | + var nodeToDelete = sourceNode; |
| 452 | + es.DocumentNode.traverseUpstream( nodeToDelete, function( node ) { |
| 453 | + if ( node.getParent().children.length === 1 ) { |
| 454 | + nodeToDelete = sourceNode.getParent(); |
| 455 | + } else { |
| 456 | + return false; |
| 457 | + } |
| 458 | + } ); |
| 459 | + var range = new es.Range(); |
| 460 | + range.from = this.documentView.getOffsetFromNode( nodeToDelete, false ); |
| 461 | + range.to = range.from + nodeToDelete.getElementLength(); |
| 462 | + tx = this.documentView.model.prepareRemoval( range ); |
| 463 | + this.documentView.model.commit ( tx ); |
| 464 | + } |
| 465 | + } else { |
| 466 | + // selection removal |
| 467 | + var tx = this.documentView.model.prepareRemoval( this.selection ); |
| 468 | + this.documentView.model.commit( tx ); |
| 469 | + this.documentView.clearSelection(); |
| 470 | + this.selection.from = this.selection.to = this.selection.start; |
| 471 | + this.showCursor(); |
| 472 | + } |
| 473 | +}; |
| 474 | + |
481 | 475 | es.SurfaceView.prototype.insertFromInput = function() { |
482 | 476 | var val = this.$input.val(); |
483 | 477 | this.$input.val( '' ); |