/* 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: * */ /* * Global loader queue * @property _loaderQueue * @type Queue * @private */ YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Y.Queue(); var NOT_FOUND = {}, GLOBAL_ENV = YUI.Env, GLOBAL_LOADED, BASE = 'base', CSS = 'css', JS = 'js', CSSRESET = 'cssreset', CSSFONTS = 'cssfonts', CSSGRIDS = 'cssgrids', CSSBASE = 'cssbase', CSS_AFTER = [CSSRESET, CSSFONTS, CSSGRIDS, 'cssreset-context', 'cssfonts-context', 'cssgrids-context'], YUI_CSS = ['reset', 'fonts', 'grids', BASE], VERSION = Y.version, ROOT = VERSION + '/build/', CONTEXT = '-context', ANIMBASE = 'anim-base', ATTRIBUTE = 'attribute', ATTRIBUTEBASE = ATTRIBUTE + '-base', BASEBASE = 'base-base', DDDRAG = 'dd-drag', DOM = 'dom', DATASCHEMABASE = 'dataschema-base', DATASOURCELOCAL = 'datasource-local', DOMBASE = 'dom-base', DOMSTYLE = 'dom-style', DOMSCREEN = 'dom-screen', DUMP = 'dump', GET = 'get', EVENTBASE = 'event-base', EVENTCUSTOM = 'event-custom', EVENTCUSTOMBASE = 'event-custom-base', IOBASE = 'io-base', NODE = 'node', NODEBASE = 'node-base', NODESTYLE = 'node-style', NODESCREEN = 'node-screen', OOP = 'oop', PLUGINHOST = 'pluginhost', SELECTORCSS2 = 'selector-css2', SUBSTITUTE = 'substitute', WIDGET = 'widget', WIDGETPOSITION = 'widget-position', YUIBASE = 'yui-base', PLUGIN = 'plugin', META = { version: VERSION, root: ROOT, base: 'http://yui.yahooapis.com/' + ROOT, comboBase: 'http://yui.yahooapis.com/combo?', skin: { defaultSkin: 'sam', base: 'assets/skins/', path: 'skin.css', after: CSS_AFTER //rollup: 3 }, modules: { dom: { requires: [OOP], submodules: { 'dom-base': { requires: [OOP] }, 'dom-style': { requires: [DOMBASE] }, 'dom-screen': { requires: [DOMBASE, DOMSTYLE] }, 'selector-native': { requires: [DOMBASE] }, 'selector-css2': { requires: ['selector-native'] }, 'selector': { requires: [DOMBASE] } }, plugins: { 'selector-css3': { requires: [SELECTORCSS2] } } }, node: { requires: [DOM, EVENTBASE], // expound: EVENT, submodules: { 'node-base': { requires: [DOMBASE, SELECTORCSS2, EVENTBASE] }, 'node-style': { requires: [DOMSTYLE, NODEBASE] }, 'node-screen': { requires: [DOMSCREEN, NODEBASE] }, 'node-pluginhost': { requires: [NODEBASE, PLUGINHOST] }, 'node-event-delegate': { requires: [NODEBASE, 'event-delegate'] } }, plugins: { 'node-event-simulate': { requires: [NODEBASE, 'event-simulate'] } } }, anim: { submodules: { 'anim-base': { requires: [BASEBASE, NODESTYLE] }, 'anim-color': { requires: [ANIMBASE] }, 'anim-easing': { requires: [ANIMBASE] }, 'anim-scroll': { requires: [ANIMBASE] }, 'anim-xy': { requires: [ANIMBASE, NODESCREEN] }, 'anim-curve': { requires: ['anim-xy'] }, 'anim-node-plugin': { requires: ['node-pluginhost', ANIMBASE] } } }, attribute: { submodules: { 'attribute-base': { requires: [EVENTCUSTOM] }, 'attribute-complex': { requires: [ATTRIBUTEBASE] } } }, base: { submodules: { 'base-base': { requires: [ATTRIBUTEBASE] }, 'base-build': { requires: [BASEBASE] }, 'base-pluginhost': { requires: [BASEBASE, PLUGINHOST] } } }, cache: { requires: [PLUGIN] }, compat: { requires: [NODE, DUMP, SUBSTITUTE] }, classnamemanager: { requires: [YUIBASE] }, collection: { requires: [OOP] }, console: { requires: ['yui-log', WIDGET, SUBSTITUTE], skinnable: true, plugins: { 'console-filters': { requires: [PLUGIN, 'console'], skinnable: true } } }, cookie: { requires: [YUIBASE] }, dataschema:{ submodules: { 'dataschema-base': { requires: [BASE] }, 'dataschema-array': { requires: [DATASCHEMABASE] }, 'dataschema-json': { requires: [DATASCHEMABASE, 'json'] }, 'dataschema-text': { requires: [DATASCHEMABASE] }, 'dataschema-xml': { requires: [DATASCHEMABASE] } } }, datasource:{ submodules: { 'datasource-local': { requires: [BASE] }, 'datasource-arrayschema': { requires: [DATASOURCELOCAL, PLUGIN, 'dataschema-array'] }, 'datasource-cache': { requires: [DATASOURCELOCAL, 'cache'] }, 'datasource-function': { requires: [DATASOURCELOCAL] }, 'datasource-jsonschema': { requires: [DATASOURCELOCAL, PLUGIN, 'dataschema-json'] }, 'datasource-polling': { requires: [DATASOURCELOCAL] }, 'datasource-get': { requires: [DATASOURCELOCAL, GET] }, 'datasource-textschema': { requires: [DATASOURCELOCAL, PLUGIN, 'dataschema-text'] }, 'datasource-io': { requires: [DATASOURCELOCAL, IOBASE] }, 'datasource-xmlschema': { requires: [DATASOURCELOCAL, PLUGIN, 'dataschema-xml'] } } }, datatype:{ submodules: { 'datatype-date': { requires: [YUIBASE] }, 'datatype-number': { requires: [YUIBASE] }, 'datatype-xml': { requires: [YUIBASE] } } }, dd:{ submodules: { 'dd-ddm-base': { requires: [NODE, BASE] }, 'dd-ddm':{ requires: ['dd-ddm-base', 'event-resize'] }, 'dd-ddm-drop':{ requires: ['dd-ddm'] }, 'dd-drag':{ requires: ['dd-ddm-base'] }, 'dd-drop':{ requires: ['dd-ddm-drop'] }, 'dd-proxy':{ requires: [DDDRAG] }, 'dd-constrain':{ requires: [DDDRAG] }, 'dd-scroll':{ requires: [DDDRAG] }, 'dd-plugin':{ requires: [DDDRAG], optional: ['dd-constrain', 'dd-proxy'] }, 'dd-drop-plugin':{ requires: ['dd-drop'] } } }, dump: { requires: [YUIBASE] }, event: { expound: NODEBASE, submodules: { 'event-base': { expound: NODEBASE, requires: [EVENTCUSTOMBASE] }, 'event-delegate': { requires: [NODEBASE] }, 'event-focus': { requires: [NODEBASE] }, 'event-key': { requires: [NODEBASE] }, 'event-mouseenter': { requires: [NODEBASE] }, 'event-mousewheel': { requires: [NODEBASE] }, 'event-resize': { requires: [NODEBASE] } } }, 'event-custom': { submodules: { 'event-custom-base': { requires: [OOP, 'yui-later'] }, 'event-custom-complex': { requires: [EVENTCUSTOMBASE] } } }, 'event-simulate': { requires: [EVENTBASE] }, 'node-focusmanager': { requires: [ATTRIBUTE, NODE, PLUGIN, 'node-event-simulate', 'event-key', 'event-focus'] }, history: { requires: [NODE] }, imageloader: { requires: [BASEBASE, NODESTYLE, NODESCREEN] }, io:{ submodules: { 'io-base': { requires: [EVENTCUSTOMBASE] }, 'io-xdr': { requires: [IOBASE, 'datatype-xml'] }, 'io-form': { requires: [IOBASE, NODEBASE, NODESTYLE] }, 'io-upload-iframe': { requires: [IOBASE, NODEBASE] }, 'io-queue': { requires: [IOBASE, 'queue-promote'] } } }, json: { submodules: { 'json-parse': { requires: [YUIBASE] }, 'json-stringify': { requires: [YUIBASE] } } }, loader: { requires: [GET] }, 'node-menunav': { requires: [NODE, 'classnamemanager', PLUGIN, 'node-focusmanager'], skinnable: true }, oop: { requires: [YUIBASE] }, overlay: { requires: [WIDGET, WIDGETPOSITION, 'widget-position-ext', 'widget-stack', 'widget-stdmod'], skinnable: true }, plugin: { requires: [BASEBASE] }, pluginhost: { requires: [YUIBASE] }, profiler: { requires: [YUIBASE] }, 'queue-promote': { requires: [YUIBASE] }, // deprecated package, replaced with async-queue 'queue-run': { requires: [EVENTCUSTOM], path: 'async-queue/async-queue-min.js' }, 'async-queue': { requires: [EVENTCUSTOM], supersedes: ['queue-run'] }, slider: { requires: [WIDGET, 'dd-constrain'], skinnable: true }, stylesheet: { requires: [YUIBASE] }, substitute: { optional: [DUMP] }, widget: { requires: [ATTRIBUTE, 'event-focus', BASE, NODE, 'classnamemanager'], plugins: { 'widget-position': { }, 'widget-position-ext': { requires: [WIDGETPOSITION] }, 'widget-stack': { skinnable: true }, 'widget-stdmod': { } }, skinnable: true }, yui: { submodules: { 'yui-base': {}, get: {}, 'yui-log': {}, 'yui-later': {} } }, test: { requires: [SUBSTITUTE, NODE, 'json', 'event-simulate'] } } }, _path = Y.cached(function(dir, file, type) { return dir + '/' + file + '-min.' + (type || CSS); }), _queue = YUI.Env._loaderQueue, mods = META.modules, i, bname, mname, contextname, L = Y.Lang; // Create the metadata for both the regular and context-aware // versions of the YUI CSS foundation. for (i=0; i -1); /** * Ignore modules registered on the YUI global * @property ignoreRegistered * @default false */ // this.ignoreRegistered = false; /** * Root path to prepend to module path for the combo * service * @property root * @type string * @default [YUI VERSION]/build/ */ this.root = Y.Env.meta.root; /** * Timeout value in milliseconds. If set, this value will be used by * the get utility. the timeout event will fire if * a timeout occurs. * @property timeout * @type int */ this.timeout = 0; /** * A list of modules that should not be loaded, even if * they turn up in the dependency tree * @property ignore * @type string[] */ // this.ignore = null; /** * A list of modules that should always be loaded, even * if they have already been inserted into the page. * @property force * @type string[] */ // this.force = null; this.forceMap = {}; /** * Should we allow rollups * @property allowRollup * @type boolean * @default true */ // this.allowRollup = true; /** * A filter to apply to result urls. This filter will modify the default * path for all modules. The default path for the YUI library is the * minified version of the files (e.g., event-min.js). The filter property * can be a predefined filter or a custom filter. The valid predefined * filters are: *
*
DEBUG
*
Selects the debug versions of the library (e.g., event-debug.js). * This option will automatically include the Logger widget
*
RAW
*
Selects the non-minified version of the library (e.g., event.js).
*
* You can also define a custom filter, which must be an object literal * containing a search expression and a replace string: *
     *  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. *
*
name:
required, the component name
*
type:
required, the component type (js or css)
*
path:
required, the path to the script from "base"
*
requires:
array of modules required by this component
*
optional:
array of optional modules for this component
*
supersedes:
array of the modules this component replaces
*
after:
array of modules the components which, if present, should be sorted above this one
*
rollup:
the number of superseded modules required for automatic rollup
*
fullpath:
If fullpath is specified, this is used instead of the configured base + path
*
skinnable:
flag to determine if skin assets should automatically be pulled in
*
submodules:
a has of submodules
*
* @method addModule * @param o An object containing the module data * @param name the module name (optional), required if not in the module data * @return {boolean} true if the module was added, false if * the object passed in did not provide all required attributes */ addModule: function(o, name) { name = name || o.name; o.name = name; if (!o || !o.name) { return false; } if (!o.type) { o.type = JS; } if (!o.path && !o.fullpath) { // o.path = name + "/" + name + "-min." + o.type; o.path = _path(name, name, o.type); } o.ext = ('ext' in o) ? o.ext : (this._internal) ? false : true; o.requires = o.requires || []; this.moduleInfo[name] = o; // Handle submodule logic var subs = o.submodules, i, l, sup, s, smod, plugins, plug; if (subs) { sup = []; l = 0; for (i in subs) { if (subs.hasOwnProperty(i)) { s = subs[i]; s.path = _path(name, i, o.type); this.addModule(s, i); sup.push(i); if (o.skinnable) { smod = this._addSkin(this.skin.defaultSkin, i, name); sup.push(smod.name); } l++; } } o.supersedes = sup; o.rollup = (l<4) ? l : Math.min(l-1, 4); } plugins = o.plugins; if (plugins) { for (i in plugins) { if (plugins.hasOwnProperty(i)) { plug = plugins[i]; plug.path = _path(name, i, o.type); plug.requires = plug.requires || []; // plug.requires.push(name); this.addModule(plug, i); if (o.skinnable) { this._addSkin(this.skin.defaultSkin, i, name); } } } } this.dirty = true; return o; }, /** * Add a requirement for one or more module * @method require * @param what {string[] | string*} the modules to load */ require: function(what) { var a = (typeof what === "string") ? arguments : what; this.dirty = true; Y.mix(this.required, Y.Array.hash(a)); }, /** * Returns an object containing properties for all modules required * in order to load the requested module * @method getRequires * @param mod The module definition from moduleInfo */ getRequires: function(mod) { if (!mod) { return []; } if (!this.dirty && mod.expanded) { return mod.expanded; } var i, d=[], r=mod.requires, o=mod.optional, info=this.moduleInfo, m, j, add; for (i=0; i= m.rollup); if (roll) { break; } } } if (roll) { // add the rollup r[i] = true; rolled = true; // expand the rollup's dependencies this.getRequires(m); } } } } // if we made it here w/o rolling up something, we are done if (!rolled) { break; } } }, /** * Remove superceded modules and loaded modules. Called by * calculate() after we have the mega list of all dependencies * @method _reduce * @private */ _reduce: function() { var i, j, s, m, r=this.required, type = this.loadType; for (i in r) { if (r.hasOwnProperty(i)) { m = this.getModule(i); // remove if already loaded if ((this.loaded[i] && (!this.forceMap[i]) && !this.ignoreRegistered) || (type && m && m.type != type)) { delete r[i]; // remove anything this module supersedes } else { s = m && m.supersedes; if (s) { for (j=0; j -1) { return true; } // check if this module should be sorted after the other if (after && Y.Array.indexOf(after, mod2) > -1) { return true; } // check if this module requires one the other supersedes s = info[mod2] && info[mod2].supersedes; if (s) { for (i=0; i 0) { _queue.running = true; _queue.next()(); } }, /** * inserts the requested modules and their dependencies. * 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