summaryrefslogtreecommitdiff
path: root/core/command.js
diff options
context:
space:
mode:
Diffstat (limited to 'core/command.js')
-rw-r--r--core/command.js255
1 files changed, 255 insertions, 0 deletions
diff --git a/core/command.js b/core/command.js
new file mode 100644
index 0000000..cab97a4
--- /dev/null
+++ b/core/command.js
@@ -0,0 +1,255 @@
+/**
+ * @license Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.html or http://ckeditor.com/license
+ */
+
+/**
+ * Represents a command that can be executed on an editor instance.
+ *
+ * var command = new CKEDITOR.command( editor, {
+ * exec: function( editor ) {
+ * alert( editor.document.getBody().getHtml() );
+ * }
+ * } );
+ *
+ * @class
+ * @mixins CKEDITOR.event
+ * @constructor Creates a command class instance.
+ * @param {CKEDITOR.editor} editor The editor instance this command will be
+ * related to.
+ * @param {CKEDITOR.commandDefinition} commandDefinition The command
+ * definition.
+ */
+CKEDITOR.command = function( editor, commandDefinition ) {
+ /**
+ * Lists UI items that are associated to this command. This list can be
+ * used to interact with the UI on command execution (by the execution code
+ * itself, for example).
+ *
+ * alert( 'Number of UI items associated to this command: ' + command.uiItems.length );
+ */
+ this.uiItems = [];
+
+ /**
+ * Executes the command.
+ *
+ * command.exec(); // The command gets executed.
+ *
+ * @param {Object} [data] Any data to pass to the command. Depends on the
+ * command implementation and requirements.
+ * @returns {Boolean} A boolean indicating that the command has been successfully executed.
+ */
+ this.exec = function( data ) {
+ if ( this.state == CKEDITOR.TRISTATE_DISABLED || !this.checkAllowed() )
+ return false;
+
+ if ( this.editorFocus ) // Give editor focus if necessary (#4355).
+ editor.focus();
+
+ if ( this.fire( 'exec' ) === false )
+ return true;
+
+ return ( commandDefinition.exec.call( this, editor, data ) !== false );
+ };
+
+ /**
+ * Explicitly update the status of the command, by firing the {@link CKEDITOR.command#event-refresh} event,
+ * as well as invoke the {@link CKEDITOR.command#method-refresh} method if defined, this method
+ * is to allow different parts of the editor code to contribute in command status resolution.
+ *
+ * @todo
+ */
+ this.refresh = function( editor, path ) {
+ // Do nothing is we're on read-only and this command doesn't support it.
+ // We don't need to disabled the command explicitely here, because this
+ // is already done by the "readOnly" event listener.
+ if ( !this.readOnly && editor.readOnly )
+ return true;
+
+ // Disable commands that are not allowed in the current selection path context.
+ if ( this.context && !path.isContextFor( this.context ) ) {
+ this.disable();
+ return true;
+ }
+
+ // Make the "enabled" state as basis.
+ this.enable();
+
+ if ( this.fire( 'refresh', { editor: editor, path: path } ) === false )
+ return true;
+
+ return ( commandDefinition.refresh && commandDefinition.refresh.apply( this, arguments ) !== false );
+ };
+
+ var allowed;
+
+ /**
+ * Checks whether this command is allowed by the allowed
+ * content filter ({@link CKEDITOR.filter}). This means
+ * that if command implements {@link CKEDITOR.feature} interface it will be tested
+ * by {@link CKEDITOR.filter#checkFeature}.
+ *
+ * @since 4.1
+ * @returns {Boolean} Whether this command is allowed.
+ */
+ this.checkAllowed = function() {
+ if ( typeof allowed == 'boolean' )
+ return allowed;
+
+ return allowed = editor.filter.checkFeature( this );
+ };
+
+ CKEDITOR.tools.extend( this, commandDefinition, {
+ /**
+ * The editor modes within which the command can be executed. The
+ * execution will have no action if the current mode is not listed
+ * in this property.
+ *
+ * // Enable the command in both WYSIWYG and Source modes.
+ * command.modes = { wysiwyg:1,source:1 };
+ *
+ * // Enable the command in Source mode only.
+ * command.modes = { source:1 };
+ *
+ * @see CKEDITOR.editor#mode
+ */
+ modes: { wysiwyg:1 },
+
+ /**
+ * Indicates that the editor will get the focus before executing
+ * the command.
+ *
+ * // Do not force the editor to have focus when executing the command.
+ * command.editorFocus = false;
+ *
+ * @property {Boolean} [=true]
+ */
+ editorFocus: 1,
+
+ /**
+ * Indicates that this command is sensible to the selection context.
+ * If `true`, the {@link CKEDITOR.command#method-refresh} method will be
+ * called for this command on the {@link CKEDITOR.editor#event-selectionChange} event.
+ *
+ * @property {Boolean} [=false]
+ */
+ contextSensitive: !!commandDefinition.context,
+
+ /**
+ * Indicates the editor state. Possible values are:
+ *
+ * * {@link CKEDITOR#TRISTATE_DISABLED}: the command is
+ * disabled. It's execution will have no effect. Same as {@link #disable}.
+ * * {@link CKEDITOR#TRISTATE_ON}: the command is enabled
+ * and currently active in the editor (for context sensitive commands, for example).
+ * * {@link CKEDITOR#TRISTATE_OFF}: the command is enabled
+ * and currently inactive in the editor (for context sensitive commands, for example).
+ *
+ * Do not set this property directly, using the {@link #setState} method instead.
+ *
+ * if ( command.state == CKEDITOR.TRISTATE_DISABLED )
+ * alert( 'This command is disabled' );
+ *
+ * @property {Number} [=CKEDITOR.TRISTATE_DISABLED]
+ */
+ state: CKEDITOR.TRISTATE_DISABLED
+ });
+
+ // Call the CKEDITOR.event constructor to initialize this instance.
+ CKEDITOR.event.call( this );
+};
+
+CKEDITOR.command.prototype = {
+ /**
+ * Enables the command for execution. The command state (see
+ * {@link CKEDITOR.command#property-state}) available before disabling it is restored.
+ *
+ * command.enable();
+ * command.exec(); // Execute the command.
+ */
+ enable: function() {
+ if ( this.state == CKEDITOR.TRISTATE_DISABLED && this.checkAllowed() )
+ this.setState( ( !this.preserveState || ( typeof this.previousState == 'undefined' ) ) ? CKEDITOR.TRISTATE_OFF : this.previousState );
+ },
+
+ /**
+ * Disables the command for execution. The command state (see
+ * {@link CKEDITOR.command#property-state}) will be set to {@link CKEDITOR#TRISTATE_DISABLED}.
+ *
+ * command.disable();
+ * command.exec(); // "false" - Nothing happens.
+ */
+ disable: function() {
+ this.setState( CKEDITOR.TRISTATE_DISABLED );
+ },
+
+ /**
+ * Sets the command state.
+ *
+ * command.setState( CKEDITOR.TRISTATE_ON );
+ * command.exec(); // Execute the command.
+ * command.setState( CKEDITOR.TRISTATE_DISABLED );
+ * command.exec(); // 'false' - Nothing happens.
+ * command.setState( CKEDITOR.TRISTATE_OFF );
+ * command.exec(); // Execute the command.
+ *
+ * @param {Number} newState The new state. See {@link #property-state}.
+ * @returns {Boolean} Returns `true` if the command state changed.
+ */
+ setState: function( newState ) {
+ // Do nothing if there is no state change.
+ if ( this.state == newState || !this.checkAllowed() )
+ return false;
+
+ this.previousState = this.state;
+
+ // Set the new state.
+ this.state = newState;
+
+ // Fire the "state" event, so other parts of the code can react to the
+ // change.
+ this.fire( 'state' );
+
+ return true;
+ },
+
+ /**
+ * Toggles the on/off (active/inactive) state of the command. This is
+ * mainly used internally by context sensitive commands.
+ *
+ * command.toggleState();
+ */
+ toggleState: function() {
+ if ( this.state == CKEDITOR.TRISTATE_OFF )
+ this.setState( CKEDITOR.TRISTATE_ON );
+ else if ( this.state == CKEDITOR.TRISTATE_ON )
+ this.setState( CKEDITOR.TRISTATE_OFF );
+ }
+};
+
+CKEDITOR.event.implementOn( CKEDITOR.command.prototype );
+
+/**
+ * Indicates the previous command state.
+ *
+ * alert( command.previousState );
+ *
+ * @property {Number} previousState
+ * @see #state
+ */
+
+/**
+ * Fired when the command state changes.
+ *
+ * command.on( 'state', function() {
+ * // Alerts the new state.
+ * alert( this.state );
+ * } );
+ *
+ * @event state
+ */
+
+ /**
+ * @event refresh
+ * @todo
+ */