1 /* command.js is part of Aloha Editor project http://aloha-editor.org
  2  *
  3  * Aloha Editor is a WYSIWYG HTML5 inline editing library and editor.
  4  * Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
  5  * Contributors http://aloha-editor.org/contribution.php
  6  *
  7  * Aloha Editor is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU General Public License
  9  * as published by the Free Software Foundation; either version 2
 10  * of the License, or any later version.
 11  *
 12  * Aloha Editor is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  * GNU General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU General Public License
 18  * along with this program; if not, write to the Free Software
 19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 20  *
 21  * As an additional permission to the GNU GPL version 2, you may distribute
 22  * non-source (e.g., minimized or compacted) forms of the Aloha-Editor
 23  * source code without the copy of the GNU GPL normally required,
 24  * provided you include this license notice and a URL through which
 25  * recipients can access the Corresponding Source.
 26  */
 27 define([
 28 	'aloha/core',
 29 	'aloha/registry',
 30 	'aloha/engine',
 31 	'util/dom',
 32 	'aloha/contenthandlermanager'
 33 ], function (
 34 	Aloha,
 35 	Registry,
 36 	Engine,
 37 	Dom,
 38 	ContentHandlerManager
 39 ) {
 40 	"use strict";
 41 
 42 	//			Action: What the command does when executed via execCommand(). Every command defined
 43 	//			in CommandManager specification has an action defined for it in the relevant section. For example,
 44 	//			the bold command's action generally makes the current selection bold, or removes bold if
 45 	//			the selection is already bold. An editing toolbar might provide buttons that execute the
 46 	//			action for a command if clicked, or a script might run an action without user interaction
 47 	//			to achieve some particular effect.
 48 	//
 49 	//			Indeterminate: A boolean value returned by queryCommandIndeterm(), depending on the
 50 	//			current state of the document. Generally, a command that has a state defined will be
 51 	//			indeterminate if the state is true for part but not all of the current selection, and a
 52 	//			command that has a value defined will be indeterminate if different parts of the
 53 	//			selection have different values. An editing toolbar might display a button or control
 54 	//			in a special way if the command is indeterminate, like showing a "bold" button as
 55 	//			partially depressed, or leaving a font size selector blank instead of showing the font
 56 	//			size of the current selection. As a rule, a command can only be indeterminate if its
 57 	//			state is false, supposing it has a state.
 58 	//
 59 	//			State: A boolean value returned by queryCommandState(), depending on the current state
 60 	//			of the document. The state of a command is true if it is already in effect, in some
 61 	//			sense specific to the command. Most commands that have a state defined will take opposite
 62 	//			actions depending on whether the state is true or false, such as making the selection
 63 	//			bold if the state is false and removing bold if the state is true. Others will just
 64 	//			have no effect if the state is true, like the justifyCenter command. Still others will
 65 	//			have the same effect regardless, like the styleWithCss command. An editing toolbar might
 66 	//			display a button or control differently depending on the state and indeterminacy of the
 67 	//			command.
 68 	//
 69 	//			Value: A string returned by queryCommandValue(), depending on the current state of the
 70 	//			document. A command usually has a value instead of a state if the property it modifies
 71 	//			can take more than two different values, like the foreColor command. If the command is
 72 	//			indeterminate, its value is generally based on the start of the selection. Otherwise,
 73 	//			in most cases the value holds true for the entire selection, but see the justifyCenter
 74 	//			command and its three companions for an exception. An editing toolbar might display the
 75 	//			value of a command as selected in a drop-down or filled in in a text box, if the command
 76 	//			isn't indeterminate.
 77 	//
 78 	//			Relevant CSS property: CommandManager is defined for certain inline formatting commands, and
 79 	//			is used in algorithms specific to those commands. It is an implementation detail, and
 80 	//			is not exposed to authors. If a command does not have a relevant CSS property
 81 	//			specified, it defaults to null.
 82  83 
	var CommandManager = {
 84 
 85 		execCommand: function (commandId, showUi, value, range) {
 86 			var evtObj = {
 87 				commandId: commandId,
 88 				preventDefault: false
 89 			};
 90 			Aloha.trigger('aloha-command-will-execute', evtObj);
 91 
 92 			if (evtObj.preventDefault === true) {
 93 				return;
 94 			}
 95 			// Read current selection if not passed
 96 			if (!range) {
 97 				if (!Aloha.getSelection().getRangeCount()) {
 98 					return;
 99 				}
100 				range = Aloha.getSelection().getRangeAt(0);
101 			}
102 
103 			// For the insertHTML command we provide contenthandler API
104 			if (commandId.toLowerCase() === 'inserthtml') {
105 				//if (typeof Aloha.settings.contentHandler.insertHtml === 'undefined') {
106 				//	use all registered content handler; used for copy & paste atm (or write log message)
107 				//	Aloha.settings.contentHandler.insertHtml = Aloha.defaults.contentHandler.insertHtml;
108 				//}
109 				value = ContentHandlerManager.handleContent(value, {
110 					contenthandler: Aloha.settings.contentHandler.insertHtml,
111 					command: 'insertHtml'
112 				});
113 			}
114 
115 			Engine.execCommand(commandId, showUi, value, range);
116 
117 			if (Aloha.getSelection().getRangeCount()) {
118 				// Read range after engine modification
119 				range = Aloha.getSelection().getRangeAt(0);
120 
121 				// FIX: doCleanup should work with W3C range
122 				var startnode = range.commonAncestorContainer;
123 				if (startnode.parentNode) {
124 					startnode = startnode.parentNode;
125 				}
126 				var rangeObject = new window.GENTICS.Utils.RangeObject();
127 				rangeObject.startContainer = range.startContainer;
128 				rangeObject.startOffset = range.startOffset;
129 				rangeObject.endContainer = range.endContainer;
130 				rangeObject.endOffset = range.endOffset;
131 				Dom.doCleanup({
132 					merge: true,
133 					removeempty: false
134 				}, rangeObject, startnode);
135 				rangeObject.select();
136 			}
137 
138 			Aloha.trigger('aloha-command-executed', commandId);
139 		},
140 
141 		// If command is available and not disabled or the active range is not null
142 		// the command is enabled
143 		queryCommandEnabled: function (commandId, range) {
144 
145 			// Take current selection if not passed
146 			if (!range) {
147 				if (!Aloha.getSelection().getRangeCount()) {
148 					return;
149 				}
150 				range = Aloha.getSelection().getRangeAt(0);
151 			}
152 			return Engine.queryCommandEnabled(commandId, range);
153 		},
154 
155 		// "Return true if command is indeterminate, otherwise false."
156 		queryCommandIndeterm: function (commandId, range) {
157 
158 			// Take current selection if not passed
159 			if (!range) {
160 				if (!Aloha.getSelection().getRangeCount()) {
161 					return;
162 				}
163 				range = Aloha.getSelection().getRangeAt(0);
164 			}
165 			return Engine.queryCommandIndeterm(commandId, range);
166 
167 		},
168 
169 		queryCommandState: function (commandId, range) {
170 
171 			// Take current selection if not passed
172 			if (!range) {
173 				if (!Aloha.getSelection().getRangeCount()) {
174 					return;
175 				}
176 				range = Aloha.getSelection().getRangeAt(0);
177 			}
178 			return Engine.queryCommandState(commandId, range);
179 
180 		},
181 
182 		// "When the queryCommandSupported(command) method on the HTMLDocument
183 		// interface is invoked, the user agent must return true if command is
184 		// supported, and false otherwise."
185 		queryCommandSupported: function (commandId) {
186 
187 			return Engine.queryCommandSupported(commandId);
188 		},
189 
190 		queryCommandValue: function (commandId, range) {
191 
192 			// Take current selection if not passed
193 			if (!range) {
194 				if (!Aloha.getSelection().getRangeCount()) {
195 					return;
196 				}
197 				range = Aloha.getSelection().getRangeAt(0);
198 			}
199 
200 			// "Return command's value."
201 			return Engine.queryCommandValue(commandId, range);
202 		},
203 		querySupportedCommands: function () {
204 
205 			var commands = [],
206 				command;
207 
208 			for (command in Engine.commands) {
209 				if (Engine.commands.hasOwnProperty(command)) {
210 					commands.push(command);
211 				}
212 			}
213 			return commands;
214 		},
215 		getStateOverride: Engine.getStateOverride,
216 		setStateOverride: Engine.setStateOverride,
217 		resetOverrides: Engine.resetOverrides,
218 		unsetStateOverride: Engine.unsetStateOverride
219 	};
220 
221 	// create an instance
222 	CommandManager = new (Registry.extend(CommandManager))();
223 
224 	/**
225 	 * Executes a registered command.
226 	 * http://aryeh.name/spec/editing/editing.html#methods-of-the-htmldocument-interface
227 	 * @method
228 	 * @param command name of the command
229 	 * @param showUI has no effect for Aloha Editor and is only here because in spec...
230 	 * @param value depends on the used command and it impementation
231 	 * @range optional a range on which the command will be executed if not specified
232 	 *        the current selection will be used as range
233 	 */
234 	Aloha.execCommand = CommandManager.execCommand;
235 
236 	/**
237 	 * Check wheater the command in enabled.
238 	 * If command is not supported, raise a NOT_SUPPORTED_ERR exception.
239 	 * @param command name of the command
240 	 * @return true if command is enabled, false otherwise.
241 	 */
242 	Aloha.queryCommandEnabled = CommandManager.queryCommandEnabled;
243 
244 	/**
245 	 * Check if the command has an indetermed state.
246 	 * If command is not supported, a NOT_SUPPORTED_ERR exception is thrown
247 	 * If command has no indeterminacy, INVALID_ACCESS_ERR exception is thrown
248 	 * If command is not enabled, return false.
249 	 * @param command name of the command
250 	 * @range optional a range on which the command will be executed if not specified
251 	 *        the current selection will be used as range
252 	 * @return true if command is indeterminate, otherwise false.
253 	 */
254 	Aloha.queryCommandIndeterm = CommandManager.queryCommandIndeterm;
255 
256 	/**
257 	 * Returns the state of a given command
258 	 * If command is not supported, a NOT_SUPPORTED_ERR exception is thrown
259 	 * If command has no state, an INVALID_ACCESS_ERR exception is thrown
260 	 * If command is not enabled, return false
261 	 * If the state override for command is set, it returns the state
262 	 * @param command name of the command
263 	 * @return state override or true if command's state is true, otherwise false.
264 	 */
265 	Aloha.queryCommandState = CommandManager.queryCommandState;
266 
267 	/**
268 	 * Check if a given command is supported
269 	 * @return true if command is supported, and false otherwise.
270 	 */
271 	Aloha.queryCommandSupported = CommandManager.queryCommandSupported;
272 
273 	/**
274 	 * Returns the Value of a given Command
275 	 * If command is not supported, a NOT_SUPPORTED_ERR exception is thrown
276 	 * If command is not enabled, returns an empty string
277 	 * If command is "fontSize" and its value override is set, an integer
278 	 * number of pixels is returned as font size for the result.
279 	 * If the value override for command is set, it returns that.
280 	 * @return command's value.
281 	 */
282 	Aloha.queryCommandValue = CommandManager.queryCommandValue;
283 
284 	Aloha.querySupportedCommands = CommandManager.querySupportedCommands;
285 
286 	return CommandManager;
287 });
288