1 /* 2 Copyright (c) 2003-2012, 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 CKEDITOR.fire( name + CKEDITOR.tools.capitalize( this.fileName ) + 'Ready', 90 this.registered[ name ] = definition || {} ); 91 }, 92 93 /** 94 * Gets the definition of a specific resource. 95 * @param {String} name The resource name. 96 * @type Object 97 * @example 98 * var definition = <b>CKEDITOR.plugins.get( 'sample' )</b>; 99 */ 100 get : function( name ) 101 { 102 return this.registered[ name ] || null; 103 }, 104 105 /** 106 * Get the folder path for a specific loaded resource. 107 * @param {String} name The resource name. 108 * @type String 109 * @example 110 * alert( <b>CKEDITOR.plugins.getPath( 'sample' )</b> ); // "<editor path>/plugins/sample/" 111 */ 112 getPath : function( name ) 113 { 114 var external = this.externals[ name ]; 115 return CKEDITOR.getUrl( ( external && external.dir ) || this.basePath + name + '/' ); 116 }, 117 118 /** 119 * Get the file path for a specific loaded resource. 120 * @param {String} name The resource name. 121 * @type String 122 * @example 123 * alert( <b>CKEDITOR.plugins.getFilePath( 'sample' )</b> ); // "<editor path>/plugins/sample/plugin.js" 124 */ 125 getFilePath : function( name ) 126 { 127 var external = this.externals[ name ]; 128 return CKEDITOR.getUrl( 129 this.getPath( name ) + 130 ( ( external && ( typeof external.file == 'string' ) ) ? external.file : this.fileName + '.js' ) ); 131 }, 132 133 /** 134 * Registers one or more resources to be loaded from an external path 135 * instead of the core base path. 136 * @param {String} names The resource names, separated by commas. 137 * @param {String} path The path of the folder containing the resource. 138 * @param {String} [fileName] The resource file name. If not provided, the 139 * default name is used; If provided with a empty string, will implicitly indicates that {@param path} 140 * is already the full path. 141 * @example 142 * // Loads a plugin from '/myplugin/samples/plugin.js'. 143 * CKEDITOR.plugins.addExternal( 'sample', '/myplugins/sample/' ); 144 * @example 145 * // Loads a plugin from '/myplugin/samples/my_plugin.js'. 146 * CKEDITOR.plugins.addExternal( 'sample', '/myplugins/sample/', 'my_plugin.js' ); 147 * @example 148 * // Loads a plugin from '/myplugin/samples/my_plugin.js'. 149 * CKEDITOR.plugins.addExternal( 'sample', '/myplugins/sample/my_plugin.js', '' ); 150 */ 151 addExternal : function( names, path, fileName ) 152 { 153 names = names.split( ',' ); 154 for ( var i = 0 ; i < names.length ; i++ ) 155 { 156 var name = names[ i ]; 157 158 this.externals[ name ] = 159 { 160 dir : path, 161 file : fileName 162 }; 163 } 164 }, 165 166 /** 167 * Loads one or more resources. 168 * @param {String|Array} name The name of the resource to load. It may be a 169 * string with a single resource name, or an array with several names. 170 * @param {Function} callback A function to be called when all resources 171 * are loaded. The callback will receive an array containing all 172 * loaded names. 173 * @param {Object} [scope] The scope object to be used for the callback 174 * call. 175 * @example 176 * <b>CKEDITOR.plugins.load</b>( 'myplugin', function( plugins ) 177 * { 178 * alert( plugins['myplugin'] ); // "object" 179 * }); 180 */ 181 load : function( names, callback, scope ) 182 { 183 // Ensure that we have an array of names. 184 if ( !CKEDITOR.tools.isArray( names ) ) 185 names = names ? [ names ] : []; 186 187 var loaded = this.loaded, 188 registered = this.registered, 189 urls = [], 190 urlsNames = {}, 191 resources = {}; 192 193 // Loop through all names. 194 for ( var i = 0 ; i < names.length ; i++ ) 195 { 196 var name = names[ i ]; 197 198 if ( !name ) 199 continue; 200 201 // If not available yet. 202 if ( !loaded[ name ] && !registered[ name ] ) 203 { 204 var url = this.getFilePath( name ); 205 urls.push( url ); 206 if ( !( url in urlsNames ) ) 207 urlsNames[ url ] = []; 208 urlsNames[ url ].push( name ); 209 } 210 else 211 resources[ name ] = this.get( name ); 212 } 213 214 CKEDITOR.scriptLoader.load( urls, function( completed, failed ) 215 { 216 if ( failed.length ) 217 { 218 throw '[CKEDITOR.resourceManager.load] Resource name "' + urlsNames[ failed[ 0 ] ].join( ',' ) 219 + '" was not found at "' + failed[ 0 ] + '".'; 220 } 221 222 for ( var i = 0 ; i < completed.length ; i++ ) 223 { 224 var nameList = urlsNames[ completed[ i ] ]; 225 for ( var j = 0 ; j < nameList.length ; j++ ) 226 { 227 var name = nameList[ j ]; 228 resources[ name ] = this.get( name ); 229 230 loaded[ name ] = 1; 231 } 232 } 233 234 callback.call( scope, resources ); 235 } 236 , this); 237 } 238 }; 239