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