command.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or http://ckeditor.com/license
  4. */
  5. /**
  6. * Represents a command that can be executed on an editor instance.
  7. *
  8. * var command = new CKEDITOR.command( editor, {
  9. * exec: function( editor ) {
  10. * alert( editor.document.getBody().getHtml() );
  11. * }
  12. * } );
  13. *
  14. * @class
  15. * @mixins CKEDITOR.event
  16. * @constructor Creates a command class instance.
  17. * @param {CKEDITOR.editor} editor The editor instance this command will be
  18. * related to.
  19. * @param {CKEDITOR.commandDefinition} commandDefinition The command
  20. * definition.
  21. */
  22. CKEDITOR.command = function( editor, commandDefinition ) {
  23. /**
  24. * Lists UI items that are associated to this command. This list can be
  25. * used to interact with the UI on command execution (by the execution code
  26. * itself, for example).
  27. *
  28. * alert( 'Number of UI items associated to this command: ' + command.uiItems.length );
  29. */
  30. this.uiItems = [];
  31. /**
  32. * Executes the command.
  33. *
  34. * command.exec(); // The command gets executed.
  35. *
  36. * @param {Object} [data] Any data to pass to the command. Depends on the
  37. * command implementation and requirements.
  38. * @returns {Boolean} A boolean indicating that the command has been successfully executed.
  39. */
  40. this.exec = function( data ) {
  41. if ( this.state == CKEDITOR.TRISTATE_DISABLED || !this.checkAllowed() )
  42. return false;
  43. if ( this.editorFocus ) // Give editor focus if necessary (#4355).
  44. editor.focus();
  45. if ( this.fire( 'exec' ) === false )
  46. return true;
  47. return ( commandDefinition.exec.call( this, editor, data ) !== false );
  48. };
  49. /**
  50. * Explicitly update the status of the command, by firing the {@link CKEDITOR.command#event-refresh} event,
  51. * as well as invoke the {@link CKEDITOR.commandDefinition#refresh} method if defined, this method
  52. * is to allow different parts of the editor code to contribute in command status resolution.
  53. *
  54. * @param {CKEDITOR.editor} editor The editor instance.
  55. * @param {CKEDITOR.dom.elementPath} path
  56. */
  57. this.refresh = function( editor, path ) {
  58. // Do nothing is we're on read-only and this command doesn't support it.
  59. // We don't need to disabled the command explicitely here, because this
  60. // is already done by the "readOnly" event listener.
  61. if ( !this.readOnly && editor.readOnly )
  62. return true;
  63. // Disable commands that are not allowed in the current selection path context.
  64. if ( this.context && !path.isContextFor( this.context ) ) {
  65. this.disable();
  66. return true;
  67. }
  68. // Disable commands that are not allowed by the active filter.
  69. if ( !this.checkAllowed( true ) ) {
  70. this.disable();
  71. return true;
  72. }
  73. // Make the "enabled" state a default for commands enabled from start.
  74. if ( !this.startDisabled )
  75. this.enable();
  76. // Disable commands which shouldn't be enabled in this mode.
  77. if ( this.modes && !this.modes[ editor.mode ] )
  78. this.disable();
  79. if ( this.fire( 'refresh', { editor: editor, path: path } ) === false )
  80. return true;
  81. return ( commandDefinition.refresh && commandDefinition.refresh.apply( this, arguments ) !== false );
  82. };
  83. var allowed;
  84. /**
  85. * Checks whether this command is allowed by the active allowed
  86. * content filter ({@link CKEDITOR.editor#activeFilter}). This means
  87. * that if command implements {@link CKEDITOR.feature} interface it will be tested
  88. * by the {@link CKEDITOR.filter#checkFeature} method.
  89. *
  90. * @since 4.1
  91. * @param {Boolean} [noCache] Skip cache for example due to active filter change. Since CKEditor 4.2.
  92. * @returns {Boolean} Whether this command is allowed.
  93. */
  94. this.checkAllowed = function( noCache ) {
  95. if ( !noCache && typeof allowed == 'boolean' )
  96. return allowed;
  97. return allowed = editor.activeFilter.checkFeature( this );
  98. };
  99. CKEDITOR.tools.extend( this, commandDefinition, {
  100. /**
  101. * The editor modes within which the command can be executed. The
  102. * execution will have no action if the current mode is not listed
  103. * in this property.
  104. *
  105. * // Enable the command in both WYSIWYG and Source modes.
  106. * command.modes = { wysiwyg:1,source:1 };
  107. *
  108. * // Enable the command in Source mode only.
  109. * command.modes = { source:1 };
  110. *
  111. * @see CKEDITOR.editor#mode
  112. */
  113. modes: { wysiwyg: 1 },
  114. /**
  115. * Indicates that the editor will get the focus before executing
  116. * the command.
  117. *
  118. * // Do not force the editor to have focus when executing the command.
  119. * command.editorFocus = false;
  120. *
  121. * @property {Boolean} [=true]
  122. */
  123. editorFocus: 1,
  124. /**
  125. * Indicates that this command is sensible to the selection context.
  126. * If `true`, the {@link CKEDITOR.command#method-refresh} method will be
  127. * called for this command on the {@link CKEDITOR.editor#event-selectionChange} event.
  128. *
  129. * @property {Boolean} [=false]
  130. */
  131. contextSensitive: !!commandDefinition.context,
  132. /**
  133. * Indicates the editor state. Possible values are:
  134. *
  135. * * {@link CKEDITOR#TRISTATE_DISABLED}: the command is
  136. * disabled. It's execution will have no effect. Same as {@link #disable}.
  137. * * {@link CKEDITOR#TRISTATE_ON}: the command is enabled
  138. * and currently active in the editor (for context sensitive commands, for example).
  139. * * {@link CKEDITOR#TRISTATE_OFF}: the command is enabled
  140. * and currently inactive in the editor (for context sensitive commands, for example).
  141. *
  142. * Do not set this property directly, using the {@link #setState} method instead.
  143. *
  144. * if ( command.state == CKEDITOR.TRISTATE_DISABLED )
  145. * alert( 'This command is disabled' );
  146. *
  147. * @property {Number} [=CKEDITOR.TRISTATE_DISABLED]
  148. */
  149. state: CKEDITOR.TRISTATE_DISABLED
  150. } );
  151. // Call the CKEDITOR.event constructor to initialize this instance.
  152. CKEDITOR.event.call( this );
  153. };
  154. CKEDITOR.command.prototype = {
  155. /**
  156. * Enables the command for execution. The command state (see
  157. * {@link CKEDITOR.command#property-state}) available before disabling it is restored.
  158. *
  159. * command.enable();
  160. * command.exec(); // Execute the command.
  161. */
  162. enable: function() {
  163. if ( this.state == CKEDITOR.TRISTATE_DISABLED && this.checkAllowed() )
  164. this.setState( ( !this.preserveState || ( typeof this.previousState == 'undefined' ) ) ? CKEDITOR.TRISTATE_OFF : this.previousState );
  165. },
  166. /**
  167. * Disables the command for execution. The command state (see
  168. * {@link CKEDITOR.command#property-state}) will be set to {@link CKEDITOR#TRISTATE_DISABLED}.
  169. *
  170. * command.disable();
  171. * command.exec(); // "false" - Nothing happens.
  172. */
  173. disable: function() {
  174. this.setState( CKEDITOR.TRISTATE_DISABLED );
  175. },
  176. /**
  177. * Sets the command state.
  178. *
  179. * command.setState( CKEDITOR.TRISTATE_ON );
  180. * command.exec(); // Execute the command.
  181. * command.setState( CKEDITOR.TRISTATE_DISABLED );
  182. * command.exec(); // 'false' - Nothing happens.
  183. * command.setState( CKEDITOR.TRISTATE_OFF );
  184. * command.exec(); // Execute the command.
  185. *
  186. * @param {Number} newState The new state. See {@link #property-state}.
  187. * @returns {Boolean} Returns `true` if the command state changed.
  188. */
  189. setState: function( newState ) {
  190. // Do nothing if there is no state change.
  191. if ( this.state == newState )
  192. return false;
  193. if ( newState != CKEDITOR.TRISTATE_DISABLED && !this.checkAllowed() )
  194. return false;
  195. this.previousState = this.state;
  196. // Set the new state.
  197. this.state = newState;
  198. // Fire the "state" event, so other parts of the code can react to the
  199. // change.
  200. this.fire( 'state' );
  201. return true;
  202. },
  203. /**
  204. * Toggles the on/off (active/inactive) state of the command. This is
  205. * mainly used internally by context sensitive commands.
  206. *
  207. * command.toggleState();
  208. */
  209. toggleState: function() {
  210. if ( this.state == CKEDITOR.TRISTATE_OFF )
  211. this.setState( CKEDITOR.TRISTATE_ON );
  212. else if ( this.state == CKEDITOR.TRISTATE_ON )
  213. this.setState( CKEDITOR.TRISTATE_OFF );
  214. }
  215. };
  216. CKEDITOR.event.implementOn( CKEDITOR.command.prototype );
  217. /**
  218. * Indicates the previous command state.
  219. *
  220. * alert( command.previousState );
  221. *
  222. * @property {Number} previousState
  223. * @see #state
  224. */
  225. /**
  226. * Fired when the command state changes.
  227. *
  228. * command.on( 'state', function() {
  229. * // Alerts the new state.
  230. * alert( this.state );
  231. * } );
  232. *
  233. * @event state
  234. */
  235. /**
  236. * @event refresh
  237. * @todo
  238. */