X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/7a654f8d43fdb43d78b63d90528bed6e86b608cc..refs/heads/master:/docs/source/Loader.html?ds=inline diff --git a/docs/source/Loader.html b/docs/source/Loader.html index 14ba4e6b..f7e95e37 100644 --- a/docs/source/Loader.html +++ b/docs/source/Loader.html @@ -1,139 +1,153 @@ -
+ +/** - * @author Jacky Nguyen <jacky@sencha.com> + + + + +\ No newline at end of file +The source code + + + + + + +/** + * @class Ext.Loader + * @singleton + * @author Jacky Nguyen <jacky@sencha.com> * @docauthor Jacky Nguyen <jacky@sencha.com> - * @class Ext.Loader * - -Ext.Loader is the heart of the new dynamic dependency loading capability in Ext JS 4+. It is most commonly used -via the {@link Ext#require} shorthand. Ext.Loader supports both asynchronous and synchronous loading -approaches, and leverage their advantages for the best development flow. We'll discuss about the pros and cons of each approach: - -# Asynchronous Loading # - -- Advantages: - + Cross-domain - + No web server needed: you can run the application via the file system protocol (i.e: `file://path/to/your/index - .html`) - + Best possible debugging experience: error messages come with the exact file name and line number - -- Disadvantages: - + Dependencies need to be specified before-hand - -### Method 1: Explicitly include what you need: ### - - // Syntax - Ext.require({String/Array} expressions); - - // Example: Single alias - Ext.require('widget.window'); - - // Example: Single class name - Ext.require('Ext.window.Window'); - - // Example: Multiple aliases / class names mix - Ext.require(['widget.window', 'layout.border', 'Ext.data.Connection']); - - // Wildcards - Ext.require(['widget.*', 'layout.*', 'Ext.data.*']); - -### Method 2: Explicitly exclude what you don't need: ### - - // Syntax: Note that it must be in this chaining format. - Ext.exclude({String/Array} expressions) - .require({String/Array} expressions); - - // Include everything except Ext.data.* - Ext.exclude('Ext.data.*').require('*');Â - - // Include all widgets except widget.checkbox*, - // which will match widget.checkbox, widget.checkboxfield, widget.checkboxgroup, etc. - Ext.exclude('widget.checkbox*').require('widget.*'); - -# Synchronous Loading on Demand # - -- *Advantages:* - + There's no need to specify dependencies before-hand, which is always the convenience of including ext-all.js - before - -- *Disadvantages:* - + Not as good debugging experience since file name won't be shown (except in Firebug at the moment) - + Must be from the same domain due to XHR restriction - + Need a web server, same reason as above - -There's one simple rule to follow: Instantiate everything with Ext.create instead of the `new` keyword - - Ext.create('widget.window', { ... }); // Instead of new Ext.window.Window({...}); - - Ext.create('Ext.window.Window', {}); // Same as above, using full class name instead of alias - - Ext.widget('window', {}); // Same as above, all you need is the traditional `xtype` - -Behind the scene, {@link Ext.ClassManager} will automatically check whether the given class name / alias has already - existed on the page. If it's not, Ext.Loader will immediately switch itself to synchronous mode and automatic load the given - class and all its dependencies. - -# Hybrid Loading - The Best of Both Worlds # - -It has all the advantages combined from asynchronous and synchronous loading. The development flow is simple: - -### Step 1: Start writing your application using synchronous approach. Ext.Loader will automatically fetch all - dependencies on demand as they're needed during run-time. For example: ### - - Ext.onReady(function(){ - var window = Ext.createWidget('window', { - width: 500, - height: 300, - layout: { - type: 'border', - padding: 5 - }, - title: 'Hello Dialog', - items: [{ - title: 'Navigation', - collapsible: true, - region: 'west', - width: 200, - html: 'Hello', - split: true - }, { - title: 'TabPanel', - region: 'center' - }] - }); - - window.show(); - }) - -### Step 2: Along the way, when you need better debugging ability, watch the console for warnings like these: ### - - [Ext.Loader] Synchronously loading 'Ext.window.Window'; consider adding Ext.require('Ext.window.Window') before your application's code - ClassManager.js:432 - [Ext.Loader] Synchronously loading 'Ext.layout.container.Border'; consider adding Ext.require('Ext.layout.container.Border') before your application's code - -Simply copy and paste the suggested code above `Ext.onReady`, i.e: - - Ext.require('Ext.window.Window'); - Ext.require('Ext.layout.container.Border'); - - Ext.onReady(...); - -Everything should now load via asynchronous mode. - -# Deployment # - -It's important to note that dynamic loading should only be used during development on your local machines. -During production, all dependencies should be combined into one single JavaScript file. Ext.Loader makes -the whole process of transitioning from / to between development / maintenance and production as easy as -possible. Internally {@link Ext.Loader#history Ext.Loader.history} maintains the list of all dependencies your application -needs in the exact loading sequence. It's as simple as concatenating all files in this array into one, -then include it on top of your application. - -This process will be automated with Sencha Command, to be released and documented towards Ext JS 4 Final. - - * @singleton - * @markdown + * Ext.Loader is the heart of the new dynamic dependency loading capability in Ext JS 4+. It is most commonly used + * via the {@link Ext#require} shorthand. Ext.Loader supports both asynchronous and synchronous loading + * approaches, and leverage their advantages for the best development flow. We'll discuss about the pros and cons + * of each approach: + * + * # Asynchronous Loading + * + * - Advantages: + * + Cross-domain + * + No web server needed: you can run the application via the file system protocol + * (i.e: `file://path/to/your/index.html`) + * + Best possible debugging experience: error messages come with the exact file name and line number + * + * - Disadvantages: + * + Dependencies need to be specified before-hand + * + * ### Method 1: Explicitly include what you need: + * + * // Syntax + * Ext.require({String/Array} expressions); + * + * // Example: Single alias + * Ext.require('widget.window'); + * + * // Example: Single class name + * Ext.require('Ext.window.Window'); + * + * // Example: Multiple aliases / class names mix + * Ext.require(['widget.window', 'layout.border', 'Ext.data.Connection']); + * + * // Wildcards + * Ext.require(['widget.*', 'layout.*', 'Ext.data.*']); + * + * ### Method 2: Explicitly exclude what you don't need: + * + * // Syntax: Note that it must be in this chaining format. + * Ext.exclude({String/Array} expressions) + * .require({String/Array} expressions); + * + * // Include everything except Ext.data.* + * Ext.exclude('Ext.data.*').require('*');Â + * + * // Include all widgets except widget.checkbox*, + * // which will match widget.checkbox, widget.checkboxfield, widget.checkboxgroup, etc. + * Ext.exclude('widget.checkbox*').require('widget.*'); + * + * # Synchronous Loading on Demand + * + * - Advantages: + * + There's no need to specify dependencies before-hand, which is always the convenience of including + * ext-all.js before + * + * - Disadvantages: + * + Not as good debugging experience since file name won't be shown (except in Firebug at the moment) + * + Must be from the same domain due to XHR restriction + * + Need a web server, same reason as above + * + * There's one simple rule to follow: Instantiate everything with Ext.create instead of the `new` keyword + * + * Ext.create('widget.window', { ... }); // Instead of new Ext.window.Window({...}); + * + * Ext.create('Ext.window.Window', {}); // Same as above, using full class name instead of alias + * + * Ext.widget('window', {}); // Same as above, all you need is the traditional `xtype` + * + * Behind the scene, {@link Ext.ClassManager} will automatically check whether the given class name / alias has already + * existed on the page. If it's not, Ext.Loader will immediately switch itself to synchronous mode and automatic load + * the given class and all its dependencies. + * + * # Hybrid Loading - The Best of Both Worlds + * + * It has all the advantages combined from asynchronous and synchronous loading. The development flow is simple: + * + * ### Step 1: Start writing your application using synchronous approach. + * + * Ext.Loader will automatically fetch all dependencies on demand as they're needed during run-time. For example: + * + * Ext.onReady(function(){ + * var window = Ext.createWidget('window', { + * width: 500, + * height: 300, + * layout: { + * type: 'border', + * padding: 5 + * }, + * title: 'Hello Dialog', + * items: [{ + * title: 'Navigation', + * collapsible: true, + * region: 'west', + * width: 200, + * html: 'Hello', + * split: true + * }, { + * title: 'TabPanel', + * region: 'center' + * }] + * }); + * + * window.show(); + * }) + * + * ### Step 2: Along the way, when you need better debugging ability, watch the console for warnings like these: + * + * [Ext.Loader] Synchronously loading 'Ext.window.Window'; consider adding Ext.require('Ext.window.Window') before your application's code ClassManager.js:432 + * [Ext.Loader] Synchronously loading 'Ext.layout.container.Border'; consider adding Ext.require('Ext.layout.container.Border') before your application's code + * + * Simply copy and paste the suggested code above `Ext.onReady`, e.g.: + * + * Ext.require('Ext.window.Window'); + * Ext.require('Ext.layout.container.Border'); + * + * Ext.onReady(...); + * + * Everything should now load via asynchronous mode. + * + * # Deployment + * + * It's important to note that dynamic loading should only be used during development on your local machines. + * During production, all dependencies should be combined into one single JavaScript file. Ext.Loader makes + * the whole process of transitioning from / to between development / maintenance and production as easy as + * possible. Internally {@link Ext.Loader#history Ext.Loader.history} maintains the list of all dependencies + * your application needs in the exact loading sequence. It's as simple as concatenating all files in this + * array into one, then include it on top of your application. + * + * This process will be automated with Sencha Command, to be released and documented towards Ext JS 4 Final. */ - (function(Manager, Class, flexSetter, alias) { var @@ -210,12 +224,9 @@ This process will be automated with Sencha Command, to be released and documente classNameToFilePathMap: {}, /** - * An array of class names to keep track of the dependency loading order. - * This is not guaranteed to be the same everytime due to the asynchronous - * nature of the Loader. - * - * @property history - * @type Array + * @property {String[]} history + * An array of class names to keep track of the dependency loading order. + * This is not guaranteed to be the same everytime due to the asynchronous nature of the Loader. */ history: [], @@ -225,39 +236,38 @@ This process will be automated with Sencha Command, to be released and documente */ config: { /** - * Whether or not to enable the dynamic dependency loading feature - * Defaults to false - * @cfg {Boolean} enabled + * @cfg {Boolean} enabled + * Whether or not to enable the dynamic dependency loading feature. */ enabled: false, /** * @cfg {Boolean} disableCaching - * Appends current timestamp to script files to prevent caching - * Defaults to true + * Appends current timestamp to script files to prevent caching. */ disableCaching: true, /** * @cfg {String} disableCachingParam * The get parameter name for the cache buster's timestamp. - * Defaults to '_dc' */ disableCachingParam: '_dc', /** * @cfg {Object} paths * The mapping from namespaces to file paths - { - 'Ext': '.', // This is set by default, Ext.layout.container.Container will be - // loaded from ./layout/Container.js - - 'My': './src/my_own_folder' // My.layout.Container will be loaded from - // ./src/my_own_folder/layout/Container.js - } + * + * { + * 'Ext': '.', // This is set by default, Ext.layout.container.Container will be + * // loaded from ./layout/Container.js + * + * 'My': './src/my_own_folder' // My.layout.Container will be loaded from + * // ./src/my_own_folder/layout/Container.js + * } + * * Note that all relative paths are relative to the current HTML document. - * If not being specified, for example, <code>Other.awesome.Class</code> - * will simply be loaded from <code>./Other/awesome/Class.js</code> + * If not being specified, for example, `Other.awesome.Class` + * will simply be loaded from `./Other/awesome/Class.js` */ paths: { 'Ext': '.' @@ -266,30 +276,30 @@ This process will be automated with Sencha Command, to be released and documente /** * Set the configuration for the loader. This should be called right after ext-core.js - * (or ext-core-debug.js) is included in the page, i.e: - - <script type="text/javascript" src="ext-core-debug.js"></script> - <script type="text/javascript"> - Ext.Loader.setConfig({ - enabled: true, - paths: { - 'My': 'my_own_path' - } - }); - <script> - <script type="text/javascript"> - Ext.require(...); - - Ext.onReady(function() { - // application code here - }); - </script> - - * Refer to {@link Ext.Loader#configs} for the list of possible properties + * (or ext-core-debug.js) is included in the page, e.g.: + * + * <script type="text/javascript" src="ext-core-debug.js"></script> + * <script type="text/javascript"> + * Ext.Loader.setConfig({ + * enabled: true, + * paths: { + * 'My': 'my_own_path' + * } + * }); + * <script> + * <script type="text/javascript"> + * Ext.require(...); + * + * Ext.onReady(function() { + * // application code here + * }); + * </script> + * + * Refer to config options of {@link Ext.Loader} for the list of possible properties. * - * @param {Object} config The config object to override the default values in {@link Ext.Loader#config} + * @param {String/Object} name Name of the value to override, or a config object to override multiple values. + * @param {Object} value (optional) The new value to set, needed if first parameter is String. * @return {Ext.Loader} this - * @markdown */ setConfig: function(name, value) { if (Ext.isObject(name) && arguments.length === 1) { @@ -303,9 +313,10 @@ This process will be automated with Sencha Command, to be released and documente }, /** - * Get the config value corresponding to the specified name. If no name is given, will return the config object + * Get the config value corresponding to the specified name. + * If no name is given, will return the config object. * @param {String} name The config property name - * @return {Object/Mixed} + * @return {Object} */ getConfig: function(name) { if (name) { @@ -315,16 +326,15 @@ This process will be automated with Sencha Command, to be released and documente return this.config; }, - /** - * Sets the path of a namespace. - * For Example: - - Ext.Loader.setPath('Ext', '.'); - + /** + * Sets the path of a namespace. For Example: + * + * Ext.Loader.setPath('Ext', '.'); + * * @param {String/Object} name See {@link Ext.Function#flexSetter flexSetter} * @param {String} path See {@link Ext.Function#flexSetter flexSetter} * @return {Ext.Loader} this - * @markdown + * @method */ setPath: flexSetter(function(name, path) { //<if nonBrowser> @@ -340,32 +350,31 @@ This process will be automated with Sencha Command, to be released and documente }), /** - * Translates a className to a file path by adding the - * the proper prefix and converting the .'s to /'s. For example: - - Ext.Loader.setPath('My', '/path/to/My'); - - alert(Ext.Loader.getPath('My.awesome.Class')); // alerts '/path/to/My/awesome/Class.js' - + * Translates a className to a file path by adding the the proper prefix and converting the .'s to /'s. + * For example: + * + * Ext.Loader.setPath('My', '/path/to/My'); + * + * alert(Ext.Loader.getPath('My.awesome.Class')); // alerts '/path/to/My/awesome/Class.js' + * * Note that the deeper namespace levels, if explicitly set, are always resolved first. For example: - - Ext.Loader.setPath({ - 'My': '/path/to/lib', - 'My.awesome': '/other/path/for/awesome/stuff', - 'My.awesome.more': '/more/awesome/path' - }); - - alert(Ext.Loader.getPath('My.awesome.Class')); // alerts '/other/path/for/awesome/stuff/Class.js' - - alert(Ext.Loader.getPath('My.awesome.more.Class')); // alerts '/more/awesome/path/Class.js' - - alert(Ext.Loader.getPath('My.cool.Class')); // alerts '/path/to/lib/cool/Class.js' - - alert(Ext.Loader.getPath('Unknown.strange.Stuff')); // alerts 'Unknown/strange/Stuff.js' - + * + * Ext.Loader.setPath({ + * 'My': '/path/to/lib', + * 'My.awesome': '/other/path/for/awesome/stuff', + * 'My.awesome.more': '/more/awesome/path' + * }); + * + * alert(Ext.Loader.getPath('My.awesome.Class')); // alerts '/other/path/for/awesome/stuff/Class.js' + * + * alert(Ext.Loader.getPath('My.awesome.more.Class')); // alerts '/more/awesome/path/Class.js' + * + * alert(Ext.Loader.getPath('My.cool.Class')); // alerts '/path/to/lib/cool/Class.js' + * + * alert(Ext.Loader.getPath('Unknown.strange.Stuff')); // alerts 'Unknown/strange/Stuff.js' + * * @param {String} className * @return {String} path - * @markdown */ getPath: function(className) { var path = '', @@ -443,7 +452,7 @@ This process will be automated with Sencha Command, to be released and documente do { if (Manager.isCreated(requires[j])) { // Take out from the queue - requires.splice(j, 1); + Ext.Array.erase(requires, j, 1); } else { j++; @@ -451,7 +460,7 @@ This process will be automated with Sencha Command, to be released and documente } while (j < requires.length); if (item.requires.length === 0) { - this.queue.splice(i, 1); + Ext.Array.erase(this.queue, i, 1); item.callback.call(item.scope); this.refreshQueue(); break; @@ -509,7 +518,7 @@ This process will be automated with Sencha Command, to be released and documente * * @param {String} url * @param {Function} onLoad - * @param {Scope} scope + * @param {Object} scope * @param {Boolean} synchronous * @private */ @@ -591,15 +600,16 @@ This process will be automated with Sencha Command, to be released and documente /** * Explicitly exclude files from being loaded. Useful when used in conjunction with a broad include expression. - * Can be chained with more `require` and `exclude` methods, eg: - - Ext.exclude('Ext.data.*').require('*'); - - Ext.exclude('widget.button*').require('widget.*'); - - * @param {Array} excludes + * Can be chained with more `require` and `exclude` methods, e.g.: + * + * Ext.exclude('Ext.data.*').require('*'); + * + * Ext.exclude('widget.button*').require('widget.*'); + * + * {@link Ext#exclude Ext.exclude} is alias for {@link Ext.Loader#exclude Ext.Loader.exclude} for convenience. + * + * @param {String/String[]} excludes * @return {Object} object contains `require` method for chaining - * @markdown */ exclude: function(excludes) { var me = this; @@ -616,12 +626,15 @@ This process will be automated with Sencha Command, to be released and documente }, /** - * Synchronously loads all classes by the given names and all their direct dependencies; optionally executes the given callback function when finishes, within the optional scope. This method is aliased by {@link Ext#syncRequire} for convenience - * @param {String/Array} expressions Can either be a string or an array of string + * Synchronously loads all classes by the given names and all their direct dependencies; + * optionally executes the given callback function when finishes, within the optional scope. + * + * {@link Ext#syncRequire Ext.syncRequire} is alias for {@link Ext.Loader#syncRequire Ext.Loader.syncRequire} for convenience. + * + * @param {String/String[]} expressions Can either be a string or an array of string * @param {Function} fn (Optional) The callback function * @param {Object} scope (Optional) The execution scope (`this`) of the callback function - * @param {String/Array} excludes (Optional) Classes to be excluded, useful when being used with expressions - * @markdown + * @param {String/String[]} excludes (Optional) Classes to be excluded, useful when being used with expressions */ syncRequire: function() { this.syncModeEnabled = true; @@ -631,13 +644,15 @@ This process will be automated with Sencha Command, to be released and documente }, /** - * Loads all classes by the given names and all their direct dependencies; optionally executes the given callback function when - * finishes, within the optional scope. This method is aliased by {@link Ext#require Ext.require} for convenience - * @param {String/Array} expressions Can either be a string or an array of string + * Loads all classes by the given names and all their direct dependencies; + * optionally executes the given callback function when finishes, within the optional scope. + * + * {@link Ext#require Ext.require} is alias for {@link Ext.Loader#require Ext.Loader.require} for convenience. + * + * @param {String/String[]} expressions Can either be a string or an array of string * @param {Function} fn (Optional) The callback function * @param {Object} scope (Optional) The execution scope (`this`) of the callback function - * @param {String/Array} excludes (Optional) Classes to be excluded, useful when being used with expressions - * @markdown + * @param {String/String[]} excludes (Optional) Classes to be excluded, useful when being used with expressions */ require: function(expressions, fn, scope, excludes) { var filePath, expression, exclude, className, excluded = {}, @@ -899,10 +914,10 @@ This process will be automated with Sencha Command, to be released and documente }, /** - * Add a new listener to be executed when all required scripts are fully loaded + * Adds new listener to be executed when all required scripts are fully loaded. * * @param {Function} fn The function callback to be executed - * @param {Object} scope The execution scope (<code>this</code>) of the callback function + * @param {Object} scope The execution scope (`this`) of the callback function * @param {Boolean} withDomReady Whether or not to wait for document dom ready as well */ onReady: function(fn, scope, withDomReady, options) { @@ -941,36 +956,49 @@ This process will be automated with Sencha Command, to be released and documente }; /** - * Convenient alias of {@link Ext.Loader#require}. Please see the introduction documentation of - * {@link Ext.Loader} for examples. - * @member Ext + * @member Ext * @method require + * @alias Ext.Loader#require */ Ext.require = alias(Loader, 'require'); /** - * Synchronous version of {@link Ext#require}, convenient alias of {@link Ext.Loader#syncRequire}. - * - * @member Ext + * @member Ext * @method syncRequire + * @alias Ext.Loader#syncRequire */ Ext.syncRequire = alias(Loader, 'syncRequire'); /** - * Convenient shortcut to {@link Ext.Loader#exclude} - * @member Ext + * @member Ext * @method exclude + * @alias Ext.Loader#exclude */ Ext.exclude = alias(Loader, 'exclude'); /** * @member Ext * @method onReady + * @alias Ext.Loader#onReady */ Ext.onReady = function(fn, scope, options) { Loader.onReady(fn, scope, true, options); }; + /** + * @cfg {String[]} requires + * @member Ext.Class + * List of classes that have to be loaded before instantiating this class. + * For example: + * + * Ext.define('Mother', { + * requires: ['Child'], + * giveBirth: function() { + * // we can be sure that child class is available. + * return new Child(); + * } + * }); + */ Class.registerPreprocessor('loader', function(cls, data, continueFn) { var me = this, dependencies = [], @@ -1015,7 +1043,7 @@ This process will be automated with Sencha Command, to be released and documente } } } - else { + else if (typeof propertyValue != 'function') { for (j in propertyValue) { if (propertyValue.hasOwnProperty(j)) { value = propertyValue[j]; @@ -1096,7 +1124,7 @@ This process will be automated with Sencha Command, to be released and documente } } } - else { + else if (typeof propertyValue != 'function') { for (var k in propertyValue) { if (propertyValue.hasOwnProperty(k)) { value = propertyValue[k]; @@ -1118,6 +1146,23 @@ This process will be automated with Sencha Command, to be released and documente Class.setDefaultPreprocessorPosition('loader', 'after', 'className'); + /** + * @cfg {String[]} uses + * @member Ext.Class + * List of classes to load together with this class. These aren't neccessarily loaded before + * this class is instantiated. For example: + * + * Ext.define('Mother', { + * uses: ['Child'], + * giveBirth: function() { + * // This code might, or might not work: + * // return new Child(); + * + * // Instead use Ext.create() to load the class at the spot if not loaded already: + * return Ext.create('Child'); + * } + * }); + */ Manager.registerPostprocessor('uses', function(name, cls, data) { var uses = Ext.Array.from(data.uses), items = [], @@ -1137,4 +1182,6 @@ This process will be automated with Sencha Command, to be released and documente Manager.setDefaultPostprocessorPosition('uses', 'last'); })(Ext.ClassManager, Ext.Class, Ext.Function.flexSetter, Ext.Function.alias); -