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