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 "init" method defined.
151 				for ( var i = 0 ; i < plugins.length ; i++ )
152 				{
153 					var pluginName = plugins[ i ];
154 					var plugin = CKEDITOR.plugins.get( pluginName );
155 					if ( plugin && plugin.init )
156 						plugin.init( editor, CKEDITOR.plugins.getPath( pluginName ) );
157 				}
158
159 				// Load the editor skin and theme.
160 				loadSkinTheme( editor );
161 			});
162 	};
163
164 	var loadSkinTheme = function( editor )
165 	{
166 		// Load the skin.
167 		CKEDITOR.skins.load( editor.config.skin, 'editor' );
168
169 		// Load the theme.
170 		var theme = editor.config.theme;
171 		CKEDITOR.themes.load( theme, function()
172 			{
173 				CKEDITOR.themes.get( theme ).build( editor, CKEDITOR.themes.getPath( theme ) );
174 			});
175 	};
176
177 	return function( element, instanceConfig )
178 	{
179 		this._ = {};
180
181 		// Call the base constructor.
182 		CKEDITOR.event.call( this );
183
184 		/**
185 		 * The DOM element that has been replaced by this editor instance. This
186 		 * element holds the editor data on load and post.
187 		 * @name CKEDITOR.editor.prototype.element
188 		 * @type CKEDITOR.dom.element
189 		 * @example
190 		 * var editor = CKEDITOR.instances.editor1;
191 		 * alert( <b>editor.element</b>.getName() );  "textarea"
192 		 */
193 		this.element = element;
194
195 		/**
196 		 * The editor instance name. It hay be the replaced element id, name or
197 		 * a default name using a progressive counter (editor1, editor2, ...).
198 		 * @name CKEDITOR.editor.prototype.name
199 		 * @type String
200 		 * @example
201 		 * var editor = CKEDITOR.instances.editor1;
202 		 * alert( <b>editor.name</b> );  "editor1"
203 		 */
204 		this.name = element.getId() || element.getNameAtt() || getNewName();
205
206 		/**
207 		 * The configurations for this editor instance. It inherits all
208 		 * settings defined in (@link CKEDITOR.config}, combined with settings
209 		 * loaded from custom configuration files and those defined inline in
210 		 * the page when creating the editor.
211 		 * @name CKEDITOR.editor.prototype.config
212 		 * @type Object
213 		 * @example
214 		 * var editor = CKEDITOR.instances.editor1;
215 		 * alert( <b>editor.config.theme</b> );  "default" e.g.
216 		 */
217 		this.config = new config();
218
219 		// Call initConfig using events, to be sure that instancecreated is
220 		// fired first.
221 		this.on( 'instancecreated', function()
222 			{
223 				initConfig( this, instanceConfig );
224 			});
225 	};
226 }());
227
228 CKEDITOR.editor.prototype =
229 {
230 	// Both fire and fireOnce will always pass this editor instance as the
231 	// "editor" param in CKEDITOR.event.fire. So, we override it to do that
232 	// automaticaly.
233
234 	/** @ignore */
235 	fire : function( eventName, data )
236 	{
237 		return CKEDITOR.event.prototype.fire.call( this, eventName, data, this );
238 	},
239
240 	/** @ignore */
241 	fireOnce : function( eventName, data )
242 	{
243 		return CKEDITOR.event.prototype.fireOnce.call( this, eventName, data, this );
244 	}
245 };
246
247 // "Inherit" (copy actually) from CKEDITOR.event.
248 CKEDITOR.tools.extend( CKEDITOR.editor.prototype, CKEDITOR.event.prototype );
249