1 /* 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 /** 7 * @fileOverview Defines the {@link CKEDITOR.resourceManager} class, which is 8 * the base for resource managers, like plugins and themes. 9 */ 10 11 /** 12 * Base class for resource managers, like plugins and themes. This class is not 13 * intended to be used out of the CKEditor core code. 14 * @param {String} basePath The path for the resources folder. 15 * @param {String} fileName The name used for resource files. 16 * @namespace 17 * @example 18 */ 19 CKEDITOR.resourceManager = function( basePath, fileName ) 20 { 21 /** 22 * The base directory containing all resources. 23 * @name CKEDITOR.resourceManager.prototype.basePath 24 * @type String 25 * @example 26 */ 27 this.basePath = basePath; 28 29 /** 30 * The name used for resource files. 31 * @name CKEDITOR.resourceManager.prototype.fileName 32 * @type String 33 * @example 34 */ 35 this.fileName = fileName; 36 37 /** 38 * Contains references to all resources that have already been registered 39 * with {@link #add}. 40 * @name CKEDITOR.resourceManager.prototype.registered 41 * @type Object 42 * @example 43 */ 44 this.registered = {}; 45 46 /** 47 * Contains references to all resources that have already been loaded 48 * with {@link #load}. 49 * @name CKEDITOR.resourceManager.prototype.loaded 50 * @type Object 51 * @example 52 */ 53 this.loaded = {}; 54 55 /** 56 * Contains references to all resources that have already been registered 57 * with {@link #addExternal}. 58 * @name CKEDITOR.resourceManager.prototype.externals 59 * @type Object 60 * @example 61 */ 62 this.externals = {}; 63 64 /** 65 * @private 66 */ 67 this._ = 68 { 69 // List of callbacks waiting for plugins to be loaded. 70 waitingList : {} 71 }; 72 }; 73 74 CKEDITOR.resourceManager.prototype = 75 { 76 /** 77 * Registers a resource. 78 * @param {String} name The resource name. 79 * @param {Object} [definition] The resource definition. 80 * @example 81 * CKEDITOR.plugins.add( 'sample', { ... plugin definition ... } ); 82 * @see CKEDITOR.pluginDefinition 83 */ 84 add : function( name, definition ) 85 { 86 if ( this.registered[ name ] ) 87 throw '[CKEDITOR.resourceManager.add] The resource name "' + name + '" is already registered.'; 88 89 this.registered[ name ] = definition || {}; 90 }, 91 92 /** 93 * Gets the definition of a specific resource. 94 * @param {String} name The resource name. 95 * @type Object 96 * @example 97 * var definition = <b>CKEDITOR.plugins.get( 'sample' )</b>; 98 */ 99 get : function( name ) 100 { 101 return this.registered[ name ] || null; 102 }, 103 104 /** 105 * Get the folder path for a specific loaded resource. 106 * @param {String} name The resource name. 107 * @type String 108 * @example 109 * alert( <b>CKEDITOR.plugins.getPath( 'sample' )</b> ); // "<editor path>/plugins/sample/" 110 */ 111 getPath : function( name ) 112 { 113 var external = this.externals[ name ]; 114 return CKEDITOR.getUrl( ( external && external.dir ) || this.basePath + name + '/' ); 115 }, 116 117 /** 118 * Get the file path for a specific loaded resource. 119 * @param {String} name The resource name. 120 * @type String 121 * @example 122 * alert( <b>CKEDITOR.plugins.getFilePath( 'sample' )</b> ); // "<editor path>/plugins/sample/plugin.js" 123 */ 124 getFilePath : function( name ) 125 { 126 var external = this.externals[ name ]; 127 return CKEDITOR.getUrl( 128 this.getPath( name ) + 129 ( ( external && external.file ) || ( this.fileName + '.js' ) ) ); 130 }, 131 132 /** 133 * Registers one or more resources to be loaded from an external path 134 * instead of the core base path. 135 * @param {String} names The resource names, separated by commas. 136 * @param {String} path The path of the folder containing the resource. 137 * @param {String} [fileName] The resource file name. If not provided, the 138 * default name is used. 139 * @example 140 * // Loads a plugin from '/myplugin/samples/plugin.js'. 141 * CKEDITOR.plugins.addExternal( 'sample', '/myplugins/sample/' ); 142 * @example 143 * // Loads a plugin from '/myplugin/samples/my_plugin.js'. 144 * CKEDITOR.plugins.addExternal( 'sample', '/myplugins/sample/', 'my_plugin.js' ); 145 */ 146 addExternal : function( names, path, fileName ) 147 { 148 names = names.split( ',' ); 149 for ( var i = 0 ; i < names.length ; i++ ) 150 { 151 var name = names[ i ]; 152 153 this.externals[ name ] = 154 { 155 dir : path, 156 file : fileName 157 }; 158 } 159 }, 160 161 /** 162 * Loads one or more resources. 163 * @param {String|Array} name The name of the resource to load. It may be a 164 * string with a single resource name, or an array with several names. 165 * @param {Function} callback A function to be called when all resources 166 * are loaded. The callback will receive an array containing all 167 * loaded names. 168 * @param {Object} [scope] The scope object to be used for the callback 169 * call. 170 * @example 171 * <b>CKEDITOR.plugins.load</b>( 'myplugin', function( plugins ) 172 * { 173 * alert( plugins['myplugin'] ); // "object" 174 * }); 175 */ 176 load : function( names, callback, scope ) 177 { 178 // Ensure that we have an array of names. 179 if ( !CKEDITOR.tools.isArray( names ) ) 180 names = names ? [ names ] : []; 181 182 var loaded = this.loaded, 183 registered = this.registered, 184 urls = [], 185 urlsNames = {}, 186 resources = {}; 187 188 // Loop through all names. 189 for ( var i = 0 ; i < names.length ; i++ ) 190 { 191 var name = names[ i ]; 192 193 if ( !name ) 194 continue; 195 196 // If not available yet. 197 if ( !loaded[ name ] && !registered[ name ] ) 198 { 199 var url = this.getFilePath( name ); 200 urls.push( url ); 201 if ( !( url in urlsNames ) ) 202 urlsNames[ url ] = []; 203 urlsNames[ url ].push( name ); 204 } 205 else 206 resources[ name ] = this.get( name ); 207 } 208 209 CKEDITOR.scriptLoader.load( urls, function( completed, failed ) 210 { 211 if ( failed.length ) 212 { 213 throw '[CKEDITOR.resourceManager.load] Resource name "' + urlsNames[ failed[ 0 ] ].join( ',' ) 214 + '" was not found at "' + failed[ 0 ] + '".'; 215 } 216 217 for ( var i = 0 ; i < completed.length ; i++ ) 218 { 219 var nameList = urlsNames[ completed[ i ] ]; 220 for ( var j = 0 ; j < nameList.length ; j++ ) 221 { 222 var name = nameList[ j ]; 223 resources[ name ] = this.get( name ); 224 225 loaded[ name ] = 1; 226 } 227 } 228 229 callback.call( scope, resources ); 230 } 231 , this); 232 } 233 }; 234