2 Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
8 * Provides dynamic loading for the YUI library. It includes the dependency
9 * info for the library, and will automatically pull in dependencies for
10 * the modules requested. It supports rollup files (such as utilities.js
11 * and yahoo-dom-event.js), and will automatically use these when
12 * appropriate in order to minimize the number of http connections
13 * required to load all of the dependencies.
16 * @namespace YAHOO.util
20 * YUILoader provides dynamic loading for YUI.
21 * @class YAHOO.util.YUILoader
23 * version management, automatic sandboxing
27 // Define YAHOO_config if it doesn't exist. Only relevant if YAHOO is not
28 // already on the page
29 if (typeof YAHOO_config
=== "undefined") {
33 // YUI is locally scoped, only pieces of it will be referenced in YAHOO
34 // after YAHOO has been loaded.
38 * The library metadata for the current release The is the default
39 * value for YAHOO.util.YUILoader.moduleInfo
45 'base': 'http://yui.yahooapis.com/2.3.0/build/',
49 'base': 'assets/skins/',
58 'path': 'animation/animation-min.js',
59 'requires': ['dom', 'event']
64 'path': 'autocomplete/autocomplete-min.js',
65 'requires': ['dom', 'event'],
66 'optional': ['connection', 'animation'],
72 'path': 'button/button-beta-min.js',
73 'requires': ['element'],
80 'path': 'calendar/calendar-min.js',
81 'requires': ['event', 'dom'],
87 'path': 'colorpicker/colorpicker-beta-min.js',
88 'requires': ['slider', 'element'],
89 'optional': ['animation'],
95 'path': 'connection/connection-min.js',
101 'path': 'container/container-min.js',
102 'requires': ['dom', 'event'],
103 // button is optional, but creates a circular dep
104 //'optional': ['dragdrop', 'animation', 'button'],
105 'optional': ['dragdrop', 'animation'],
106 'supersedes': ['containercore'],
112 'path': 'container/container_core-min.js',
113 'requires': ['dom', 'event']
118 'path': 'datasource/datasource-beta-min.js',
119 'requires': ['event'],
120 'optional': ['connection']
125 'path': 'datatable/datatable-beta-min.js',
126 'requires': ['element', 'datasource'],
127 'optional': ['calendar', 'dragdrop'],
133 'path': 'dom/dom-min.js',
134 'requires': ['yahoo']
139 'path': 'dragdrop/dragdrop-min.js',
140 'requires': ['dom', 'event']
145 'path': 'editor/editor-beta-min.js',
146 'requires': ['menu', 'container', 'element', 'button'],
147 'optional': ['animation', 'dragdrop'],
153 'path': 'element/element-beta-min.js',
154 'requires': ['dom', 'event']
159 'path': 'event/event-min.js',
160 'requires': ['yahoo']
165 'path': 'fonts/fonts-min.css'
170 'path': 'grids/grids-min.css',
171 'requires': ['fonts'],
172 'optional': ['reset']
177 'path': 'history/history-beta-min.js',
178 'requires': ['event']
183 'path': 'imageloader/imageloader-experimental-min.js',
184 'requires': ['event', 'dom']
189 'path': 'logger/logger-min.js',
190 'requires': ['event', 'dom'],
191 'optional': ['dragdrop'],
197 'path': 'menu/menu-min.js',
198 'requires': ['containercore'],
204 'path': 'reset/reset-min.css'
207 'reset-fonts-grids': {
209 'path': 'reset-fonts-grids/reset-fonts-grids.css',
210 'supersedes': ['reset', 'fonts', 'grids']
215 'path': 'slider/slider-min.js',
216 'requires': ['dragdrop'],
217 'optional': ['animation']
222 'path': 'tabview/tabview-min.js',
223 'requires': ['element'],
224 'optional': ['connection'],
230 'path': 'treeview/treeview-min.js',
231 'requires': ['event'],
237 'path': 'utilities/utilities.js',
238 'supersedes': ['yahoo', 'event', 'dragdrop', 'animation', 'dom', 'connection', 'element', 'yahoo-dom-event'],
244 'path': 'yahoo/yahoo-min.js'
249 'path': 'yahoo-dom-event/yahoo-dom-event.js',
250 'supersedes': ['yahoo', 'event', 'dom'],
256 'path': 'yuiloader/yuiloader-beta-min.js'
261 'path': 'yuitest/yuitest-beta-min.js',
262 'requires': ['logger'],
269 // Simple utils since we can't count on YAHOO.lang being available.
271 appendArray: function(o
, a
) {
273 for (var i
=0; i
<a
.length
; i
=i
+1) {
288 var o
={}, a
=arguments
, i
, j
;
289 for (i
=0; i
<a
.length
; i
=i
+1) {
298 keys: function(o
, ordered
) {
310 appendArray: function(a1
, a2
) {
311 Array
.prototype.push
.apply(a1
, a2
);
313 for (var i=0; i<a2.length; i=i+1) {
319 indexOf: function(a
, val
) {
320 for (var i
=0; i
<a
.length
; i
=i
+1) {
329 toObject: function(a
) {
331 for (var i
=0; i
<a
.length
; i
=i
+1) {
339 * Returns a unique array. Does not maintain order, which is fine
340 * for this application, and performs better than it would if it
344 return YUI
.ObjectUtil
.keys(YUI
.ArrayUtil
.toObject(a
));
352 finishInit: function(yahooref
) {
354 // YAHOO has been loaded either in this window or passed
355 // from the sandbox routine. Set up local references
356 // to the loader and module metadata in the YAHOO object
357 // in question so additional modules can be loaded.
359 yahooref
= yahooref
|| YAHOO
;
361 yahooref
.env
.YUIInfo
=YUI
.info
;
362 yahooref
.util
.YUILoader
=YUI
.YUILoader
;
367 * Global handler for the module loaded event exposed by
370 onModuleLoaded: function(minfo
) {
372 var mname
= minfo
.name
, m
;
374 for (var i
=0; i
<YUI
.loaders
.length
; i
=i
+1) {
375 YUI
.loaders
[i
].loadNext(mname
);
378 //console.log(YAHOO.lang.dump(minfo));
383 * Sets up the module metadata
387 var c
= YAHOO_config
, o
= c
.load
,
388 y_loaded
= (typeof YAHOO
!== "undefined" && YAHOO
.env
);
391 // add our listener to the existing YAHOO.env.listeners stack
394 YAHOO
.env
.listeners
.push(YUI
.onModuleLoaded
);
396 // define a listener in YAHOO_config that YAHOO will pick up
397 // when it is loaded.
401 YUI
.cachedCallback
= c
.listener
;
404 c
.listener = function(minfo
) {
405 YUI
.onModuleLoaded(minfo
);
406 if (YUI
.cachedCallback
) {
407 YUI
.cachedCallback(minfo
);
412 // Fetch the required modules immediately if specified
413 // in YAHOO_config. Otherwise detect YAHOO and fetch
414 // it if it doesn't exist so we have a place to put
415 // the loader. The problem with this is that it will
416 // prevent rollups from working
417 if (o
|| !y_loaded
) {
421 var loader
= new YUI
.YUILoader(o
);
422 loader
.onLoadComplete = function() {
426 if (o
.onLoadComplete
) {
428 loader
._pushEvents();
429 o
.onLoadComplete(loader
);
435 // If no load was requested, we must load YAHOO
436 // so we have a place to put the loader
438 loader
.require("yahoo");
441 loader
.insert(null, o
);
449 YUI
.YUILoader = function(o
) {
451 // Inform the library that it is being injected
452 YAHOO_config
.injecting
= true;
457 * Internal callback to handle multiple internal insert() calls
458 * so that css is inserted prior to js
459 * @property _internalCallback
462 this._internalCallback
= null;
465 * Callback that will be executed when the loader is finished
467 * @method onLoadComplete
470 this.onLoadComplete
= null;
473 * The base directory.
478 this.base
= ("base" in o
) ? o
.base
: YUI
.info
.base
;
481 * Should we allow rollups
482 * @property allowRollup
486 this.allowRollup
= ("allowRollup" in o
) ? o
.allowRollup
: true;
489 * Filter to apply to result url
491 * @type string|object
493 this.filter
= o
.filter
;
496 * Create a sandbox rather than inserting into lib into.
497 * the current context. Not currently supported
502 this.sandbox
= o
.sandbox
;
505 * The list of requested modules
507 * @type {string: boolean}
512 * The library metadata
513 * @property moduleInfo
515 this.moduleInfo
= o
.moduleInfo
|| YUI
.info
.moduleInfo
;
518 * List of rollup files found in the library metadata
524 * Whether or not to load optional dependencies for
525 * the requested modules
526 * @property loadOptional
530 this.loadOptional
= o
.loadOptional
|| false;
533 * All of the derived dependencies in sorted order, which
534 * will be populated when either calculate() or insert()
542 * Set when beginning to compute the dependency tree.
543 * Composed of what YAHOO reports to be loaded combined
544 * with what has been loaded by the tool
546 * @type {string: boolean}
551 * Flag to indicate the dependency tree needs to be recomputed
552 * if insert is called again.
560 * List of modules inserted by the utility
562 * @type {string: boolean}
568 * Provides the information used to skin the skinnable components.
569 * The following skin definition would result in 'skin1' and 'skin2'
570 * being loaded for calendar (if calendar was requested), and
571 * 'sam' for all other skinnable components:
576 * // The default skin, which is automatically applied if not
577 * // overriden by a component-specific skin definition.
578 * // Change this in to apply a different skin globally
579 * defaultSkin: 'sam',
581 * // This is combined with the loader base property to get
582 * // the default root directory for a skin. ex:
583 * // http://yui.yahooapis.com/2.3.0/build/assets/skins/sam/
584 * base: 'assets/skins/',
586 * // The name of the rollup css file for the skin
589 * // The number of skinnable components requested that are
590 * // required before using the rollup file rather than the
591 * // individual component css files
594 * // Any component-specific overrides can be specified here,
595 * // making it possible to load different skins for different
596 * // components. It is possible to load more than one skin
597 * // for a given component as well.
599 * calendar: ['skin1', 'skin2']
605 this.skin
= o
.skin
|| YUI
.ObjectUtil
.clone(YUI
.info
.skin
);
609 this.require(o
.require
);
612 YUI
.loaders
.push(this);
615 YUI
.YUILoader
.prototype = {
619 'searchExp': "-min\\.js",
623 'searchExp': "-min\\.js",
624 'replaceStr': "-debug.js"
628 SKIN_PREFIX
: "skin-",
630 /** Add a new module to the component metadata. The javascript
631 * component must also use YAHOO.register to notify the loader
632 * when it has been loaded, or a verifier function must be
635 * <dt>name:</dt> <dd>required, the component name</dd>
636 * <dt>type:</dt> <dd>required, the component type (js or css)</dd>
637 * <dt>path:</dt> <dd>required, the path to the script from "base"</dd>
638 * <dt>requires:</dt> <dd>the modules required by this component</dd>
639 * <dt>optional:</dt> <dd>the optional modules for this component</dd>
640 * <dt>supersedes:</dt> <dd>the modules this component replaces</dd>
641 * <dt>rollup:</dt> <dd>the number of superseded modules required for automatic rollup</dd>
642 * <dt>verifier:</dt> <dd>a function that is executed to determine when the module is fully loaded</dd>
643 * <dt>fullpath:</dt> <dd>If fullpath is specified, this is used instead of the configured base + path</dd>
644 * <dt>skinnable:</dt> <dd>flag to determine if skin assets should automatically be pulled in</dd>
647 * @param o An object containing the module data
648 * @return {boolean} true if the module was added, false if
649 * the object passed in did not provide all required attributes
651 addModule: function(o
) {
653 if (!o
|| !o
.name
|| !o
.type
|| (!o
.path
&& !o
.fullpath
)) {
657 this.moduleInfo
[o
.name
] = o
;
664 * Add a requirement for one or more module
666 * @param what {string[] | string*} the modules to load
668 require: function(what
) {
669 var a
= (typeof what
=== "string") ? arguments
: what
;
673 for (var i
=0; i
<a
.length
; i
=i
+1) {
674 this.required
[a
[i
]] = true;
675 var s
= this.parseSkin(a
[i
]);
677 this._addSkin(s
.skin
, s
.module
);
680 YUI
.ObjectUtil
.appendArray(this.required
, a
);
685 * Adds the skin def to the module info
689 _addSkin: function(skin
, mod
) {
691 // Add a module definition for the skin rollup css
692 var name
= this.formatSkin(skin
);
693 if (!this.moduleInfo
[name
]) {
697 'path': this.skin
.base
+ skin
+ "/" + this.skin
.path
,
699 'rollup': this.skin
.rollup
703 // Add a module definition for the module-specific skin css
705 name
= this.formatSkin(skin
, mod
);
706 if (!this.moduleInfo
[name
]) {
710 //'path': this.skin.base + skin + "/" + mod + ".css"
711 'path': mod
+ '/' + this.skin
.base
+ skin
+ "/" + mod
+ ".css"
718 * Returns an object containing properties for all modules required
719 * in order to load the requested module
720 * @method getRequires
721 * @param mod The module definition from moduleInfo
723 getRequires: function(mod
) {
724 if (!this.dirty
&& mod
.expanded
) {
728 mod
.requires
=mod
.requires
|| [];
729 var i
, d
=[], r
=mod
.requires
, o
=mod
.optional
, s
=mod
.supersedes
, info
=this.moduleInfo
;
730 for (i
=0; i
<r
.length
; i
=i
+1) {
732 YUI
.ArrayUtil
.appendArray(d
, this.getRequires(info
[r
[i
]]));
735 if (o
&& this.loadOptional
) {
736 for (i
=0; i
<o
.length
; i
=i
+1) {
738 YUI
.ArrayUtil
.appendArray(d
, this.getRequires(info
[o
[i
]]));
742 mod
.expanded
= YUI
.ArrayUtil
.uniq(d
);
748 * Returns an object literal of the modules the supplied module satisfies
749 * @method getProvides
750 * @param mod The module definition from moduleInfo
751 * @return what this module provides
753 getProvides: function(name
) {
754 var mod
= this.moduleInfo
[name
];
758 s
= mod
&& mod
.supersedes
;
760 YUI
.ObjectUtil
.appendArray(o
, s
);
762 // console.log(this.sorted + ", " + name + " provides " + YUI.ObjectUtil.keys(o));
768 * Calculates the dependency tree, the result is stored in the sorted
771 * @param o optional options object
773 calculate: function(o
) {
779 if (this.allowRollup
) {
790 * Investigates the current YUI configuration on the page. By default,
791 * modules already detected will not be loaded again unless a force
792 * option is encountered. Called by calculate()
794 * @param o optional options object
797 _setup: function(o
) {
800 this.loaded
= YUI
.ObjectUtil
.clone(this.inserted
);
802 if (!this.sandbox
&& typeof YAHOO
!== "undefined" && YAHOO
.env
) {
803 this.loaded
= YUI
.ObjectUtil
.merge(this.loaded
, YAHOO
.env
.modules
);
806 // add the ignore list to the list of loaded packages
808 YUI
.ObjectUtil
.appendArray(this.loaded
, o
.ignore
);
811 // remove modules on the force list from the loaded list
813 for (var i
=0; i
<o
.force
.length
; i
=i
+1) {
814 if (o
.force
[i
] in this.loaded
) {
815 delete this.loaded
[o
.force
[i
]];
823 * Inspects the required modules list looking for additional
824 * dependencies. Expands the required list to include all
825 * required modules. Called by calculate()
829 _explode: function() {
831 var r
=this.required
, i
, mod
;
834 mod
= this.moduleInfo
[i
];
837 var req
= this.getRequires(mod
);
840 YUI
.ObjectUtil
.appendArray(r
, req
);
847 * Sets up the requirements for the skin assets if any of the
848 * requested modules are skinnable
854 var r
=this.required
, i
, mod
;
857 mod
= this.moduleInfo
[i
];
858 if (mod
&& mod
.skinnable
) {
859 var o
=this.skin
.override
, j
;
861 for (j
=0; j
<o
[i
].length
; j
=j
+1) {
862 this.require(this.formatSkin(o
[i
][j
], i
));
865 this.require(this.formatSkin(this.skin
.defaultSkin
, i
));
872 * Returns the skin module name for the specified skin name. If a
873 * module name is supplied, the returned skin module name is
874 * specific to the module passed in.
876 * @param skin {string} the name of the skin
877 * @param mod {string} optional: the name of a module to skin
878 * @return {string} the full skin module name
880 formatSkin: function(skin
, mod
) {
881 var s
= this.SKIN_PREFIX
+ skin
;
890 * Reverses <code>formatSkin</code>, providing the skin name and
891 * module name if the string matches the pattern for skins.
893 * @param mod {string} the module name to parse
894 * @return {skin: string, module: string} the parsed skin name
895 * and module name, or null if the supplied string does not match
898 parseSkin: function(mod
) {
900 if (mod
.indexOf(this.SKIN_PREFIX
) === 0) {
901 var a
= mod
.split("-");
902 return {skin
: a
[1], module
: a
[2]};
909 * Look for rollup packages to determine if all of the modules a
910 * rollup supersedes are required. If so, include the rollup to
911 * help reduce the total number of connections required. Called
916 _rollup: function() {
917 var i
, j
, m
, s
, rollups
={}, r
=this.required
, roll
;
919 // find and cache rollup modules
920 if (this.dirty
|| !this.rollups
) {
921 for (i
in this.moduleInfo
) {
922 m
= this.moduleInfo
[i
];
923 //if (m && m.rollup && m.supersedes) {
929 this.rollups
= rollups
;
932 // make as many passes as needed to pick up rollup rollups
936 // go through the rollup candidates
939 // there can be only one
940 if (!r
[i
] && !this.loaded
[i
]) {
941 m
=this.moduleInfo
[i
]; s
= m
.supersedes
; roll
=true;
948 var skin
= this.parseSkin(i
), c
= 0;
952 if (i
!== j
&& this.parseSkin(j
)) {
954 roll
= (c
>= m
.rollup
);
964 // require all modules to trigger a rollup (using the
965 // threshold value has not proved worthwhile)
966 for (j
=0;j
<s
.length
;j
=j
+1) {
968 // if the superseded module is loaded, we can't load the rollup
969 if (this.loaded
[s
[j
]]) {
972 // increment the counter if this module is required. if we are
973 // beyond the rollup threshold, we will use the rollup module
974 } else if (r
[s
[j
]]) {
976 roll
= (c
>= m
.rollup
);
989 // expand the rollup's dependencies
995 // if we made it here w/o rolling up something, we are done
1003 * Remove superceded modules and loaded modules. Called by
1004 * calculate() after we have the mega list of all dependencies
1008 _reduce: function() {
1010 var i
, j
, s
, m
, r
=this.required
;
1013 // remove if already loaded
1014 if (i
in this.loaded
) {
1017 // remove anything this module supersedes
1020 var skinDef
= this.parseSkin(i
);
1023 //console.log("skin found in reduce: " + skinDef.skin + ", " + skinDef.module);
1024 // the skin rollup will not have a module name
1025 if (!skinDef
.module
) {
1026 var skin_pre
= this.SKIN_PREFIX
+ skinDef
.skin
;
1027 //console.log("skin_pre: " + skin_pre);
1029 if (j
!== i
&& j
.indexOf(skin_pre
) > -1) {
1030 //console.log ("removing component skin: " + j);
1037 m
= this.moduleInfo
[i
];
1038 s
= m
&& m
.supersedes
;
1040 for (j
=0;j
<s
.length
;j
=j
+1) {
1052 * Sorts the dependency tree. The last step of calculate()
1057 // create an indexed list
1058 var s
=[], info
=this.moduleInfo
, loaded
=this.loaded
;
1060 // returns true if b is not loaded, and is required
1061 // directly or by means of modules it supersedes.
1062 var requires = function(aa
, bb
) {
1067 var ii
, mm
=info
[aa
], rr
=mm
&& mm
.expanded
;
1069 if (rr
&& YUI
.ArrayUtil
.indexOf(rr
, bb
) > -1) {
1073 var ss
=info
[bb
] && info
[bb
].supersedes
;
1075 for (ii
=0; ii
<ss
.length
; ii
=i
+1) {
1076 if (requires(aa
, ss
[ii
])) {
1085 // get the required items out of the obj into an array so we
1087 for (var i
in this.required
) {
1091 // pointer to the first unsorted item
1094 // keep going until we make a pass without moving anything
1097 var l
=s
.length
, a
, b
, j
, k
, moved
=false;
1099 // start the loop after items that are already sorted
1100 for (j
=p
; j
<l
; j
=j
+1) {
1102 // check the next module on the list to see if its
1103 // dependencies have been met
1106 // check everything below current item and move if we
1107 // find a requirement for the current item
1108 for (k
=j
+1; k
<l
; k
=k
+1) {
1109 if (requires(a
, s
[k
])) {
1111 // extract the dependency so we can move it up
1114 // insert the dependency above the item that
1116 s
.splice(j
, 0, b
[0]);
1123 // jump out of loop if we moved something
1126 // this item is sorted, move our pointer and keep going
1132 // when we make it here and moved is false, we are
1144 * inserts the requested modules and their dependencies.
1145 * <code>type</code> can be "js" or "css". Both script and
1146 * css are inserted if type is not provided.
1148 * @param callback {Function} a function to execute when the load
1150 * @param o optional options object
1151 * @param type {string} the type of dependency to insert
1153 insert: function(callback
, o
, type
) {
1155 //if (!this.onLoadComplete) {
1156 //this.onLoadComplete = callback;
1161 this._internalCallback = function() {
1162 self
._internalCallback
= null;
1163 self
.insert(callback
, o
, "js");
1165 this.insert(null, o
, "css");
1171 // store the callback for when we are done
1172 this.onLoadComplete
= callback
|| this.onLoadComplete
;
1174 // store the optional filter
1175 var f
= o
&& o
.filter
|| null;
1177 if (typeof f
=== "string") {
1178 f
= f
.toUpperCase();
1180 // the logger must be available in order to use the debug
1181 // versions of the library
1182 if (f
=== "DEBUG") {
1183 this.require("logger");
1187 this.filter
= this.FILTERS
[f
] || f
|| this.FILTERS
[this.filter
] || this.filter
;
1189 // store the options... not currently in use
1190 this.insertOptions
= o
;
1192 // build the dependency list
1195 // set a flag to indicate the load has started
1196 this.loading
= true;
1198 // keep the loadType (js, css or undefined) cached
1199 this.loadType
= type
;
1207 * Executed every time a module is loaded, and if we are in a load
1208 * cycle, we attempt to load the next script. Public so that it
1209 * is possible to call this if using a method other than
1210 * YAHOO.register to determine when scripts are fully loaded
1212 * @param mname {string} optional the name of the module that has
1213 * been loaded (which is usually why it is time to load the next
1216 loadNext: function(mname
) {
1218 // console.log("loadNext executing, just loaded " + mname);
1220 // The global handler that is called when each module is loaded
1221 // will pass that module name to this function. Storing this
1222 // data to avoid loading the same module multiple times
1224 this.inserted
[mname
] = true;
1225 //var o = this.getProvides(mname);
1226 //this.inserted = YUI.ObjectUtil.merge(this.inserted, o);
1229 // It is possible that this function is executed due to something
1230 // else one the page loading a YUI module. Only react when we
1231 // are actively loading something
1232 if (!this.loading
) {
1236 // if the module that was just loaded isn't what we were expecting,
1238 if (mname
&& mname
!== this.loading
) {
1242 var s
=this.sorted
, len
=s
.length
, i
, m
, url
;
1244 for (i
=0; i
<len
; i
=i
+1) {
1246 // This.inserted keeps track of what the loader has loaded
1247 if (s
[i
] in this.inserted
) {
1248 // console.log(s[i] + " alread loaded ");
1252 // Because rollups will cause multiple load notifications
1253 // from YAHOO, loadNext may be called multiple times for
1254 // the same module when loading a rollup. We can safely
1255 // skip the subsequent requests
1256 if (s
[i
] === this.loading
) {
1257 // console.log("still loading " + s[i] + ", waiting");
1261 // log("inserting " + s[i]);
1263 m
= this.moduleInfo
[s
[i
]];
1265 // The load type is stored to offer the possibility to load
1266 // the css separately from the script.
1267 if (!this.loadType
|| this.loadType
=== m
.type
) {
1268 this.loading
= s
[i
];
1270 // Insert the css node and continue. It is possible
1271 // that the css file will load out of order ... this
1272 // may be a problem that needs to be addressed, but
1273 // unlike the script files, there is no notification
1274 // mechanism in place for the css files.
1275 if (m
.type
=== "css") {
1277 url
= m
.fullpath
|| this._url(m
.path
);
1279 this.insertCss(url
);
1280 this.inserted
[s
[i
]] = true;
1282 // Scripts must be loaded in order, so we wait for the
1283 // notification from YAHOO or a verifier function to
1284 // process the next script
1287 url
= m
.fullpath
|| this._url(m
.path
);
1288 this.insertScript(url
);
1290 // if a verifier was included for this module, execute
1291 // it, passing the name of the module, and a callback
1292 // that must be exectued when the verifier is done.
1294 var self
= this, name
=s
[i
];
1295 m
.verifier(name
, function() {
1296 self
.loadNext(name
);
1306 this.loading
= null;
1309 // internal callback for loading css first
1310 if (this._internalCallback
) {
1311 var f
= this._internalCallback
;
1312 this._internalCallback
= null;
1314 } else if (this.onLoadComplete
) {
1316 this.onLoadComplete(this);
1322 * In IE, the onAvailable/onDOMReady events need help when Event is
1323 * loaded dynamically
1324 * @method _pushEvents
1327 _pushEvents: function() {
1328 if (typeof YAHOO
!== "undefined" && YAHOO
.util
&& YAHOO
.util
.Event
) {
1329 YAHOO
.util
.Event
._load();
1334 * Generates the full url for a module
1336 * @param path {string} the path fragment
1337 * @return {string} the full url
1340 _url: function(path
) {
1342 var u
= this.base
|| "", f
=this.filter
;
1346 // console.log("filter: " + f + ", " + f.searchExp +
1347 // ", " + f.replaceStr);
1348 u
= u
.replace(new RegExp(f
.searchExp
), f
.replaceStr
);
1357 * Inserts a script node
1358 * @method insertScript
1359 * @param url {string} the full url for the script
1360 * @param win {Window} optional window to target
1362 insertScript: function(url
, win
) {
1364 //console.log("inserting script " + url);
1365 var w
= win
|| window
, d
=w
.document
, n
=d
.createElement("script"),
1366 h
= d
.getElementsByTagName("head")[0];
1369 n
.type
= "text/javascript";
1374 * Inserts a css link node
1376 * @param url {string} the full url for the script
1377 * @param win {Window} optional window to target
1379 insertCss: function(url
, win
) {
1380 // console.log("inserting css " + url);
1381 var w
= win
|| window
, d
=w
.document
, n
=d
.createElement("link"),
1382 h
= d
.getElementsByTagName("head")[0];
1385 n
.type
= "text/css";
1386 n
.rel
= "stylesheet";
1391 * Interns the script for the requested modules. The callback is
1392 * provided a reference to the sandboxed YAHOO object. This only
1393 * applies to the script: css can not be sandboxed. Not implemented.
1395 * @param callback {Function} the callback to exectued when the load is
1399 sandbox: function(callback
) {