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.loader} objects, which is used to
 24  *		load core scripts and their dependencies from _source.
 25  */
 26
 27 if ( typeof CKEDITOR == 'undefined' )
 28 	CKEDITOR = {};
 29
 30 /**
 31  * Load core scripts and their dependencies from _source.
 32  * @namespace
 33  * @example
 34  */
 35 CKEDITOR.loader = (function()
 36 {
 37 	// Table of script names and their dependencies.
 38 	var scripts =
 39 	{
 40 		'lang/en'				: [],	// TODO: Remove me
 41
 42 		'core/_bootstrap'		: [ 'core/config', 'core/ckeditor', 'core/plugins', 'core/scriptLoader', 'core/tools', /* The following are entries that we wnat to force loading to at the end to avoid dependence recursion */ 'core/dom/text' ],
 43 		'core/ajax'				: [ 'core/xml' ],
 44 		'core/ckeditor'			: [ 'core/ajax', 'core/ckeditor_basic', 'core/dom', 'core/dom/document', 'core/dom/element', 'core/editor', 'core/event', 'core/tools' ],
 45 		'core/ckeditor_base'	: [],
 46 		'core/ckeditor_basic'	: [ 'core/env', 'core/event' ],
 47 		'core/config'			: [ 'core/ckeditor_base' ],
 48 		'core/dom'				: [],
 49 		'core/dom/document'		: [ 'core/dom','core/dom/element', 'core/dom/domobject', 'core/dom/window' ],
 50 		'core/dom/element'		: [ 'core/dom', 'core/dom/document', 'core/dom/domobject', 'core/dom/node', 'core/tools' ],
 51 		'core/dom/event'		: [],
 52 		'core/dom/node'			: [ 'core/dom/domobject', 'core/tools' ],
 53 		'core/dom/domobject'	: [ 'core/dom/event' ],
 54 		'core/dom/text'			: [ 'core/dom/node', 'core/dom/domobject' ],
 55 		'core/dom/window'		: [ 'core/dom/domobject' ],
 56 		'core/editor'			: [ 'core/config', 'core/event', 'core/plugins', 'core/skins', 'core/themes', 'core/tools', 'core/ui' ],
 57 		'core/env'				: [],
 58 		'core/event'			: [],
 59 		'core/plugins'			: [ 'core/resourceManager' ],
 60 		'core/resourceManager'	: [ 'core/scriptLoader', 'core/tools' ],
 61 		'core/scriptLoader'		: [ 'core/dom/element', 'core/env' ],
 62 		'core/skins'			: [],
 63 		'core/themes'			: [ 'lang/en', 'core/resourceManager' ],
 64 		'core/tools'			: [ 'core/env' ],
 65 		'core/ui'				: [],
 66 		'core/xml'				: [ 'core/env' ]
 67 	};
 68
 69 	var basePath = (function()
 70 	{
 71 		// This is a copy of CKEDITOR.basePath, but requires the script having
 72 		// "_source/core/loader.js".
 73 		if ( CKEDITOR && CKEDITOR.basePath )
 74 			return CKEDITOR.basePath;
 75
 76 		// Find out the editor directory path, based on its <script> tag.
 77 		var path = '';
 78 		var scripts = document.getElementsByTagName( 'script' );
 79
 80 		for ( var i = 0 ; i < scripts.length ; i++ )
 81 		{
 82 			var match = scripts[i].src.match( /(^|.*[\\\/])core\/loader.js(?:\?.*)?$/i );
 83
 84 			if ( match )
 85 			{
 86 				path = match[1];
 87 				break;
 88 			}
 89 		}
 90
 91 		// In IE (only) the script.src string is the raw valued entered in the
 92 		// HTML. Other browsers return the full resolved URL instead.
 93 		if ( path.indexOf('://') == -1 )
 94 		{
 95 			// Absolute path.
 96 			if ( path.indexOf( '/' ) === 0 )
 97 				path = location.href.match( /^.*?:\/\/[^\/]*/ )[0] + path;
 98 			// Relative path.
 99 			else
100 				path = location.href.match( /^[^\?]*\// )[0] + path;
101 		}
102
103 		return path;
104 	})();
105
106 	var timestamp = ( CKEDITOR && CKEDITOR.timestamp ) || ( new Date() ).valueOf();	// @Packager.RemoveLine
107 	/*																				// @Packager.RemoveLine
108 	 * The production implementation contains a fixed timestamp						// @Packager.RemoveLine
109 	 * generated by the releaser													// @Packager.RemoveLine
110 	var timestamp = '%TIMESTAMP%';
111 	 */																				// @Packager.RemoveLine
112
113 	var getUrl = function( resource )
114 	{
115 		if ( CKEDITOR && CKEDITOR.getUrl )
116 			return CKEDITOR.getUrl( resource );
117
118 		return basePath + resource +
119 			( resource.indexOf( '?' ) >= 0 ? '&' : '?' ) +
120 			't=' + timestamp;
121 	};
122
123 	/** @lends CKEDITOR.loader */
124 	return {
125 		/**
126 		 * The list of loaded scripts in their loading order.
127 		 * @type Array
128 		 * @example
129 		 * // Alert the loaded script names.
130 		 * alert( <b>CKEDITOR.loader.loadedScripts</b> );
131 		 */
132 		loadedScripts : [],
133
134 		/**
135 		 * Loads a specific script, including its dependencies. This is not a
136 		 * synchronous loading, which means that the code the be loaded will
137 		 * not necessarily be available after this call.
138 		 * @example
139 		 * CKEDITOR.loader.load( 'core/dom/element' );
140 		 */
141 		load : function( scriptName )
142 		{
143 			// Check if the script has already been loaded.
144 			if ( scriptName in this.loadedScripts )
145 				return;
146
147 			// Get the script dependencies list.
148 			var dependencies = scripts[ scriptName ];
149 			if ( !dependencies )
150 				throw 'The script name"' + scriptName + '" is not defined.';
151
152 			// Mark the script as loaded, even before really loading it, to
153 			// avoid cross references recursion.
154 			this.loadedScripts[ scriptName ] = true;
155
156 			// Load all dependencies first.
157 			for ( var i = 0 ; i < dependencies.length ; i++ )
158 				this.load( dependencies[ i ] );
159
160 			// Append this script to the list of loaded scripts.
161 			this.loadedScripts.push( scriptName );
162
163 			var scriptSrc = getUrl( '_source/' + scriptName + '.js' );
164
165 			// Append the <script> element to the DOM.
166 			if ( document.body )
167 			{
168 				var script = document.createElement( 'script' );
169 				script.type = 'text/javascript';
170 				script.src = scriptSrc;
171
172 				document.body.appendChild( script );
173 			}
174 			else
175 				document.write( '<script src="' + scriptSrc + '" type="text/javascript"><\/script>' );
176 		}
177 	};
178 })();
179
180 // Check if any script has been defined for autoload.
181 if ( CKEDITOR._autoLoad )
182 {
183 	CKEDITOR.loader.load( CKEDITOR._autoLoad );
184 	delete CKEDITOR._autoLoad;
185 }
186