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