resourcemanager.js 6.4 KB

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