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  * Base class for resource managers, like plugins and themes.
 24  * @namespace
 25  */
 26 CKEDITOR.resourceManager = function( basePath, fileName )
 27 {
 28 	this.basePath = basePath;
 29 	this.fileName = fileName;
 30 
 31 	// List of callbacks waiting for plugins to be loaded.
 32 	this._waitingList = {};
 33 };
 34 
 35 CKEDITOR.resourceManager.prototype =
 36 {
 37 	registered : {},
 38 
 39 	loaded : {},
 40 	
 41 	externals : {},
 42 
 43 	add : function( name, definition )
 44 	{
 45 		if ( this.registered[ name ] )
 46 			throw '[CKEDITOR.resourceManager.add] The resource name "' + name + '" is already registered.';
 47 
 48 		this.registered[ name ] = definition;
 49 	},
 50 
 51 	get : function( name )
 52 	{
 53 		return this.registered[ name ] || null;
 54 	},
 55 	
 56 	getPath : function( name )
 57 	{
 58 		return this.loaded[ name ] || null;
 59 	},
 60 	
 61 	import : function( name, path )
 62 	{
 63 		if ( this.registered[ name ] || this.externals[ name ] )
 64 			throw '[CKEDITOR.resourceManager.import] The resource name "' + name + '" is already registered or imported.';
 65 
 66 		this.externals[ name ] = path;
 67 	},
 68 
 69 	/**
 70 	 * Loads one or more items.
 71 	 * @param {String|Array} name The name of the item to load.
 72 	 * @param {Function} callback A function to be called when all plugins are loaded.
 73 	 * @param {Object} [scope] The scope object to be used for the callback call.
 74 	 * @type {Undefined}
 75 	 */
 76 	load : function( name, callback, scope )
 77 	{
 78 		// Ensure that we have an Array of names.
 79 		var names = CKEDITOR.tools.isArray( name ) ? name : [ name ];
 80 
 81 		var total = names.length;
 82 
 83 		// Nothing to load, just call the callback.
 84 		if ( total == 0 )
 85 		{
 86 			callback.call( scope || window, names );
 87 			return;
 88 		}
 89 
 90 		// This function is used to count the loaded plugins and call the
 91 		// callback when finished loading.
 92 		callback._loaded = 0;
 93 		callback._total = total;
 94 		var loadCheck = function( callback )
 95 		{
 96 			if ( ++callback._loaded == callback._total )
 97 				callback.call( scope || window, names );
 98 		};
 99 
100 		var loaded = this.loaded;
101 		var waitingList = this._waitingList;
102 
103 		// Loop through all names.
104 		for ( var i = 0 ; i < names.length ; i++ )
105 		{
106 			var name = names[ i ];
107 
108 			// If not loaded already.
109 			if ( name && !loaded[ name ] && !this.registered[ name ] )
110 			{
111 				var waitingInfo = waitingList[ name ] || ( waitingList[ name ] = [] );
112 				waitingInfo.push( callback );
113 
114 				// If this is the first call for it, go ahead loading.
115 				if ( waitingInfo.length == 1 )
116 				{
117 					// Calculate the plugin script path.
118 					var path = this.externals[ name ] || ( this.basePath + name + '/' );
119 
120 					// Load the plugin script.
121 					CKEDITOR.scriptLoader.load( path + this.fileName + '.js', function( success )
122 						{
123 							if ( !success )
124 								throw '[CKEDITOR.resourceManager.load] Resource name "' + name + '" was not found at "' + path + this.fileName + '.js".';
125 
126 							loaded[ name ] = path;
127 
128 							// Check all callbacks that were waiting for this
129 							// resource.
130 							for ( var j = 0 ; j < waitingList[ name ].length ; j++ )
131 								loadCheck( waitingList[ name ][ j ] );
132 
133 							delete waitingList[ name ];
134 						});
135 				}
136 			}
137 			else
138 				loadCheck( callback );
139 		}
140 	}
141 };
142