]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/loader/loader.js
Release 6.2.0beta4
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / loader / loader.js
1 /*
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 3.0.0
6 build: 1549
7 */
8 YUI.add('loader', function(Y) {
9
10 (function() {
11 /**
12  * Loader dynamically loads script and css files.  It includes the dependency
13  * info for the version of the library in use, and will automatically pull in
14  * dependencies for the modules requested.  It supports rollup files and will
15  * automatically use these when appropriate in order to minimize the number of
16  * http connections required to load all of the dependencies.  It can load the
17  * files from the Yahoo! CDN, and it can utilize the combo service provided on
18  * this network to reduce the number of http connections required to download 
19  * YUI files.
20  *
21  * @module loader
22  */
23
24 /**
25  * Loader dynamically loads script and css files.  It includes the dependency
26  * info for the version of the library in use, and will automatically pull in
27  * dependencies for the modules requested.  It supports rollup files and will
28  * automatically use these when appropriate in order to minimize the number of
29  * http connections required to load all of the dependencies.  It can load the
30  * files from the Yahoo! CDN, and it can utilize the combo service provided on
31  * this network to reduce the number of http connections required to download 
32  * YUI files.
33  *
34  * While the loader can be instantiated by the end user, it normally is not.
35  * @see YUI.use for the normal use case.  The use function automatically will
36  * pull in missing dependencies.
37  *
38  * @class Loader
39  * @constructor
40  * @param o an optional set of configuration options.  Valid options:
41  * <ul>
42  *  <li>base:
43  *  The base dir</li>
44  *  <li>secureBase:
45  *  The secure base dir (not implemented)</li>
46  *  <li>comboBase:
47  *  The YUI combo service base dir. Ex: http://yui.yahooapis.com/combo?</li>
48  *  <li>root:
49  *  The root path to prepend to module names for the combo service. Ex: 2.5.2/build/</li>
50  *  <li>filter:
51  *  
52  * A filter to apply to result urls.  This filter will modify the default
53  * path for all modules.  The default path for the YUI library is the
54  * minified version of the files (e.g., event-min.js).  The filter property
55  * can be a predefined filter or a custom filter.  The valid predefined 
56  * filters are:
57  * <dl>
58  *  <dt>DEBUG</dt>
59  *  <dd>Selects the debug versions of the library (e.g., event-debug.js).
60  *      This option will automatically include the Logger widget</dd>
61  *  <dt>RAW</dt>
62  *  <dd>Selects the non-minified version of the library (e.g., event.js).</dd>
63  * </dl>
64  * You can also define a custom filter, which must be an object literal 
65  * containing a search expression and a replace string:
66  * <pre>
67  *  myFilter: &#123; 
68  *      'searchExp': "-min\\.js", 
69  *      'replaceStr': "-debug.js"
70  *  &#125;
71  * </pre>
72  *
73  *  </li>
74  *  <li>filters: per-component filter specification.  If specified for a given component, this overrides the filter config</li>
75  *  <li>combine:
76  *  Use the YUI combo service to reduce the number of http connections required to load your dependencies</li>
77  *  <li>ignore:
78  *  A list of modules that should never be dynamically loaded</li>
79  *  <li>force:
80  *  A list of modules that should always be loaded when required, even if already present on the page</li>
81  *  <li>insertBefore:
82  *  Node or id for a node that should be used as the insertion point for new nodes</li>
83  *  <li>charset:
84  *  charset for dynamic nodes (deprecated, use jsAttributes or cssAttributes)</li>
85  *  <li>jsAttributes: object literal containing attributes to add to script nodes</li>
86  *  <li>cssAttributes: object literal containing attributes to add to link nodes</li>
87  *  <li>timeout:
88  *  number of milliseconds before a timeout occurs when dynamically loading nodes.  in not set, there is no timeout</li>
89  *  <li>context:
90  *  execution context for all callbacks</li>
91  *  <li>onSuccess:
92  *  callback for the 'success' event</li>
93  *  <li>onFailure: callback for the 'failure' event</li>
94  *  <li>onCSS: callback for the 'CSSComplete' event.  When loading YUI components with CSS
95  *  the CSS is loaded first, then the script.  This provides a moment you can tie into to improve
96  *  the presentation of the page while the script is loading.</li>
97  *  <li>onTimeout:
98  *  callback for the 'timeout' event</li>
99  *  <li>onProgress:
100  *  callback executed each time a script or css file is loaded</li>
101  *  <li>modules:
102  *  A list of module definitions.  See Loader.addModule for the supported module metadata</li>
103  * </ul>
104  */
105
106 /*
107  * Global loader queue
108  * @property _loaderQueue
109  * @type Queue
110  * @private
111  */
112 YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Y.Queue();
113
114 var NOT_FOUND = {},
115     GLOBAL_ENV = YUI.Env,
116     GLOBAL_LOADED,
117     BASE = 'base', 
118     CSS = 'css',
119     JS = 'js',
120     CSSRESET = 'cssreset',
121     CSSFONTS = 'cssfonts',
122     CSSGRIDS = 'cssgrids',
123     CSSBASE  = 'cssbase',
124     CSS_AFTER = [CSSRESET, CSSFONTS, CSSGRIDS, 
125                  'cssreset-context', 'cssfonts-context', 'cssgrids-context'],
126     YUI_CSS = ['reset', 'fonts', 'grids', BASE],
127     VERSION = Y.version,
128     ROOT = VERSION + '/build/',
129     CONTEXT = '-context',
130
131     ANIMBASE = 'anim-base',
132         ATTRIBUTE = 'attribute',
133     ATTRIBUTEBASE = ATTRIBUTE + '-base',
134     BASEBASE = 'base-base',
135     DDDRAG = 'dd-drag',
136     DOM = 'dom',
137     DATASCHEMABASE = 'dataschema-base',
138     DATASOURCELOCAL = 'datasource-local',
139     DOMBASE = 'dom-base',
140     DOMSTYLE = 'dom-style',
141     DOMSCREEN = 'dom-screen',
142     DUMP = 'dump',
143     GET = 'get',
144     EVENTBASE = 'event-base',
145     EVENTCUSTOM = 'event-custom',
146     EVENTCUSTOMBASE = 'event-custom-base',
147     IOBASE = 'io-base',
148     NODE = 'node',
149     NODEBASE = 'node-base',
150     NODESTYLE = 'node-style',
151     NODESCREEN = 'node-screen',
152     OOP = 'oop',
153     PLUGINHOST = 'pluginhost',
154     SELECTORCSS2 = 'selector-css2',
155     SUBSTITUTE = 'substitute',
156     WIDGET = 'widget',
157     WIDGETPOSITION = 'widget-position',
158     YUIBASE = 'yui-base',
159
160         PLUGIN = 'plugin',
161
162     META = {
163
164     version: VERSION,
165
166     root: ROOT,
167
168     base: 'http://yui.yahooapis.com/' + ROOT,
169
170     comboBase: 'http://yui.yahooapis.com/combo?',
171
172     skin: {
173         defaultSkin: 'sam',
174         base: 'assets/skins/',
175         path: 'skin.css',
176         after: CSS_AFTER
177         //rollup: 3
178     },
179
180     modules: {
181
182        dom: {
183             requires: [OOP],
184             submodules: {
185
186                 'dom-base': {
187                     requires: [OOP]
188                 },
189
190                 'dom-style': {
191                     requires: [DOMBASE]
192                 },
193
194                 'dom-screen': {
195                     requires: [DOMBASE, DOMSTYLE]
196                 },
197
198                 'selector-native': {
199                     requires: [DOMBASE]
200                 },
201
202                 'selector-css2': {
203                     requires: ['selector-native']
204                 },
205
206                 'selector': {
207                     requires: [DOMBASE]
208                 }
209
210             },
211
212             plugins: {
213                 'selector-css3': {
214                     requires: [SELECTORCSS2]
215                 }
216             }
217         },
218
219         node: {
220             requires: [DOM, EVENTBASE],
221             // expound: EVENT,
222
223             submodules: {
224                 'node-base': {
225                     requires: [DOMBASE, SELECTORCSS2, EVENTBASE]
226                 },
227
228                 'node-style': {
229                     requires: [DOMSTYLE, NODEBASE]
230                 },
231
232                 'node-screen': {
233                     requires: [DOMSCREEN, NODEBASE]
234                 },
235
236                 'node-pluginhost': {
237                     requires: [NODEBASE, PLUGINHOST]
238                 },
239
240
241                 'node-event-delegate': {
242                     requires: [NODEBASE, 'event-delegate']
243                 }
244             },
245
246             plugins: {
247                 'node-event-simulate': {
248                     requires: [NODEBASE, 'event-simulate']
249                 }
250             }
251         },
252
253         anim: {
254             submodules: {
255
256                 'anim-base': {
257                     requires: [BASEBASE, NODESTYLE]
258                 },
259
260                 'anim-color': {
261                     requires: [ANIMBASE]
262                 },
263
264                 'anim-easing': {
265                     requires: [ANIMBASE]
266                 },
267
268                 'anim-scroll': {
269                     requires: [ANIMBASE]
270                 },
271
272                 'anim-xy': {
273                     requires: [ANIMBASE, NODESCREEN]
274                 },
275
276                 'anim-curve': {
277                     requires: ['anim-xy']
278                 },
279
280                 'anim-node-plugin': {
281                      requires: ['node-pluginhost', ANIMBASE]
282                 }
283             }
284         },
285
286         attribute: { 
287             submodules: {
288                 'attribute-base': {
289                     requires: [EVENTCUSTOM]
290                 },
291
292                 'attribute-complex': {
293                     requires: [ATTRIBUTEBASE]
294                 }
295             }
296         },
297
298         base: {
299             submodules: {
300                 'base-base': {
301                     requires: [ATTRIBUTEBASE]
302                 },
303
304                 'base-build': {
305                     requires: [BASEBASE]
306                 },
307
308                 'base-pluginhost': {
309                     requires: [BASEBASE, PLUGINHOST]
310                 }
311             }
312         },
313
314         cache: { 
315             requires: [PLUGIN]
316         },
317         
318         compat: { 
319             requires: [NODE, DUMP, SUBSTITUTE]
320         },
321
322         classnamemanager: { 
323             requires: [YUIBASE]
324         },
325
326         collection: { 
327             requires: [OOP]
328         },
329
330         console: {
331             requires: ['yui-log', WIDGET, SUBSTITUTE],
332             skinnable: true,
333             plugins: {
334                 'console-filters': {
335                     requires: [PLUGIN, 'console'],
336                     skinnable: true
337                 }
338             }
339         },
340         
341         cookie: { 
342             requires: [YUIBASE]
343         },
344
345         dataschema:{
346             submodules: {
347                 'dataschema-base': {
348                     requires: [BASE]
349                 },
350                 'dataschema-array': {
351                     requires: [DATASCHEMABASE]
352                 },
353                 'dataschema-json': {
354                     requires: [DATASCHEMABASE, 'json']
355                 },
356                 'dataschema-text': {
357                     requires: [DATASCHEMABASE]
358                 },
359                 'dataschema-xml': {
360                     requires: [DATASCHEMABASE]
361                 }
362             }
363         },
364
365         datasource:{
366             submodules: {
367                 'datasource-local': {
368                     requires: [BASE]
369                 },
370                 'datasource-arrayschema': {
371                     requires: [DATASOURCELOCAL, PLUGIN, 'dataschema-array']
372                 },
373                 'datasource-cache': {
374                     requires: [DATASOURCELOCAL, 'cache']
375                 },
376                 'datasource-function': {
377                     requires: [DATASOURCELOCAL]
378                 },
379                 'datasource-jsonschema': {
380                     requires: [DATASOURCELOCAL, PLUGIN, 'dataschema-json']
381                 },
382                 'datasource-polling': {
383                     requires: [DATASOURCELOCAL]
384                 },
385                 'datasource-get': {
386                     requires: [DATASOURCELOCAL, GET]
387                 },
388                 'datasource-textschema': {
389                     requires: [DATASOURCELOCAL, PLUGIN, 'dataschema-text']
390                 },
391                 'datasource-io': {
392                     requires: [DATASOURCELOCAL, IOBASE]
393                 },
394                 'datasource-xmlschema': {
395                     requires: [DATASOURCELOCAL, PLUGIN, 'dataschema-xml']
396                 }
397             }
398         },
399
400         datatype:{
401             submodules: {
402                 'datatype-date': {
403                     requires: [YUIBASE]
404                 },
405                 'datatype-number': {
406                     requires: [YUIBASE]
407                 },
408                 'datatype-xml': {
409                     requires: [YUIBASE]
410                 }
411             }
412         },
413
414         dd:{
415             submodules: {
416                 'dd-ddm-base': {
417                     requires: [NODE, BASE]
418                 }, 
419                 'dd-ddm':{
420                     requires: ['dd-ddm-base', 'event-resize']
421                 }, 
422                 'dd-ddm-drop':{
423                     requires: ['dd-ddm']
424                 }, 
425                 'dd-drag':{
426                     requires: ['dd-ddm-base']
427                 }, 
428                 'dd-drop':{
429                     requires: ['dd-ddm-drop']
430                 }, 
431                 'dd-proxy':{
432                     requires: [DDDRAG]
433                 }, 
434                 'dd-constrain':{
435                     requires: [DDDRAG]
436                 }, 
437                 'dd-scroll':{
438                     requires: [DDDRAG]
439                 }, 
440                 'dd-plugin':{
441                     requires: [DDDRAG],
442                     optional: ['dd-constrain', 'dd-proxy']
443                 },
444                 'dd-drop-plugin':{
445                     requires: ['dd-drop']
446                 }
447             }
448         },
449
450         dump: { 
451             requires: [YUIBASE]
452         },
453
454         event: { 
455             expound: NODEBASE,
456             submodules: {
457                 'event-base': {
458                     expound: NODEBASE,
459                     requires: [EVENTCUSTOMBASE]
460                 },
461                 'event-delegate': {
462                     requires: [NODEBASE]
463                 },
464                 'event-focus': {
465                     requires: [NODEBASE]
466                 },
467                 'event-key': {
468                     requires: [NODEBASE]
469                 },
470                 'event-mouseenter': {
471                     requires: [NODEBASE]
472                 },
473                 'event-mousewheel': {
474                     requires: [NODEBASE]
475                 },
476                 'event-resize': {
477                     requires: [NODEBASE]
478                 }
479             }
480         },
481
482         'event-custom': { 
483             submodules: {
484                 'event-custom-base': {
485                     requires: [OOP, 'yui-later']
486                 },
487                 'event-custom-complex': {
488                     requires: [EVENTCUSTOMBASE]
489                 }
490             }
491         },
492
493         'event-simulate': { 
494             requires: [EVENTBASE]
495         },
496
497         'node-focusmanager': { 
498             requires: [ATTRIBUTE, NODE, PLUGIN, 'node-event-simulate', 'event-key', 'event-focus']
499         },
500
501         history: { 
502             requires: [NODE]
503         },
504
505         imageloader: { 
506             requires: [BASEBASE, NODESTYLE, NODESCREEN]
507         },
508
509         io:{
510             submodules: {
511
512                 'io-base': {
513                     requires: [EVENTCUSTOMBASE]
514                 }, 
515
516                 'io-xdr': {
517                     requires: [IOBASE, 'datatype-xml']
518                 }, 
519
520                 'io-form': {
521                     requires: [IOBASE, NODEBASE, NODESTYLE]
522                 }, 
523
524                 'io-upload-iframe': {
525                     requires: [IOBASE, NODEBASE]
526                 },
527
528                 'io-queue': {
529                     requires: [IOBASE, 'queue-promote']
530                 }
531             }
532         },
533
534         json: {
535             submodules: {
536                 'json-parse': {
537                     requires: [YUIBASE]
538                 },
539
540                 'json-stringify': {
541                     requires: [YUIBASE]
542                 }
543             }
544         },
545
546         loader: { 
547             requires: [GET]
548         },
549
550         'node-menunav': {
551             requires: [NODE, 'classnamemanager', PLUGIN, 'node-focusmanager'],
552             skinnable: true
553         },
554         
555         oop: { 
556             requires: [YUIBASE]
557         },
558
559         overlay: {
560             requires: [WIDGET, WIDGETPOSITION, 'widget-position-ext', 'widget-stack', 'widget-stdmod'],
561             skinnable: true
562         },
563
564         plugin: { 
565             requires: [BASEBASE]
566         },
567
568         pluginhost: { 
569             requires: [YUIBASE]
570         },
571
572         profiler: { 
573             requires: [YUIBASE]
574         },
575
576         'queue-promote': {
577             requires: [YUIBASE]
578         },
579
580         // deprecated package, replaced with async-queue
581         'queue-run': {
582             requires: [EVENTCUSTOM],
583             path: 'async-queue/async-queue-min.js'
584         },
585
586         'async-queue': {
587             requires: [EVENTCUSTOM],
588             supersedes: ['queue-run']
589         },
590
591         slider: {
592             requires: [WIDGET, 'dd-constrain'],
593             skinnable: true
594         },
595
596         stylesheet: { 
597             requires: [YUIBASE]
598         },
599
600         substitute: {
601             optional: [DUMP]
602         },
603
604         widget: {
605             requires: [ATTRIBUTE, 'event-focus', BASE, NODE, 'classnamemanager'],
606             plugins: {
607                 'widget-position': { },
608                 'widget-position-ext': {
609                     requires: [WIDGETPOSITION]
610                 },
611                 'widget-stack': {
612                     skinnable: true
613                 },
614                 'widget-stdmod': { }
615             },
616             skinnable: true
617         },
618
619         yui: {
620             submodules: {
621                 'yui-base': {},
622                 get: {},
623                 'yui-log': {},
624                 'yui-later': {}
625             }
626         },
627
628         test: {                                                                                                                                                        
629             requires: [SUBSTITUTE, NODE, 'json', 'event-simulate']                                                                                                                     
630         }  
631
632     }
633 },
634
635 _path = Y.cached(function(dir, file, type) {
636     return dir + '/' + file + '-min.' + (type || CSS);
637 }),
638
639 _queue = YUI.Env._loaderQueue,
640
641 mods  = META.modules, i, bname, mname, contextname,
642 L     = Y.Lang;
643
644 // Create the metadata for both the regular and context-aware
645 // versions of the YUI CSS foundation.
646 for (i=0; i<YUI_CSS.length; i=i+1) {
647     bname = YUI_CSS[i];
648     mname = CSS + bname;
649
650     mods[mname] = {
651         type: CSS,
652         path: _path(mname, bname)
653     };
654
655     // define -context module
656     contextname = mname + CONTEXT;
657     bname = bname + CONTEXT;
658
659     mods[contextname] = {
660         type: CSS,
661         path: _path(mname, bname)
662     };
663
664     if (mname == CSSGRIDS) {
665         mods[mname].requires = [CSSFONTS];
666         mods[mname].optional = [CSSRESET];
667         mods[contextname].requires = [CSSFONTS + CONTEXT];
668         mods[contextname].optional = [CSSRESET + CONTEXT];
669     } else if (mname == CSSBASE) {
670         mods[mname].after = CSS_AFTER;
671         mods[contextname].after = CSS_AFTER;
672     }
673 }
674
675 Y.Env.meta = META;
676
677 GLOBAL_LOADED = GLOBAL_ENV._loaded;
678
679 Y.Loader = function(o) {
680
681     /**
682      * Internal callback to handle multiple internal insert() calls
683      * so that css is inserted prior to js
684      * @property _internalCallback
685      * @private
686      */
687     // this._internalCallback = null;
688
689     /**
690      * Callback that will be executed when the loader is finished
691      * with an insert
692      * @method onSuccess
693      * @type function
694      */
695     // this.onSuccess = null;
696
697     /**
698      * Callback that will be executed if there is a failure
699      * @method onFailure
700      * @type function
701      */
702     // this.onFailure = null;
703
704     /**
705      * Callback for the 'CSSComplete' event.  When loading YUI components with CSS
706      * the CSS is loaded first, then the script.  This provides a moment you can tie into to improve
707      * the presentation of the page while the script is loading.
708      * @method onCSS
709      * @type function
710      */
711     // this.onCSS = null;
712
713     /**
714      * Callback executed each time a script or css file is loaded
715      * @method onProgress
716      * @type function
717      */
718     // this.onProgress = null;
719
720     /**
721      * Callback that will be executed if a timeout occurs
722      * @method onTimeout
723      * @type function
724      */
725     // this.onTimeout = null;
726
727     /**
728      * The execution context for all callbacks
729      * @property context
730      * @default {YUI} the YUI instance
731      */
732     this.context = Y;
733
734     /**
735      * Data that is passed to all callbacks
736      * @property data
737      */
738     // this.data = null;
739
740     /**
741      * Node reference or id where new nodes should be inserted before
742      * @property insertBefore
743      * @type string|HTMLElement
744      */
745     // this.insertBefore = null;
746
747     /**
748      * The charset attribute for inserted nodes
749      * @property charset
750      * @type string
751      * @deprecated, use cssAttributes or jsAttributes
752      */
753     // this.charset = null;
754
755     /**
756      * An object literal containing attributes to add to link nodes
757      * @property cssAttributes
758      * @type object
759      */
760     // this.cssAttributes = null;
761
762     /**
763      * An object literal containing attributes to add to script nodes
764      * @property jsAttributes
765      * @type object
766      */
767     // this.jsAttributes = null;
768
769     /**
770      * The base directory.
771      * @property base
772      * @type string
773      * @default http://yui.yahooapis.com/[YUI VERSION]/build/
774      */
775     this.base = Y.Env.meta.base;
776
777     /**
778      * Base path for the combo service
779      * @property comboBase
780      * @type string
781      * @default http://yui.yahooapis.com/combo?
782      */
783     this.comboBase = Y.Env.meta.comboBase;
784
785     /**
786      * If configured, YUI JS resources will use the combo
787      * handler
788      * @property combine
789      * @type boolean
790      * @default true if a base dir isn't in the config
791      */
792     this.combine = o.base && (o.base.indexOf( this.comboBase.substr(0, 20)) > -1);
793
794     /**
795      * Ignore modules registered on the YUI global
796      * @property ignoreRegistered
797      * @default false
798      */
799     // this.ignoreRegistered = false;
800
801     /**
802      * Root path to prepend to module path for the combo
803      * service
804      * @property root
805      * @type string
806      * @default [YUI VERSION]/build/
807      */
808     this.root = Y.Env.meta.root;
809
810     /**
811      * Timeout value in milliseconds.  If set, this value will be used by
812      * the get utility.  the timeout event will fire if
813      * a timeout occurs.
814      * @property timeout
815      * @type int
816      */
817     this.timeout = 0;
818
819     /**
820      * A list of modules that should not be loaded, even if
821      * they turn up in the dependency tree
822      * @property ignore
823      * @type string[]
824      */
825     // this.ignore = null;
826
827     /**
828      * A list of modules that should always be loaded, even
829      * if they have already been inserted into the page.
830      * @property force
831      * @type string[]
832      */
833     // this.force = null;
834
835     this.forceMap = {};
836
837     /**
838      * Should we allow rollups
839      * @property allowRollup
840      * @type boolean
841      * @default true
842      */
843     // this.allowRollup = true;
844
845     /**
846      * A filter to apply to result urls.  This filter will modify the default
847      * path for all modules.  The default path for the YUI library is the
848      * minified version of the files (e.g., event-min.js).  The filter property
849      * can be a predefined filter or a custom filter.  The valid predefined 
850      * filters are:
851      * <dl>
852      *  <dt>DEBUG</dt>
853      *  <dd>Selects the debug versions of the library (e.g., event-debug.js).
854      *      This option will automatically include the Logger widget</dd>
855      *  <dt>RAW</dt>
856      *  <dd>Selects the non-minified version of the library (e.g., event.js).</dd>
857      * </dl>
858      * You can also define a custom filter, which must be an object literal 
859      * containing a search expression and a replace string:
860      * <pre>
861      *  myFilter: &#123; 
862      *      'searchExp': "-min\\.js", 
863      *      'replaceStr': "-debug.js"
864      *  &#125;
865      * </pre>
866      * @property filter
867      * @type string|{searchExp: string, replaceStr: string}
868      */
869     // this.filter = null;
870
871     /**
872      * per-component filter specification.  If specified for a given component, this 
873      * overrides the filter config.
874      * @property filters
875      * @type object
876      */
877     this.filters = {};
878
879     /**
880      * The list of requested modules
881      * @property required
882      * @type {string: boolean}
883      */
884     this.required = {};
885
886     /**
887      * The library metadata
888      * @property moduleInfo
889      */
890     // this.moduleInfo = Y.merge(Y.Env.meta.moduleInfo);
891     this.moduleInfo = {};
892
893     /**
894      * Provides the information used to skin the skinnable components.
895      * The following skin definition would result in 'skin1' and 'skin2'
896      * being loaded for calendar (if calendar was requested), and
897      * 'sam' for all other skinnable components:
898      *
899      *   <code>
900      *   skin: {
901      *
902      *      // The default skin, which is automatically applied if not
903      *      // overriden by a component-specific skin definition.
904      *      // Change this in to apply a different skin globally
905      *      defaultSkin: 'sam', 
906      *
907      *      // This is combined with the loader base property to get
908      *      // the default root directory for a skin. ex:
909      *      // http://yui.yahooapis.com/2.3.0/build/assets/skins/sam/
910      *      base: 'assets/skins/',
911      *
912      *      // The name of the rollup css file for the skin
913      *      path: 'skin.css',
914      *
915      *      // The number of skinnable components requested that are
916      *      // required before using the rollup file rather than the
917      *      // individual component css files
918      *      rollup: 3,
919      *
920      *      // Any component-specific overrides can be specified here,
921      *      // making it possible to load different skins for different
922      *      // components.  It is possible to load more than one skin
923      *      // for a given component as well.
924      *      overrides: {
925      *          calendar: ['skin1', 'skin2']
926      *      }
927      *   }
928      *   </code>
929      *   @property skin
930      */
931      this.skin = Y.merge(Y.Env.meta.skin);
932     
933     var defaults = Y.Env.meta.modules, i, onPage = YUI.Env.mods;
934
935     this._internal = true;
936     for (i in defaults) {
937         if (defaults.hasOwnProperty(i)) {
938             this.addModule(defaults[i], i);
939         }
940     }
941
942     for (i in onPage) {
943         if (onPage.hasOwnProperty(i) && !this.moduleInfo[i] && onPage[i].details) {
944             this.addModule(onPage[i].details, i);
945         }
946     }
947     this._internal = false;
948
949     /**
950      * List of rollup files found in the library metadata
951      * @property rollups
952      */
953     // this.rollups = null;
954
955     /**
956      * Whether or not to load optional dependencies for 
957      * the requested modules
958      * @property loadOptional
959      * @type boolean
960      * @default false
961      */
962     // this.loadOptional = false;
963
964     /**
965      * All of the derived dependencies in sorted order, which
966      * will be populated when either calculate() or insert()
967      * is called
968      * @property sorted
969      * @type string[]
970      */
971     this.sorted = [];
972
973     /**
974      * Set when beginning to compute the dependency tree. 
975      * Composed of what YUI reports to be loaded combined
976      * with what has been loaded by any instance on the page
977      * with the version number specified in the metadata.
978      * @propery loaded
979      * @type {string: boolean}
980      */
981     this.loaded = GLOBAL_LOADED[VERSION];
982
983     /**
984      * A list of modules to attach to the YUI instance when complete.
985      * If not supplied, the sorted list of dependencies are applied.
986      * @property attaching
987      */
988     // this.attaching = null;
989
990     /**
991      * Flag to indicate the dependency tree needs to be recomputed
992      * if insert is called again.
993      * @property dirty
994      * @type boolean
995      * @default true
996      */
997     this.dirty = true;
998
999     /**
1000      * List of modules inserted by the utility
1001      * @property inserted
1002      * @type {string: boolean}
1003      */
1004     this.inserted = {};
1005
1006     /**
1007      * List of skipped modules during insert() because the module
1008      * was not defined
1009      * @property skipped
1010      */
1011     this.skipped = {};
1012
1013
1014     // Y.on('yui:load', this.loadNext, this);
1015
1016     this._config(o);
1017
1018 };
1019
1020 Y.Loader.prototype = {
1021
1022     FILTER_DEFS: {
1023         RAW: { 
1024             'searchExp': "-min\\.js", 
1025             'replaceStr': ".js"
1026         },
1027         DEBUG: { 
1028             'searchExp': "-min\\.js", 
1029             'replaceStr': "-debug.js"
1030         }
1031     },
1032
1033     SKIN_PREFIX: "skin-",
1034
1035     _config: function(o) {
1036
1037         var i, j, val, f;
1038
1039         // apply config values
1040         if (o) {
1041             for (i in o) {
1042                 if (o.hasOwnProperty(i)) {
1043                     val = o[i];
1044                     if (i == 'require') {
1045                         this.require(val);
1046                     } else if (i == 'modules') {
1047
1048                         // add a hash of module definitions
1049                         for (j in val) {
1050                             if (val.hasOwnProperty(j)) {
1051                                 this.addModule(val[j], j);
1052                             }
1053                         }
1054
1055                     } else {
1056                         this[i] = val;
1057                     }
1058                 }
1059             }
1060         }
1061
1062         // fix filter
1063         f = this.filter;
1064
1065         if (L.isString(f)) {
1066             f = f.toUpperCase();
1067             this.filterName = f;
1068             this.filter = this.FILTER_DEFS[f];
1069             if (f == 'DEBUG') {
1070                 this.require('yui-log', 'dump');
1071             }
1072         }
1073
1074     },
1075
1076     /**
1077      * Returns the skin module name for the specified skin name.  If a
1078      * module name is supplied, the returned skin module name is 
1079      * specific to the module passed in.
1080      * @method formatSkin
1081      * @param skin {string} the name of the skin
1082      * @param mod {string} optional: the name of a module to skin
1083      * @return {string} the full skin module name
1084      */
1085     formatSkin: function(skin, mod) {
1086         var s = this.SKIN_PREFIX + skin;
1087         if (mod) {
1088             s = s + "-" + mod;
1089         }
1090
1091         return s;
1092     },
1093
1094     /*
1095      * Reverses <code>formatSkin</code>, providing the skin name and
1096      * module name if the string matches the pattern for skins.
1097      * @method parseSkin
1098      * @param mod {string} the module name to parse
1099      * @return {skin: string, module: string} the parsed skin name 
1100      * and module name, or null if the supplied string does not match
1101      * the skin pattern
1102      * 
1103      * This isn't being used at the moment
1104      *
1105      */
1106     // parseSkin: function(mod) {
1107     //     
1108     //     if (mod.indexOf(this.SKIN_PREFIX) === 0) {
1109     //         var a = mod.split("-");
1110     //         return {skin: a[1], module: a[2]};
1111     //     } 
1112     //     return null;
1113     // },
1114
1115     /**
1116      * Adds the skin def to the module info
1117      * @method _addSkin
1118      * @param skin {string} the name of the skin
1119      * @param mod {string} the name of the module
1120      * @param parent {string} parent module if this is a skin of a
1121      * submodule or plugin
1122      * @return {string} the module name for the skin
1123      * @private
1124      */
1125     _addSkin: function(skin, mod, parent) {
1126
1127         var name = this.formatSkin(skin), 
1128             info = this.moduleInfo,
1129             sinf = this.skin, 
1130             ext  = info[mod] && info[mod].ext,
1131             mdef, pkg;
1132
1133         /*
1134         // Add a module definition for the skin rollup css
1135         if (!info[name]) {
1136             this.addModule({
1137                 'name': name,
1138                 'type': 'css',
1139                 'path': sinf.base + skin + '/' + sinf.path,
1140                 //'supersedes': '*',
1141                 'after': sinf.after,
1142                 'rollup': sinf.rollup,
1143                 'ext': ext
1144             });
1145         }
1146         */
1147
1148         // Add a module definition for the module-specific skin css
1149         if (mod) {
1150             name = this.formatSkin(skin, mod);
1151             if (!info[name]) {
1152                 mdef = info[mod];
1153                 pkg = mdef.pkg || mod;
1154                 this.addModule({
1155                     'name': name,
1156                     'type': 'css',
1157                     'after': sinf.after,
1158                     'path': (parent || pkg) + '/' + sinf.base + skin + '/' + mod + '.css',
1159                     'ext': ext
1160                 });
1161             }
1162         }
1163
1164         return name;
1165     },
1166
1167     /** Add a new module to the component metadata.         
1168      * <dl>
1169      *     <dt>name:</dt>       <dd>required, the component name</dd>
1170      *     <dt>type:</dt>       <dd>required, the component type (js or css)</dd>
1171      *     <dt>path:</dt>       <dd>required, the path to the script from "base"</dd>
1172      *     <dt>requires:</dt>   <dd>array of modules required by this component</dd>
1173      *     <dt>optional:</dt>   <dd>array of optional modules for this component</dd>
1174      *     <dt>supersedes:</dt> <dd>array of the modules this component replaces</dd>
1175      *     <dt>after:</dt>      <dd>array of modules the components which, if present, should be sorted above this one</dd>
1176      *     <dt>rollup:</dt>     <dd>the number of superseded modules required for automatic rollup</dd>
1177      *     <dt>fullpath:</dt>   <dd>If fullpath is specified, this is used instead of the configured base + path</dd>
1178      *     <dt>skinnable:</dt>  <dd>flag to determine if skin assets should automatically be pulled in</dd>
1179      *     <dt>submodules:</dt> <dd>a has of submodules</dd>
1180      * </dl>
1181      * @method addModule
1182      * @param o An object containing the module data
1183      * @param name the module name (optional), required if not in the module data
1184      * @return {boolean} true if the module was added, false if 
1185      * the object passed in did not provide all required attributes
1186      */
1187     addModule: function(o, name) {
1188
1189         name = name || o.name;
1190         o.name = name;
1191
1192         if (!o || !o.name) {
1193             return false;
1194         }
1195
1196         if (!o.type) {
1197             o.type = JS;
1198         }
1199
1200         if (!o.path && !o.fullpath) {
1201             // o.path = name + "/" + name + "-min." + o.type;
1202             o.path = _path(name, name, o.type);
1203         }
1204
1205         o.ext = ('ext' in o) ? o.ext : (this._internal) ? false : true;
1206         o.requires = o.requires || [];
1207
1208
1209         this.moduleInfo[name] = o;
1210
1211         // Handle submodule logic
1212         var subs = o.submodules, i, l, sup, s, smod, plugins, plug;
1213         if (subs) {
1214             sup = []; 
1215             l   = 0;
1216
1217             for (i in subs) {
1218                 if (subs.hasOwnProperty(i)) {
1219                     s = subs[i];
1220                     s.path = _path(name, i, o.type);
1221                     this.addModule(s, i);
1222                     sup.push(i);
1223
1224                     if (o.skinnable) {
1225                         smod = this._addSkin(this.skin.defaultSkin, i, name);
1226                         sup.push(smod.name);
1227                     }
1228
1229                     l++;
1230                 }
1231             }
1232
1233             o.supersedes = sup;
1234             o.rollup = (l<4) ? l : Math.min(l-1, 4);
1235         }
1236
1237         plugins = o.plugins;
1238         if (plugins) {
1239             for (i in plugins) {
1240                 if (plugins.hasOwnProperty(i)) {
1241                     plug = plugins[i];
1242                     plug.path = _path(name, i, o.type);
1243                     plug.requires = plug.requires || [];
1244                     // plug.requires.push(name);
1245                     this.addModule(plug, i);
1246                     if (o.skinnable) {
1247                         this._addSkin(this.skin.defaultSkin, i, name);
1248                     }
1249                 }
1250             }
1251         }
1252
1253         this.dirty = true;
1254
1255         return o;
1256     },
1257
1258     /**
1259      * Add a requirement for one or more module
1260      * @method require
1261      * @param what {string[] | string*} the modules to load
1262      */
1263     require: function(what) {
1264         var a = (typeof what === "string") ? arguments : what;
1265         this.dirty = true;
1266         Y.mix(this.required, Y.Array.hash(a));
1267     },
1268
1269     /**
1270      * Returns an object containing properties for all modules required
1271      * in order to load the requested module
1272      * @method getRequires
1273      * @param mod The module definition from moduleInfo
1274      */
1275     getRequires: function(mod) {
1276
1277         if (!mod) {
1278             return [];
1279         }
1280
1281         if (!this.dirty && mod.expanded) {
1282             return mod.expanded;
1283         }
1284
1285         var i, d=[], r=mod.requires, o=mod.optional, 
1286             info=this.moduleInfo, m, j, add;
1287
1288         for (i=0; i<r.length; i=i+1) {
1289             d.push(r[i]);
1290             m = this.getModule(r[i]);
1291             add = this.getRequires(m);
1292             for (j=0;j<add.length;j=j+1) {
1293                 d.push(add[j]);
1294             }
1295         }
1296
1297         // get the requirements from superseded modules, if any
1298         r=mod.supersedes;
1299         if (r) {
1300             for (i=0; i<r.length; i=i+1) {
1301                 d.push(r[i]);
1302                 m = this.getModule(r[i]);
1303                 add = this.getRequires(m);
1304                 for (j=0;j<add.length;j=j+1) {
1305                     d.push(add[j]);
1306                 }
1307             }
1308         }
1309
1310         if (o && this.loadOptional) {
1311             for (i=0; i<o.length; i=i+1) {
1312                 d.push(o[i]);
1313                 add = this.getRequires(info[o[i]]);
1314                 for (j=0;j<add.length;j=j+1) {
1315                     d.push(add[j]);
1316                 }
1317             }
1318         }
1319
1320         mod.expanded = Y.Object.keys(Y.Array.hash(d));
1321         return mod.expanded;
1322     },
1323
1324
1325     /**
1326      * Returns a hash of module names the supplied module satisfies.
1327      * @method getProvides
1328      * @param name {string} The name of the module
1329      * @return what this module provides
1330      */
1331     getProvides: function(name) {
1332         var m = this.getModule(name), o, s;
1333
1334         if (!m) {
1335             return NOT_FOUND;
1336         }
1337
1338         if (m && !m.provides) {
1339             o = {};
1340             s = m.supersedes;
1341
1342             if (s) {
1343                 Y.Array.each(s, function(v) {
1344                     Y.mix(o, this.getProvides(v));
1345                 }, this);
1346             }
1347
1348             o[name] = true;
1349             m.provides = o;
1350         }
1351
1352         return m.provides;
1353     },
1354
1355
1356     /**
1357      * Calculates the dependency tree, the result is stored in the sorted 
1358      * property
1359      * @method calculate
1360      * @param o optional options object
1361      * @param type optional argument to prune modules 
1362      */
1363     calculate: function(o, type) {
1364         if (o || type || this.dirty) {
1365             this._config(o);
1366             this._setup();
1367             this._explode();
1368             if (this.allowRollup && !this.combine) {
1369                 this._rollup();
1370             }
1371             this._reduce();
1372             this._sort();
1373
1374
1375             this.dirty = false;
1376         }
1377     },
1378
1379     /**
1380      * Investigates the current YUI configuration on the page.  By default,
1381      * modules already detected will not be loaded again unless a force
1382      * option is encountered.  Called by calculate()
1383      * @method _setup
1384      * @private
1385      */
1386     _setup: function() {
1387
1388         var info = this.moduleInfo, name, i, j, m, o, l, smod;
1389
1390         // Create skin modules
1391         for (name in info) {
1392             if (info.hasOwnProperty(name)) {
1393                 m = info[name];
1394                 if (m && m.skinnable) {
1395                     o = this.skin.overrides;
1396                     if (o && o[name]) {
1397                         for (i=0; i<o[name].length; i=i+1) {
1398                             smod = this._addSkin(o[name][i], name);
1399                         }
1400                     } else {
1401                         smod = this._addSkin(this.skin.defaultSkin, name);
1402                     }
1403
1404                     m.requires.push(smod);
1405                 }
1406             }
1407         }
1408
1409         l = Y.merge(this.inserted); // shallow clone
1410
1411         // available modules
1412         if (!this.ignoreRegistered) {
1413             Y.mix(l, GLOBAL_ENV.mods);
1414         }
1415         
1416
1417         // add the ignore list to the list of loaded packages
1418         if (this.ignore) {
1419             // OU.appendArray(l, this.ignore);
1420             Y.mix(l, Y.Array.hash(this.ignore));
1421         }
1422
1423         // expand the list to include superseded modules
1424         for (j in l) {
1425             if (l.hasOwnProperty(j)) {
1426                 Y.mix(l, this.getProvides(j));
1427             }
1428         }
1429
1430         // remove modules on the force list from the loaded list
1431         if (this.force) {
1432             for (i=0; i<this.force.length; i=i+1) {
1433                 if (this.force[i] in l) {
1434                     delete l[this.force[i]];
1435                 }
1436             }
1437         }
1438
1439
1440         Y.mix(this.loaded, l);
1441
1442         // this.loaded = l;
1443
1444     },
1445     
1446
1447     /**
1448      * Inspects the required modules list looking for additional 
1449      * dependencies.  Expands the required list to include all 
1450      * required modules.  Called by calculate()
1451      * @method _explode
1452      * @private
1453      */
1454     _explode: function() {
1455
1456         var r = this.required, m, reqs;
1457
1458         Y.Object.each(r, function(v, name) {
1459
1460             m = this.getModule(name);
1461
1462             var expound = m && m.expound;
1463
1464             if (m) {
1465
1466                 if (expound) {
1467                     r[expound] = this.getModule(expound);
1468                     reqs = this.getRequires(r[expound]);
1469                     Y.mix(r, Y.Array.hash(reqs));
1470                 }
1471
1472                 reqs = this.getRequires(m);
1473
1474                 Y.mix(r, Y.Array.hash(reqs));
1475             }
1476
1477         }, this);
1478     },
1479
1480     getModule: function(name) {
1481
1482         var m = this.moduleInfo[name];
1483
1484         // create the default module
1485         // if (!m) {
1486             // m = this.addModule({ext: false}, name);
1487         // }
1488
1489         return m;
1490     },
1491
1492     /**
1493      * Look for rollup packages to determine if all of the modules a
1494      * rollup supersedes are required.  If so, include the rollup to
1495      * help reduce the total number of connections required.  Called
1496      * by calculate()
1497      * @method _rollup
1498      * @private
1499      */
1500     _rollup: function() {
1501         var i, j, m, s, rollups={}, r=this.required, roll,
1502             info = this.moduleInfo, rolled, c;
1503
1504         // find and cache rollup modules
1505         if (this.dirty || !this.rollups) {
1506             for (i in info) {
1507                 if (info.hasOwnProperty(i)) {
1508                     m = this.getModule(i);
1509                     // if (m && m.rollup && m.supersedes) {
1510                     if (m && m.rollup) {
1511                         rollups[i] = m;
1512                     }
1513                 }
1514             }
1515
1516             this.rollups = rollups;
1517             this.forceMap = (this.force) ? Y.Array.hash(this.force) : {};
1518         }
1519
1520         // make as many passes as needed to pick up rollup rollups
1521         for (;;) {
1522             rolled = false;
1523
1524             // go through the rollup candidates
1525             for (i in rollups) { 
1526
1527                 if (rollups.hasOwnProperty(i)) {
1528
1529                     // there can be only one, unless forced
1530                     if (!r[i] && ((!this.loaded[i]) || this.forceMap[i])) {
1531                         m = this.getModule(i); 
1532                         s = m.supersedes || []; 
1533                         roll = false;
1534
1535                         // @TODO remove continue
1536                         if (!m.rollup) {
1537                             continue;
1538                         }
1539
1540                         c = 0;
1541
1542                         // check the threshold
1543                         for (j=0;j<s.length;j=j+1) {
1544
1545
1546                             // if the superseded module is loaded, we can't load the rollup
1547                             // unless it has been forced
1548                             if (this.loaded[s[j]] && !this.forceMap[s[j]]) {
1549                                 roll = false;
1550                                 break;
1551                             // increment the counter if this module is required.  if we are
1552                             // beyond the rollup threshold, we will use the rollup module
1553                             } else if (r[s[j]]) {
1554                                 c++;
1555                                 roll = (c >= m.rollup);
1556                                 if (roll) {
1557                                     break;
1558                                 }
1559                             }
1560                         }
1561
1562                         if (roll) {
1563                             // add the rollup
1564                             r[i] = true;
1565                             rolled = true;
1566
1567                             // expand the rollup's dependencies
1568                             this.getRequires(m);
1569                         }
1570                     }
1571                 }
1572             }
1573
1574             // if we made it here w/o rolling up something, we are done
1575             if (!rolled) {
1576                 break;
1577             }
1578         }
1579     },
1580
1581     /**
1582      * Remove superceded modules and loaded modules.  Called by
1583      * calculate() after we have the mega list of all dependencies
1584      * @method _reduce
1585      * @private
1586      */
1587     _reduce: function() {
1588         var i, j, s, m, r=this.required, type = this.loadType;
1589         for (i in r) {
1590             if (r.hasOwnProperty(i)) {
1591                 m = this.getModule(i);
1592                 // remove if already loaded
1593                 if ((this.loaded[i] && (!this.forceMap[i]) && !this.ignoreRegistered) || (type && m && m.type != type)) { 
1594                     delete r[i];
1595                 // remove anything this module supersedes
1596                 } else {
1597                     
1598                     s = m && m.supersedes;
1599                     if (s) {
1600                         for (j=0; j<s.length; j=j+1) {
1601                             if (s[j] in r) {
1602                                 delete r[s[j]];
1603                             }
1604                         }
1605                     }
1606                 }
1607             }
1608         }
1609     },
1610
1611     _attach: function() {
1612         // this is the full list of items the YUI needs attached,
1613         // which is needed if some dependencies are already on
1614         // the page without their dependencies.
1615         if (this.attaching) {
1616             Y._attach(this.attaching);
1617         } else {
1618             Y._attach(this.sorted);
1619         }
1620
1621         // this._pushEvents();
1622
1623     },
1624
1625     _finish: function() {
1626         _queue.running = false;
1627         this._continue();
1628     },
1629
1630     _onSuccess: function() {
1631
1632
1633         this._attach();
1634
1635         var skipped = this.skipped, i, f;
1636
1637         for (i in skipped) {
1638             if (skipped.hasOwnProperty(i)) {
1639                 delete this.inserted[i];
1640             }
1641         }
1642
1643         this.skipped = {};
1644
1645         f = this.onSuccess;
1646
1647         if (f) {
1648             f.call(this.context, {
1649                 msg: 'success',
1650                 data: this.data,
1651                 success: true
1652             });
1653         }
1654
1655         this._finish();
1656
1657     },
1658
1659     _onFailure: function(o) {
1660
1661
1662         this._attach();
1663
1664         var f = this.onFailure;
1665         if (f) {
1666             f.call(this.context, {
1667                 msg: 'failure: ' + o.msg,
1668                 data: this.data,
1669                 success: false
1670             });
1671         }
1672
1673         this._finish();
1674     },
1675
1676     _onTimeout: function() {
1677
1678
1679         this._attach();
1680
1681         var f = this.onTimeout;
1682         if (f) {
1683             f.call(this.context, {
1684                 msg: 'timeout',
1685                 data: this.data,
1686                 success: false
1687             });
1688         }
1689
1690         this._finish();
1691     },
1692     
1693     /**
1694      * Sorts the dependency tree.  The last step of calculate()
1695      * @method _sort
1696      * @private
1697      */
1698     _sort: function() {
1699
1700         // create an indexed list
1701         var s = Y.Object.keys(this.required), 
1702             info = this.moduleInfo, 
1703             loaded = this.loaded,
1704             done = {},
1705             p=0, l, a, b, j, k, moved, doneKey,
1706
1707         // returns true if b is not loaded, and is required
1708         // directly or by means of modules it supersedes.
1709             requires = Y.cached(function(mod1, mod2) {
1710
1711                 var m = info[mod1], i, r, after, other = info[mod2], s;
1712
1713                 if (loaded[mod2] || !m || !other) {
1714                     return false;
1715                 }
1716
1717                 r     = m.expanded;
1718                 after = m.after; 
1719
1720                 // check if this module requires the other directly
1721                 if (r && Y.Array.indexOf(r, mod2) > -1) {
1722                     return true;
1723                 }
1724
1725                 // check if this module should be sorted after the other
1726                 if (after && Y.Array.indexOf(after, mod2) > -1) {
1727                     return true;
1728                 }
1729
1730                 // check if this module requires one the other supersedes
1731                 s = info[mod2] && info[mod2].supersedes;
1732                 if (s) {
1733                     for (i=0; i<s.length; i=i+1) {
1734                         if (requires(mod1, s[i])) {
1735                             return true;
1736                         }
1737                     }
1738                 }
1739
1740                 // external css files should be sorted below yui css
1741                 if (m.ext && m.type == CSS && !other.ext && other.type == CSS) {
1742                     return true;
1743                 }
1744
1745                 return false;
1746             });
1747
1748         // keep going until we make a pass without moving anything
1749         for (;;) {
1750            
1751             l     = s.length; 
1752             moved = false;
1753
1754             // start the loop after items that are already sorted
1755             for (j=p; j<l; j=j+1) {
1756
1757                 // check the next module on the list to see if its
1758                 // dependencies have been met
1759                 a = s[j];
1760
1761                 // check everything below current item and move if we
1762                 // find a requirement for the current item
1763                 for (k=j+1; k<l; k=k+1) {
1764                     doneKey = a + s[k];
1765                     if (!done[doneKey] && requires(a, s[k])) {
1766
1767                         // extract the dependency so we can move it up
1768                         b = s.splice(k, 1);
1769
1770                         // insert the dependency above the item that 
1771                         // requires it
1772                         s.splice(j, 0, b[0]);
1773
1774                         // only swap two dependencies once to short circut
1775                         // circular dependencies
1776                         done[doneKey] = true;
1777
1778                         // keep working 
1779                         moved = true;
1780
1781                         break;
1782                     }
1783                 }
1784
1785                 // jump out of loop if we moved something
1786                 if (moved) {
1787                     break;
1788                 // this item is sorted, move our pointer and keep going
1789                 } else {
1790                     p = p + 1;
1791                 }
1792             }
1793
1794             // when we make it here and moved is false, we are 
1795             // finished sorting
1796             if (!moved) {
1797                 break;
1798             }
1799
1800         }
1801
1802         this.sorted = s;
1803     },
1804
1805     _insert: function(source, o, type) {
1806
1807
1808         // restore the state at the time of the request
1809         if (source) {
1810             this._config(source);
1811         }
1812
1813         // build the dependency list
1814         this.calculate(o); // don't include type so we can process CSS and script in
1815                            // one pass when the type is not specified.
1816         this.loadType = type;
1817
1818         if (!type) {
1819
1820             var self = this;
1821
1822             this._internalCallback = function() {
1823                 var f = self.onCSS;
1824                 if (f) {
1825                     f.call(self.context, Y);
1826                 }
1827                 self._internalCallback = null;
1828                 self._insert(null, null, JS);
1829             };
1830
1831             // _queue.running = false;
1832             this._insert(null, null, CSS);
1833
1834             return;
1835         }
1836
1837
1838         // set a flag to indicate the load has started
1839         this._loading = true;
1840
1841         // flag to indicate we are done with the combo service
1842         // and any additional files will need to be loaded
1843         // individually
1844         this._combineComplete = {};
1845
1846
1847         // start the load
1848         this.loadNext();
1849
1850     },
1851
1852     _continue: function() {
1853         if (!(_queue.running) && _queue.size() > 0) {
1854             _queue.running = true;
1855             _queue.next()();
1856         }
1857     },
1858
1859     /**
1860      * inserts the requested modules and their dependencies.  
1861      * <code>type</code> can be "js" or "css".  Both script and 
1862      * css are inserted if type is not provided.
1863      * @method insert
1864      * @param o optional options object
1865      * @param type {string} the type of dependency to insert
1866      */
1867     insert: function(o, type) {
1868
1869
1870         var self = this, copy = Y.merge(this, true);
1871
1872         delete copy.require;
1873         delete copy.dirty;
1874
1875         _queue.add(function() {
1876             self._insert(copy, o, type);
1877         });
1878
1879         this._continue();
1880
1881     },
1882
1883     /**
1884      * Executed every time a module is loaded, and if we are in a load
1885      * cycle, we attempt to load the next script.  Public so that it
1886      * is possible to call this if using a method other than
1887      * Y.register to determine when scripts are fully loaded
1888      * @method loadNext
1889      * @param mname {string} optional the name of the module that has
1890      * been loaded (which is usually why it is time to load the next
1891      * one)
1892      */
1893     loadNext: function(mname) {
1894
1895         // It is possible that this function is executed due to something
1896         // else one the page loading a YUI module.  Only react when we
1897         // are actively loading something
1898         if (!this._loading) {
1899             return;
1900         }
1901
1902         var s, len, i, m, url, self=this, type=this.loadType, fn, msg, attr,
1903             callback=function(o) {
1904                 this._combineComplete[type] = true;
1905
1906                 var c=this._combining, len=c.length, i;
1907
1908                 for (i=0; i<len; i=i+1) {
1909                     this.inserted[c[i]] = true;
1910                 }
1911
1912                 this.loadNext(o.data);
1913             },
1914             onsuccess=function(o) {
1915                 self.loadNext(o.data);
1916             };
1917
1918         // @TODO this will need to handle the two phase insert when
1919         // CSS support is added
1920         if (this.combine && (!this._combineComplete[type])) {
1921
1922             this._combining = []; 
1923             s=this.sorted;
1924             len=s.length;
1925             url=this.comboBase;
1926
1927
1928             for (i=0; i<len; i=i+1) {
1929                 m = this.getModule(s[i]);
1930                 // Do not try to combine non-yui JS
1931                 if (m && (m.type === type) && !m.ext) {
1932                     url += this.root + m.path;
1933                     if (i < len-1) {
1934                         url += '&';
1935                     }
1936
1937                     this._combining.push(s[i]);
1938                 }
1939             }
1940
1941             if (this._combining.length) {
1942
1943
1944                 // if (m.type === CSS) {
1945                 if (type === CSS) {
1946                     fn = Y.Get.css;
1947                     attr = this.cssAttributes;
1948                 } else {
1949                     fn = Y.Get.script;
1950                     attr = this.jsAttributes;
1951                 }
1952
1953                 // @TODO get rid of the redundant Get code
1954                 fn(this._filter(url), {
1955                     data: this._loading,
1956                     onSuccess: callback,
1957                     onFailure: this._onFailure,
1958                     onTimeout: this._onTimeout,
1959                     insertBefore: this.insertBefore,
1960                     charset: this.charset,
1961                     attributes: attr,
1962                     timeout: this.timeout,
1963                     autopurge: false,
1964                     context: self 
1965                 });
1966
1967                 return;
1968
1969             } else {
1970                 this._combineComplete[type] = true;
1971             }
1972         }
1973
1974         if (mname) {
1975
1976             // if the module that was just loaded isn't what we were expecting,
1977             // continue to wait
1978             if (mname !== this._loading) {
1979                 return;
1980             }
1981
1982
1983             // The global handler that is called when each module is loaded
1984             // will pass that module name to this function.  Storing this
1985             // data to avoid loading the same module multiple times
1986             this.inserted[mname] = true;
1987             this.loaded[mname] = true;
1988
1989             if (this.onProgress) {
1990                 this.onProgress.call(this.context, {
1991                         name: mname,
1992                         data: this.data
1993                     });
1994             }
1995
1996
1997         }
1998
1999         s=this.sorted;
2000         len=s.length;
2001
2002         for (i=0; i<len; i=i+1) {
2003
2004             // this.inserted keeps track of what the loader has loaded.
2005             // move on if this item is done.
2006             if (s[i] in this.inserted) {
2007                 continue;
2008             }
2009
2010             // Because rollups will cause multiple load notifications
2011             // from Y, loadNext may be called multiple times for
2012             // the same module when loading a rollup.  We can safely
2013             // skip the subsequent requests
2014             if (s[i] === this._loading) {
2015                 return;
2016             }
2017
2018             // log("inserting " + s[i]);
2019             m = this.getModule(s[i]);
2020
2021             if (!m) {
2022
2023                 msg = "Undefined module " + s[i] + " skipped";
2024                 this.inserted[s[i]] = true;
2025                 this.skipped[s[i]] = true;
2026                 continue;
2027
2028             }
2029
2030
2031             // The load type is stored to offer the possibility to load
2032             // the css separately from the script.
2033             if (!type || type === m.type) {
2034                 this._loading = s[i];
2035
2036                 if (m.type === CSS) {
2037                     fn = Y.Get.css;
2038                     attr = this.cssAttributes;
2039                 } else {
2040                     fn = Y.Get.script;
2041                     attr = this.jsAttributes;
2042                 }
2043
2044                 url = (m.fullpath) ? this._filter(m.fullpath, s[i]) : this._url(m.path, s[i]);
2045
2046                 fn(url, {
2047                     data: s[i],
2048                     onSuccess: onsuccess,
2049                     insertBefore: this.insertBefore,
2050                     charset: this.charset,
2051                     attributes: attr,
2052                     onFailure: this._onFailure,
2053                     onTimeout: this._onTimeout,
2054                     timeout: this.timeout,
2055                     autopurge: false,
2056                     context: self 
2057                 });
2058
2059                 return;
2060             }
2061         }
2062
2063         // we are finished
2064         this._loading = null;
2065
2066         fn = this._internalCallback;
2067
2068         // internal callback for loading css first
2069         if (fn) {
2070             this._internalCallback = null;
2071             fn.call(this);
2072
2073         // } else if (this.onSuccess) {
2074         } else {
2075             // call Y.use passing this instance. Y will use the sorted
2076             // dependency list.
2077             this._onSuccess();
2078         }
2079
2080     },
2081
2082     /**
2083      * Apply filter defined for this instance to a url/path
2084      * method _filter
2085      * @param u {string} the string to filter
2086      * @param name {string} the name of the module, if we are processing
2087      * a single module as opposed to a combined url
2088      * @return {string} the filtered string
2089      * @private
2090      */
2091     _filter: function(u, name) {
2092
2093         var f = this.filter, 
2094             hasFilter = name && (name in this.filters),
2095             modFilter = hasFilter && this.filters[name];
2096
2097         if (u) {
2098
2099             if (hasFilter) {
2100                 f = (L.isString(modFilter)) ? this.FILTER_DEFS[modFilter.toUpperCase()] || null : modFilter;
2101             }
2102
2103             if (f) {
2104                 u = u.replace(new RegExp(f.searchExp, 'g'), f.replaceStr);
2105             }
2106         }
2107
2108         return u;
2109
2110     },
2111
2112     /**
2113      * Generates the full url for a module
2114      * method _url
2115      * @param path {string} the path fragment
2116      * @return {string} the full url
2117      * @private
2118      */
2119     _url: function(path, name) {
2120         return this._filter((this.base || "") + path, name);
2121     }
2122
2123 };
2124
2125 })();
2126
2127
2128
2129 }, '3.0.0' );