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