deletecommand.js 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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/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 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. * @param {Object} [options] The command options.
  50. * @param {'character'} [options.unit='character'] See {@link module:engine/controller/modifyselection~modifySelection}'s
  51. * options.
  52. */
  53. _doExecute( options = {} ) {
  54. const doc = this.editor.document;
  55. const dataController = this.editor.data;
  56. doc.enqueueChanges( () => {
  57. this._buffer.lock();
  58. const selection = Selection.createFromSelection( doc.selection );
  59. // Try to extend the selection in the specified direction.
  60. if ( selection.isCollapsed ) {
  61. dataController.modifySelection( selection, { direction: this.direction, unit: options.unit } );
  62. }
  63. // If selection is still collapsed, then there's nothing to delete.
  64. if ( selection.isCollapsed ) {
  65. return;
  66. }
  67. let changeCount = 0;
  68. selection.getFirstRange().getMinimalFlatRanges().forEach( ( range ) => {
  69. changeCount += count(
  70. range.getWalker( { singleCharacters: true, ignoreElementEnd: true, shallow: true } )
  71. );
  72. } );
  73. dataController.deleteContent( selection, this._buffer.batch, { merge: true } );
  74. this._buffer.input( changeCount );
  75. doc.selection.setRanges( selection.getRanges(), selection.isBackward );
  76. this._buffer.unlock();
  77. } );
  78. }
  79. }