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