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 == '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 }); 86 } 87 88 Engine.execCommand( commandId, showUi, value, range ); 89 90 if ( Aloha.getSelection().getRangeCount() ) { 91 // Read range after engine modification 92 93 range = Aloha.getSelection().getRangeAt( 0 ); 94 95 // FIX: doCleanup should work with W3C range 96 var startnode = range.commonAncestorContainer; 97 var rangeObject = new window.GENTICS.Utils.RangeObject(); 98 rangeObject.startContainer = range.startContainer; 99 rangeObject.startOffset = range.startOffset; 100 rangeObject.endContainer = range.endContainer; 101 rangeObject.endOffset = range.endOffset; 102 Dom.doCleanup({merge:true, removeempty: false}, rangeObject, startnode); 103 rangeObject.select(); 104 } 105 106 Aloha.trigger('aloha-command-executed', commandId); 107 }, 108 109 // If command is available and not disabled or the active range is not null 110 // the command is enabled 111 queryCommandEnabled: function( commandId, range ) { 112 113 // Take current selection if not passed 114 if ( !range ) { 115 if ( !Aloha.getSelection().getRangeCount() ) { 116 return; 117 } 118 range = Aloha.getSelection().getRangeAt(0); 119 } 120 return Engine.queryCommandEnabled( commandId, range ); 121 }, 122 123 // "Return true if command is indeterminate, otherwise false." 124 queryCommandIndeterm: function( commandId, range ) { 125 126 // Take current selection if not passed 127 if ( !range ) { 128 if ( !Aloha.getSelection().getRangeCount() ) { 129 return; 130 } 131 range = Aloha.getSelection().getRangeAt(0); 132 } 133 return Engine.queryCommandIndeterm( commandId, range ); 134 135 }, 136 137 queryCommandState: function( commandId, range ) { 138 139 // Take current selection if not passed 140 if ( !range ) { 141 if ( !Aloha.getSelection().getRangeCount() ) { 142 return; 143 } 144 range = Aloha.getSelection().getRangeAt(0); 145 } 146 return Engine.queryCommandState( commandId, range ); 147 148 }, 149 150 // "When the queryCommandSupported(command) method on the HTMLDocument 151 // interface is invoked, the user agent must return true if command is 152 // supported, and false otherwise." 153 queryCommandSupported: function( commandId ) { 154 155 return Engine.queryCommandSupported( commandId ); 156 }, 157 158 queryCommandValue: function( commandId, range ) { 159 160 // Take current selection if not passed 161 if ( !range ) { 162 if ( !Aloha.getSelection().getRangeCount() ) { 163 return; 164 } 165 range = Aloha.getSelection().getRangeAt(0); 166 } 167 168 // "Return command's value." 169 return Engine.queryCommandValue( commandId, range ); 170 }, 171 querySupportedCommands: function() { 172 173 var 174 commands = [], 175 command; 176 177 for ( command in Engine.commands ) { 178 commands.push( command ); 179 } 180 return commands; 181 } 182 }; 183 184 // create an instance 185 CommandManager = new ( Registry.extend( CommandManager ) )(); 186 187 /** 188 * Executes a registered command. 189 * http://aryeh.name/spec/editing/editing.html#methods-of-the-htmldocument-interface 190 * @method 191 * @param command name of the command 192 * @param showUI has no effect for Aloha Editor and is only here because in spec... 193 * @param value depends on the used command and it impementation 194 * @range optional a range on which the command will be executed if not specified 195 * the current selection will be used as range 196 */ 197 Aloha.execCommand = CommandManager.execCommand; 198 199 /** 200 * Check wheater the command in enabled. 201 * If command is not supported, raise a NOT_SUPPORTED_ERR exception. 202 * @param command name of the command 203 * @return true if command is enabled, false otherwise. 204 */ 205 Aloha.queryCommandEnabled = CommandManager.queryCommandEnabled; 206 207 /** 208 * Check if the command has an indetermed state. 209 * If command is not supported, a NOT_SUPPORTED_ERR exception is thrown 210 * If command has no indeterminacy, INVALID_ACCESS_ERR exception is thrown 211 * If command is not enabled, return false. 212 * @param command name of the command 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 * @return true if command is indeterminate, otherwise false. 217 */ 218 Aloha.queryCommandIndeterm = CommandManager.queryCommandIndeterm; 219 220 /** 221 * Returns the state of a given command 222 * If command is not supported, a NOT_SUPPORTED_ERR exception is thrown 223 * If command has no state, an INVALID_ACCESS_ERR exception is thrown 224 * If command is not enabled, return false 225 * If the state override for command is set, it returns the state 226 * @param command name of the command 227 * @return state override or true if command's state is true, otherwise false. 228 */ 229 Aloha.queryCommandState = CommandManager.queryCommandState; 230 231 /** 232 * Check if a given command is supported 233 * @return true if command is supported, and false otherwise. 234 */ 235 Aloha.queryCommandSupported = CommandManager.queryCommandSupported; 236 237 /** 238 * Returns the Value of a given Command 239 * If command is not supported, a NOT_SUPPORTED_ERR exception is thrown 240 * If command is not enabled, returns an empty string 241 * If command is "fontSize" and its value override is set, an integer 242 * number of pixels is returned as font size for the result. 243 * If the value override for command is set, it returns that. 244 * @return command's value. 245 */ 246 Aloha.queryCommandValue = CommandManager.queryCommandValue; 247 248 Aloha.querySupportedCommands = CommandManager.querySupportedCommands; 249 250 return CommandManager; 251 }); 252