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