inputcommand.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /**
  2. * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. /**
  6. * @module typing/inputcommand
  7. */
  8. import Command from '@ckeditor/ckeditor5-core/src/command';
  9. import ChangeBuffer from './utils/changebuffer';
  10. /**
  11. * The input command. Used by the {@link module:typing/input~Input input feature} to handle typing.
  12. *
  13. * @extends module:core/command~Command
  14. */
  15. export default class InputCommand extends Command {
  16. /**
  17. * Creates an instance of the command.
  18. *
  19. * @param {module:core/editor/editor~Editor} editor
  20. * @param {Number} undoStepSize The maximum number of atomic changes
  21. * which can be contained in one batch in the command buffer.
  22. */
  23. constructor( editor, undoStepSize ) {
  24. super( editor );
  25. /**
  26. * Typing's change buffer used to group subsequent changes into batches.
  27. *
  28. * @readonly
  29. * @private
  30. * @member {module:typing/utils/changebuffer~ChangeBuffer} #_buffer
  31. */
  32. this._buffer = new ChangeBuffer( editor.model, undoStepSize );
  33. /**
  34. * Stores batches created by the input command. The batches are used to differentiate input batches from other batches using
  35. * {@link module:typing/input~Input#isInput} method.
  36. *
  37. * @type {WeakSet<module:engine/model/batch~Batch>}
  38. * @protected
  39. */
  40. this._batches = new WeakSet();
  41. }
  42. /**
  43. * The current change buffer.
  44. *
  45. * @type {module:typing/utils/changebuffer~ChangeBuffer}
  46. */
  47. get buffer() {
  48. return this._buffer;
  49. }
  50. /**
  51. * @inheritDoc
  52. */
  53. destroy() {
  54. super.destroy();
  55. this._buffer.destroy();
  56. }
  57. /**
  58. * Executes the input command. It replaces the content within the given range with the given text.
  59. * Replacing is a two step process, first the content within the range is removed and then the new text is inserted
  60. * at the beginning of the range (which after the removal is a collapsed range).
  61. *
  62. * @fires execute
  63. * @param {Object} [options] The command options.
  64. * @param {String} [options.text=''] The text to be inserted.
  65. * @param {module:engine/model/range~Range} [options.range] The range in which the text is inserted. Defaults
  66. * to the first range in the current selection.
  67. * @param {module:engine/model/range~Range} [options.resultRange] The range where the selection
  68. * should be placed after the insertion. If not specified, the selection will be placed right after
  69. * the inserted text.
  70. */
  71. execute( options = {} ) {
  72. const model = this.editor.model;
  73. const doc = model.document;
  74. const text = options.text || '';
  75. const textInsertions = text.length;
  76. const selection = options.range ? model.createSelection( options.range ) : doc.selection;
  77. const resultRange = options.resultRange;
  78. model.enqueueChange( this._buffer.batch, writer => {
  79. this._buffer.lock();
  80. // Store the batch as an 'input' batch for the Input.isInput( batch ) check.
  81. this._batches.add( this._buffer.batch );
  82. model.deleteContent( selection );
  83. if ( text ) {
  84. model.insertContent( writer.createText( text, doc.selection.getAttributes() ), selection );
  85. }
  86. if ( resultRange ) {
  87. writer.setSelection( resultRange );
  88. } else if ( !selection.is( 'documentSelection' ) ) {
  89. writer.setSelection( selection );
  90. }
  91. this._buffer.unlock();
  92. this._buffer.input( textInsertions );
  93. } );
  94. }
  95. }