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