1 /* 2 * CKEditor - The text editor for Internet - http://ckeditor.com 3 * Copyright (C) 2003-2008 Frederico Caldeira Knabben 4 * 5 * == BEGIN LICENSE == 6 * 7 * Licensed under the terms of any of the following licenses at your 8 * choice: 9 * 10 * - GNU General Public License Version 2 or later (the "GPL") 11 * http://www.gnu.org/licenses/gpl.html 12 * 13 * - GNU Lesser General Public License Version 2.1 or later (the "LGPL") 14 * http://www.gnu.org/licenses/lgpl.html 15 * 16 * - Mozilla Public License Version 1.1 or later (the "MPL") 17 * http://www.mozilla.org/MPL/MPL-1.1.html 18 * 19 * == END LICENSE == 20 */ 21 22 /** 23 * @fileOverview Defines the {@link CKEDITOR.editor} class, which represents an 24 * editor instance. 25 */ 26 27 /** 28 * Represents an editor instance. This constructor should be rarely used, being 29 * the standard replacement methods preferible. 30 * @constructor 31 * @param {CKEDITOR.dom.element} element The original element replaced by this 32 * editor instance. 33 * @augments CKEDITOR.event 34 * @example 35 * var myTextarea = CKEDITOR.document.getById( 'myTextarea' ); 36 * var myEditor = <b>new CKEDITOR.editor( myTextarea )</b>; 37 * CKEDITOR.add( myEditor ); 38 */ 39 CKEDITOR.editor = ( function() 40 { 41 // The counter for automatic instance names. 42 var nameCounter = 0; 43 44 var getNewName = function() 45 { 46 var name = 'editor' + ( ++nameCounter ); 47 return CKEDITOR.instances[ name ] ? getNewName() : name; 48 }; 49 50 // ##### START: Config Privates 51 52 // These function loads custom configuration files and cache the 53 // CKEDITOR.editorConfig functions defined on them, so there is no need to 54 // download them more than once for several instances. 55 var loadConfigLoaded = {}; 56 var loadConfig = function( editor ) 57 { 58 var customConfig = editor.config.customConfig; 59 60 // Check if there is a custom config to load. 61 if ( !customConfig ) 62 return false; 63 64 var loadedConfig = loadConfigLoaded[ customConfig ] || ( loadConfigLoaded[ customConfig ] = { editors : [] } ); 65 66 // If the custom config has already been downloaded, reuse it. 67 if ( loadedConfig.fn ) 68 { 69 // Call the cached CKEDITOR.editorConfig defined in the custom 70 // config file for the editor instance depending on it. 71 loadedConfig.fn.call( editor, editor ); 72 73 // If there is no other customConfig in the chain, fire the 74 // "configLoaded" event. 75 if ( editor.config.customConfig == customConfig || !loadConfig( editor ) ) 76 editor.fireOnce( 'customConfigLoaded' ); 77 } 78 else 79 { 80 // Add the editor to the list of editors waiting for this config. 81 loadedConfig.editors.push( editor ); 82 83 // Load the custom configuration file. 84 CKEDITOR.scriptLoader.load( customConfig, function() 85 { 86 // If the CKEDITOR.editorConfig function has been properly 87 // defined in the custom configuration file, cache it. 88 if ( CKEDITOR.editorConfig ) 89 loadedConfig.fn = CKEDITOR.editorConfig; 90 else 91 loadedConfig.fn = function(){}; 92 93 delete CKEDITOR.editorConfig; 94 95 for ( var i = 0, length = loadedConfig.editors.length ; i < length ; i++ ) 96 { 97 // Call the load config again. This time the custom 98 // config is already cached and so it will get loaded. 99 loadConfig( loadedConfig.editors[ i ] ); 100 } 101 102 delete loadedConfig.editors; 103 }); 104 } 105 106 return true; 107 }; 108 109 var initConfig = function( editor, instanceConfig ) 110 { 111 // Setup the lister for the "customConfigLoaded" event. 112 editor.on( 'customConfigLoaded', function() 113 { 114 // Overwrite the settings from the in-page config. 115 if ( instanceConfig ) 116 CKEDITOR.tools.extend( editor.config, instanceConfig, true ); 117 118 // Fire the "configLoaded" event. 119 editor.fireOnce( 'configLoaded' ); 120 121 // Start loading the plugins. 122 loadPlugins( editor ); 123 }); 124 125 // The instance config may override the customConfig setting to avoid 126 // loading the default ~/config.js file. 127 if ( instanceConfig && instanceConfig.customConfig != undefined ) 128 editor.config.customConfig = instanceConfig.customConfig; 129 130 // Load configs from the custom configuration files. 131 if ( !loadConfig( editor ) ) 132 editor.fireOnce( 'customConfigLoaded' ); 133 }; 134 135 // Basic config class to inherit the default settings from CKEDITOR.config. 136 var config = function() 137 {}; 138 config.prototype = CKEDITOR.config; 139 140 // ##### END: Config Privates 141 142 var loadPlugins = function( editor ) 143 { 144 // Load all plugins defined in the "plugins" setting. 145 CKEDITOR.plugins.load( editor.config.plugins.split( ',' ), function( plugins ) 146 { 147 // Cache the loaded plugin names. 148 editor.plugins = plugins; 149 150 // Initialize all plugins that have the "beforeInit" and "init" methods defined. 151 var methods = [ 'beforeInit', 'init' ]; 152 for ( var m = 0 ; m < methods.length ; m++ ) 153 { 154 for ( var i = 0 ; i < plugins.length ; i++ ) 155 { 156 var pluginName = plugins[ i ]; 157 var plugin = CKEDITOR.plugins.get( pluginName ); 158 if ( plugin && plugin[ methods[ m ] ] ) 159 plugin[ methods[ m ] ]( editor, CKEDITOR.plugins.getPath( pluginName ) ); 160 } 161 } 162 163 // Load the editor skin and theme. 164 loadSkinTheme( editor ); 165 }); 166 }; 167 168 var loadSkinTheme = function( editor ) 169 { 170 // Load the skin. 171 CKEDITOR.skins.load( editor.config.skin, 'editor' ); 172 173 // Load the theme. 174 var theme = editor.config.theme; 175 CKEDITOR.themes.load( theme, function() 176 { 177 CKEDITOR.themes.get( theme ).build( editor, CKEDITOR.themes.getPath( theme ) ); 178 }); 179 }; 180 181 return function( element, instanceConfig ) 182 { 183 this._ = 184 { 185 commands : {} 186 }; 187 188 // Call the base constructor. 189 CKEDITOR.event.call( this ); 190 191 /** 192 * The DOM element that has been replaced by this editor instance. This 193 * element holds the editor data on load and post. 194 * @name CKEDITOR.editor.prototype.element 195 * @type CKEDITOR.dom.element 196 * @example 197 * var editor = CKEDITOR.instances.editor1; 198 * alert( <b>editor.element</b>.getName() ); "textarea" 199 */ 200 this.element = element; 201 202 /** 203 * The editor instance name. It hay be the replaced element id, name or 204 * a default name using a progressive counter (editor1, editor2, ...). 205 * @name CKEDITOR.editor.prototype.name 206 * @type String 207 * @example 208 * var editor = CKEDITOR.instances.editor1; 209 * alert( <b>editor.name</b> ); "editor1" 210 */ 211 this.name = element.getId() || element.getNameAtt() || getNewName(); 212 213 /** 214 * The configurations for this editor instance. It inherits all 215 * settings defined in (@link CKEDITOR.config}, combined with settings 216 * loaded from custom configuration files and those defined inline in 217 * the page when creating the editor. 218 * @name CKEDITOR.editor.prototype.config 219 * @type Object 220 * @example 221 * var editor = CKEDITOR.instances.editor1; 222 * alert( <b>editor.config.theme</b> ); "default" e.g. 223 */ 224 this.config = new config(); 225 226 /** 227 * Namespace containing UI features related to this editor instance. 228 * @name CKEDITOR.editor.prototype.ui 229 * @type CKEDITOR.ui 230 * @example 231 */ 232 this.ui = new CKEDITOR.ui( this ); 233 234 // Call initConfig using events, to be sure that instanceCreated is 235 // fired first. 236 this.on( 'instanceCreated', function() 237 { 238 initConfig( this, instanceConfig ); 239 }); 240 }; 241 })(); 242 243 CKEDITOR.editor.prototype = 244 { 245 /** 246 * Adds a command definition to the editor instance. Commands added with 247 * this function can be later executed with {@link #execCommand}. 248 * @param {String} commandName The indentifier name of the command. 249 * @param {CKEDITOR.commandDefinition} commandDefinition The command definition. 250 * @example 251 * editorInstance.addCommand( 'sample', 252 * { 253 * exec : function( editor ) 254 * { 255 * alert( 'Executing a command for the editor name "' + editor.name + '"!' ); 256 * } 257 * }); 258 */ 259 addCommand : function( commandName, commandDefinition ) 260 { 261 this._.commands[ commandName ] = commandDefinition; 262 }, 263 264 /** 265 * Executes a command. 266 * @param {String} commandName The indentifier name of the command. 267 * @param {Object} [data] Data to be passed to the command 268 * @example 269 * editorInstance.execCommand( 'Bold' ); 270 */ 271 execCommand : function( commandName, data ) 272 { 273 var command = this._.commands[ commandName ]; 274 if ( command ) 275 return command.exec( this, data ); 276 277 throw 'Unknown command name "' + commandName + '"'; 278 }, 279 280 // Both fire and fireOnce will always pass this editor instance as the 281 // "editor" param in CKEDITOR.event.fire. So, we override it to do that 282 // automaticaly. 283 284 /** @ignore */ 285 fire : function( eventName, data ) 286 { 287 return CKEDITOR.event.prototype.fire.call( this, eventName, data, this ); 288 }, 289 290 /** @ignore */ 291 fireOnce : function( eventName, data ) 292 { 293 return CKEDITOR.event.prototype.fireOnce.call( this, eventName, data, this ); 294 }, 295 296 /** 297 * Gets the editor data. The data will be in raw format. It is the same 298 * data that is posted by the editor. 299 * @type String 300 * @returns (String) The editor data. 301 * @example 302 * if ( CKEDITOR.instances.editor1.<b>getData()</b> == '' ) 303 * alert( 'There is no data available' ); 304 */ 305 getData : function() 306 { 307 this.fire( 'beforeGetData' ); 308 309 // Fire "getData" so data manipulation may happen. 310 var eventData = { dataValue : this._.data || this.element.$.value }; 311 this.fire( 'getData', eventData ); 312 313 return eventData.dataValue; 314 }, 315 316 /** 317 * Sets the editor data. The data must be provided in raw format. 318 * @example 319 * CKEDITOR.instances.editor1.<b>setData( '<p>This is the editor data.</p>' )</b>; 320 */ 321 setData : function( data ) 322 { 323 // Fire "setData" so data manipulation may happen. 324 var eventData = { dataValue : data }; 325 this.fire( 'setData', eventData ); 326 327 this._.data = eventData.dataValue; 328 329 this.fire( 'afterSetData' ); 330 }, 331 332 /** 333 * Updates the <textarea> element that has been replaced by the editor with 334 * the current data available in the editor. 335 * @example 336 * CKEDITOR.instances.editor1.updateElement(); 337 * alert( document.getElementById( 'editor1' ).value ); // The current editor data. 338 */ 339 updateElement : function() 340 { 341 this.element.$.value = this.getData(); 342 } 343 }; 344 345 // "Inherit" (copy actually) from CKEDITOR.event. 346 CKEDITOR.event.implementOn( CKEDITOR.editor.prototype ); 347