deletecommand.js 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /**
  2. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /**
  6. * @module typing/deletecommand
  7. */
  8. import Command from '@ckeditor/ckeditor5-core/src/command';
  9. import Selection from '@ckeditor/ckeditor5-engine/src/model/selection';
  10. import ChangeBuffer from './changebuffer';
  11. import count from '@ckeditor/ckeditor5-utils/src/count';
  12. /**
  13. * The delete command. Used by the {@link module:typing/delete~Delete delete feature} to handle the <kbd>Delete</kbd> and
  14. * <kbd>Backspace</kbd> keys.
  15. *
  16. * @extends module:core/command~Command
  17. */
  18. export default class DeleteCommand extends Command {
  19. /**
  20. * Creates an instance of the command.
  21. *
  22. * @param {module:core/editor/editor~Editor} editor
  23. * @param {'forward'|'backward'} direction The directionality of the delete describing in what direction it
  24. * should consume the content when the selection is collapsed.
  25. */
  26. constructor( editor, direction ) {
  27. super( editor );
  28. /**
  29. * The directionality of the delete describing in what direction it should
  30. * consume the content when the selection is collapsed.
  31. *
  32. * @readonly
  33. * @member {'forward'|'backward'} #direction
  34. */
  35. this.direction = direction;
  36. /**
  37. * Delete's change buffer used to group subsequent changes into batches.
  38. *
  39. * @readonly
  40. * @private
  41. * @member {typing.ChangeBuffer} #buffer
  42. */
  43. this._buffer = new ChangeBuffer( editor.document, editor.config.get( 'typing.undoStep' ) );
  44. }
  45. /**
  46. * Executes the delete command. Depending on whether the selection is collapsed or not, deletes its content
  47. * or a piece of content in the {@link #direction defined direction}.
  48. *
  49. * @fires execute
  50. * @param {Object} [options] The command options.
  51. * @param {'character'} [options.unit='character'] See {@link module:engine/controller/modifyselection~modifySelection}'s
  52. * options.
  53. */
  54. execute( options = {} ) {
  55. const doc = this.editor.document;
  56. const dataController = this.editor.data;
  57. doc.enqueueChanges( () => {
  58. this._buffer.lock();
  59. const selection = Selection.createFromSelection( doc.selection );
  60. // Try to extend the selection in the specified direction.
  61. if ( selection.isCollapsed ) {
  62. dataController.modifySelection( selection, { direction: this.direction, unit: options.unit } );
  63. }
  64. // If selection is still collapsed, then there's nothing to delete.
  65. if ( selection.isCollapsed ) {
  66. return;
  67. }
  68. let changeCount = 0;
  69. selection.getFirstRange().getMinimalFlatRanges().forEach( range => {
  70. changeCount += count(
  71. range.getWalker( { singleCharacters: true, ignoreElementEnd: true, shallow: true } )
  72. );
  73. } );
  74. dataController.deleteContent( selection, this._buffer.batch );
  75. this._buffer.input( changeCount );
  76. doc.selection.setRanges( selection.getRanges(), selection.isBackward );
  77. this._buffer.unlock();
  78. } );
  79. }
  80. }