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 }; 216 217 // create an instance 218 CommandManager = new (Registry.extend(CommandManager))(); 219 220 /** 221 * Executes a registered command. 222 * http://aryeh.name/spec/editing/editing.html#methods-of-the-htmldocument-interface 223 * @method 224 * @param command name of the command 225 * @param showUI has no effect for Aloha Editor and is only here because in spec... 226 * @param value depends on the used command and it impementation 227 * @range optional a range on which the command will be executed if not specified 228 * the current selection will be used as range 229 */ 230 Aloha.execCommand = CommandManager.execCommand; 231 232 /** 233 * Check wheater the command in enabled. 234 * If command is not supported, raise a NOT_SUPPORTED_ERR exception. 235 * @param command name of the command 236 * @return true if command is enabled, false otherwise. 237 */ 238 Aloha.queryCommandEnabled = CommandManager.queryCommandEnabled; 239 240 /** 241 * Check if the command has an indetermed state. 242 * If command is not supported, a NOT_SUPPORTED_ERR exception is thrown 243 * If command has no indeterminacy, INVALID_ACCESS_ERR exception is thrown 244 * If command is not enabled, return false. 245 * @param command name of the command 246 * @range optional a range on which the command will be executed if not specified 247 * the current selection will be used as range 248 * @return true if command is indeterminate, otherwise false. 249 */ 250 Aloha.queryCommandIndeterm = CommandManager.queryCommandIndeterm; 251 252 /** 253 * Returns the state of a given command 254 * If command is not supported, a NOT_SUPPORTED_ERR exception is thrown 255 * If command has no state, an INVALID_ACCESS_ERR exception is thrown 256 * If command is not enabled, return false 257 * If the state override for command is set, it returns the state 258 * @param command name of the command 259 * @return state override or true if command's state is true, otherwise false. 260 */ 261 Aloha.queryCommandState = CommandManager.queryCommandState; 262 263 /** 264 * Check if a given command is supported 265 * @return true if command is supported, and false otherwise. 266 */ 267 Aloha.queryCommandSupported = CommandManager.queryCommandSupported; 268 269 /** 270 * Returns the Value of a given Command 271 * If command is not supported, a NOT_SUPPORTED_ERR exception is thrown 272 * If command is not enabled, returns an empty string 273 * If command is "fontSize" and its value override is set, an integer 274 * number of pixels is returned as font size for the result. 275 * If the value override for command is set, it returns that. 276 * @return command's value. 277 */ 278 Aloha.queryCommandValue = CommandManager.queryCommandValue; 279 280 Aloha.querySupportedCommands = CommandManager.querySupportedCommands; 281 282 return CommandManager; 283 }); 284