loader.js revision 7610ea6bb4900ac3e259a4f299f9317f77f76971
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * Loader dynamically loads script and css files. It includes the dependency
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * info for the version of the library in use, and will automatically pull in
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * dependencies for the modules requested. It supports rollup files and will
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * automatically use these when appropriate in order to minimize the number of
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * http connections required to load all of the dependencies. It can load the
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * files from the Yahoo! CDN, and it can utilize the combo service provided on
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * this network to reduce the number of http connections required to download
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * @module yui
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * @submodule loader
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * Loader dynamically loads script and css files. It includes the dependency
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * info for the version of the library in use, and will automatically pull in
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * dependencies for the modules requested. It supports rollup files and will
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * automatically use these when appropriate in order to minimize the number of
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * http connections required to load all of the dependencies. It can load the
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * files from the Yahoo! CDN, and it can utilize the combo service provided on
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * this network to reduce the number of http connections required to download
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * @class Loader
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * @constructor
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * @param o an optional set of configuration options. Valid options:
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * The base dir</li>
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * <li>secureBase:
6f1205897504b8f50b1785975482c995888dd630Tinderbox User * The secure base dir (not implemented)</li>
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * <li>comboBase:
794b79e6bbc3f5db1ea6ae154d739b9f1ef1a375Tinderbox User * The YUI combo service base dir. Ex: http://yui.yahooapis.com/combo?</li>
794b79e6bbc3f5db1ea6ae154d739b9f1ef1a375Tinderbox User * The root path to prepend to module names for the combo service. Ex: 2.5.2/build/</li>
794b79e6bbc3f5db1ea6ae154d739b9f1ef1a375Tinderbox User * <li>filter:
794b79e6bbc3f5db1ea6ae154d739b9f1ef1a375Tinderbox User * A filter to apply to result urls. This filter will modify the default
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * path for all modules. The default path for the YUI library is the
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater * minified version of the files (e.g., event-min.js). The filter property
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater * can be a predefined filter or a custom filter. The valid predefined
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater * filters are:
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater * <dt>DEBUG</dt>
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * <dd>Selects the debug versions of the library (e.g., event-debug.js).
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * This option will automatically include the Logger widget</dd>
6f1205897504b8f50b1785975482c995888dd630Tinderbox User * <dt>RAW</dt>
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * <dd>Selects the non-minified version of the library (e.g., event.js).</dd>
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * You can also define a custom filter, which must be an object literal
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * containing a search expression and a replace string:
8e821eea5f57ac47a94305aa7ab0c3570d92a311Automatic Updater * myFilter: {
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews * 'searchExp': "-min\\.js",
aaaf8d4f4873d21e55c3ffb4f656203d08339865Mark Andrews * 'replaceStr': "-debug.js"
2a6d4c9948b3f4f31311bd799d114585a30419a9Automatic Updater * <li>filters: per-component filter specification. If specified for a given component, this overrides the filter config</li>
8e821eea5f57ac47a94305aa7ab0c3570d92a311Automatic Updater * <li>combine:
8e821eea5f57ac47a94305aa7ab0c3570d92a311Automatic Updater * Use the YUI combo service to reduce the number of http connections required to load your dependencies</li>
2a6d4c9948b3f4f31311bd799d114585a30419a9Automatic Updater * A list of modules that should never be dynamically loaded</li>
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * A list of modules that should always be loaded when required, even if already present on the page</li>
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * <li>insertBefore:
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * Node or id for a node that should be used as the insertion point for new nodes</li>
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * <li>charset:
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * charset for dynamic nodes (deprecated, use jsAttributes or cssAttributes)</li>
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * <li>jsAttributes: object literal containing attributes to add to script nodes</li>
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * <li>cssAttributes: object literal containing attributes to add to link nodes</li>
2a6d4c9948b3f4f31311bd799d114585a30419a9Automatic Updater * <li>timeout:
2a6d4c9948b3f4f31311bd799d114585a30419a9Automatic Updater * number of milliseconds before a timeout occurs when dynamically loading nodes. in not set, there is no timeout</li>
2a6d4c9948b3f4f31311bd799d114585a30419a9Automatic Updater * <li>context:
2a6d4c9948b3f4f31311bd799d114585a30419a9Automatic Updater * execution context for all callbacks</li>
2a6d4c9948b3f4f31311bd799d114585a30419a9Automatic Updater * <li>onSuccess:
2a6d4c9948b3f4f31311bd799d114585a30419a9Automatic Updater * callback for the 'success' event</li>
2a6d4c9948b3f4f31311bd799d114585a30419a9Automatic Updater * <li>onFailure: callback for the 'failure' event</li>
8ec3c085233cedb22b05da36e2773c8f357a7e45Automatic Updater * <li>onCSS: callback for the 'CSSComplete' event. When loading YUI components with CSS
6ea2385360e9e2167e65f9286447da9eea189457Tinderbox User * the CSS is loaded first, then the script. This provides a moment you can tie into to improve
6ea2385360e9e2167e65f9286447da9eea189457Tinderbox User * the presentation of the page while the script is loading.</li>
6ea2385360e9e2167e65f9286447da9eea189457Tinderbox User * <li>onTimeout:
6ea2385360e9e2167e65f9286447da9eea189457Tinderbox User * callback for the 'timeout' event</li>
6ea2385360e9e2167e65f9286447da9eea189457Tinderbox User * <li>onProgress:
6ea2385360e9e2167e65f9286447da9eea189457Tinderbox User * callback executed each time a script or css file is loaded</li>
6ea2385360e9e2167e65f9286447da9eea189457Tinderbox User * <li>modules:
6ea2385360e9e2167e65f9286447da9eea189457Tinderbox User * A list of module definitions. See Loader.addModule for the supported module metadata</li>
6ea2385360e9e2167e65f9286447da9eea189457Tinderbox User// @TODO backed out the custom event changes so that the event system
6ea2385360e9e2167e65f9286447da9eea189457Tinderbox User// isn't required in the seed build. If needed, we may want to
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont// add them back if the event system is detected.
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * Executed when the loader successfully completes an insert operation
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * This can be subscribed to normally, or a listener can be passed
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * as an onSuccess config option.
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * @event success
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * Executed when the loader fails to complete an insert operation.
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * This can be subscribed to normally, or a listener can be passed
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * as an onFailure config option.
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * @event failure
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * Executed when a Get operation times out.
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * This can be subscribed to normally, or a listener can be passed
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * as an onTimeout config option.
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * @event timeout
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User// http://yui.yahooapis.com/combo?2.5.2/build/yahoo/yahoo-min.js&2.5.2/build/dom/dom-min.js&2.5.2/build/event/event-min.js&2.5.2/build/autocomplete/autocomplete-min.js"
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * Global loader queue
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User * @property _loaderQueue
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * @type Queue
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont * @for YUI.Env
90f35c2f2a1c660f3b96eec413036d238df395f6Francis DupontYUI.Env._loaderQueue = YUI.Env._loaderQueue || new Y.Queue();
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater CSS_AFTER = [CSSRESET, CSSFONTS, CSSGRIDS,
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater 'cssreset-context', 'cssfonts-context', 'cssgrids-context'],
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater YUI_CSS = ['reset', 'fonts', 'grids', BASE],
a3f8c8e20780e488141d200acdfea6c5f3303513Automatic Updater comboBase: 'http://yui.yahooapis.com/combo?',
794b79e6bbc3f5db1ea6ae154d739b9f1ef1a375Tinderbox User 'dom-base': {
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont 'dom-style': {
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont 'dom-screen': {
6f1205897504b8f50b1785975482c995888dd630Tinderbox User 'selector-native': {
a3416b0a1b5482b6df32839445ca98c016945570Automatic Updater 'selector-css3': {
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater 'node-base': {
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater 'node-style': {
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater 'node-screen': {
f8e3e03cacd16ffb923a9603fca23a9e1a1fee07Automatic Updater 'node-event-simulate': {
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater 'anim-base': {
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater 'anim-color': {
f8e3e03cacd16ffb923a9603fca23a9e1a1fee07Automatic Updater 'anim-curve': {
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater 'anim-easing': {
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater 'anim-scroll': {
794b79e6bbc3f5db1ea6ae154d739b9f1ef1a375Tinderbox User 'anim-node-plugin': {
794b79e6bbc3f5db1ea6ae154d739b9f1ef1a375Tinderbox User 'base-base': {
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater 'base-build': {
c7d32c0b0ff4c01f0d4479af3410d3c06044d48aAutomatic Updater 'console-filters': {
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont 'dataschema-base': {
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont 'dataschema-array': {
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont 'dataschema-json': {
bbbf2e27d3a981163dab139497d6b2dc85449db0Tinderbox User 'dataschema-text': {
90f35c2f2a1c660f3b96eec413036d238df395f6Francis Dupont 'dataschema-xml': {
submodules: {
datatype:{
submodules: {
dd:{
submodules: {
dump: {
event: {
get: {
history: {
imageloader: {
io:{
submodules: {
json: {
submodules: {
loader: {
skinnable: true
oop: {
overlay: {
skinnable: true
plugin: {
profiler: {
queue: {
submodules: {
plugins: {
slider: {
skinnable: true
stylesheet: {
substitute: {
widget: {
plugins: {
skinnable: true
skinnable: true
yui: {
test: {
L = Y.Lang,
Y.Loader = function(o) {
this._internalCallback = null;
this._useYahooListener = false;
this.onSuccess = null;
this.onFailure = null;
this.onCSS = null;
this.onProgress = null;
this.onTimeout = null;
this.context = Y;
this.data = null;
this.insertBefore = null;
this.charset = null;
this.cssAttributes = null;
this.jsAttributes = null;
* @default http://yui.yahooapis.com/[YUI VERSION]/build/
* @default http://yui.yahooapis.com/combo?
this.ignoreRegistered = false;
this.ignore = null;
this.force = null;
this.allowRollup = true;
* minified version of the files (e.g., event-min.js). The filter property
* <dd>Selects the debug versions of the library (e.g., event-debug.js).
* <dd>Selects the non-minified version of the library (e.g., event.js).</dd>
* 'replaceStr': "-debug.js"
this.filter = null;
this.filters = {};
this.required = {};
this.moduleInfo = {};
for (i in defaults) {
this._internal = true;
this._internal = false;
this.rollups = null;
this.loadOptional = false;
this.sorted = [];
this.attaching = null;
this.dirty = true;
this.inserted = {};
this.skipped = {};
this._config(o);
FILTER_DEFS: {
RAW: {
DEBUG: {
_config: function(o) {
var i, j, val, f;
if (o.hasOwnProperty(i)) {
val = o[i];
for (j in val) {
this[i] = val;
f = this.filter;
if (L.isString(f)) {
f = f.toUpperCase();
this.filterName = f;
if (mod) {
if (mod) {
this.addModule({
return name;
* <dt>after:</dt> <dd>array of modules the components which, if present, should be sorted above this one</dd>
* <dt>fullpath:</dt> <dd>If fullpath is specified, this is used instead of the configured base + path</dd>
if (!o || !o.name) {
if (!o.type) {
if (subs) {
sup = [];
for (i in subs) {
s = subs[i];
this.addModule(s, i);
if (o.skinnable) {
if (plugins) {
for (i in plugins) {
if (o.skinnable) {
this.dirty = true;
this.dirty = true;
if (!mod) {
d.push(r[i]);
m = this.getModule(r[i]);
d.push(r[i]);
m = this.getModule(r[i]);
if (o && this.loadOptional) {
d.push(o[i]);
if (m[ckey]) {
return m[ckey];
s = m.supersedes;
done = {};
me = this;
add(s[i]);
m[SUPER] = o;
return m[ckey];
calculate: function(o) {
if (o || this.dirty) {
this._config(o);
this._setup();
this._explode();
this._rollup();
this._reduce();
this._sort();
this.dirty = false;
_setup: function() {
if (m && m.skinnable) {
if (o && o[name]) {
if (!this.ignoreRegistered) {
if (this.ignore) {
if (l.hasOwnProperty(j)) {
if (this.force) {
if (this.force[i] in l) {
delete l[this.force[i]];
_explode: function() {
if (mod) {
if (expound) {
if (r.hasOwnProperty(i)) {
_rollup: function() {
for (i in info) {
m = this.getModule(i);
if (m && m.rollup) {
rollups[i] = m;
rolled = false;
for (i in rollups) {
if (!r[i] && !this.loaded[i]) {
m = this.getModule(i);
s = m.supersedes || [];
roll = false;
if (!m.rollup) {
if (this.loaded[s[j]]) {
roll = false;
if (roll) {
if (roll) {
rolled = true;
this.getRequires(m);
if (!rolled) {
_reduce: function() {
var i, j, s, m, r=this.required;
if (r.hasOwnProperty(i)) {
m = this.getModule(i);
s = m && m.supersedes;
_attach: function() {
if (this.attaching) {
_finish: function() {
this._continue();
_onSuccess: function() {
this._attach();
for (i in skipped) {
delete this.inserted[i];
this.skipped = {};
f = this.onSuccess;
success: true
this._finish();
_onFailure: function(o) {
this._attach();
var f = this.onFailure;
success: false
this._finish();
_onTimeout: function() {
this._attach();
var f = this.onTimeout;
success: false
this._finish();
_sort: function() {
p, l, a, b, j, k, moved,
if (ss) {
l = s.length;
moved = false;
if (requires(a, s[k])) {
moved = true;
if (moved) {
if (!moved) {
this.sorted = s;
if (source) {
this.calculate(o);
if (!type) {
var self = this;
this._internalCallback = function() {
this._loading = true;
this._combineComplete = {};
this.loadNext();
_continue: function() {
this._continue();
if (!this._loading) {
callback=function(o) {
this.inserted[c[i]] = true;
onsuccess=function(o) {
this._combining = [];
s=this.sorted;
m = this.getModule(s[i]);
autopurge: false,
if (mname) {
if (this.onProgress) {
s=this.sorted;
if (s[i] in this.inserted) {
if (s[i] === this._loading) {
m = this.getModule(s[i]);
this.inserted[s[i]] = true;
this.skipped[s[i]] = true;
this._loading = s[i];
data: s[i],
autopurge: false,
this._loading = null;
if (fn) {
this._internalCallback = null;
this._onSuccess();
var f = this.filter,
if (hasFilter) {