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.resourceManager} class, which is 24 * the base for resource managers, like plugins and themes. 25 */ 26 27 /** 28 * Base class for resource managers, like plugins and themes. This class is not 29 * intended to be used out of the CKEditor core code. 30 * @param {String} basePath The path for the resources folder. 31 * @param {String} fileName The name used for resource files. 32 * @namespace 33 * @example 34 */ 35 CKEDITOR.resourceManager = function( basePath, fileName ) 36 { 37 /** 38 * The base directory containing all resources. 39 * @name CKEDITOR.resourceManager.prototype.basePath 40 * @type String 41 * @example 42 */ 43 this.basePath = basePath; 44 45 /** 46 * The name used for resource files. 47 * @name CKEDITOR.resourceManager.prototype.fileName 48 * @type String 49 * @example 50 */ 51 this.fileName = fileName; 52 53 /** 54 * @private 55 */ 56 this._ = 57 { 58 // List of callbacks waiting for plugins to be loaded. 59 waitingList : {} 60 }; 61 }; 62 63 CKEDITOR.resourceManager.prototype = 64 { 65 /** 66 * Contains references to all resources that have already been registered 67 * with {@link #add}. 68 * @type Object 69 * @example 70 */ 71 registered : {}, 72 73 /** 74 * Contains references to all resources that have already been loaded 75 * with {@link #load}. 76 * @type Object 77 * @example 78 */ 79 loaded : {}, 80 81 /** 82 * Contains references to all resources that have already been registered 83 * with {@link #addExternal}. 84 * @type Object 85 * @example 86 */ 87 externals : {}, 88 89 /** 90 * Registers a resource. 91 * @param {String} name The resource name. 92 * @param {Object} definition The resource definition. 93 * @type undefined 94 * @example 95 * CKEDITOR.plugins.add( 'sample', { ... plugin definition ... } ); 96 * @see CKEDITOR.pluginDefinition 97 */ 98 add : function( name, definition ) 99 { 100 if ( this.registered[ name ] ) 101 throw '[CKEDITOR.resourceManager.add] The resource name "' + name + '" is already registered.'; 102 103 this.registered[ name ] = definition; 104 }, 105 106 /** 107 * Gets the definition of a specific resource. 108 * @param {String} name The resource name. 109 * @type Object 110 * @example 111 * var definition = <b>CKEDITOR.plugins.get( 'sample' )</b>; 112 */ 113 get : function( name ) 114 { 115 return this.registered[ name ] || null; 116 }, 117 118 /** 119 * Get the full path for a specific loaded resource. 120 * @param {String} name The resource name. 121 * @type String 122 * @example 123 * alert( <b>CKEDITOR.plugins.getPath( 'sample' )</b> ); // "<editor path>/plugins/sample/" 124 */ 125 getPath : function( name ) 126 { 127 return this.loaded[ name ] || null; 128 }, 129 130 /** 131 * Registers a resource to be loaded from an external path instead of the core base path. 132 * @param {String} name The resource name. 133 * @param {String} path The resource external path. 134 * @type undefined 135 * @example 136 * // Loads a plugin from '/myplugin/samples/plugin.js'. 137 * CKEDITOR.plugins.addExternal( 'sample', '/myplugins/sample/' ); 138 */ 139 addExternal : function( name, path ) 140 { 141 if ( this.registered[ name ] || this.externals[ name ] ) 142 throw '[CKEDITOR.resourceManager.import] The resource name "' + name + '" is already registered or imported.'; 143 144 this.externals[ name ] = path; 145 }, 146 147 /** 148 * Loads one or more resources. 149 * @param {String|Array} name The name of the resource to load. It may be a 150 * string with a single resource name, or an array with several names. 151 * @param {Function} callback A function to be called when all resources 152 * are loaded. The callback will receive an array containing all 153 * loaded names. 154 * @param {Object} [scope] The scope object to be used for the callback 155 * call. 156 * @type undefined 157 * @example 158 * <b>CKEDITOR.plugins.load</b>( 'myplugin', function( plugins ) 159 * { 160 * alert( plugins[0] ); // "myplugin" 161 * }); 162 */ 163 load : function( name, callback, scope ) 164 { 165 // Ensure that we have an Array of names. 166 var names = CKEDITOR.tools.isArray( name ) ? name : [ name ]; 167 168 var total = names.length; 169 170 // Nothing to load, just call the callback. 171 if ( !total ) 172 { 173 callback.call( scope || window, names ); 174 return; 175 } 176 177 // This function is used to count the loaded plugins and call the 178 // callback when finished loading. 179 callback._loaded = 0; 180 callback._total = total; 181 var loadCheck = function( callback ) 182 { 183 if ( ++callback._loaded == callback._total ) 184 callback.call( scope || window, names ); 185 }; 186 187 var loaded = this.loaded; 188 var waitingList = this._waitingList; 189 190 // Loop through all names. 191 for ( var i = 0 ; i < names.length ; i++ ) 192 { 193 name = names[ i ]; 194 195 // If not loaded already. 196 if ( name && !loaded[ name ] && !this.registered[ name ] ) 197 { 198 var waitingInfo = waitingList[ name ] || ( waitingList[ name ] = [] ); 199 waitingInfo.push( callback ); 200 201 // If this is the first call for it, go ahead loading. 202 if ( waitingInfo.length == 1 ) 203 { 204 // Calculate the plugin script path. 205 var path = this.externals[ name ] || ( this.basePath + name + '/' ); 206 207 // Load the plugin script. 208 CKEDITOR.scriptLoader.load( path + this.fileName + '.js', function( success ) 209 { 210 if ( !success ) 211 throw '[CKEDITOR.resourceManager.load] Resource name "' + name + '" was not found at "' + path + this.fileName + '.js".'; 212 213 loaded[ name ] = path; 214 215 // Check all callbacks that were waiting for this 216 // resource. 217 for ( var j = 0 ; j < waitingInfo.length ; j++ ) 218 loadCheck( waitingInfo[ j ] ); 219 220 delete waitingList[ name ]; 221 }); 222 } 223 } 224 else 225 loadCheck( callback ); 226 } 227 } 228 }; 229