/* Copyright (c) 2009, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 3.0.0 build: 1549 */ YUI.add('loader', function(Y) { (function() { /** * Loader dynamically loads script and css files. It includes the dependency * info for the version of the library in use, and will automatically pull in * dependencies for the modules requested. It supports rollup files and will * automatically use these when appropriate in order to minimize the number of * http connections required to load all of the dependencies. It can load the * files from the Yahoo! CDN, and it can utilize the combo service provided on * this network to reduce the number of http connections required to download * YUI files. * * @module loader */ /** * Loader dynamically loads script and css files. It includes the dependency * info for the version of the library in use, and will automatically pull in * dependencies for the modules requested. It supports rollup files and will * automatically use these when appropriate in order to minimize the number of * http connections required to load all of the dependencies. It can load the * files from the Yahoo! CDN, and it can utilize the combo service provided on * this network to reduce the number of http connections required to download * YUI files. * * While the loader can be instantiated by the end user, it normally is not. * @see YUI.use for the normal use case. The use function automatically will * pull in missing dependencies. * * @class Loader * @constructor * @param o an optional set of configuration options. Valid options: *
* myFilter: { * 'searchExp': "-min\\.js", * 'replaceStr': "-debug.js" * } ** *
* myFilter: { * 'searchExp': "-min\\.js", * 'replaceStr': "-debug.js" * } ** @property filter * @type string|{searchExp: string, replaceStr: string} */ // this.filter = null; /** * per-component filter specification. If specified for a given component, this * overrides the filter config. * @property filters * @type object */ this.filters = {}; /** * The list of requested modules * @property required * @type {string: boolean} */ this.required = {}; /** * The library metadata * @property moduleInfo */ // this.moduleInfo = Y.merge(Y.Env.meta.moduleInfo); this.moduleInfo = {}; /** * Provides the information used to skin the skinnable components. * The following skin definition would result in 'skin1' and 'skin2' * being loaded for calendar (if calendar was requested), and * 'sam' for all other skinnable components: * *
* skin: {
*
* // The default skin, which is automatically applied if not
* // overriden by a component-specific skin definition.
* // Change this in to apply a different skin globally
* defaultSkin: 'sam',
*
* // This is combined with the loader base property to get
* // the default root directory for a skin. ex:
* // http://yui.yahooapis.com/2.3.0/build/assets/skins/sam/
* base: 'assets/skins/',
*
* // The name of the rollup css file for the skin
* path: 'skin.css',
*
* // The number of skinnable components requested that are
* // required before using the rollup file rather than the
* // individual component css files
* rollup: 3,
*
* // Any component-specific overrides can be specified here,
* // making it possible to load different skins for different
* // components. It is possible to load more than one skin
* // for a given component as well.
* overrides: {
* calendar: ['skin1', 'skin2']
* }
* }
*
* @property skin
*/
this.skin = Y.merge(Y.Env.meta.skin);
var defaults = Y.Env.meta.modules, i, onPage = YUI.Env.mods;
this._internal = true;
for (i in defaults) {
if (defaults.hasOwnProperty(i)) {
this.addModule(defaults[i], i);
}
}
for (i in onPage) {
if (onPage.hasOwnProperty(i) && !this.moduleInfo[i] && onPage[i].details) {
this.addModule(onPage[i].details, i);
}
}
this._internal = false;
/**
* List of rollup files found in the library metadata
* @property rollups
*/
// this.rollups = null;
/**
* Whether or not to load optional dependencies for
* the requested modules
* @property loadOptional
* @type boolean
* @default false
*/
// this.loadOptional = false;
/**
* All of the derived dependencies in sorted order, which
* will be populated when either calculate() or insert()
* is called
* @property sorted
* @type string[]
*/
this.sorted = [];
/**
* Set when beginning to compute the dependency tree.
* Composed of what YUI reports to be loaded combined
* with what has been loaded by any instance on the page
* with the version number specified in the metadata.
* @propery loaded
* @type {string: boolean}
*/
this.loaded = GLOBAL_LOADED[VERSION];
/**
* A list of modules to attach to the YUI instance when complete.
* If not supplied, the sorted list of dependencies are applied.
* @property attaching
*/
// this.attaching = null;
/**
* Flag to indicate the dependency tree needs to be recomputed
* if insert is called again.
* @property dirty
* @type boolean
* @default true
*/
this.dirty = true;
/**
* List of modules inserted by the utility
* @property inserted
* @type {string: boolean}
*/
this.inserted = {};
/**
* List of skipped modules during insert() because the module
* was not defined
* @property skipped
*/
this.skipped = {};
// Y.on('yui:load', this.loadNext, this);
this._config(o);
};
Y.Loader.prototype = {
FILTER_DEFS: {
RAW: {
'searchExp': "-min\\.js",
'replaceStr': ".js"
},
DEBUG: {
'searchExp': "-min\\.js",
'replaceStr': "-debug.js"
}
},
SKIN_PREFIX: "skin-",
_config: function(o) {
var i, j, val, f;
// apply config values
if (o) {
for (i in o) {
if (o.hasOwnProperty(i)) {
val = o[i];
if (i == 'require') {
this.require(val);
} else if (i == 'modules') {
// add a hash of module definitions
for (j in val) {
if (val.hasOwnProperty(j)) {
this.addModule(val[j], j);
}
}
} else {
this[i] = val;
}
}
}
}
// fix filter
f = this.filter;
if (L.isString(f)) {
f = f.toUpperCase();
this.filterName = f;
this.filter = this.FILTER_DEFS[f];
if (f == 'DEBUG') {
this.require('yui-log', 'dump');
}
}
},
/**
* Returns the skin module name for the specified skin name. If a
* module name is supplied, the returned skin module name is
* specific to the module passed in.
* @method formatSkin
* @param skin {string} the name of the skin
* @param mod {string} optional: the name of a module to skin
* @return {string} the full skin module name
*/
formatSkin: function(skin, mod) {
var s = this.SKIN_PREFIX + skin;
if (mod) {
s = s + "-" + mod;
}
return s;
},
/*
* Reverses formatSkin
, providing the skin name and
* module name if the string matches the pattern for skins.
* @method parseSkin
* @param mod {string} the module name to parse
* @return {skin: string, module: string} the parsed skin name
* and module name, or null if the supplied string does not match
* the skin pattern
*
* This isn't being used at the moment
*
*/
// parseSkin: function(mod) {
//
// if (mod.indexOf(this.SKIN_PREFIX) === 0) {
// var a = mod.split("-");
// return {skin: a[1], module: a[2]};
// }
// return null;
// },
/**
* Adds the skin def to the module info
* @method _addSkin
* @param skin {string} the name of the skin
* @param mod {string} the name of the module
* @param parent {string} parent module if this is a skin of a
* submodule or plugin
* @return {string} the module name for the skin
* @private
*/
_addSkin: function(skin, mod, parent) {
var name = this.formatSkin(skin),
info = this.moduleInfo,
sinf = this.skin,
ext = info[mod] && info[mod].ext,
mdef, pkg;
/*
// Add a module definition for the skin rollup css
if (!info[name]) {
this.addModule({
'name': name,
'type': 'css',
'path': sinf.base + skin + '/' + sinf.path,
//'supersedes': '*',
'after': sinf.after,
'rollup': sinf.rollup,
'ext': ext
});
}
*/
// Add a module definition for the module-specific skin css
if (mod) {
name = this.formatSkin(skin, mod);
if (!info[name]) {
mdef = info[mod];
pkg = mdef.pkg || mod;
this.addModule({
'name': name,
'type': 'css',
'after': sinf.after,
'path': (parent || pkg) + '/' + sinf.base + skin + '/' + mod + '.css',
'ext': ext
});
}
}
return name;
},
/** Add a new module to the component metadata.
* type
can be "js" or "css". Both script and
* css are inserted if type is not provided.
* @method insert
* @param o optional options object
* @param type {string} the type of dependency to insert
*/
insert: function(o, type) {
var self = this, copy = Y.merge(this, true);
delete copy.require;
delete copy.dirty;
_queue.add(function() {
self._insert(copy, o, type);
});
this._continue();
},
/**
* Executed every time a module is loaded, and if we are in a load
* cycle, we attempt to load the next script. Public so that it
* is possible to call this if using a method other than
* Y.register to determine when scripts are fully loaded
* @method loadNext
* @param mname {string} optional the name of the module that has
* been loaded (which is usually why it is time to load the next
* one)
*/
loadNext: function(mname) {
// It is possible that this function is executed due to something
// else one the page loading a YUI module. Only react when we
// are actively loading something
if (!this._loading) {
return;
}
var s, len, i, m, url, self=this, type=this.loadType, fn, msg, attr,
callback=function(o) {
this._combineComplete[type] = true;
var c=this._combining, len=c.length, i;
for (i=0; i