command.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. import ObservableMixin from '../../utils/observablemixin.js';
  7. import EmitterMixin from '../../utils/emittermixin.js';
  8. import utils from '../../utils/utils.js';
  9. /**
  10. * The base class for CKEditor commands.
  11. *
  12. * Commands are main way to manipulate editor contents and state. They are mostly used by UI elements (or by other
  13. * commands) to make changes in Tree Model. Commands are available in every part of code that has access to
  14. * {@link core.Editor} instance, since they are registered in it and executed through {@link core.Editor#execute}.
  15. * Commands instances are available through {@link core.Editor#commands}.
  16. *
  17. * This is an abstract base class for all commands.
  18. *
  19. * @mixes utils.ObservableMixin
  20. * @mixes utils.EmitterMixin
  21. * @memberOf core.command
  22. */
  23. export default class Command {
  24. /**
  25. * Creates a new Command instance.
  26. *
  27. * @param {core.Editor} editor Editor on which this command will be used.
  28. */
  29. constructor( editor ) {
  30. /**
  31. * Editor on which this command will be used.
  32. *
  33. * @member {core.Editor} core.command.Command#editor
  34. */
  35. this.editor = editor;
  36. /**
  37. * Flag indicating whether a command is enabled or disabled.
  38. * A disabled command should do nothing upon it's execution.
  39. *
  40. * @member {Boolean} core.command.Command#isEnabled
  41. */
  42. this.set( 'isEnabled', true );
  43. // If schema checking function is specified, add it to the `refreshState` listeners.
  44. // Feature will be disabled if it does not apply to schema requirements.
  45. if ( this._checkEnabled ) {
  46. this.on( 'refreshState', ( evt, data ) => {
  47. data.isEnabled = this._checkEnabled();
  48. } );
  49. }
  50. }
  51. /**
  52. * Checks if a command should be enabled according to its own rules. Mostly it will check schema to see if the command
  53. * is allowed to be executed in given position. This method can be defined in child class (but is not obligatory).
  54. * If it is defined, it will be added as a callback to `refreshState` event.
  55. *
  56. * @protected
  57. * @method core.command.Command#_checkEnabled
  58. * @returns {Boolean} `true` if command should be enabled according to {@link core.treeModel.Document#schema}. `false` otherwise.
  59. */
  60. /**
  61. * Fires `refreshState` event and checks it's resolve value to decide whether command should be enabled or not.
  62. * Other parts of code might listen to `refreshState` event on this command and add their callbacks. This
  63. * way the responsibility of deciding whether a command should be enabled is shared.
  64. *
  65. * @fires {@link core.command.Command#refreshState refreshState}
  66. */
  67. refreshState() {
  68. const data = { isEnabled: true };
  69. this.fire( 'refreshState', data );
  70. this.isEnabled = data.isEnabled;
  71. }
  72. /**
  73. * Executes the command if it is enabled.
  74. *
  75. * @protected
  76. * @param {*} param Parameter passed to {@link core.command.Command#execute execute} method of this command.
  77. */
  78. _execute( param ) {
  79. if ( this.isEnabled ) {
  80. this._doExecute( param );
  81. }
  82. }
  83. /**
  84. * Disables the command. This should be used only by the command itself. Other parts of code should add
  85. * listeners to `refreshState` event.
  86. *
  87. * @protected
  88. */
  89. _disable() {
  90. this.on( 'refreshState', disableCallback );
  91. this.refreshState();
  92. }
  93. /**
  94. * Enables the command (internally). This should be used only by the command itself. Command will be enabled if
  95. * other listeners does not return false on `refreshState` event callbacks. Firing {@link core.command.Command#_enable}
  96. * does not guarantee that {@link core.command.Command#isEnabled} will be set to true, as it depends on other listeners.
  97. *
  98. * @protected
  99. */
  100. _enable() {
  101. this.off( 'refreshState', disableCallback );
  102. this.refreshState();
  103. }
  104. /**
  105. * Executes command.
  106. * This is an abstract method that should be overwritten in child classes.
  107. *
  108. * @protected
  109. */
  110. _doExecute() {}
  111. }
  112. function disableCallback( evt, data ) {
  113. data.isEnabled = false;
  114. }
  115. utils.mix( Command, ObservableMixin );
  116. utils.mix( Command, EmitterMixin );
  117. /**
  118. * Fired whenever command has to have it's {@link core.command.Command#isEnabled} property refreshed. Every feature,
  119. * command or other class which should be able to disable command (set `isEnabled` to `false`) should listen to this
  120. * event.
  121. *
  122. * @event core.command.Command#refreshState
  123. */