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 "use strict"; 28 define( [ 'aloha/core', 'aloha/registry', 'aloha/engine', 'util/dom', 'aloha/contenthandlermanager' ], 29 function( Aloha, Registry, Engine, Dom, ContentHandlerManager ) { 30 31 // Action: What the command does when executed via execCommand(). Every command defined 32 // in CommandManager specification has an action defined for it in the relevant section. For example, 33 // the bold command's action generally makes the current selection bold, or removes bold if 34 // the selection is already bold. An editing toolbar might provide buttons that execute the 35 // action for a command if clicked, or a script might run an action without user interaction 36 // to achieve some particular effect. 37 // 38 // Indeterminate: A boolean value returned by queryCommandIndeterm(), depending on the 39 // current state of the document. Generally, a command that has a state defined will be 40 // indeterminate if the state is true for part but not all of the current selection, and a 41 // command that has a value defined will be indeterminate if different parts of the 42 // selection have different values. An editing toolbar might display a button or control 43 // in a special way if the command is indeterminate, like showing a "bold" button as 44 // partially depressed, or leaving a font size selector blank instead of showing the font 45 // size of the current selection. As a rule, a command can only be indeterminate if its 46 // state is false, supposing it has a state. 47 48 // 49 // State: A boolean value returned by queryCommandState(), depending on the current state 50 // of the document. The state of a command is true if it is already in effect, in some 51 // sense specific to the command. Most commands that have a state defined will take opposite 52 // actions depending on whether the state is true or false, such as making the selection 53 // bold if the state is false and removing bold if the state is true. Others will just 54 // have no effect if the state is true, like the justifyCenter command. Still others will 55 // have the same effect regardless, like the styleWithCss command. An editing toolbar might 56 // display a button or control differently depending on the state and indeterminacy of the 57 // command. 58 // 59 // Value: A string returned by queryCommandValue(), depending on the current state of the 60 // document. A command usually has a value instead of a state if the property it modifies 61 // can take more than two different values, like the foreColor command. If the command is 62 // indeterminate, its value is generally based on the start of the selection. Otherwise, 63 // in most cases the value holds true for the entire selection, but see the justifyCenter 64 // command and its three companions for an exception. An editing toolbar might display the 65 // value of a command as selected in a drop-down or filled in in a text box, if the command 66 // isn't indeterminate. 67 // 68 // Relevant CSS property: CommandManager is defined for certain inline formatting commands, and 69 // is used in algorithms specific to those commands. It is an implementation detail, and 70 // is not exposed to authors. If a command does not have a relevant CSS property 71 // specified, it defaults to null. 72 73 var CommandManager = { 74 75 execCommand: function( commandId, showUi, value, range ) { 76 var evtObj = { 77 commandId: commandId, 78 preventDefault: false 79 } 80 Aloha.trigger('aloha-command-will-execute', evtObj); 81 82 if (evtObj.preventDefault === true) { 83 return; 84 } 85 // Read current selection if not passed 86 if ( !range ) { 87 if ( !Aloha.getSelection().getRangeCount() ) { 88 return; 89 } 90 range = Aloha.getSelection().getRangeAt( 0 ); 91 } 92 93 // For the insertHTML command we provide contenthandler API 94 if ( commandId.toLowerCase() === 'inserthtml' ) { 95 //if (typeof Aloha.settings.contentHandler.insertHtml === 'undefined') { 96 // use all registered content handler; used for copy & paste atm (or write log message) 97 // Aloha.settings.contentHandler.insertHtml = Aloha.defaults.contentHandler.insertHtml; 98 //} 99 value = ContentHandlerManager.handleContent( value, { 100 contenthandler: Aloha.settings.contentHandler.insertHtml, 101 command: 'insertHtml' 102 }); 103 } 104 105 Engine.execCommand( commandId, showUi, value, range ); 106 107 if ( Aloha.getSelection().getRangeCount() ) { 108 // Read range after engine modification 109 range = Aloha.getSelection().getRangeAt( 0 ); 110 111 // FIX: doCleanup should work with W3C range 112 var startnode = range.commonAncestorContainer; 113 if (startnode.parentNode) { 114 startnode = startnode.parentNode; 115 } 116 var rangeObject = new window.GENTICS.Utils.RangeObject(); 117 rangeObject.startContainer = range.startContainer; 118 rangeObject.startOffset = range.startOffset; 119 rangeObject.endContainer = range.endContainer; 120 rangeObject.endOffset = range.endOffset; 121 Dom.doCleanup({merge:true, removeempty: false}, rangeObject, startnode); 122 rangeObject.select(); 123 } 124 125 Aloha.trigger('aloha-command-executed', commandId); 126 }, 127 128 // If command is available and not disabled or the active range is not null 129 // the command is enabled 130 queryCommandEnabled: function( commandId, range ) { 131 132 // Take current selection if not passed 133 if ( !range ) { 134 if ( !Aloha.getSelection().getRangeCount() ) { 135 return; 136 } 137 range = Aloha.getSelection().getRangeAt(0); 138 } 139 return Engine.queryCommandEnabled( commandId, range ); 140 }, 141 142 // "Return true if command is indeterminate, otherwise false." 143 queryCommandIndeterm: 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.queryCommandIndeterm( commandId, range ); 153 154 }, 155 156 queryCommandState: 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.queryCommandState( commandId, range ); 166 167 }, 168 169 // "When the queryCommandSupported(command) method on the HTMLDocument 170 // interface is invoked, the user agent must return true if command is 171 // supported, and false otherwise." 172 queryCommandSupported: function( commandId ) { 173 174 return Engine.queryCommandSupported( commandId ); 175 }, 176 177 queryCommandValue: function( commandId, range ) { 178 179 // Take current selection if not passed 180 if ( !range ) { 181 if ( !Aloha.getSelection().getRangeCount() ) { 182 return; 183 } 184 range = Aloha.getSelection().getRangeAt(0); 185 } 186 187 // "Return command's value." 188 return Engine.queryCommandValue( commandId, range ); 189 }, 190 querySupportedCommands: function() { 191 192 var 193 commands = [], 194 command; 195 196 for ( command in Engine.commands ) { 197 commands.push( command ); 198 } 199 return commands; 200 } 201 }; 202 203 // create an instance 204 CommandManager = new ( Registry.extend( CommandManager ) )(); 205 206 /** 207 * Executes a registered command. 208 * http://aryeh.name/spec/editing/editing.html#methods-of-the-htmldocument-interface 209 * @method 210 * @param command name of the command 211 * @param showUI has no effect for Aloha Editor and is only here because in spec... 212 * @param value depends on the used command and it impementation 213 * @range optional a range on which the command will be executed if not specified 214 * the current selection will be used as range 215 */ 216 Aloha.execCommand = CommandManager.execCommand; 217 218 /** 219 * Check wheater the command in enabled. 220 * If command is not supported, raise a NOT_SUPPORTED_ERR exception. 221 * @param command name of the command 222 * @return true if command is enabled, false otherwise. 223 */ 224 Aloha.queryCommandEnabled = CommandManager.queryCommandEnabled; 225 226 /** 227 * Check if the command has an indetermed state. 228 * If command is not supported, a NOT_SUPPORTED_ERR exception is thrown 229 * If command has no indeterminacy, INVALID_ACCESS_ERR exception is thrown 230 * If command is not enabled, return false. 231 * @param command name of the command 232 * @range optional a range on which the command will be executed if not specified 233 * the current selection will be used as range 234 * @return true if command is indeterminate, otherwise false. 235 */ 236 Aloha.queryCommandIndeterm = CommandManager.queryCommandIndeterm; 237 238 /** 239 * Returns the state of a given command 240 * If command is not supported, a NOT_SUPPORTED_ERR exception is thrown 241 * If command has no state, an INVALID_ACCESS_ERR exception is thrown 242 * If command is not enabled, return false 243 * If the state override for command is set, it returns the state 244 * @param command name of the command 245 * @return state override or true if command's state is true, otherwise false. 246 */ 247 Aloha.queryCommandState = CommandManager.queryCommandState; 248 249 /** 250 * Check if a given command is supported 251 * @return true if command is supported, and false otherwise. 252 */ 253 Aloha.queryCommandSupported = CommandManager.queryCommandSupported; 254 255 /** 256 * Returns the Value of a given Command 257 * If command is not supported, a NOT_SUPPORTED_ERR exception is thrown 258 * If command is not enabled, returns an empty string 259 * If command is "fontSize" and its value override is set, an integer 260 * number of pixels is returned as font size for the result. 261 * If the value override for command is set, it returns that. 262 263 * @return command's value. 264 */ 265 Aloha.queryCommandValue = CommandManager.queryCommandValue; 266 267 Aloha.querySupportedCommands = CommandManager.querySupportedCommands; 268 269 return CommandManager; 270 }); 271