command.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /**
  2. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /**
  6. * @module core/command
  7. */
  8. import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
  9. import mix from '@ckeditor/ckeditor5-utils/src/mix';
  10. /**
  11. * The base class for CKEditor commands.
  12. *
  13. * Commands are the main way to manipulate editor contents and state. They are mostly used by UI elements (or by other
  14. * commands) to make changes in the model. Commands are available in every part of code that has access to
  15. * the {@link module:core/editor/editor~Editor editor} instance.
  16. *
  17. * Instances of registered commands can be retrieved from {@link module:core/editor/editor~Editor#commands}.
  18. * The easiest way to execute a command is through {@link module:core/editor/editor~Editor#execute}.
  19. *
  20. * By default commands are disabled when editor is in {@link module:core/editor/editor~Editor#readOnly read-only} mode.
  21. *
  22. * @mixes module:utils/observablemixin~ObservableMixin
  23. */
  24. export default class Command {
  25. /**
  26. * Creates a new `Command` instance.
  27. *
  28. * @param {module:core/editor/editor~Editor} editor Editor on which this command will be used.
  29. */
  30. constructor( editor ) {
  31. /**
  32. * The editor on which this command will be used.
  33. *
  34. * @readonly
  35. * @member {module:core/editor/editor~Editor}
  36. */
  37. this.editor = editor;
  38. /**
  39. * The value of a command. Concrete command class should define what it represents.
  40. *
  41. * For example, the `bold` command's value is whether the selection starts in a bolded text.
  42. * And the value of the `link` command may be an object with links details.
  43. *
  44. * It's possible for a command to have no value (e.g. for stateless actions such as `uploadImage`).
  45. *
  46. * @observable
  47. * @readonly
  48. * @member #value
  49. */
  50. this.set( 'value', undefined );
  51. /**
  52. * Flag indicating whether a command is enabled or disabled.
  53. * A disabled command should do nothing when executed.
  54. *
  55. * @observable
  56. * @readonly
  57. * @member {Boolean} #isEnabled
  58. */
  59. this.set( 'isEnabled', false );
  60. this.decorate( 'execute' );
  61. // By default every command is refreshed when changes are applied to the model.
  62. this.listenTo( this.editor.document, 'changesDone', () => {
  63. this.refresh();
  64. } );
  65. this.on( 'execute', evt => {
  66. if ( !this.isEnabled ) {
  67. evt.stop();
  68. }
  69. }, { priority: 'high' } );
  70. // By default commands are disabled when editor switches to read-only mode.
  71. this.listenTo( editor, 'change:readOnly', ( evt, name, value ) => {
  72. if ( value ) {
  73. this.on( 'change:isEnabled', forceDisable, { priority: 'high' } );
  74. this.isEnabled = false;
  75. } else {
  76. this.off( 'change:isEnabled', forceDisable );
  77. this.refresh();
  78. }
  79. } );
  80. // Forces command#isEnabled value to be false.
  81. function forceDisable( evt ) {
  82. this.isEnabled = false;
  83. evt.stop();
  84. }
  85. }
  86. /**
  87. * Refreshes the command. The command should update its {@link #isEnabled} and {@link #value} property
  88. * in this method.
  89. *
  90. * This method is automatically called when
  91. * {@link module:engine/model/document~Document#event:changesDone any changes are applied to the model}.
  92. */
  93. refresh() {
  94. this.isEnabled = true;
  95. }
  96. /**
  97. * Executes the command.
  98. *
  99. * A command may accept parameters. They will be passed from {@link module:core/editor/editor~Editor#execute}
  100. * to the command.
  101. *
  102. * The `execute()` method will automatically abort when the command is disabled ({@link #isEnabled} is `false`).
  103. * This behavior is implemented by a high priority listener to the {@link #event:execute} event.
  104. *
  105. * @fires execute
  106. */
  107. execute() {}
  108. /**
  109. * Destroys the command.
  110. */
  111. destroy() {
  112. this.stopListening();
  113. }
  114. /**
  115. * Event fired by the {@link #execute} method. The command action is a listener to this event so it's
  116. * possible to change/cancel the behavior of the command by listening to this event.
  117. *
  118. * See {@link module:utils/observablemixin~ObservableMixin.decorate} for more information and samples.
  119. *
  120. * **Note:** This event is fired even if command is disabled. However, it is automatically blocked
  121. * by a high priority listener in order to prevent command execution.
  122. *
  123. * @event execute
  124. */
  125. }
  126. mix( Command, ObservableMixin );