src/cm/media/js/lib/yui/yui_3.10.3/build/loader-base/loader-base-debug.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     3 Copyright 2013 Yahoo! Inc. All rights reserved.
       
     4 Licensed under the BSD License.
       
     5 http://yuilibrary.com/license/
       
     6 */
       
     7 
       
     8 YUI.add('loader-base', function (Y, NAME) {
       
     9 
       
    10 /**
       
    11  * The YUI loader core
       
    12  * @module loader
       
    13  * @submodule loader-base
       
    14  */
       
    15 
       
    16 if (!YUI.Env[Y.version]) {
       
    17 
       
    18     (function() {
       
    19         var VERSION = Y.version,
       
    20             BUILD = '/build/',
       
    21             ROOT = VERSION + '/',
       
    22             CDN_BASE = Y.Env.base,
       
    23             GALLERY_VERSION = 'gallery-2013.06.05-22-14',
       
    24             TNT = '2in3',
       
    25             TNT_VERSION = '4',
       
    26             YUI2_VERSION = '2.9.0',
       
    27             COMBO_BASE = CDN_BASE + 'combo?',
       
    28             META = { version: VERSION,
       
    29                               root: ROOT,
       
    30                               base: Y.Env.base,
       
    31                               comboBase: COMBO_BASE,
       
    32                               skin: { defaultSkin: 'sam',
       
    33                                            base: 'assets/skins/',
       
    34                                            path: 'skin.css',
       
    35                                            after: ['cssreset',
       
    36                                                           'cssfonts',
       
    37                                                           'cssgrids',
       
    38                                                           'cssbase',
       
    39                                                           'cssreset-context',
       
    40                                                           'cssfonts-context']},
       
    41                               groups: {},
       
    42                               patterns: {} },
       
    43             groups = META.groups,
       
    44             yui2Update = function(tnt, yui2, config) {
       
    45 
       
    46                 var root = TNT + '.' +
       
    47                         (tnt || TNT_VERSION) + '/' +
       
    48                         (yui2 || YUI2_VERSION) + BUILD,
       
    49                     base = (config && config.base) ? config.base : CDN_BASE,
       
    50                     combo = (config && config.comboBase) ? config.comboBase : COMBO_BASE;
       
    51 
       
    52                 groups.yui2.base = base + root;
       
    53                 groups.yui2.root = root;
       
    54                 groups.yui2.comboBase = combo;
       
    55             },
       
    56             galleryUpdate = function(tag, config) {
       
    57                 var root = (tag || GALLERY_VERSION) + BUILD,
       
    58                     base = (config && config.base) ? config.base : CDN_BASE,
       
    59                     combo = (config && config.comboBase) ? config.comboBase : COMBO_BASE;
       
    60 
       
    61                 groups.gallery.base = base + root;
       
    62                 groups.gallery.root = root;
       
    63                 groups.gallery.comboBase = combo;
       
    64             };
       
    65 
       
    66 
       
    67         groups[VERSION] = {};
       
    68 
       
    69         groups.gallery = {
       
    70             ext: false,
       
    71             combine: true,
       
    72             comboBase: COMBO_BASE,
       
    73             update: galleryUpdate,
       
    74             patterns: { 'gallery-': { },
       
    75                         'lang/gallery-': {},
       
    76                         'gallerycss-': { type: 'css' } }
       
    77         };
       
    78 
       
    79         groups.yui2 = {
       
    80             combine: true,
       
    81             ext: false,
       
    82             comboBase: COMBO_BASE,
       
    83             update: yui2Update,
       
    84             patterns: {
       
    85                 'yui2-': {
       
    86                     configFn: function(me) {
       
    87                         if (/-skin|reset|fonts|grids|base/.test(me.name)) {
       
    88                             me.type = 'css';
       
    89                             me.path = me.path.replace(/\.js/, '.css');
       
    90                             // this makes skins in builds earlier than
       
    91                             // 2.6.0 work as long as combine is false
       
    92                             me.path = me.path.replace(/\/yui2-skin/,
       
    93                                              '/assets/skins/sam/yui2-skin');
       
    94                         }
       
    95                     }
       
    96                 }
       
    97             }
       
    98         };
       
    99 
       
   100         galleryUpdate();
       
   101         yui2Update();
       
   102 
       
   103         YUI.Env[VERSION] = META;
       
   104     }());
       
   105 }
       
   106 
       
   107 
       
   108 /*jslint forin: true, maxlen: 350 */
       
   109 
       
   110 /**
       
   111  * Loader dynamically loads script and css files.  It includes the dependency
       
   112  * information for the version of the library in use, and will automatically pull in
       
   113  * dependencies for the modules requested. It can also load the
       
   114  * files from the Yahoo! CDN, and it can utilize the combo service provided on
       
   115  * this network to reduce the number of http connections required to download
       
   116  * YUI files.
       
   117  *
       
   118  * @module loader
       
   119  * @main loader
       
   120  * @submodule loader-base
       
   121  */
       
   122 
       
   123 var NOT_FOUND = {},
       
   124     NO_REQUIREMENTS = [],
       
   125     MAX_URL_LENGTH = 1024,
       
   126     GLOBAL_ENV = YUI.Env,
       
   127     GLOBAL_LOADED = GLOBAL_ENV._loaded,
       
   128     CSS = 'css',
       
   129     JS = 'js',
       
   130     INTL = 'intl',
       
   131     DEFAULT_SKIN = 'sam',
       
   132     VERSION = Y.version,
       
   133     ROOT_LANG = '',
       
   134     YObject = Y.Object,
       
   135     oeach = YObject.each,
       
   136     yArray = Y.Array,
       
   137     _queue = GLOBAL_ENV._loaderQueue,
       
   138     META = GLOBAL_ENV[VERSION],
       
   139     SKIN_PREFIX = 'skin-',
       
   140     L = Y.Lang,
       
   141     ON_PAGE = GLOBAL_ENV.mods,
       
   142     modulekey,
       
   143     _path = function(dir, file, type, nomin) {
       
   144         var path = dir + '/' + file;
       
   145         if (!nomin) {
       
   146             path += '-min';
       
   147         }
       
   148         path += '.' + (type || CSS);
       
   149 
       
   150         return path;
       
   151     };
       
   152 
       
   153 
       
   154     if (!YUI.Env._cssLoaded) {
       
   155         YUI.Env._cssLoaded = {};
       
   156     }
       
   157 
       
   158 
       
   159 /**
       
   160  * The component metadata is stored in Y.Env.meta.
       
   161  * Part of the loader module.
       
   162  * @property meta
       
   163  * @for YUI
       
   164  */
       
   165 Y.Env.meta = META;
       
   166 
       
   167 /**
       
   168  * Loader dynamically loads script and css files.  It includes the dependency
       
   169  * info for the version of the library in use, and will automatically pull in
       
   170  * dependencies for the modules requested. It can load the
       
   171  * files from the Yahoo! CDN, and it can utilize the combo service provided on
       
   172  * this network to reduce the number of http connections required to download
       
   173  * YUI files. You can also specify an external, custom combo service to host
       
   174  * your modules as well.
       
   175 
       
   176         var Y = YUI();
       
   177         var loader = new Y.Loader({
       
   178             filter: 'debug',
       
   179             base: '../../',
       
   180             root: 'build/',
       
   181             combine: true,
       
   182             require: ['node', 'dd', 'console']
       
   183         });
       
   184         var out = loader.resolve(true);
       
   185 
       
   186  * @constructor
       
   187  * @class Loader
       
   188  * @param {Object} config an optional set of configuration options.
       
   189  * @param {String} config.base The base dir which to fetch this module from
       
   190  * @param {String} config.comboBase The Combo service base path. Ex: `http://yui.yahooapis.com/combo?`
       
   191  * @param {String} config.root The root path to prepend to module names for the combo service. Ex: `2.5.2/build/`
       
   192  * @param {String|Object} config.filter A filter to apply to result urls. <a href="#property_filter">See filter property</a>
       
   193  * @param {Object} config.filters Per-component filter specification.  If specified for a given component, this overrides the filter config.
       
   194  * @param {Boolean} config.combine Use a combo service to reduce the number of http connections required to load your dependencies
       
   195  * @param {Boolean} [config.async=true] Fetch files in async
       
   196  * @param {Array} config.ignore: A list of modules that should never be dynamically loaded
       
   197  * @param {Array} config.force A list of modules that should always be loaded when required, even if already present on the page
       
   198  * @param {HTMLElement|String} config.insertBefore Node or id for a node that should be used as the insertion point for new nodes
       
   199  * @param {Object} config.jsAttributes Object literal containing attributes to add to script nodes
       
   200  * @param {Object} config.cssAttributes Object literal containing attributes to add to link nodes
       
   201  * @param {Number} config.timeout The number of milliseconds before a timeout occurs when dynamically loading nodes.  If not set, there is no timeout
       
   202  * @param {Object} config.context Execution context for all callbacks
       
   203  * @param {Function} config.onSuccess Callback for the 'success' event
       
   204  * @param {Function} config.onFailure Callback for the 'failure' event
       
   205  * @param {Function} config.onCSS Callback for the 'CSSComplete' event.  When loading YUI components with CSS the CSS is loaded first, then the script.  This provides a moment you can tie into to improve the presentation of the page while the script is loading.
       
   206  * @param {Function} config.onTimeout Callback for the 'timeout' event
       
   207  * @param {Function} config.onProgress Callback executed each time a script or css file is loaded
       
   208  * @param {Object} config.modules A list of module definitions.  See <a href="#method_addModule">Loader.addModule</a> for the supported module metadata
       
   209  * @param {Object} config.groups A list of group definitions.  Each group can contain specific definitions for `base`, `comboBase`, `combine`, and accepts a list of `modules`.
       
   210  * @param {String} config.2in3 The version of the YUI 2 in 3 wrapper to use.  The intrinsic support for YUI 2 modules in YUI 3 relies on versions of the YUI 2 components inside YUI 3 module wrappers.  These wrappers change over time to accomodate the issues that arise from running YUI 2 in a YUI 3 sandbox.
       
   211  * @param {String} config.yui2 When using the 2in3 project, you can select the version of YUI 2 to use.  Valid values are `2.2.2`, `2.3.1`, `2.4.1`, `2.5.2`, `2.6.0`, `2.7.0`, `2.8.0`, `2.8.1` and `2.9.0` [default] -- plus all versions of YUI 2 going forward.
       
   212  */
       
   213 Y.Loader = function(o) {
       
   214 
       
   215     var self = this;
       
   216 
       
   217     //Catch no config passed.
       
   218     o = o || {};
       
   219 
       
   220     modulekey = META.md5;
       
   221 
       
   222     /**
       
   223      * Internal callback to handle multiple internal insert() calls
       
   224      * so that css is inserted prior to js
       
   225      * @property _internalCallback
       
   226      * @private
       
   227      */
       
   228     // self._internalCallback = null;
       
   229 
       
   230     /**
       
   231      * Callback that will be executed when the loader is finished
       
   232      * with an insert
       
   233      * @method onSuccess
       
   234      * @type function
       
   235      */
       
   236     // self.onSuccess = null;
       
   237 
       
   238     /**
       
   239      * Callback that will be executed if there is a failure
       
   240      * @method onFailure
       
   241      * @type function
       
   242      */
       
   243     // self.onFailure = null;
       
   244 
       
   245     /**
       
   246      * Callback for the 'CSSComplete' event.  When loading YUI components
       
   247      * with CSS the CSS is loaded first, then the script.  This provides
       
   248      * a moment you can tie into to improve the presentation of the page
       
   249      * while the script is loading.
       
   250      * @method onCSS
       
   251      * @type function
       
   252      */
       
   253     // self.onCSS = null;
       
   254 
       
   255     /**
       
   256      * Callback executed each time a script or css file is loaded
       
   257      * @method onProgress
       
   258      * @type function
       
   259      */
       
   260     // self.onProgress = null;
       
   261 
       
   262     /**
       
   263      * Callback that will be executed if a timeout occurs
       
   264      * @method onTimeout
       
   265      * @type function
       
   266      */
       
   267     // self.onTimeout = null;
       
   268 
       
   269     /**
       
   270      * The execution context for all callbacks
       
   271      * @property context
       
   272      * @default {YUI} the YUI instance
       
   273      */
       
   274     self.context = Y;
       
   275 
       
   276     /**
       
   277      * Data that is passed to all callbacks
       
   278      * @property data
       
   279      */
       
   280     // self.data = null;
       
   281 
       
   282     /**
       
   283      * Node reference or id where new nodes should be inserted before
       
   284      * @property insertBefore
       
   285      * @type string|HTMLElement
       
   286      */
       
   287     // self.insertBefore = null;
       
   288 
       
   289     /**
       
   290      * The charset attribute for inserted nodes
       
   291      * @property charset
       
   292      * @type string
       
   293      * @deprecated , use cssAttributes or jsAttributes.
       
   294      */
       
   295     // self.charset = null;
       
   296 
       
   297     /**
       
   298      * An object literal containing attributes to add to link nodes
       
   299      * @property cssAttributes
       
   300      * @type object
       
   301      */
       
   302     // self.cssAttributes = null;
       
   303 
       
   304     /**
       
   305      * An object literal containing attributes to add to script nodes
       
   306      * @property jsAttributes
       
   307      * @type object
       
   308      */
       
   309     // self.jsAttributes = null;
       
   310 
       
   311     /**
       
   312      * The base directory.
       
   313      * @property base
       
   314      * @type string
       
   315      * @default http://yui.yahooapis.com/[YUI VERSION]/build/
       
   316      */
       
   317     self.base = Y.Env.meta.base + Y.Env.meta.root;
       
   318 
       
   319     /**
       
   320      * Base path for the combo service
       
   321      * @property comboBase
       
   322      * @type string
       
   323      * @default http://yui.yahooapis.com/combo?
       
   324      */
       
   325     self.comboBase = Y.Env.meta.comboBase;
       
   326 
       
   327     /*
       
   328      * Base path for language packs.
       
   329      */
       
   330     // self.langBase = Y.Env.meta.langBase;
       
   331     // self.lang = "";
       
   332 
       
   333     /**
       
   334      * If configured, the loader will attempt to use the combo
       
   335      * service for YUI resources and configured external resources.
       
   336      * @property combine
       
   337      * @type boolean
       
   338      * @default true if a base dir isn't in the config
       
   339      */
       
   340     self.combine = o.base &&
       
   341         (o.base.indexOf(self.comboBase.substr(0, 20)) > -1);
       
   342 
       
   343     /**
       
   344     * The default seperator to use between files in a combo URL
       
   345     * @property comboSep
       
   346     * @type {String}
       
   347     * @default Ampersand
       
   348     */
       
   349     self.comboSep = '&';
       
   350     /**
       
   351      * Max url length for combo urls.  The default is 1024. This is the URL
       
   352      * limit for the Yahoo! hosted combo servers.  If consuming
       
   353      * a different combo service that has a different URL limit
       
   354      * it is possible to override this default by supplying
       
   355      * the maxURLLength config option.  The config option will
       
   356      * only take effect if lower than the default.
       
   357      *
       
   358      * @property maxURLLength
       
   359      * @type int
       
   360      */
       
   361     self.maxURLLength = MAX_URL_LENGTH;
       
   362 
       
   363     /**
       
   364      * Ignore modules registered on the YUI global
       
   365      * @property ignoreRegistered
       
   366      * @default false
       
   367      */
       
   368     self.ignoreRegistered = o.ignoreRegistered;
       
   369 
       
   370     /**
       
   371      * Root path to prepend to module path for the combo
       
   372      * service
       
   373      * @property root
       
   374      * @type string
       
   375      * @default [YUI VERSION]/build/
       
   376      */
       
   377     self.root = Y.Env.meta.root;
       
   378 
       
   379     /**
       
   380      * Timeout value in milliseconds.  If set, self value will be used by
       
   381      * the get utility.  the timeout event will fire if
       
   382      * a timeout occurs.
       
   383      * @property timeout
       
   384      * @type int
       
   385      */
       
   386     self.timeout = 0;
       
   387 
       
   388     /**
       
   389      * A list of modules that should not be loaded, even if
       
   390      * they turn up in the dependency tree
       
   391      * @property ignore
       
   392      * @type string[]
       
   393      */
       
   394     // self.ignore = null;
       
   395 
       
   396     /**
       
   397      * A list of modules that should always be loaded, even
       
   398      * if they have already been inserted into the page.
       
   399      * @property force
       
   400      * @type string[]
       
   401      */
       
   402     // self.force = null;
       
   403 
       
   404     self.forceMap = {};
       
   405 
       
   406     /**
       
   407      * Should we allow rollups
       
   408      * @property allowRollup
       
   409      * @type boolean
       
   410      * @default false
       
   411      */
       
   412     self.allowRollup = false;
       
   413 
       
   414     /**
       
   415      * A filter to apply to result urls.  This filter will modify the default
       
   416      * path for all modules.  The default path for the YUI library is the
       
   417      * minified version of the files (e.g., event-min.js).  The filter property
       
   418      * can be a predefined filter or a custom filter.  The valid predefined
       
   419      * filters are:
       
   420      * <dl>
       
   421      *  <dt>DEBUG</dt>
       
   422      *  <dd>Selects the debug versions of the library (e.g., event-debug.js).
       
   423      *      This option will automatically include the Logger widget</dd>
       
   424      *  <dt>RAW</dt>
       
   425      *  <dd>Selects the non-minified version of the library (e.g., event.js).
       
   426      *  </dd>
       
   427      * </dl>
       
   428      * You can also define a custom filter, which must be an object literal
       
   429      * containing a search expression and a replace string:
       
   430      *
       
   431      *      myFilter: {
       
   432      *          'searchExp': "-min\\.js",
       
   433      *          'replaceStr': "-debug.js"
       
   434      *      }
       
   435      *
       
   436      * @property filter
       
   437      * @type string| {searchExp: string, replaceStr: string}
       
   438      */
       
   439     // self.filter = null;
       
   440 
       
   441     /**
       
   442      * per-component filter specification.  If specified for a given
       
   443      * component, this overrides the filter config.
       
   444      * @property filters
       
   445      * @type object
       
   446      */
       
   447     self.filters = {};
       
   448 
       
   449     /**
       
   450      * The list of requested modules
       
   451      * @property required
       
   452      * @type {string: boolean}
       
   453      */
       
   454     self.required = {};
       
   455 
       
   456     /**
       
   457      * If a module name is predefined when requested, it is checked againsts
       
   458      * the patterns provided in this property.  If there is a match, the
       
   459      * module is added with the default configuration.
       
   460      *
       
   461      * At the moment only supporting module prefixes, but anticipate
       
   462      * supporting at least regular expressions.
       
   463      * @property patterns
       
   464      * @type Object
       
   465      */
       
   466     // self.patterns = Y.merge(Y.Env.meta.patterns);
       
   467     self.patterns = {};
       
   468 
       
   469     /**
       
   470      * The library metadata
       
   471      * @property moduleInfo
       
   472      */
       
   473     // self.moduleInfo = Y.merge(Y.Env.meta.moduleInfo);
       
   474     self.moduleInfo = {};
       
   475 
       
   476     self.groups = Y.merge(Y.Env.meta.groups);
       
   477 
       
   478     /**
       
   479      * Provides the information used to skin the skinnable components.
       
   480      * The following skin definition would result in 'skin1' and 'skin2'
       
   481      * being loaded for calendar (if calendar was requested), and
       
   482      * 'sam' for all other skinnable components:
       
   483      *
       
   484      *      skin: {
       
   485      *          // The default skin, which is automatically applied if not
       
   486      *          // overriden by a component-specific skin definition.
       
   487      *          // Change this in to apply a different skin globally
       
   488      *          defaultSkin: 'sam',
       
   489      *
       
   490      *          // This is combined with the loader base property to get
       
   491      *          // the default root directory for a skin. ex:
       
   492      *          // http://yui.yahooapis.com/2.3.0/build/assets/skins/sam/
       
   493      *          base: 'assets/skins/',
       
   494      *
       
   495      *          // Any component-specific overrides can be specified here,
       
   496      *          // making it possible to load different skins for different
       
   497      *          // components.  It is possible to load more than one skin
       
   498      *          // for a given component as well.
       
   499      *          overrides: {
       
   500      *              calendar: ['skin1', 'skin2']
       
   501      *          }
       
   502      *      }
       
   503      * @property skin
       
   504      * @type {Object}
       
   505      */
       
   506     self.skin = Y.merge(Y.Env.meta.skin);
       
   507 
       
   508     /*
       
   509      * Map of conditional modules
       
   510      * @since 3.2.0
       
   511      */
       
   512     self.conditions = {};
       
   513 
       
   514     // map of modules with a hash of modules that meet the requirement
       
   515     // self.provides = {};
       
   516 
       
   517     self.config = o;
       
   518     self._internal = true;
       
   519 
       
   520     self._populateCache();
       
   521 
       
   522     /**
       
   523      * Set when beginning to compute the dependency tree.
       
   524      * Composed of what YUI reports to be loaded combined
       
   525      * with what has been loaded by any instance on the page
       
   526      * with the version number specified in the metadata.
       
   527      * @property loaded
       
   528      * @type {string: boolean}
       
   529      */
       
   530     self.loaded = GLOBAL_LOADED[VERSION];
       
   531 
       
   532 
       
   533     /**
       
   534     * Should Loader fetch scripts in `async`, defaults to `true`
       
   535     * @property async
       
   536     */
       
   537 
       
   538     self.async = true;
       
   539 
       
   540     self._inspectPage();
       
   541 
       
   542     self._internal = false;
       
   543 
       
   544     self._config(o);
       
   545 
       
   546     self.forceMap = (self.force) ? Y.Array.hash(self.force) : {};
       
   547 
       
   548     self.testresults = null;
       
   549 
       
   550     if (Y.config.tests) {
       
   551         self.testresults = Y.config.tests;
       
   552     }
       
   553 
       
   554     /**
       
   555      * List of rollup files found in the library metadata
       
   556      * @property rollups
       
   557      */
       
   558     // self.rollups = null;
       
   559 
       
   560     /**
       
   561      * Whether or not to load optional dependencies for
       
   562      * the requested modules
       
   563      * @property loadOptional
       
   564      * @type boolean
       
   565      * @default false
       
   566      */
       
   567     // self.loadOptional = false;
       
   568 
       
   569     /**
       
   570      * All of the derived dependencies in sorted order, which
       
   571      * will be populated when either calculate() or insert()
       
   572      * is called
       
   573      * @property sorted
       
   574      * @type string[]
       
   575      */
       
   576     self.sorted = [];
       
   577 
       
   578     /*
       
   579      * A list of modules to attach to the YUI instance when complete.
       
   580      * If not supplied, the sorted list of dependencies are applied.
       
   581      * @property attaching
       
   582      */
       
   583     // self.attaching = null;
       
   584 
       
   585     /**
       
   586      * Flag to indicate the dependency tree needs to be recomputed
       
   587      * if insert is called again.
       
   588      * @property dirty
       
   589      * @type boolean
       
   590      * @default true
       
   591      */
       
   592     self.dirty = true;
       
   593 
       
   594     /**
       
   595      * List of modules inserted by the utility
       
   596      * @property inserted
       
   597      * @type {string: boolean}
       
   598      */
       
   599     self.inserted = {};
       
   600 
       
   601     /**
       
   602      * List of skipped modules during insert() because the module
       
   603      * was not defined
       
   604      * @property skipped
       
   605      */
       
   606     self.skipped = {};
       
   607 
       
   608     // Y.on('yui:load', self.loadNext, self);
       
   609 
       
   610     self.tested = {};
       
   611 
       
   612     /*
       
   613      * Cached sorted calculate results
       
   614      * @property results
       
   615      * @since 3.2.0
       
   616      */
       
   617     //self.results = {};
       
   618 
       
   619     if (self.ignoreRegistered) {
       
   620         //Clear inpage already processed modules.
       
   621         self._resetModules();
       
   622     }
       
   623 
       
   624 };
       
   625 
       
   626 Y.Loader.prototype = {
       
   627     /**
       
   628     * Checks the cache for modules and conditions, if they do not exist
       
   629     * process the default metadata and populate the local moduleInfo hash.
       
   630     * @method _populateCache
       
   631     * @private
       
   632     */
       
   633     _populateCache: function() {
       
   634         var self = this,
       
   635             defaults = META.modules,
       
   636             cache = GLOBAL_ENV._renderedMods,
       
   637             i;
       
   638 
       
   639         if (cache && !self.ignoreRegistered) {
       
   640             for (i in cache) {
       
   641                 if (cache.hasOwnProperty(i)) {
       
   642                     self.moduleInfo[i] = Y.merge(cache[i]);
       
   643                 }
       
   644             }
       
   645 
       
   646             cache = GLOBAL_ENV._conditions;
       
   647             for (i in cache) {
       
   648                 if (cache.hasOwnProperty(i)) {
       
   649                     self.conditions[i] = Y.merge(cache[i]);
       
   650                 }
       
   651             }
       
   652 
       
   653         } else {
       
   654             for (i in defaults) {
       
   655                 if (defaults.hasOwnProperty(i)) {
       
   656                     self.addModule(defaults[i], i);
       
   657                 }
       
   658             }
       
   659         }
       
   660 
       
   661     },
       
   662     /**
       
   663     * Reset modules in the module cache to a pre-processed state so additional
       
   664     * computations with a different skin or language will work as expected.
       
   665     * @method _resetModules
       
   666     * @private
       
   667     */
       
   668     _resetModules: function() {
       
   669         var self = this, i, o,
       
   670             mod, name, details;
       
   671         for (i in self.moduleInfo) {
       
   672             if (self.moduleInfo.hasOwnProperty(i)) {
       
   673                 mod = self.moduleInfo[i];
       
   674                 name = mod.name;
       
   675                 details  = (YUI.Env.mods[name] ? YUI.Env.mods[name].details : null);
       
   676 
       
   677                 if (details) {
       
   678                     self.moduleInfo[name]._reset = true;
       
   679                     self.moduleInfo[name].requires = details.requires || [];
       
   680                     self.moduleInfo[name].optional = details.optional || [];
       
   681                     self.moduleInfo[name].supersedes = details.supercedes || [];
       
   682                 }
       
   683 
       
   684                 if (mod.defaults) {
       
   685                     for (o in mod.defaults) {
       
   686                         if (mod.defaults.hasOwnProperty(o)) {
       
   687                             if (mod[o]) {
       
   688                                 mod[o] = mod.defaults[o];
       
   689                             }
       
   690                         }
       
   691                     }
       
   692                 }
       
   693                 delete mod.langCache;
       
   694                 delete mod.skinCache;
       
   695                 if (mod.skinnable) {
       
   696                     self._addSkin(self.skin.defaultSkin, mod.name);
       
   697                 }
       
   698             }
       
   699         }
       
   700     },
       
   701     /**
       
   702     Regex that matches a CSS URL. Used to guess the file type when it's not
       
   703     specified.
       
   704 
       
   705     @property REGEX_CSS
       
   706     @type RegExp
       
   707     @final
       
   708     @protected
       
   709     @since 3.5.0
       
   710     **/
       
   711     REGEX_CSS: /\.css(?:[?;].*)?$/i,
       
   712 
       
   713     /**
       
   714     * Default filters for raw and debug
       
   715     * @property FILTER_DEFS
       
   716     * @type Object
       
   717     * @final
       
   718     * @protected
       
   719     */
       
   720     FILTER_DEFS: {
       
   721         RAW: {
       
   722             'searchExp': '-min\\.js',
       
   723             'replaceStr': '.js'
       
   724         },
       
   725         DEBUG: {
       
   726             'searchExp': '-min\\.js',
       
   727             'replaceStr': '-debug.js'
       
   728         },
       
   729         COVERAGE: {
       
   730             'searchExp': '-min\\.js',
       
   731             'replaceStr': '-coverage.js'
       
   732         }
       
   733     },
       
   734     /*
       
   735     * Check the pages meta-data and cache the result.
       
   736     * @method _inspectPage
       
   737     * @private
       
   738     */
       
   739     _inspectPage: function() {
       
   740         var self = this, v, m, req, mr, i;
       
   741 
       
   742         //Inspect the page for CSS only modules and mark them as loaded.
       
   743         for (i in self.moduleInfo) {
       
   744             if (self.moduleInfo.hasOwnProperty(i)) {
       
   745                 v = self.moduleInfo[i];
       
   746                 if (v.type && v.type === CSS) {
       
   747                     if (self.isCSSLoaded(v.name)) {
       
   748                         Y.log('Found CSS module on page: ' + v.name, 'info', 'loader');
       
   749                         self.loaded[i] = true;
       
   750                     }
       
   751                 }
       
   752             }
       
   753         }
       
   754         for (i in ON_PAGE) {
       
   755             if (ON_PAGE.hasOwnProperty(i)) {
       
   756                 v = ON_PAGE[i];
       
   757                 if (v.details) {
       
   758                     m = self.moduleInfo[v.name];
       
   759                     req = v.details.requires;
       
   760                     mr = m && m.requires;
       
   761 
       
   762                    if (m) {
       
   763                        if (!m._inspected && req && mr.length !== req.length) {
       
   764                            // console.log('deleting ' + m.name);
       
   765                            delete m.expanded;
       
   766                        }
       
   767                    } else {
       
   768                        m = self.addModule(v.details, i);
       
   769                    }
       
   770                    m._inspected = true;
       
   771                }
       
   772             }
       
   773         }
       
   774     },
       
   775     /*
       
   776     * returns true if b is not loaded, and is required directly or by means of modules it supersedes.
       
   777     * @private
       
   778     * @method _requires
       
   779     * @param {String} mod1 The first module to compare
       
   780     * @param {String} mod2 The second module to compare
       
   781     */
       
   782    _requires: function(mod1, mod2) {
       
   783 
       
   784         var i, rm, after_map, s,
       
   785             info = this.moduleInfo,
       
   786             m = info[mod1],
       
   787             other = info[mod2];
       
   788 
       
   789         if (!m || !other) {
       
   790             return false;
       
   791         }
       
   792 
       
   793         rm = m.expanded_map;
       
   794         after_map = m.after_map;
       
   795 
       
   796         // check if this module should be sorted after the other
       
   797         // do this first to short circut circular deps
       
   798         if (after_map && (mod2 in after_map)) {
       
   799             return true;
       
   800         }
       
   801 
       
   802         after_map = other.after_map;
       
   803 
       
   804         // and vis-versa
       
   805         if (after_map && (mod1 in after_map)) {
       
   806             return false;
       
   807         }
       
   808 
       
   809         // check if this module requires one the other supersedes
       
   810         s = info[mod2] && info[mod2].supersedes;
       
   811         if (s) {
       
   812             for (i = 0; i < s.length; i++) {
       
   813                 if (this._requires(mod1, s[i])) {
       
   814                     return true;
       
   815                 }
       
   816             }
       
   817         }
       
   818 
       
   819         s = info[mod1] && info[mod1].supersedes;
       
   820         if (s) {
       
   821             for (i = 0; i < s.length; i++) {
       
   822                 if (this._requires(mod2, s[i])) {
       
   823                     return false;
       
   824                 }
       
   825             }
       
   826         }
       
   827 
       
   828         // check if this module requires the other directly
       
   829         // if (r && yArray.indexOf(r, mod2) > -1) {
       
   830         if (rm && (mod2 in rm)) {
       
   831             return true;
       
   832         }
       
   833 
       
   834         // external css files should be sorted below yui css
       
   835         if (m.ext && m.type === CSS && !other.ext && other.type === CSS) {
       
   836             return true;
       
   837         }
       
   838 
       
   839         return false;
       
   840     },
       
   841     /**
       
   842     * Apply a new config to the Loader instance
       
   843     * @method _config
       
   844     * @private
       
   845     * @param {Object} o The new configuration
       
   846     */
       
   847     _config: function(o) {
       
   848         var i, j, val, a, f, group, groupName, self = this,
       
   849             mods = [], mod;
       
   850         // apply config values
       
   851         if (o) {
       
   852             for (i in o) {
       
   853                 if (o.hasOwnProperty(i)) {
       
   854                     val = o[i];
       
   855                     //TODO This should be a case
       
   856                     if (i === 'require') {
       
   857                         self.require(val);
       
   858                     } else if (i === 'skin') {
       
   859                         //If the config.skin is a string, format to the expected object
       
   860                         if (typeof val === 'string') {
       
   861                             self.skin.defaultSkin = o.skin;
       
   862                             val = {
       
   863                                 defaultSkin: val
       
   864                             };
       
   865                         }
       
   866 
       
   867                         Y.mix(self.skin, val, true);
       
   868                     } else if (i === 'groups') {
       
   869                         for (j in val) {
       
   870                             if (val.hasOwnProperty(j)) {
       
   871                                 // Y.log('group: ' + j);
       
   872                                 groupName = j;
       
   873                                 group = val[j];
       
   874                                 self.addGroup(group, groupName);
       
   875                                 if (group.aliases) {
       
   876                                     for (a in group.aliases) {
       
   877                                         if (group.aliases.hasOwnProperty(a)) {
       
   878                                             self.addAlias(group.aliases[a], a);
       
   879                                         }
       
   880                                     }
       
   881                                 }
       
   882                             }
       
   883                         }
       
   884 
       
   885                     } else if (i === 'modules') {
       
   886                         // add a hash of module definitions
       
   887                         for (j in val) {
       
   888                             if (val.hasOwnProperty(j)) {
       
   889                                 self.addModule(val[j], j);
       
   890                             }
       
   891                         }
       
   892                     } else if (i === 'aliases') {
       
   893                         for (j in val) {
       
   894                             if (val.hasOwnProperty(j)) {
       
   895                                 self.addAlias(val[j], j);
       
   896                             }
       
   897                         }
       
   898                     } else if (i === 'gallery') {
       
   899                         if (this.groups.gallery.update) {
       
   900                             this.groups.gallery.update(val, o);
       
   901                         }
       
   902                     } else if (i === 'yui2' || i === '2in3') {
       
   903                         if (this.groups.yui2.update) {
       
   904                             this.groups.yui2.update(o['2in3'], o.yui2, o);
       
   905                         }
       
   906                     } else {
       
   907                         self[i] = val;
       
   908                     }
       
   909                 }
       
   910             }
       
   911         }
       
   912 
       
   913         // fix filter
       
   914         f = self.filter;
       
   915 
       
   916         if (L.isString(f)) {
       
   917             f = f.toUpperCase();
       
   918             self.filterName = f;
       
   919             self.filter = self.FILTER_DEFS[f];
       
   920             if (f === 'DEBUG') {
       
   921                 self.require('yui-log', 'dump');
       
   922             }
       
   923         }
       
   924 
       
   925         if (self.filterName && self.coverage) {
       
   926             if (self.filterName === 'COVERAGE' && L.isArray(self.coverage) && self.coverage.length) {
       
   927                 for (i = 0; i < self.coverage.length; i++) {
       
   928                     mod = self.coverage[i];
       
   929                     if (self.moduleInfo[mod] && self.moduleInfo[mod].use) {
       
   930                         mods = [].concat(mods, self.moduleInfo[mod].use);
       
   931                     } else {
       
   932                         mods.push(mod);
       
   933                     }
       
   934                 }
       
   935                 self.filters = self.filters || {};
       
   936                 Y.Array.each(mods, function(mod) {
       
   937                     self.filters[mod] = self.FILTER_DEFS.COVERAGE;
       
   938                 });
       
   939                 self.filterName = 'RAW';
       
   940                 self.filter = self.FILTER_DEFS[self.filterName];
       
   941             }
       
   942         }
       
   943 
       
   944     },
       
   945 
       
   946     /**
       
   947      * Returns the skin module name for the specified skin name.  If a
       
   948      * module name is supplied, the returned skin module name is
       
   949      * specific to the module passed in.
       
   950      * @method formatSkin
       
   951      * @param {string} skin the name of the skin.
       
   952      * @param {string} mod optional: the name of a module to skin.
       
   953      * @return {string} the full skin module name.
       
   954      */
       
   955     formatSkin: function(skin, mod) {
       
   956         var s = SKIN_PREFIX + skin;
       
   957         if (mod) {
       
   958             s = s + '-' + mod;
       
   959         }
       
   960 
       
   961         return s;
       
   962     },
       
   963 
       
   964     /**
       
   965      * Adds the skin def to the module info
       
   966      * @method _addSkin
       
   967      * @param {string} skin the name of the skin.
       
   968      * @param {string} mod the name of the module.
       
   969      * @param {string} parent parent module if this is a skin of a
       
   970      * submodule or plugin.
       
   971      * @return {string} the module name for the skin.
       
   972      * @private
       
   973      */
       
   974     _addSkin: function(skin, mod, parent) {
       
   975         var mdef, pkg, name, nmod,
       
   976             info = this.moduleInfo,
       
   977             sinf = this.skin,
       
   978             ext = info[mod] && info[mod].ext;
       
   979 
       
   980         // Add a module definition for the module-specific skin css
       
   981         if (mod) {
       
   982             name = this.formatSkin(skin, mod);
       
   983             if (!info[name]) {
       
   984                 mdef = info[mod];
       
   985                 pkg = mdef.pkg || mod;
       
   986                 nmod = {
       
   987                     skin: true,
       
   988                     name: name,
       
   989                     group: mdef.group,
       
   990                     type: 'css',
       
   991                     after: sinf.after,
       
   992                     path: (parent || pkg) + '/' + sinf.base + skin +
       
   993                           '/' + mod + '.css',
       
   994                     ext: ext
       
   995                 };
       
   996                 if (mdef.base) {
       
   997                     nmod.base = mdef.base;
       
   998                 }
       
   999                 if (mdef.configFn) {
       
  1000                     nmod.configFn = mdef.configFn;
       
  1001                 }
       
  1002                 this.addModule(nmod, name);
       
  1003 
       
  1004                 Y.log('Adding skin (' + name + '), ' + parent + ', ' + pkg + ', ' + info[name].path, 'info', 'loader');
       
  1005             }
       
  1006         }
       
  1007 
       
  1008         return name;
       
  1009     },
       
  1010     /**
       
  1011     * Adds an alias module to the system
       
  1012     * @method addAlias
       
  1013     * @param {Array} use An array of modules that makes up this alias
       
  1014     * @param {String} name The name of the alias
       
  1015     * @example
       
  1016     *       var loader = new Y.Loader({});
       
  1017     *       loader.addAlias([ 'node', 'yql' ], 'davglass');
       
  1018     *       loader.require(['davglass']);
       
  1019     *       var out = loader.resolve(true);
       
  1020     *
       
  1021     *       //out.js will contain Node and YQL modules
       
  1022     */
       
  1023     addAlias: function(use, name) {
       
  1024         YUI.Env.aliases[name] = use;
       
  1025         this.addModule({
       
  1026             name: name,
       
  1027             use: use
       
  1028         });
       
  1029     },
       
  1030     /**
       
  1031      * Add a new module group
       
  1032      * @method addGroup
       
  1033      * @param {Object} config An object containing the group configuration data
       
  1034      * @param {String} config.name required, the group name
       
  1035      * @param {String} config.base The base directory for this module group
       
  1036      * @param {String} config.root The root path to add to each combo resource path
       
  1037      * @param {Boolean} config.combine Should the request be combined
       
  1038      * @param {String} config.comboBase Combo service base path
       
  1039      * @param {Object} config.modules The group of modules
       
  1040      * @param {String} name the group name.
       
  1041      * @example
       
  1042      *      var loader = new Y.Loader({});
       
  1043      *      loader.addGroup({
       
  1044      *          name: 'davglass',
       
  1045      *          combine: true,
       
  1046      *          comboBase: '/combo?',
       
  1047      *          root: '',
       
  1048      *          modules: {
       
  1049      *              //Module List here
       
  1050      *          }
       
  1051      *      }, 'davglass');
       
  1052      */
       
  1053     addGroup: function(o, name) {
       
  1054         var mods = o.modules,
       
  1055             self = this, i, v;
       
  1056 
       
  1057         name = name || o.name;
       
  1058         o.name = name;
       
  1059         self.groups[name] = o;
       
  1060 
       
  1061         if (o.patterns) {
       
  1062             for (i in o.patterns) {
       
  1063                 if (o.patterns.hasOwnProperty(i)) {
       
  1064                     o.patterns[i].group = name;
       
  1065                     self.patterns[i] = o.patterns[i];
       
  1066                 }
       
  1067             }
       
  1068         }
       
  1069 
       
  1070         if (mods) {
       
  1071             for (i in mods) {
       
  1072                 if (mods.hasOwnProperty(i)) {
       
  1073                     v = mods[i];
       
  1074                     if (typeof v === 'string') {
       
  1075                         v = { name: i, fullpath: v };
       
  1076                     }
       
  1077                     v.group = name;
       
  1078                     self.addModule(v, i);
       
  1079                 }
       
  1080             }
       
  1081         }
       
  1082     },
       
  1083 
       
  1084     /**
       
  1085      * Add a new module to the component metadata.
       
  1086      * @method addModule
       
  1087      * @param {Object} config An object containing the module data.
       
  1088      * @param {String} config.name Required, the component name
       
  1089      * @param {String} config.type Required, the component type (js or css)
       
  1090      * @param {String} config.path Required, the path to the script from `base`
       
  1091      * @param {Array} config.requires Array of modules required by this component
       
  1092      * @param {Array} [config.optional] Array of optional modules for this component
       
  1093      * @param {Array} [config.supersedes] Array of the modules this component replaces
       
  1094      * @param {Array} [config.after] Array of modules the components which, if present, should be sorted above this one
       
  1095      * @param {Object} [config.after_map] Faster alternative to 'after' -- supply a hash instead of an array
       
  1096      * @param {Number} [config.rollup] The number of superseded modules required for automatic rollup
       
  1097      * @param {String} [config.fullpath] If `fullpath` is specified, this is used instead of the configured `base + path`
       
  1098      * @param {Boolean} [config.skinnable] Flag to determine if skin assets should automatically be pulled in
       
  1099      * @param {Object} [config.submodules] Hash of submodules
       
  1100      * @param {String} [config.group] The group the module belongs to -- this is set automatically when it is added as part of a group configuration.
       
  1101      * @param {Array} [config.lang] Array of BCP 47 language tags of languages for which this module has localized resource bundles, e.g., `["en-GB", "zh-Hans-CN"]`
       
  1102      * @param {Object} [config.condition] Specifies that the module should be loaded automatically if a condition is met. This is an object with up to four fields:
       
  1103      * @param {String} [config.condition.trigger] The name of a module that can trigger the auto-load
       
  1104      * @param {Function} [config.condition.test] A function that returns true when the module is to be loaded.
       
  1105      * @param {String} [config.condition.ua] The UA name of <a href="UA.html">Y.UA</a> object that returns true when the module is to be loaded. e.g., `"ie"`, `"nodejs"`.
       
  1106      * @param {String} [config.condition.when] Specifies the load order of the conditional module
       
  1107      *  with regard to the position of the trigger module.
       
  1108      *  This should be one of three values: `before`, `after`, or `instead`.  The default is `after`.
       
  1109      * @param {Object} [config.testresults] A hash of test results from `Y.Features.all()`
       
  1110      * @param {Function} [config.configFn] A function to exectute when configuring this module
       
  1111      * @param {Object} config.configFn.mod The module config, modifying this object will modify it's config. Returning false will delete the module's config.
       
  1112      * @param {String} [name] The module name, required if not in the module data.
       
  1113      * @return {Object} the module definition or null if the object passed in did not provide all required attributes.
       
  1114      */
       
  1115     addModule: function(o, name) {
       
  1116         name = name || o.name;
       
  1117 
       
  1118         if (typeof o === 'string') {
       
  1119             o = { name: name, fullpath: o };
       
  1120         }
       
  1121 
       
  1122 
       
  1123         var subs, i, l, t, sup, s, smod, plugins, plug,
       
  1124             j, langs, packName, supName, flatSup, flatLang, lang, ret,
       
  1125             overrides, skinname, when, g, p,
       
  1126             conditions = this.conditions, trigger;
       
  1127 
       
  1128         //Only merge this data if the temp flag is set
       
  1129         //from an earlier pass from a pattern or else
       
  1130         //an override module (YUI_config) can not be used to
       
  1131         //replace a default module.
       
  1132         if (this.moduleInfo[name] && this.moduleInfo[name].temp) {
       
  1133             //This catches temp modules loaded via a pattern
       
  1134             // The module will be added twice, once from the pattern and
       
  1135             // Once from the actual add call, this ensures that properties
       
  1136             // that were added to the module the first time around (group: gallery)
       
  1137             // are also added the second time around too.
       
  1138             o = Y.merge(this.moduleInfo[name], o);
       
  1139         }
       
  1140 
       
  1141         o.name = name;
       
  1142 
       
  1143         if (!o || !o.name) {
       
  1144             return null;
       
  1145         }
       
  1146 
       
  1147         if (!o.type) {
       
  1148             //Always assume it's javascript unless the CSS pattern is matched.
       
  1149             o.type = JS;
       
  1150             p = o.path || o.fullpath;
       
  1151             if (p && this.REGEX_CSS.test(p)) {
       
  1152                 Y.log('Auto determined module type as CSS', 'warn', 'loader');
       
  1153                 o.type = CSS;
       
  1154             }
       
  1155         }
       
  1156 
       
  1157         if (!o.path && !o.fullpath) {
       
  1158             o.path = _path(name, name, o.type);
       
  1159         }
       
  1160         o.supersedes = o.supersedes || o.use;
       
  1161 
       
  1162         o.ext = ('ext' in o) ? o.ext : (this._internal) ? false : true;
       
  1163 
       
  1164         // Handle submodule logic
       
  1165         subs = o.submodules;
       
  1166 
       
  1167         this.moduleInfo[name] = o;
       
  1168 
       
  1169         o.requires = o.requires || [];
       
  1170 
       
  1171         /*
       
  1172         Only allowing the cascade of requires information, since
       
  1173         optional and supersedes are far more fine grained than
       
  1174         a blanket requires is.
       
  1175         */
       
  1176         if (this.requires) {
       
  1177             for (i = 0; i < this.requires.length; i++) {
       
  1178                 o.requires.push(this.requires[i]);
       
  1179             }
       
  1180         }
       
  1181         if (o.group && this.groups && this.groups[o.group]) {
       
  1182             g = this.groups[o.group];
       
  1183             if (g.requires) {
       
  1184                 for (i = 0; i < g.requires.length; i++) {
       
  1185                     o.requires.push(g.requires[i]);
       
  1186                 }
       
  1187             }
       
  1188         }
       
  1189 
       
  1190 
       
  1191         if (!o.defaults) {
       
  1192             o.defaults = {
       
  1193                 requires: o.requires ? [].concat(o.requires) : null,
       
  1194                 supersedes: o.supersedes ? [].concat(o.supersedes) : null,
       
  1195                 optional: o.optional ? [].concat(o.optional) : null
       
  1196             };
       
  1197         }
       
  1198 
       
  1199         if (o.skinnable && o.ext && o.temp) {
       
  1200             skinname = this._addSkin(this.skin.defaultSkin, name);
       
  1201             o.requires.unshift(skinname);
       
  1202         }
       
  1203 
       
  1204         if (o.requires.length) {
       
  1205             o.requires = this.filterRequires(o.requires) || [];
       
  1206         }
       
  1207 
       
  1208         if (!o.langPack && o.lang) {
       
  1209             langs = yArray(o.lang);
       
  1210             for (j = 0; j < langs.length; j++) {
       
  1211                 lang = langs[j];
       
  1212                 packName = this.getLangPackName(lang, name);
       
  1213                 smod = this.moduleInfo[packName];
       
  1214                 if (!smod) {
       
  1215                     smod = this._addLangPack(lang, o, packName);
       
  1216                 }
       
  1217             }
       
  1218         }
       
  1219 
       
  1220 
       
  1221         if (subs) {
       
  1222             sup = o.supersedes || [];
       
  1223             l = 0;
       
  1224 
       
  1225             for (i in subs) {
       
  1226                 if (subs.hasOwnProperty(i)) {
       
  1227                     s = subs[i];
       
  1228 
       
  1229                     s.path = s.path || _path(name, i, o.type);
       
  1230                     s.pkg = name;
       
  1231                     s.group = o.group;
       
  1232 
       
  1233                     if (s.supersedes) {
       
  1234                         sup = sup.concat(s.supersedes);
       
  1235                     }
       
  1236 
       
  1237                     smod = this.addModule(s, i);
       
  1238                     sup.push(i);
       
  1239 
       
  1240                     if (smod.skinnable) {
       
  1241                         o.skinnable = true;
       
  1242                         overrides = this.skin.overrides;
       
  1243                         if (overrides && overrides[i]) {
       
  1244                             for (j = 0; j < overrides[i].length; j++) {
       
  1245                                 skinname = this._addSkin(overrides[i][j],
       
  1246                                          i, name);
       
  1247                                 sup.push(skinname);
       
  1248                             }
       
  1249                         }
       
  1250                         skinname = this._addSkin(this.skin.defaultSkin,
       
  1251                                         i, name);
       
  1252                         sup.push(skinname);
       
  1253                     }
       
  1254 
       
  1255                     // looks like we are expected to work out the metadata
       
  1256                     // for the parent module language packs from what is
       
  1257                     // specified in the child modules.
       
  1258                     if (s.lang && s.lang.length) {
       
  1259 
       
  1260                         langs = yArray(s.lang);
       
  1261                         for (j = 0; j < langs.length; j++) {
       
  1262                             lang = langs[j];
       
  1263                             packName = this.getLangPackName(lang, name);
       
  1264                             supName = this.getLangPackName(lang, i);
       
  1265                             smod = this.moduleInfo[packName];
       
  1266 
       
  1267                             if (!smod) {
       
  1268                                 smod = this._addLangPack(lang, o, packName);
       
  1269                             }
       
  1270 
       
  1271                             flatSup = flatSup || yArray.hash(smod.supersedes);
       
  1272 
       
  1273                             if (!(supName in flatSup)) {
       
  1274                                 smod.supersedes.push(supName);
       
  1275                             }
       
  1276 
       
  1277                             o.lang = o.lang || [];
       
  1278 
       
  1279                             flatLang = flatLang || yArray.hash(o.lang);
       
  1280 
       
  1281                             if (!(lang in flatLang)) {
       
  1282                                 o.lang.push(lang);
       
  1283                             }
       
  1284 
       
  1285 // Y.log('pack ' + packName + ' should supersede ' + supName);
       
  1286 // Add rollup file, need to add to supersedes list too
       
  1287 
       
  1288                             // default packages
       
  1289                             packName = this.getLangPackName(ROOT_LANG, name);
       
  1290                             supName = this.getLangPackName(ROOT_LANG, i);
       
  1291 
       
  1292                             smod = this.moduleInfo[packName];
       
  1293 
       
  1294                             if (!smod) {
       
  1295                                 smod = this._addLangPack(lang, o, packName);
       
  1296                             }
       
  1297 
       
  1298                             if (!(supName in flatSup)) {
       
  1299                                 smod.supersedes.push(supName);
       
  1300                             }
       
  1301 
       
  1302 // Y.log('pack ' + packName + ' should supersede ' + supName);
       
  1303 // Add rollup file, need to add to supersedes list too
       
  1304 
       
  1305                         }
       
  1306                     }
       
  1307 
       
  1308                     l++;
       
  1309                 }
       
  1310             }
       
  1311             //o.supersedes = YObject.keys(yArray.hash(sup));
       
  1312             o.supersedes = yArray.dedupe(sup);
       
  1313             if (this.allowRollup) {
       
  1314                 o.rollup = (l < 4) ? l : Math.min(l - 1, 4);
       
  1315             }
       
  1316         }
       
  1317 
       
  1318         plugins = o.plugins;
       
  1319         if (plugins) {
       
  1320             for (i in plugins) {
       
  1321                 if (plugins.hasOwnProperty(i)) {
       
  1322                     plug = plugins[i];
       
  1323                     plug.pkg = name;
       
  1324                     plug.path = plug.path || _path(name, i, o.type);
       
  1325                     plug.requires = plug.requires || [];
       
  1326                     plug.group = o.group;
       
  1327                     this.addModule(plug, i);
       
  1328                     if (o.skinnable) {
       
  1329                         this._addSkin(this.skin.defaultSkin, i, name);
       
  1330                     }
       
  1331 
       
  1332                 }
       
  1333             }
       
  1334         }
       
  1335 
       
  1336         if (o.condition) {
       
  1337             t = o.condition.trigger;
       
  1338             if (YUI.Env.aliases[t]) {
       
  1339                 t = YUI.Env.aliases[t];
       
  1340             }
       
  1341             if (!Y.Lang.isArray(t)) {
       
  1342                 t = [t];
       
  1343             }
       
  1344 
       
  1345             for (i = 0; i < t.length; i++) {
       
  1346                 trigger = t[i];
       
  1347                 when = o.condition.when;
       
  1348                 conditions[trigger] = conditions[trigger] || {};
       
  1349                 conditions[trigger][name] = o.condition;
       
  1350                 // the 'when' attribute can be 'before', 'after', or 'instead'
       
  1351                 // the default is after.
       
  1352                 if (when && when !== 'after') {
       
  1353                     if (when === 'instead') { // replace the trigger
       
  1354                         o.supersedes = o.supersedes || [];
       
  1355                         o.supersedes.push(trigger);
       
  1356                     }
       
  1357                     // before the trigger
       
  1358                         // the trigger requires the conditional mod,
       
  1359                         // so it should appear before the conditional
       
  1360                         // mod if we do not intersede.
       
  1361                 } else { // after the trigger
       
  1362                     o.after = o.after || [];
       
  1363                     o.after.push(trigger);
       
  1364                 }
       
  1365             }
       
  1366         }
       
  1367 
       
  1368         if (o.supersedes) {
       
  1369             o.supersedes = this.filterRequires(o.supersedes);
       
  1370         }
       
  1371 
       
  1372         if (o.after) {
       
  1373             o.after = this.filterRequires(o.after);
       
  1374             o.after_map = yArray.hash(o.after);
       
  1375         }
       
  1376 
       
  1377         // this.dirty = true;
       
  1378 
       
  1379         if (o.configFn) {
       
  1380             ret = o.configFn(o);
       
  1381             if (ret === false) {
       
  1382                 Y.log('Config function returned false for ' + name + ', skipping.', 'info', 'loader');
       
  1383                 delete this.moduleInfo[name];
       
  1384                 delete GLOBAL_ENV._renderedMods[name];
       
  1385                 o = null;
       
  1386             }
       
  1387         }
       
  1388         //Add to global cache
       
  1389         if (o) {
       
  1390             if (!GLOBAL_ENV._renderedMods) {
       
  1391                 GLOBAL_ENV._renderedMods = {};
       
  1392             }
       
  1393             GLOBAL_ENV._renderedMods[name] = Y.mix(GLOBAL_ENV._renderedMods[name] || {}, o);
       
  1394             GLOBAL_ENV._conditions = conditions;
       
  1395         }
       
  1396 
       
  1397         return o;
       
  1398     },
       
  1399 
       
  1400     /**
       
  1401      * Add a requirement for one or more module
       
  1402      * @method require
       
  1403      * @param {string[] | string*} what the modules to load.
       
  1404      */
       
  1405     require: function(what) {
       
  1406         var a = (typeof what === 'string') ? yArray(arguments) : what;
       
  1407         this.dirty = true;
       
  1408         this.required = Y.merge(this.required, yArray.hash(this.filterRequires(a)));
       
  1409 
       
  1410         this._explodeRollups();
       
  1411     },
       
  1412     /**
       
  1413     * Grab all the items that were asked for, check to see if the Loader
       
  1414     * meta-data contains a "use" array. If it doesm remove the asked item and replace it with
       
  1415     * the content of the "use".
       
  1416     * This will make asking for: "dd"
       
  1417     * Actually ask for: "dd-ddm-base,dd-ddm,dd-ddm-drop,dd-drag,dd-proxy,dd-constrain,dd-drop,dd-scroll,dd-drop-plugin"
       
  1418     * @private
       
  1419     * @method _explodeRollups
       
  1420     */
       
  1421     _explodeRollups: function() {
       
  1422         var self = this, m, m2, i, a, v, len, len2,
       
  1423         r = self.required;
       
  1424 
       
  1425         if (!self.allowRollup) {
       
  1426             for (i in r) {
       
  1427                 if (r.hasOwnProperty(i)) {
       
  1428                     m = self.getModule(i);
       
  1429                     if (m && m.use) {
       
  1430                         len = m.use.length;
       
  1431                         for (a = 0; a < len; a++) {
       
  1432                             m2 = self.getModule(m.use[a]);
       
  1433                             if (m2 && m2.use) {
       
  1434                                 len2 = m2.use.length;
       
  1435                                 for (v = 0; v < len2; v++) {
       
  1436                                     r[m2.use[v]] = true;
       
  1437                                 }
       
  1438                             } else {
       
  1439                                 r[m.use[a]] = true;
       
  1440                             }
       
  1441                         }
       
  1442                     }
       
  1443                 }
       
  1444             }
       
  1445             self.required = r;
       
  1446         }
       
  1447 
       
  1448     },
       
  1449     /**
       
  1450     * Explodes the required array to remove aliases and replace them with real modules
       
  1451     * @method filterRequires
       
  1452     * @param {Array} r The original requires array
       
  1453     * @return {Array} The new array of exploded requirements
       
  1454     */
       
  1455     filterRequires: function(r) {
       
  1456         if (r) {
       
  1457             if (!Y.Lang.isArray(r)) {
       
  1458                 r = [r];
       
  1459             }
       
  1460             r = Y.Array(r);
       
  1461             var c = [], i, mod, o, m;
       
  1462 
       
  1463             for (i = 0; i < r.length; i++) {
       
  1464                 mod = this.getModule(r[i]);
       
  1465                 if (mod && mod.use) {
       
  1466                     for (o = 0; o < mod.use.length; o++) {
       
  1467                         //Must walk the other modules in case a module is a rollup of rollups (datatype)
       
  1468                         m = this.getModule(mod.use[o]);
       
  1469                         if (m && m.use && (m.name !== mod.name)) {
       
  1470                             c = Y.Array.dedupe([].concat(c, this.filterRequires(m.use)));
       
  1471                         } else {
       
  1472                             c.push(mod.use[o]);
       
  1473                         }
       
  1474                     }
       
  1475                 } else {
       
  1476                     c.push(r[i]);
       
  1477                 }
       
  1478             }
       
  1479             r = c;
       
  1480         }
       
  1481         return r;
       
  1482     },
       
  1483     /**
       
  1484      * Returns an object containing properties for all modules required
       
  1485      * in order to load the requested module
       
  1486      * @method getRequires
       
  1487      * @param {object}  mod The module definition from moduleInfo.
       
  1488      * @return {array} the expanded requirement list.
       
  1489      */
       
  1490     getRequires: function(mod) {
       
  1491 
       
  1492         if (!mod) {
       
  1493             //console.log('returning no reqs for ' + mod.name);
       
  1494             return NO_REQUIREMENTS;
       
  1495         }
       
  1496 
       
  1497         if (mod._parsed) {
       
  1498             //console.log('returning requires for ' + mod.name, mod.requires);
       
  1499             return mod.expanded || NO_REQUIREMENTS;
       
  1500         }
       
  1501 
       
  1502         //TODO add modue cache here out of scope..
       
  1503 
       
  1504         var i, m, j, add, packName, lang, testresults = this.testresults,
       
  1505             name = mod.name, cond,
       
  1506             adddef = ON_PAGE[name] && ON_PAGE[name].details,
       
  1507             d, go, def,
       
  1508             r, old_mod,
       
  1509             o, skinmod, skindef, skinpar, skinname,
       
  1510             intl = mod.lang || mod.intl,
       
  1511             info = this.moduleInfo,
       
  1512             ftests = Y.Features && Y.Features.tests.load,
       
  1513             hash, reparse;
       
  1514 
       
  1515         // console.log(name);
       
  1516 
       
  1517         // pattern match leaves module stub that needs to be filled out
       
  1518         if (mod.temp && adddef) {
       
  1519             old_mod = mod;
       
  1520             mod = this.addModule(adddef, name);
       
  1521             mod.group = old_mod.group;
       
  1522             mod.pkg = old_mod.pkg;
       
  1523             delete mod.expanded;
       
  1524         }
       
  1525 
       
  1526         // console.log('cache: ' + mod.langCache + ' == ' + this.lang);
       
  1527 
       
  1528         //If a skin or a lang is different, reparse..
       
  1529         reparse = !((!this.lang || mod.langCache === this.lang) && (mod.skinCache === this.skin.defaultSkin));
       
  1530 
       
  1531         if (mod.expanded && !reparse) {
       
  1532             //Y.log('Already expanded ' + name + ', ' + mod.expanded);
       
  1533             return mod.expanded;
       
  1534         }
       
  1535 
       
  1536 
       
  1537         d = [];
       
  1538         hash = {};
       
  1539         r = this.filterRequires(mod.requires);
       
  1540         if (mod.lang) {
       
  1541             //If a module has a lang attribute, auto add the intl requirement.
       
  1542             d.unshift('intl');
       
  1543             r.unshift('intl');
       
  1544             intl = true;
       
  1545         }
       
  1546         o = this.filterRequires(mod.optional);
       
  1547 
       
  1548         // Y.log("getRequires: " + name + " (dirty:" + this.dirty +
       
  1549         // ", expanded:" + mod.expanded + ")");
       
  1550 
       
  1551         mod._parsed = true;
       
  1552         mod.langCache = this.lang;
       
  1553         mod.skinCache = this.skin.defaultSkin;
       
  1554 
       
  1555         for (i = 0; i < r.length; i++) {
       
  1556             //Y.log(name + ' requiring ' + r[i], 'info', 'loader');
       
  1557             if (!hash[r[i]]) {
       
  1558                 d.push(r[i]);
       
  1559                 hash[r[i]] = true;
       
  1560                 m = this.getModule(r[i]);
       
  1561                 if (m) {
       
  1562                     add = this.getRequires(m);
       
  1563                     intl = intl || (m.expanded_map &&
       
  1564                         (INTL in m.expanded_map));
       
  1565                     for (j = 0; j < add.length; j++) {
       
  1566                         d.push(add[j]);
       
  1567                     }
       
  1568                 }
       
  1569             }
       
  1570         }
       
  1571 
       
  1572         // get the requirements from superseded modules, if any
       
  1573         r = this.filterRequires(mod.supersedes);
       
  1574         if (r) {
       
  1575             for (i = 0; i < r.length; i++) {
       
  1576                 if (!hash[r[i]]) {
       
  1577                     // if this module has submodules, the requirements list is
       
  1578                     // expanded to include the submodules.  This is so we can
       
  1579                     // prevent dups when a submodule is already loaded and the
       
  1580                     // parent is requested.
       
  1581                     if (mod.submodules) {
       
  1582                         d.push(r[i]);
       
  1583                     }
       
  1584 
       
  1585                     hash[r[i]] = true;
       
  1586                     m = this.getModule(r[i]);
       
  1587 
       
  1588                     if (m) {
       
  1589                         add = this.getRequires(m);
       
  1590                         intl = intl || (m.expanded_map &&
       
  1591                             (INTL in m.expanded_map));
       
  1592                         for (j = 0; j < add.length; j++) {
       
  1593                             d.push(add[j]);
       
  1594                         }
       
  1595                     }
       
  1596                 }
       
  1597             }
       
  1598         }
       
  1599 
       
  1600         if (o && this.loadOptional) {
       
  1601             for (i = 0; i < o.length; i++) {
       
  1602                 if (!hash[o[i]]) {
       
  1603                     d.push(o[i]);
       
  1604                     hash[o[i]] = true;
       
  1605                     m = info[o[i]];
       
  1606                     if (m) {
       
  1607                         add = this.getRequires(m);
       
  1608                         intl = intl || (m.expanded_map &&
       
  1609                             (INTL in m.expanded_map));
       
  1610                         for (j = 0; j < add.length; j++) {
       
  1611                             d.push(add[j]);
       
  1612                         }
       
  1613                     }
       
  1614                 }
       
  1615             }
       
  1616         }
       
  1617 
       
  1618         cond = this.conditions[name];
       
  1619 
       
  1620         if (cond) {
       
  1621             //Set the module to not parsed since we have conditionals and this could change the dependency tree.
       
  1622             mod._parsed = false;
       
  1623             if (testresults && ftests) {
       
  1624                 oeach(testresults, function(result, id) {
       
  1625                     var condmod = ftests[id].name;
       
  1626                     if (!hash[condmod] && ftests[id].trigger === name) {
       
  1627                         if (result && ftests[id]) {
       
  1628                             hash[condmod] = true;
       
  1629                             d.push(condmod);
       
  1630                         }
       
  1631                     }
       
  1632                 });
       
  1633             } else {
       
  1634                 for (i in cond) {
       
  1635                     if (cond.hasOwnProperty(i)) {
       
  1636                         if (!hash[i]) {
       
  1637                             def = cond[i];
       
  1638                             //first see if they've specfied a ua check
       
  1639                             //then see if they've got a test fn & if it returns true
       
  1640                             //otherwise just having a condition block is enough
       
  1641                             go = def && ((!def.ua && !def.test) || (def.ua && Y.UA[def.ua]) ||
       
  1642                                         (def.test && def.test(Y, r)));
       
  1643 
       
  1644                             if (go) {
       
  1645                                 hash[i] = true;
       
  1646                                 d.push(i);
       
  1647                                 m = this.getModule(i);
       
  1648                                 if (m) {
       
  1649                                     add = this.getRequires(m);
       
  1650                                     for (j = 0; j < add.length; j++) {
       
  1651                                         d.push(add[j]);
       
  1652                                     }
       
  1653 
       
  1654                                 }
       
  1655                             }
       
  1656                         }
       
  1657                     }
       
  1658                 }
       
  1659             }
       
  1660         }
       
  1661 
       
  1662         // Create skin modules
       
  1663         if (mod.skinnable) {
       
  1664             skindef = this.skin.overrides;
       
  1665             for (i in YUI.Env.aliases) {
       
  1666                 if (YUI.Env.aliases.hasOwnProperty(i)) {
       
  1667                     if (Y.Array.indexOf(YUI.Env.aliases[i], name) > -1) {
       
  1668                         skinpar = i;
       
  1669                     }
       
  1670                 }
       
  1671             }
       
  1672             if (skindef && (skindef[name] || (skinpar && skindef[skinpar]))) {
       
  1673                 skinname = name;
       
  1674                 if (skindef[skinpar]) {
       
  1675                     skinname = skinpar;
       
  1676                 }
       
  1677                 for (i = 0; i < skindef[skinname].length; i++) {
       
  1678                     skinmod = this._addSkin(skindef[skinname][i], name);
       
  1679                     if (!this.isCSSLoaded(skinmod, this._boot)) {
       
  1680                         d.push(skinmod);
       
  1681                     }
       
  1682                 }
       
  1683             } else {
       
  1684                 skinmod = this._addSkin(this.skin.defaultSkin, name);
       
  1685                 if (!this.isCSSLoaded(skinmod, this._boot)) {
       
  1686                     d.push(skinmod);
       
  1687                 }
       
  1688             }
       
  1689         }
       
  1690 
       
  1691         mod._parsed = false;
       
  1692 
       
  1693         if (intl) {
       
  1694 
       
  1695             if (mod.lang && !mod.langPack && Y.Intl) {
       
  1696                 lang = Y.Intl.lookupBestLang(this.lang || ROOT_LANG, mod.lang);
       
  1697                 //Y.log('Best lang: ' + lang + ', this.lang: ' + this.lang + ', mod.lang: ' + mod.lang);
       
  1698                 packName = this.getLangPackName(lang, name);
       
  1699                 if (packName) {
       
  1700                     d.unshift(packName);
       
  1701                 }
       
  1702             }
       
  1703             d.unshift(INTL);
       
  1704         }
       
  1705 
       
  1706         mod.expanded_map = yArray.hash(d);
       
  1707 
       
  1708         mod.expanded = YObject.keys(mod.expanded_map);
       
  1709 
       
  1710         return mod.expanded;
       
  1711     },
       
  1712     /**
       
  1713     * Check to see if named css module is already loaded on the page
       
  1714     * @method isCSSLoaded
       
  1715     * @param {String} name The name of the css file
       
  1716     * @return Boolean
       
  1717     */
       
  1718     isCSSLoaded: function(name, skip) {
       
  1719         //TODO - Make this call a batching call with name being an array
       
  1720         if (!name || !YUI.Env.cssStampEl || (!skip && this.ignoreRegistered)) {
       
  1721             Y.log('isCSSLoaded was skipped for ' + name, 'warn', 'loader');
       
  1722             return false;
       
  1723         }
       
  1724         var el = YUI.Env.cssStampEl,
       
  1725             ret = false,
       
  1726             mod = YUI.Env._cssLoaded[name],
       
  1727             style = el.currentStyle; //IE
       
  1728 
       
  1729 
       
  1730         if (mod !== undefined) {
       
  1731             //Y.log('isCSSLoaded was cached for ' + name, 'warn', 'loader');
       
  1732             return mod;
       
  1733         }
       
  1734 
       
  1735         //Add the classname to the element
       
  1736         el.className = name;
       
  1737 
       
  1738         if (!style) {
       
  1739             style = Y.config.doc.defaultView.getComputedStyle(el, null);
       
  1740         }
       
  1741 
       
  1742         if (style && style.display === 'none') {
       
  1743             ret = true;
       
  1744         }
       
  1745 
       
  1746         Y.log('Has Skin? ' + name + ' : ' + ret, 'info', 'loader');
       
  1747 
       
  1748         el.className = ''; //Reset the classname to ''
       
  1749 
       
  1750         YUI.Env._cssLoaded[name] = ret;
       
  1751 
       
  1752         return ret;
       
  1753     },
       
  1754 
       
  1755     /**
       
  1756      * Returns a hash of module names the supplied module satisfies.
       
  1757      * @method getProvides
       
  1758      * @param {string} name The name of the module.
       
  1759      * @return {object} what this module provides.
       
  1760      */
       
  1761     getProvides: function(name) {
       
  1762         var m = this.getModule(name), o, s;
       
  1763             // supmap = this.provides;
       
  1764 
       
  1765         if (!m) {
       
  1766             return NOT_FOUND;
       
  1767         }
       
  1768 
       
  1769         if (m && !m.provides) {
       
  1770             o = {};
       
  1771             s = m.supersedes;
       
  1772 
       
  1773             if (s) {
       
  1774                 yArray.each(s, function(v) {
       
  1775                     Y.mix(o, this.getProvides(v));
       
  1776                 }, this);
       
  1777             }
       
  1778 
       
  1779             o[name] = true;
       
  1780             m.provides = o;
       
  1781 
       
  1782         }
       
  1783 
       
  1784         return m.provides;
       
  1785     },
       
  1786 
       
  1787     /**
       
  1788      * Calculates the dependency tree, the result is stored in the sorted
       
  1789      * property.
       
  1790      * @method calculate
       
  1791      * @param {object} o optional options object.
       
  1792      * @param {string} type optional argument to prune modules.
       
  1793      */
       
  1794     calculate: function(o, type) {
       
  1795         if (o || type || this.dirty) {
       
  1796 
       
  1797             if (o) {
       
  1798                 this._config(o);
       
  1799             }
       
  1800 
       
  1801             if (!this._init) {
       
  1802                 this._setup();
       
  1803             }
       
  1804 
       
  1805             this._explode();
       
  1806 
       
  1807             if (this.allowRollup) {
       
  1808                 this._rollup();
       
  1809             } else {
       
  1810                 this._explodeRollups();
       
  1811             }
       
  1812             this._reduce();
       
  1813             this._sort();
       
  1814         }
       
  1815     },
       
  1816     /**
       
  1817     * Creates a "psuedo" package for languages provided in the lang array
       
  1818     * @method _addLangPack
       
  1819     * @private
       
  1820     * @param {String} lang The language to create
       
  1821     * @param {Object} m The module definition to create the language pack around
       
  1822     * @param {String} packName The name of the package (e.g: lang/datatype-date-en-US)
       
  1823     * @return {Object} The module definition
       
  1824     */
       
  1825     _addLangPack: function(lang, m, packName) {
       
  1826         var name = m.name,
       
  1827             packPath, conf,
       
  1828             existing = this.moduleInfo[packName];
       
  1829 
       
  1830         if (!existing) {
       
  1831 
       
  1832             packPath = _path((m.pkg || name), packName, JS, true);
       
  1833 
       
  1834             conf = {
       
  1835                 path: packPath,
       
  1836                 intl: true,
       
  1837                 langPack: true,
       
  1838                 ext: m.ext,
       
  1839                 group: m.group,
       
  1840                 supersedes: []
       
  1841             };
       
  1842             if (m.root) {
       
  1843                 conf.root = m.root;
       
  1844             }
       
  1845             if (m.base) {
       
  1846                 conf.base = m.base;
       
  1847             }
       
  1848 
       
  1849             if (m.configFn) {
       
  1850                 conf.configFn = m.configFn;
       
  1851             }
       
  1852 
       
  1853             this.addModule(conf, packName);
       
  1854 
       
  1855             if (lang) {
       
  1856                 Y.Env.lang = Y.Env.lang || {};
       
  1857                 Y.Env.lang[lang] = Y.Env.lang[lang] || {};
       
  1858                 Y.Env.lang[lang][name] = true;
       
  1859             }
       
  1860         }
       
  1861 
       
  1862         return this.moduleInfo[packName];
       
  1863     },
       
  1864 
       
  1865     /**
       
  1866      * Investigates the current YUI configuration on the page.  By default,
       
  1867      * modules already detected will not be loaded again unless a force
       
  1868      * option is encountered.  Called by calculate()
       
  1869      * @method _setup
       
  1870      * @private
       
  1871      */
       
  1872     _setup: function() {
       
  1873         var info = this.moduleInfo, name, i, j, m, l,
       
  1874             packName;
       
  1875 
       
  1876         for (name in info) {
       
  1877             if (info.hasOwnProperty(name)) {
       
  1878                 m = info[name];
       
  1879                 if (m) {
       
  1880 
       
  1881                     // remove dups
       
  1882                     //m.requires = YObject.keys(yArray.hash(m.requires));
       
  1883                     m.requires = yArray.dedupe(m.requires);
       
  1884 
       
  1885                     // Create lang pack modules
       
  1886                     //if (m.lang && m.lang.length) {
       
  1887                     if (m.lang) {
       
  1888                         // Setup root package if the module has lang defined,
       
  1889                         // it needs to provide a root language pack
       
  1890                         packName = this.getLangPackName(ROOT_LANG, name);
       
  1891                         this._addLangPack(null, m, packName);
       
  1892                     }
       
  1893 
       
  1894                 }
       
  1895             }
       
  1896         }
       
  1897 
       
  1898 
       
  1899         //l = Y.merge(this.inserted);
       
  1900         l = {};
       
  1901 
       
  1902         // available modules
       
  1903         if (!this.ignoreRegistered) {
       
  1904             Y.mix(l, GLOBAL_ENV.mods);
       
  1905         }
       
  1906 
       
  1907         // add the ignore list to the list of loaded packages
       
  1908         if (this.ignore) {
       
  1909             Y.mix(l, yArray.hash(this.ignore));
       
  1910         }
       
  1911 
       
  1912         // expand the list to include superseded modules
       
  1913         for (j in l) {
       
  1914             if (l.hasOwnProperty(j)) {
       
  1915                 Y.mix(l, this.getProvides(j));
       
  1916             }
       
  1917         }
       
  1918 
       
  1919         // remove modules on the force list from the loaded list
       
  1920         if (this.force) {
       
  1921             for (i = 0; i < this.force.length; i++) {
       
  1922                 if (this.force[i] in l) {
       
  1923                     delete l[this.force[i]];
       
  1924                 }
       
  1925             }
       
  1926         }
       
  1927 
       
  1928         Y.mix(this.loaded, l);
       
  1929 
       
  1930         this._init = true;
       
  1931     },
       
  1932 
       
  1933     /**
       
  1934      * Builds a module name for a language pack
       
  1935      * @method getLangPackName
       
  1936      * @param {string} lang the language code.
       
  1937      * @param {string} mname the module to build it for.
       
  1938      * @return {string} the language pack module name.
       
  1939      */
       
  1940     getLangPackName: function(lang, mname) {
       
  1941         return ('lang/' + mname + ((lang) ? '_' + lang : ''));
       
  1942     },
       
  1943     /**
       
  1944      * Inspects the required modules list looking for additional
       
  1945      * dependencies.  Expands the required list to include all
       
  1946      * required modules.  Called by calculate()
       
  1947      * @method _explode
       
  1948      * @private
       
  1949      */
       
  1950     _explode: function() {
       
  1951         //TODO Move done out of scope
       
  1952         var r = this.required, m, reqs, done = {},
       
  1953             self = this, name, expound;
       
  1954 
       
  1955         // the setup phase is over, all modules have been created
       
  1956         self.dirty = false;
       
  1957 
       
  1958         self._explodeRollups();
       
  1959         r = self.required;
       
  1960 
       
  1961         for (name in r) {
       
  1962             if (r.hasOwnProperty(name)) {
       
  1963                 if (!done[name]) {
       
  1964                     done[name] = true;
       
  1965                     m = self.getModule(name);
       
  1966                     if (m) {
       
  1967                         expound = m.expound;
       
  1968 
       
  1969                         if (expound) {
       
  1970                             r[expound] = self.getModule(expound);
       
  1971                             reqs = self.getRequires(r[expound]);
       
  1972                             Y.mix(r, yArray.hash(reqs));
       
  1973                         }
       
  1974 
       
  1975                         reqs = self.getRequires(m);
       
  1976                         Y.mix(r, yArray.hash(reqs));
       
  1977                     }
       
  1978                 }
       
  1979             }
       
  1980         }
       
  1981 
       
  1982         // Y.log('After explode: ' + YObject.keys(r));
       
  1983     },
       
  1984     /**
       
  1985     * The default method used to test a module against a pattern
       
  1986     * @method _patternTest
       
  1987     * @private
       
  1988     * @param {String} mname The module being tested
       
  1989     * @param {String} pname The pattern to match
       
  1990     */
       
  1991     _patternTest: function(mname, pname) {
       
  1992         return (mname.indexOf(pname) > -1);
       
  1993     },
       
  1994     /**
       
  1995     * Get's the loader meta data for the requested module
       
  1996     * @method getModule
       
  1997     * @param {String} mname The module name to get
       
  1998     * @return {Object} The module metadata
       
  1999     */
       
  2000     getModule: function(mname) {
       
  2001         //TODO: Remove name check - it's a quick hack to fix pattern WIP
       
  2002         if (!mname) {
       
  2003             return null;
       
  2004         }
       
  2005 
       
  2006         var p, found, pname,
       
  2007             m = this.moduleInfo[mname],
       
  2008             patterns = this.patterns;
       
  2009 
       
  2010         // check the patterns library to see if we should automatically add
       
  2011         // the module with defaults
       
  2012         if (!m || (m && m.ext)) {
       
  2013            // Y.log('testing patterns ' + YObject.keys(patterns));
       
  2014             for (pname in patterns) {
       
  2015                 if (patterns.hasOwnProperty(pname)) {
       
  2016                     // Y.log('testing pattern ' + i);
       
  2017                     p = patterns[pname];
       
  2018 
       
  2019                     //There is no test method, create a default one that tests
       
  2020                     // the pattern against the mod name
       
  2021                     if (!p.test) {
       
  2022                         p.test = this._patternTest;
       
  2023                     }
       
  2024 
       
  2025                     if (p.test(mname, pname)) {
       
  2026                         // use the metadata supplied for the pattern
       
  2027                         // as the module definition.
       
  2028                         found = p;
       
  2029                         break;
       
  2030                     }
       
  2031                 }
       
  2032             }
       
  2033         }
       
  2034 
       
  2035         if (!m) {
       
  2036             if (found) {
       
  2037                 if (p.action) {
       
  2038                     // Y.log('executing pattern action: ' + pname);
       
  2039                     p.action.call(this, mname, pname);
       
  2040                 } else {
       
  2041 Y.log('Undefined module: ' + mname + ', matched a pattern: ' +
       
  2042     pname, 'info', 'loader');
       
  2043                     // ext true or false?
       
  2044                     m = this.addModule(Y.merge(found), mname);
       
  2045                     if (found.configFn) {
       
  2046                         m.configFn = found.configFn;
       
  2047                     }
       
  2048                     m.temp = true;
       
  2049                 }
       
  2050             }
       
  2051         } else {
       
  2052             if (found && m && found.configFn && !m.configFn) {
       
  2053                 m.configFn = found.configFn;
       
  2054                 m.configFn(m);
       
  2055             }
       
  2056         }
       
  2057 
       
  2058         return m;
       
  2059     },
       
  2060 
       
  2061     // impl in rollup submodule
       
  2062     _rollup: function() { },
       
  2063 
       
  2064     /**
       
  2065      * Remove superceded modules and loaded modules.  Called by
       
  2066      * calculate() after we have the mega list of all dependencies
       
  2067      * @method _reduce
       
  2068      * @return {object} the reduced dependency hash.
       
  2069      * @private
       
  2070      */
       
  2071     _reduce: function(r) {
       
  2072 
       
  2073         r = r || this.required;
       
  2074 
       
  2075         var i, j, s, m, type = this.loadType,
       
  2076         ignore = this.ignore ? yArray.hash(this.ignore) : false;
       
  2077 
       
  2078         for (i in r) {
       
  2079             if (r.hasOwnProperty(i)) {
       
  2080                 m = this.getModule(i);
       
  2081                 // remove if already loaded
       
  2082                 if (((this.loaded[i] || ON_PAGE[i]) &&
       
  2083                         !this.forceMap[i] && !this.ignoreRegistered) ||
       
  2084                         (type && m && m.type !== type)) {
       
  2085                     delete r[i];
       
  2086                 }
       
  2087                 if (ignore && ignore[i]) {
       
  2088                     delete r[i];
       
  2089                 }
       
  2090                 // remove anything this module supersedes
       
  2091                 s = m && m.supersedes;
       
  2092                 if (s) {
       
  2093                     for (j = 0; j < s.length; j++) {
       
  2094                         if (s[j] in r) {
       
  2095                             delete r[s[j]];
       
  2096                         }
       
  2097                     }
       
  2098                 }
       
  2099             }
       
  2100         }
       
  2101 
       
  2102         return r;
       
  2103     },
       
  2104     /**
       
  2105     * Handles the queue when a module has been loaded for all cases
       
  2106     * @method _finish
       
  2107     * @private
       
  2108     * @param {String} msg The message from Loader
       
  2109     * @param {Boolean} success A boolean denoting success or failure
       
  2110     */
       
  2111     _finish: function(msg, success) {
       
  2112         Y.log('loader finishing: ' + msg + ', ' + Y.id + ', ' +
       
  2113             this.data, 'info', 'loader');
       
  2114 
       
  2115         _queue.running = false;
       
  2116 
       
  2117         var onEnd = this.onEnd;
       
  2118         if (onEnd) {
       
  2119             onEnd.call(this.context, {
       
  2120                 msg: msg,
       
  2121                 data: this.data,
       
  2122                 success: success
       
  2123             });
       
  2124         }
       
  2125         this._continue();
       
  2126     },
       
  2127     /**
       
  2128     * The default Loader onSuccess handler, calls this.onSuccess with a payload
       
  2129     * @method _onSuccess
       
  2130     * @private
       
  2131     */
       
  2132     _onSuccess: function() {
       
  2133         var self = this, skipped = Y.merge(self.skipped), fn,
       
  2134             failed = [], rreg = self.requireRegistration,
       
  2135             success, msg, i, mod;
       
  2136 
       
  2137         for (i in skipped) {
       
  2138             if (skipped.hasOwnProperty(i)) {
       
  2139                 delete self.inserted[i];
       
  2140             }
       
  2141         }
       
  2142 
       
  2143         self.skipped = {};
       
  2144 
       
  2145         for (i in self.inserted) {
       
  2146             if (self.inserted.hasOwnProperty(i)) {
       
  2147                 mod = self.getModule(i);
       
  2148                 if (mod && rreg && mod.type === JS && !(i in YUI.Env.mods)) {
       
  2149                     failed.push(i);
       
  2150                 } else {
       
  2151                     Y.mix(self.loaded, self.getProvides(i));
       
  2152                 }
       
  2153             }
       
  2154         }
       
  2155 
       
  2156         fn = self.onSuccess;
       
  2157         msg = (failed.length) ? 'notregistered' : 'success';
       
  2158         success = !(failed.length);
       
  2159         if (fn) {
       
  2160             fn.call(self.context, {
       
  2161                 msg: msg,
       
  2162                 data: self.data,
       
  2163                 success: success,
       
  2164                 failed: failed,
       
  2165                 skipped: skipped
       
  2166             });
       
  2167         }
       
  2168         self._finish(msg, success);
       
  2169     },
       
  2170     /**
       
  2171     * The default Loader onProgress handler, calls this.onProgress with a payload
       
  2172     * @method _onProgress
       
  2173     * @private
       
  2174     */
       
  2175     _onProgress: function(e) {
       
  2176         var self = this, i;
       
  2177         //set the internal cache to what just came in.
       
  2178         if (e.data && e.data.length) {
       
  2179             for (i = 0; i < e.data.length; i++) {
       
  2180                 e.data[i] = self.getModule(e.data[i].name);
       
  2181             }
       
  2182         }
       
  2183         if (self.onProgress) {
       
  2184             self.onProgress.call(self.context, {
       
  2185                 name: e.url,
       
  2186                 data: e.data
       
  2187             });
       
  2188         }
       
  2189     },
       
  2190     /**
       
  2191     * The default Loader onFailure handler, calls this.onFailure with a payload
       
  2192     * @method _onFailure
       
  2193     * @private
       
  2194     */
       
  2195     _onFailure: function(o) {
       
  2196         var f = this.onFailure, msg = [], i = 0, len = o.errors.length;
       
  2197 
       
  2198         for (i; i < len; i++) {
       
  2199             msg.push(o.errors[i].error);
       
  2200         }
       
  2201 
       
  2202         msg = msg.join(',');
       
  2203 
       
  2204         Y.log('load error: ' + msg + ', ' + Y.id, 'error', 'loader');
       
  2205 
       
  2206         if (f) {
       
  2207             f.call(this.context, {
       
  2208                 msg: msg,
       
  2209                 data: this.data,
       
  2210                 success: false
       
  2211             });
       
  2212         }
       
  2213 
       
  2214         this._finish(msg, false);
       
  2215 
       
  2216     },
       
  2217 
       
  2218     /**
       
  2219     * The default Loader onTimeout handler, calls this.onTimeout with a payload
       
  2220     * @method _onTimeout
       
  2221     * @param {Get.Transaction} transaction The Transaction object from `Y.Get`
       
  2222     * @private
       
  2223     */
       
  2224     _onTimeout: function(transaction) {
       
  2225         Y.log('loader timeout: ' + Y.id, 'error', 'loader');
       
  2226         var f = this.onTimeout;
       
  2227         if (f) {
       
  2228             f.call(this.context, {
       
  2229                 msg: 'timeout',
       
  2230                 data: this.data,
       
  2231                 success: false,
       
  2232                 transaction: transaction
       
  2233             });
       
  2234         }
       
  2235     },
       
  2236 
       
  2237     /**
       
  2238      * Sorts the dependency tree.  The last step of calculate()
       
  2239      * @method _sort
       
  2240      * @private
       
  2241      */
       
  2242     _sort: function() {
       
  2243 
       
  2244         // create an indexed list
       
  2245         var s = YObject.keys(this.required),
       
  2246             // loaded = this.loaded,
       
  2247             //TODO Move this out of scope
       
  2248             done = {},
       
  2249             p = 0, l, a, b, j, k, moved, doneKey;
       
  2250 
       
  2251         // keep going until we make a pass without moving anything
       
  2252         for (;;) {
       
  2253 
       
  2254             l = s.length;
       
  2255             moved = false;
       
  2256 
       
  2257             // start the loop after items that are already sorted
       
  2258             for (j = p; j < l; j++) {
       
  2259 
       
  2260                 // check the next module on the list to see if its
       
  2261                 // dependencies have been met
       
  2262                 a = s[j];
       
  2263 
       
  2264                 // check everything below current item and move if we
       
  2265                 // find a requirement for the current item
       
  2266                 for (k = j + 1; k < l; k++) {
       
  2267                     doneKey = a + s[k];
       
  2268 
       
  2269                     if (!done[doneKey] && this._requires(a, s[k])) {
       
  2270 
       
  2271                         // extract the dependency so we can move it up
       
  2272                         b = s.splice(k, 1);
       
  2273 
       
  2274                         // insert the dependency above the item that
       
  2275                         // requires it
       
  2276                         s.splice(j, 0, b[0]);
       
  2277 
       
  2278                         // only swap two dependencies once to short circut
       
  2279                         // circular dependencies
       
  2280                         done[doneKey] = true;
       
  2281 
       
  2282                         // keep working
       
  2283                         moved = true;
       
  2284 
       
  2285                         break;
       
  2286                     }
       
  2287                 }
       
  2288 
       
  2289                 // jump out of loop if we moved something
       
  2290                 if (moved) {
       
  2291                     break;
       
  2292                 // this item is sorted, move our pointer and keep going
       
  2293                 } else {
       
  2294                     p++;
       
  2295                 }
       
  2296             }
       
  2297 
       
  2298             // when we make it here and moved is false, we are
       
  2299             // finished sorting
       
  2300             if (!moved) {
       
  2301                 break;
       
  2302             }
       
  2303 
       
  2304         }
       
  2305 
       
  2306         this.sorted = s;
       
  2307     },
       
  2308 
       
  2309     /**
       
  2310     * Handles the actual insertion of script/link tags
       
  2311     * @method _insert
       
  2312     * @private
       
  2313     * @param {Object} source The YUI instance the request came from
       
  2314     * @param {Object} o The metadata to include
       
  2315     * @param {String} type JS or CSS
       
  2316     * @param {Boolean} [skipcalc=false] Do a Loader.calculate on the meta
       
  2317     */
       
  2318     _insert: function(source, o, type, skipcalc) {
       
  2319 
       
  2320         Y.log('private _insert() ' + (type || '') + ', ' + Y.id, "info", "loader");
       
  2321 
       
  2322         // restore the state at the time of the request
       
  2323         if (source) {
       
  2324             this._config(source);
       
  2325         }
       
  2326 
       
  2327         // build the dependency list
       
  2328         // don't include type so we can process CSS and script in
       
  2329         // one pass when the type is not specified.
       
  2330 
       
  2331         var modules = this.resolve(!skipcalc),
       
  2332             self = this, comp = 0, actions = 0,
       
  2333             mods = {}, deps, complete;
       
  2334 
       
  2335         self._refetch = [];
       
  2336 
       
  2337         if (type) {
       
  2338             //Filter out the opposite type and reset the array so the checks later work
       
  2339             modules[((type === JS) ? CSS : JS)] = [];
       
  2340         }
       
  2341         if (!self.fetchCSS) {
       
  2342             modules.css = [];
       
  2343         }
       
  2344         if (modules.js.length) {
       
  2345             comp++;
       
  2346         }
       
  2347         if (modules.css.length) {
       
  2348             comp++;
       
  2349         }
       
  2350 
       
  2351         //console.log('Resolved Modules: ', modules);
       
  2352 
       
  2353         complete = function(d) {
       
  2354             actions++;
       
  2355             var errs = {}, i = 0, o = 0, u = '', fn,
       
  2356                 modName, resMods;
       
  2357 
       
  2358             if (d && d.errors) {
       
  2359                 for (i = 0; i < d.errors.length; i++) {
       
  2360                     if (d.errors[i].request) {
       
  2361                         u = d.errors[i].request.url;
       
  2362                     } else {
       
  2363                         u = d.errors[i];
       
  2364                     }
       
  2365                     errs[u] = u;
       
  2366                 }
       
  2367             }
       
  2368 
       
  2369             if (d && d.data && d.data.length && (d.type === 'success')) {
       
  2370                 for (i = 0; i < d.data.length; i++) {
       
  2371                     self.inserted[d.data[i].name] = true;
       
  2372                     //If the external module has a skin or a lang, reprocess it
       
  2373                     if (d.data[i].lang || d.data[i].skinnable) {
       
  2374                         delete self.inserted[d.data[i].name];
       
  2375                         self._refetch.push(d.data[i].name);
       
  2376                     }
       
  2377                 }
       
  2378             }
       
  2379 
       
  2380             if (actions === comp) {
       
  2381                 self._loading = null;
       
  2382                 Y.log('Loader actions complete!', 'info', 'loader');
       
  2383                 if (self._refetch.length) {
       
  2384                     //Get the deps for the new meta-data and reprocess
       
  2385                     Y.log('Found potential modules to refetch', 'info', 'loader');
       
  2386                     for (i = 0; i < self._refetch.length; i++) {
       
  2387                         deps = self.getRequires(self.getModule(self._refetch[i]));
       
  2388                         for (o = 0; o < deps.length; o++) {
       
  2389                             if (!self.inserted[deps[o]]) {
       
  2390                                 //We wouldn't be to this point without the module being here
       
  2391                                 mods[deps[o]] = deps[o];
       
  2392                             }
       
  2393                         }
       
  2394                     }
       
  2395                     mods = Y.Object.keys(mods);
       
  2396                     if (mods.length) {
       
  2397                         Y.log('Refetching modules with new meta-data', 'info', 'loader');
       
  2398                         self.require(mods);
       
  2399                         resMods = self.resolve(true);
       
  2400                         if (resMods.cssMods.length) {
       
  2401                             for (i=0; i <  resMods.cssMods.length; i++) {
       
  2402                                 modName = resMods.cssMods[i].name;
       
  2403                                 delete YUI.Env._cssLoaded[modName];
       
  2404                                 if (self.isCSSLoaded(modName)) {
       
  2405                                     self.inserted[modName] = true;
       
  2406                                     delete self.required[modName];
       
  2407                                 }
       
  2408                             }
       
  2409                             self.sorted = [];
       
  2410                             self._sort();
       
  2411                         }
       
  2412                         d = null; //bail
       
  2413                         self._insert(); //insert the new deps
       
  2414                     }
       
  2415                 }
       
  2416                 if (d && d.fn) {
       
  2417                     Y.log('Firing final Loader callback!', 'info', 'loader');
       
  2418                     fn = d.fn;
       
  2419                     delete d.fn;
       
  2420                     fn.call(self, d);
       
  2421                 }
       
  2422             }
       
  2423         };
       
  2424 
       
  2425         this._loading = true;
       
  2426 
       
  2427         if (!modules.js.length && !modules.css.length) {
       
  2428             Y.log('No modules resolved..', 'warn', 'loader');
       
  2429             actions = -1;
       
  2430             complete({
       
  2431                 fn: self._onSuccess
       
  2432             });
       
  2433             return;
       
  2434         }
       
  2435 
       
  2436 
       
  2437         if (modules.css.length) { //Load CSS first
       
  2438             Y.log('Loading CSS modules', 'info', 'loader');
       
  2439             Y.Get.css(modules.css, {
       
  2440                 data: modules.cssMods,
       
  2441                 attributes: self.cssAttributes,
       
  2442                 insertBefore: self.insertBefore,
       
  2443                 charset: self.charset,
       
  2444                 timeout: self.timeout,
       
  2445                 context: self,
       
  2446                 onProgress: function(e) {
       
  2447                     self._onProgress.call(self, e);
       
  2448                 },
       
  2449                 onTimeout: function(d) {
       
  2450                     self._onTimeout.call(self, d);
       
  2451                 },
       
  2452                 onSuccess: function(d) {
       
  2453                     d.type = 'success';
       
  2454                     d.fn = self._onSuccess;
       
  2455                     complete.call(self, d);
       
  2456                 },
       
  2457                 onFailure: function(d) {
       
  2458                     d.type = 'failure';
       
  2459                     d.fn = self._onFailure;
       
  2460                     complete.call(self, d);
       
  2461                 }
       
  2462             });
       
  2463         }
       
  2464 
       
  2465         if (modules.js.length) {
       
  2466             Y.log('Loading JS modules', 'info', 'loader');
       
  2467             Y.Get.js(modules.js, {
       
  2468                 data: modules.jsMods,
       
  2469                 insertBefore: self.insertBefore,
       
  2470                 attributes: self.jsAttributes,
       
  2471                 charset: self.charset,
       
  2472                 timeout: self.timeout,
       
  2473                 autopurge: false,
       
  2474                 context: self,
       
  2475                 async: self.async,
       
  2476                 onProgress: function(e) {
       
  2477                     self._onProgress.call(self, e);
       
  2478                 },
       
  2479                 onTimeout: function(d) {
       
  2480                     self._onTimeout.call(self, d);
       
  2481                 },
       
  2482                 onSuccess: function(d) {
       
  2483                     d.type = 'success';
       
  2484                     d.fn = self._onSuccess;
       
  2485                     complete.call(self, d);
       
  2486                 },
       
  2487                 onFailure: function(d) {
       
  2488                     d.type = 'failure';
       
  2489                     d.fn = self._onFailure;
       
  2490                     complete.call(self, d);
       
  2491                 }
       
  2492             });
       
  2493         }
       
  2494     },
       
  2495     /**
       
  2496     * Once a loader operation is completely finished, process any additional queued items.
       
  2497     * @method _continue
       
  2498     * @private
       
  2499     */
       
  2500     _continue: function() {
       
  2501         if (!(_queue.running) && _queue.size() > 0) {
       
  2502             _queue.running = true;
       
  2503             _queue.next()();
       
  2504         }
       
  2505     },
       
  2506 
       
  2507     /**
       
  2508      * inserts the requested modules and their dependencies.
       
  2509      * <code>type</code> can be "js" or "css".  Both script and
       
  2510      * css are inserted if type is not provided.
       
  2511      * @method insert
       
  2512      * @param {object} o optional options object.
       
  2513      * @param {string} type the type of dependency to insert.
       
  2514      */
       
  2515     insert: function(o, type, skipsort) {
       
  2516          Y.log('public insert() ' + (type || '') + ', ' +
       
  2517          Y.Object.keys(this.required), "info", "loader");
       
  2518         var self = this, copy = Y.merge(this);
       
  2519         delete copy.require;
       
  2520         delete copy.dirty;
       
  2521         _queue.add(function() {
       
  2522             self._insert(copy, o, type, skipsort);
       
  2523         });
       
  2524         this._continue();
       
  2525     },
       
  2526 
       
  2527     /**
       
  2528      * Executed every time a module is loaded, and if we are in a load
       
  2529      * cycle, we attempt to load the next script.  Public so that it
       
  2530      * is possible to call this if using a method other than
       
  2531      * Y.register to determine when scripts are fully loaded
       
  2532      * @method loadNext
       
  2533      * @deprecated
       
  2534      * @param {string} mname optional the name of the module that has
       
  2535      * been loaded (which is usually why it is time to load the next
       
  2536      * one).
       
  2537      */
       
  2538     loadNext: function() {
       
  2539         Y.log('loadNext was called..', 'error', 'loader');
       
  2540         return;
       
  2541     },
       
  2542 
       
  2543     /**
       
  2544      * Apply filter defined for this instance to a url/path
       
  2545      * @method _filter
       
  2546      * @param {string} u the string to filter.
       
  2547      * @param {string} name the name of the module, if we are processing
       
  2548      * a single module as opposed to a combined url.
       
  2549      * @return {string} the filtered string.
       
  2550      * @private
       
  2551      */
       
  2552     _filter: function(u, name, group) {
       
  2553         var f = this.filter,
       
  2554             hasFilter = name && (name in this.filters),
       
  2555             modFilter = hasFilter && this.filters[name],
       
  2556             groupName = group || (this.moduleInfo[name] ? this.moduleInfo[name].group : null);
       
  2557 
       
  2558         if (groupName && this.groups[groupName] && this.groups[groupName].filter) {
       
  2559             modFilter = this.groups[groupName].filter;
       
  2560             hasFilter = true;
       
  2561         }
       
  2562 
       
  2563         if (u) {
       
  2564             if (hasFilter) {
       
  2565                 f = (L.isString(modFilter)) ? this.FILTER_DEFS[modFilter.toUpperCase()] || null : modFilter;
       
  2566             }
       
  2567             if (f) {
       
  2568                 u = u.replace(new RegExp(f.searchExp, 'g'), f.replaceStr);
       
  2569             }
       
  2570         }
       
  2571         return u;
       
  2572     },
       
  2573 
       
  2574     /**
       
  2575      * Generates the full url for a module
       
  2576      * @method _url
       
  2577      * @param {string} path the path fragment.
       
  2578      * @param {String} name The name of the module
       
  2579      * @param {String} [base=self.base] The base url to use
       
  2580      * @return {string} the full url.
       
  2581      * @private
       
  2582      */
       
  2583     _url: function(path, name, base) {
       
  2584         return this._filter((base || this.base || '') + path, name);
       
  2585     },
       
  2586     /**
       
  2587     * Returns an Object hash of file arrays built from `loader.sorted` or from an arbitrary list of sorted modules.
       
  2588     * @method resolve
       
  2589     * @param {Boolean} [calc=false] Perform a loader.calculate() before anything else
       
  2590     * @param {Array} [s=loader.sorted] An override for the loader.sorted array
       
  2591     * @return {Object} Object hash (js and css) of two arrays of file lists
       
  2592     * @example This method can be used as an off-line dep calculator
       
  2593     *
       
  2594     *        var Y = YUI();
       
  2595     *        var loader = new Y.Loader({
       
  2596     *            filter: 'debug',
       
  2597     *            base: '../../',
       
  2598     *            root: 'build/',
       
  2599     *            combine: true,
       
  2600     *            require: ['node', 'dd', 'console']
       
  2601     *        });
       
  2602     *        var out = loader.resolve(true);
       
  2603     *
       
  2604     */
       
  2605     resolve: function(calc, s) {
       
  2606 
       
  2607         var len, i, m, url, group, groupName, j, frag,
       
  2608             comboSource, comboSources, mods, comboBase,
       
  2609             base, urls, u = [], tmpBase, baseLen, resCombos = {},
       
  2610             self = this, comboSep, maxURLLength,
       
  2611             inserted = (self.ignoreRegistered) ? {} : self.inserted,
       
  2612             resolved = { js: [], jsMods: [], css: [], cssMods: [] },
       
  2613             type = self.loadType || 'js', addSingle;
       
  2614 
       
  2615         if (self.skin.overrides || self.skin.defaultSkin !== DEFAULT_SKIN || self.ignoreRegistered) {
       
  2616             self._resetModules();
       
  2617         }
       
  2618 
       
  2619         if (calc) {
       
  2620             self.calculate();
       
  2621         }
       
  2622         s = s || self.sorted;
       
  2623 
       
  2624         addSingle = function(m) {
       
  2625 
       
  2626             if (m) {
       
  2627                 group = (m.group && self.groups[m.group]) || NOT_FOUND;
       
  2628 
       
  2629                 //Always assume it's async
       
  2630                 if (group.async === false) {
       
  2631                     m.async = group.async;
       
  2632                 }
       
  2633 
       
  2634                 url = (m.fullpath) ? self._filter(m.fullpath, s[i]) :
       
  2635                       self._url(m.path, s[i], group.base || m.base);
       
  2636 
       
  2637                 if (m.attributes || m.async === false) {
       
  2638                     url = {
       
  2639                         url: url,
       
  2640                         async: m.async
       
  2641                     };
       
  2642                     if (m.attributes) {
       
  2643                         url.attributes = m.attributes;
       
  2644                     }
       
  2645                 }
       
  2646                 resolved[m.type].push(url);
       
  2647                 resolved[m.type + 'Mods'].push(m);
       
  2648             } else {
       
  2649                 Y.log('Undefined Module', 'warn', 'loader');
       
  2650             }
       
  2651 
       
  2652         };
       
  2653 
       
  2654         len = s.length;
       
  2655 
       
  2656         // the default combo base
       
  2657         comboBase = self.comboBase;
       
  2658 
       
  2659         url = comboBase;
       
  2660 
       
  2661         comboSources = {};
       
  2662 
       
  2663         for (i = 0; i < len; i++) {
       
  2664             comboSource = comboBase;
       
  2665             m = self.getModule(s[i]);
       
  2666             groupName = m && m.group;
       
  2667             group = self.groups[groupName];
       
  2668             if (groupName && group) {
       
  2669 
       
  2670                 if (!group.combine || m.fullpath) {
       
  2671                     //This is not a combo module, skip it and load it singly later.
       
  2672                     addSingle(m);
       
  2673                     continue;
       
  2674                 }
       
  2675                 m.combine = true;
       
  2676                 if (group.comboBase) {
       
  2677                     comboSource = group.comboBase;
       
  2678                 }
       
  2679 
       
  2680                 if ("root" in group && L.isValue(group.root)) {
       
  2681                     m.root = group.root;
       
  2682                 }
       
  2683                 m.comboSep = group.comboSep || self.comboSep;
       
  2684                 m.maxURLLength = group.maxURLLength || self.maxURLLength;
       
  2685             } else {
       
  2686                 if (!self.combine) {
       
  2687                     //This is not a combo module, skip it and load it singly later.
       
  2688                     addSingle(m);
       
  2689                     continue;
       
  2690                 }
       
  2691             }
       
  2692 
       
  2693             comboSources[comboSource] = comboSources[comboSource] || [];
       
  2694             comboSources[comboSource].push(m);
       
  2695         }
       
  2696 
       
  2697         for (j in comboSources) {
       
  2698             if (comboSources.hasOwnProperty(j)) {
       
  2699                 resCombos[j] = resCombos[j] || { js: [], jsMods: [], css: [], cssMods: [] };
       
  2700                 url = j;
       
  2701                 mods = comboSources[j];
       
  2702                 len = mods.length;
       
  2703 
       
  2704                 if (len) {
       
  2705                     for (i = 0; i < len; i++) {
       
  2706                         if (inserted[mods[i]]) {
       
  2707                             continue;
       
  2708                         }
       
  2709                         m = mods[i];
       
  2710                         // Do not try to combine non-yui JS unless combo def
       
  2711                         // is found
       
  2712                         if (m && (m.combine || !m.ext)) {
       
  2713                             resCombos[j].comboSep = m.comboSep;
       
  2714                             resCombos[j].group = m.group;
       
  2715                             resCombos[j].maxURLLength = m.maxURLLength;
       
  2716                             frag = ((L.isValue(m.root)) ? m.root : self.root) + (m.path || m.fullpath);
       
  2717                             frag = self._filter(frag, m.name);
       
  2718                             resCombos[j][m.type].push(frag);
       
  2719                             resCombos[j][m.type + 'Mods'].push(m);
       
  2720                         } else {
       
  2721                             //Add them to the next process..
       
  2722                             if (mods[i]) {
       
  2723                                 addSingle(mods[i]);
       
  2724                             }
       
  2725                         }
       
  2726 
       
  2727                     }
       
  2728                 }
       
  2729             }
       
  2730         }
       
  2731 
       
  2732 
       
  2733         for (j in resCombos) {
       
  2734             if (resCombos.hasOwnProperty(j)) {
       
  2735                 base = j;
       
  2736                 comboSep = resCombos[base].comboSep || self.comboSep;
       
  2737                 maxURLLength = resCombos[base].maxURLLength || self.maxURLLength;
       
  2738                 Y.log('Using maxURLLength of ' + maxURLLength, 'info', 'loader');
       
  2739                 for (type in resCombos[base]) {
       
  2740                     if (type === JS || type === CSS) {
       
  2741                         urls = resCombos[base][type];
       
  2742                         mods = resCombos[base][type + 'Mods'];
       
  2743                         len = urls.length;
       
  2744                         tmpBase = base + urls.join(comboSep);
       
  2745                         baseLen = tmpBase.length;
       
  2746                         if (maxURLLength <= base.length) {
       
  2747                             Y.log('maxURLLength (' + maxURLLength + ') is lower than the comboBase length (' + base.length + '), resetting to default (' + MAX_URL_LENGTH + ')', 'error', 'loader');
       
  2748                             maxURLLength = MAX_URL_LENGTH;
       
  2749                         }
       
  2750 
       
  2751                         if (len) {
       
  2752                             if (baseLen > maxURLLength) {
       
  2753                                 Y.log('Exceeded maxURLLength (' + maxURLLength + ') for ' + type + ', splitting', 'info', 'loader');
       
  2754                                 u = [];
       
  2755                                 for (s = 0; s < len; s++) {
       
  2756                                     u.push(urls[s]);
       
  2757                                     tmpBase = base + u.join(comboSep);
       
  2758 
       
  2759                                     if (tmpBase.length > maxURLLength) {
       
  2760                                         m = u.pop();
       
  2761                                         tmpBase = base + u.join(comboSep);
       
  2762                                         resolved[type].push(self._filter(tmpBase, null, resCombos[base].group));
       
  2763                                         u = [];
       
  2764                                         if (m) {
       
  2765                                             u.push(m);
       
  2766                                         }
       
  2767                                     }
       
  2768                                 }
       
  2769                                 if (u.length) {
       
  2770                                     tmpBase = base + u.join(comboSep);
       
  2771                                     resolved[type].push(self._filter(tmpBase, null, resCombos[base].group));
       
  2772                                 }
       
  2773                             } else {
       
  2774                                 resolved[type].push(self._filter(tmpBase, null, resCombos[base].group));
       
  2775                             }
       
  2776                         }
       
  2777                         resolved[type + 'Mods'] = resolved[type + 'Mods'].concat(mods);
       
  2778                     }
       
  2779                 }
       
  2780             }
       
  2781         }
       
  2782 
       
  2783         resCombos = null;
       
  2784 
       
  2785         return resolved;
       
  2786     },
       
  2787     /**
       
  2788     Shortcut to calculate, resolve and load all modules.
       
  2789 
       
  2790         var loader = new Y.Loader({
       
  2791             ignoreRegistered: true,
       
  2792             modules: {
       
  2793                 mod: {
       
  2794                     path: 'mod.js'
       
  2795                 }
       
  2796             },
       
  2797             requires: [ 'mod' ]
       
  2798         });
       
  2799         loader.load(function() {
       
  2800             console.log('All modules have loaded..');
       
  2801         });
       
  2802 
       
  2803 
       
  2804     @method load
       
  2805     @param {Callback} cb Executed after all load operations are complete
       
  2806     */
       
  2807     load: function(cb) {
       
  2808         if (!cb) {
       
  2809             Y.log('No callback supplied to load()', 'error', 'loader');
       
  2810             return;
       
  2811         }
       
  2812         var self = this,
       
  2813             out = self.resolve(true);
       
  2814 
       
  2815         self.data = out;
       
  2816 
       
  2817         self.onEnd = function() {
       
  2818             cb.apply(self.context || self, arguments);
       
  2819         };
       
  2820 
       
  2821         self.insert();
       
  2822     }
       
  2823 };
       
  2824 
       
  2825 
       
  2826 
       
  2827 }, '@VERSION@', {"requires": ["get", "features"]});