4 ? Y.Array(arguments, 4, true) : null;
return Y.Event.onAvailable.call(Y.Event, id, fn, o, a);
}
};
/**
* Executes the callback as soon as the specified element
* is detected in the DOM with a nextSibling property
* (indicating that the element's children are available).
* This function expects a selector
* string for the element(s) to detect. If you already have
* an element reference, you don't need this event.
* @event contentready
* @param type {string} 'contentready'
* @param fn {function} the callback function to execute.
* @param el {string} an selector for the element(s) to attach.
* @param context optional argument that specifies what 'this' refers to.
* @param args* 0..n additional arguments to pass on to the callback function.
* These arguments will be added after the event object.
* @return {EventHandle} the detach handle
* @for YUI
*/
Y.Env.evt.plugins.contentready = {
on: function(type, fn, id, o) {
var a = arguments.length > 4 ? Y.Array(arguments, 4, true) : null;
return Y.Event.onContentReady.call(Y.Event, id, fn, o, a);
}
};
}, '3.9.1', {"requires": ["event-custom-base"]});
(function() {
var stateChangeListener,
GLOBAL_ENV = YUI.Env,
config = YUI.config,
doc = config.doc,
docElement = doc && doc.documentElement,
EVENT_NAME = 'onreadystatechange',
pollInterval = config.pollInterval || 40;
if (docElement.doScroll && !GLOBAL_ENV._ieready) {
GLOBAL_ENV._ieready = function() {
GLOBAL_ENV._ready();
};
/*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */
// Internet Explorer: use the doScroll() method on the root element.
// This isolates what appears to be a safe moment to manipulate the
// DOM prior to when the document's readyState suggests it is safe to do so.
if (self !== self.top) {
stateChangeListener = function() {
if (doc.readyState == 'complete') {
GLOBAL_ENV.remove(doc, EVENT_NAME, stateChangeListener);
GLOBAL_ENV.ieready();
}
};
GLOBAL_ENV.add(doc, EVENT_NAME, stateChangeListener);
} else {
GLOBAL_ENV._dri = setInterval(function() {
try {
docElement.doScroll('left');
clearInterval(GLOBAL_ENV._dri);
GLOBAL_ENV._dri = null;
GLOBAL_ENV._ieready();
} catch (domNotReady) { }
}, pollInterval);
}
}
})();
YUI.add('event-base-ie', function (Y, NAME) {
/*
* Custom event engine, DOM event listener abstraction layer, synthetic DOM
* events.
* @module event
* @submodule event-base
*/
function IEEventFacade() {
// IEEventFacade.superclass.constructor.apply(this, arguments);
Y.DOM2EventFacade.apply(this, arguments);
}
/*
* (intentially left out of API docs)
* Alternate Facade implementation that is based on Object.defineProperty, which
* is partially supported in IE8. Properties that involve setup work are
* deferred to temporary getters using the static _define method.
*/
function IELazyFacade(e) {
var proxy = Y.config.doc.createEventObject(e),
proto = IELazyFacade.prototype;
// TODO: necessary?
proxy.hasOwnProperty = function () { return true; };
proxy.init = proto.init;
proxy.halt = proto.halt;
proxy.preventDefault = proto.preventDefault;
proxy.stopPropagation = proto.stopPropagation;
proxy.stopImmediatePropagation = proto.stopImmediatePropagation;
Y.DOM2EventFacade.apply(proxy, arguments);
return proxy;
}
var imp = Y.config.doc && Y.config.doc.implementation,
useLazyFacade = Y.config.lazyEventFacade,
buttonMap = {
0: 1, // left click
4: 2, // middle click
2: 3 // right click
},
relatedTargetMap = {
mouseout: 'toElement',
mouseover: 'fromElement'
},
resolve = Y.DOM2EventFacade.resolve,
proto = {
init: function() {
IEEventFacade.superclass.init.apply(this, arguments);
var e = this._event,
x, y, d, b, de, t;
this.target = resolve(e.srcElement);
if (('clientX' in e) && (!x) && (0 !== x)) {
x = e.clientX;
y = e.clientY;
d = Y.config.doc;
b = d.body;
de = d.documentElement;
x += (de.scrollLeft || (b && b.scrollLeft) || 0);
y += (de.scrollTop || (b && b.scrollTop) || 0);
this.pageX = x;
this.pageY = y;
}
if (e.type == "mouseout") {
t = e.toElement;
} else if (e.type == "mouseover") {
t = e.fromElement;
}
// fallback to t.relatedTarget to support simulated events.
// IE doesn't support setting toElement or fromElement on generic
// events, so Y.Event.simulate sets relatedTarget instead.
this.relatedTarget = resolve(t || e.relatedTarget);
// which should contain the unicode key code if this is a key event.
// For click events, which is normalized for which mouse button was
// clicked.
this.which = // chained assignment
this.button = e.keyCode || buttonMap[e.button] || e.button;
},
stopPropagation: function() {
this._event.cancelBubble = true;
this._wrapper.stopped = 1;
this.stopped = 1;
},
stopImmediatePropagation: function() {
this.stopPropagation();
this._wrapper.stopped = 2;
this.stopped = 2;
},
preventDefault: function(returnValue) {
this._event.returnValue = returnValue || false;
this._wrapper.prevented = 1;
this.prevented = 1;
}
};
Y.extend(IEEventFacade, Y.DOM2EventFacade, proto);
Y.extend(IELazyFacade, Y.DOM2EventFacade, proto);
IELazyFacade.prototype.init = function () {
var e = this._event,
overrides = this._wrapper.overrides,
define = IELazyFacade._define,
lazyProperties = IELazyFacade._lazyProperties,
prop;
this.altKey = e.altKey;
this.ctrlKey = e.ctrlKey;
this.metaKey = e.metaKey;
this.shiftKey = e.shiftKey;
this.type = (overrides && overrides.type) || e.type;
this.clientX = e.clientX;
this.clientY = e.clientY;
this.keyCode = // chained assignment
this.charCode = e.keyCode;
this.which = // chained assignment
this.button = e.keyCode || buttonMap[e.button] || e.button;
for (prop in lazyProperties) {
if (lazyProperties.hasOwnProperty(prop)) {
define(this, prop, lazyProperties[prop]);
}
}
if (this._touch) {
this._touch(e, this._currentTarget, this._wrapper);
}
};
IELazyFacade._lazyProperties = {
target: function () {
return resolve(this._event.srcElement);
},
relatedTarget: function () {
var e = this._event,
targetProp = relatedTargetMap[e.type] || 'relatedTarget';
// fallback to t.relatedTarget to support simulated events.
// IE doesn't support setting toElement or fromElement on generic
// events, so Y.Event.simulate sets relatedTarget instead.
return resolve(e[targetProp] || e.relatedTarget);
},
currentTarget: function () {
return resolve(this._currentTarget);
},
wheelDelta: function () {
var e = this._event;
if (e.type === "mousewheel" || e.type === "DOMMouseScroll") {
return (e.detail) ?
(e.detail * -1) :
// wheelDelta between -80 and 80 result in -1 or 1
Math.round(e.wheelDelta / 80) || ((e.wheelDelta < 0) ? -1 : 1);
}
},
pageX: function () {
var e = this._event,
val = e.pageX,
doc, bodyScroll, docScroll;
if (val === undefined) {
doc = Y.config.doc;
bodyScroll = doc.body && doc.body.scrollLeft;
docScroll = doc.documentElement.scrollLeft;
val = e.clientX + (docScroll || bodyScroll || 0);
}
return val;
},
pageY: function () {
var e = this._event,
val = e.pageY,
doc, bodyScroll, docScroll;
if (val === undefined) {
doc = Y.config.doc;
bodyScroll = doc.body && doc.body.scrollTop;
docScroll = doc.documentElement.scrollTop;
val = e.clientY + (docScroll || bodyScroll || 0);
}
return val;
}
};
/**
* Wrapper function for Object.defineProperty that creates a property whose
* value will be calulated only when asked for. After calculating the value,
* the getter wll be removed, so it will behave as a normal property beyond that
* point. A setter is also assigned so assigning to the property will clear
* the getter, so foo.prop = 'a'; foo.prop; won't trigger the getter,
* overwriting value 'a'.
*
* Used only by the DOMEventFacades used by IE8 when the YUI configuration
* lazyEventFacade
is set to true.
*
* @method _define
* @param o {DOMObject} A DOM object to add the property to
* @param prop {String} The name of the new property
* @param valueFn {Function} The function that will return the initial, default
* value for the property.
* @static
* @private
*/
IELazyFacade._define = function (o, prop, valueFn) {
function val(v) {
var ret = (arguments.length) ? v : valueFn.call(this);
delete o[prop];
Object.defineProperty(o, prop, {
value: ret,
configurable: true,
writable: true
});
return ret;
}
Object.defineProperty(o, prop, {
get: val,
set: val,
configurable: true
});
};
if (imp && (!imp.hasFeature('Events', '2.0'))) {
if (useLazyFacade) {
// Make sure we can use the lazy facade logic
try {
Object.defineProperty(Y.config.doc.createEventObject(), 'z', {});
} catch (e) {
useLazyFacade = false;
}
}
Y.DOMEventFacade = (useLazyFacade) ? IELazyFacade : IEEventFacade;
}
}, '3.9.1', {"requires": ["node-base"]});
YUI.add('pluginhost-base', function (Y, NAME) {
/**
* Provides the augmentable PluginHost interface, which can be added to any class.
* @module pluginhost
*/
/**
* Provides the augmentable PluginHost interface, which can be added to any class.
* @module pluginhost-base
*/
/**
*
* An augmentable class, which provides the augmented class with the ability to host plugins.
* It adds plug and unplug methods to the augmented class, which can
* be used to add or remove plugins from instances of the class.
*
*
* Plugins can also be added through the constructor configuration object passed to the host class' constructor using
* the "plugins" property. Supported values for the "plugins" property are those defined by the plug method.
*
* For example the following code would add the AnimPlugin and IOPlugin to Overlay (the plugin host):
*
* var o = new Overlay({plugins: [ AnimPlugin, {fn:IOPlugin, cfg:{section:"header"}}]});
*
*
*
* Plug.Host's protected _initPlugins and _destroyPlugins
* methods should be invoked by the host class at the appropriate point in the host's lifecyle.
*
*
* @class Plugin.Host
*/
var L = Y.Lang;
function PluginHost() {
this._plugins = {};
}
PluginHost.prototype = {
/**
* Adds a plugin to the host object. This will instantiate the
* plugin and attach it to the configured namespace on the host object.
*
* @method plug
* @chainable
* @param P {Function | Object |Array} Accepts the plugin class, or an
* object with a "fn" property specifying the plugin class and
* a "cfg" property specifying the configuration for the Plugin.
*
* Additionally an Array can also be passed in, with the above function or
* object values, allowing the user to add multiple plugins in a single call.
*
* @param config (Optional) If the first argument is the plugin class, the second argument
* can be the configuration for the plugin.
* @return {Base} A reference to the host object
*/
plug: function(Plugin, config) {
var i, ln, ns;
if (L.isArray(Plugin)) {
for (i = 0, ln = Plugin.length; i < ln; i++) {
this.plug(Plugin[i]);
}
} else {
if (Plugin && !L.isFunction(Plugin)) {
config = Plugin.cfg;
Plugin = Plugin.fn;
}
// Plugin should be fn by now
if (Plugin && Plugin.NS) {
ns = Plugin.NS;
config = config || {};
config.host = this;
if (this.hasPlugin(ns)) {
// Update config
if (this[ns].setAttrs) {
this[ns].setAttrs(config);
}
} else {
// Create new instance
this[ns] = new Plugin(config);
this._plugins[ns] = Plugin;
}
}
}
return this;
},
/**
* Removes a plugin from the host object. This will destroy the
* plugin instance and delete the namespace from the host object.
*
* @method unplug
* @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided,
* all registered plugins are unplugged.
* @return {Base} A reference to the host object
* @chainable
*/
unplug: function(plugin) {
var ns = plugin,
plugins = this._plugins;
if (plugin) {
if (L.isFunction(plugin)) {
ns = plugin.NS;
if (ns && (!plugins[ns] || plugins[ns] !== plugin)) {
ns = null;
}
}
if (ns) {
if (this[ns]) {
if (this[ns].destroy) {
this[ns].destroy();
}
delete this[ns];
}
if (plugins[ns]) {
delete plugins[ns];
}
}
} else {
for (ns in this._plugins) {
if (this._plugins.hasOwnProperty(ns)) {
this.unplug(ns);
}
}
}
return this;
},
/**
* Determines if a plugin has plugged into this host.
*
* @method hasPlugin
* @param {String} ns The plugin's namespace
* @return {Plugin} Returns a truthy value (the plugin instance) if present, or undefined if not.
*/
hasPlugin : function(ns) {
return (this._plugins[ns] && this[ns]);
},
/**
* Initializes static plugins registered on the host (using the
* Base.plug static method) and any plugins passed to the
* instance through the "plugins" configuration property.
*
* @method _initPlugins
* @param {Config} config The configuration object with property name/value pairs.
* @private
*/
_initPlugins: function(config) {
this._plugins = this._plugins || {};
if (this._initConfigPlugins) {
this._initConfigPlugins(config);
}
},
/**
* Unplugs and destroys all plugins on the host
* @method _destroyPlugins
* @private
*/
_destroyPlugins: function() {
this.unplug();
}
};
Y.namespace("Plugin").Host = PluginHost;
}, '3.9.1', {"requires": ["yui-base"]});
YUI.add('pluginhost-config', function (Y, NAME) {
/**
* Adds pluginhost constructor configuration and static configuration support
* @submodule pluginhost-config
*/
var PluginHost = Y.Plugin.Host,
L = Y.Lang;
/**
* A protected initialization method, used by the host class to initialize
* plugin configurations passed the constructor, through the config object.
*
* Host objects should invoke this method at the appropriate time in their
* construction lifecycle.
*
* @method _initConfigPlugins
* @param {Object} config The configuration object passed to the constructor
* @protected
* @for Plugin.Host
*/
PluginHost.prototype._initConfigPlugins = function(config) {
// Class Configuration
var classes = (this._getClasses) ? this._getClasses() : [this.constructor],
plug = [],
unplug = {},
constructor, i, classPlug, classUnplug, pluginClassName;
// TODO: Room for optimization. Can we apply statically/unplug in same pass?
for (i = classes.length - 1; i >= 0; i--) {
constructor = classes[i];
classUnplug = constructor._UNPLUG;
if (classUnplug) {
// subclasses over-write
Y.mix(unplug, classUnplug, true);
}
classPlug = constructor._PLUG;
if (classPlug) {
// subclasses over-write
Y.mix(plug, classPlug, true);
}
}
for (pluginClassName in plug) {
if (plug.hasOwnProperty(pluginClassName)) {
if (!unplug[pluginClassName]) {
this.plug(plug[pluginClassName]);
}
}
}
// User Configuration
if (config && config.plugins) {
this.plug(config.plugins);
}
};
/**
* Registers plugins to be instantiated at the class level (plugins
* which should be plugged into every instance of the class by default).
*
* @method plug
* @static
*
* @param {Function} hostClass The host class on which to register the plugins
* @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
* @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
* @for Plugin.Host
*/
PluginHost.plug = function(hostClass, plugin, config) {
// Cannot plug into Base, since Plugins derive from Base [ will cause infinite recurrsion ]
var p, i, l, name;
if (hostClass !== Y.Base) {
hostClass._PLUG = hostClass._PLUG || {};
if (!L.isArray(plugin)) {
if (config) {
plugin = {fn:plugin, cfg:config};
}
plugin = [plugin];
}
for (i = 0, l = plugin.length; i < l;i++) {
p = plugin[i];
name = p.NAME || p.fn.NAME;
hostClass._PLUG[name] = p;
}
}
};
/**
* Unregisters any class level plugins which have been registered by the host class, or any
* other class in the hierarchy.
*
* @method unplug
* @static
*
* @param {Function} hostClass The host class from which to unregister the plugins
* @param {Function | Array} plugin The plugin class, or an array of plugin classes
* @for Plugin.Host
*/
PluginHost.unplug = function(hostClass, plugin) {
var p, i, l, name;
if (hostClass !== Y.Base) {
hostClass._UNPLUG = hostClass._UNPLUG || {};
if (!L.isArray(plugin)) {
plugin = [plugin];
}
for (i = 0, l = plugin.length; i < l; i++) {
p = plugin[i];
name = p.NAME;
if (!hostClass._PLUG[name]) {
hostClass._UNPLUG[name] = p;
} else {
delete hostClass._PLUG[name];
}
}
}
};
}, '3.9.1', {"requires": ["pluginhost-base"]});
YUI.add('event-delegate', function (Y, NAME) {
/**
* Adds event delegation support to the library.
*
* @module event
* @submodule event-delegate
*/
var toArray = Y.Array,
YLang = Y.Lang,
isString = YLang.isString,
isObject = YLang.isObject,
isArray = YLang.isArray,
selectorTest = Y.Selector.test,
detachCategories = Y.Env.evt.handles;
/**
* Sets up event delegation on a container element. The delegated event
* will use a supplied selector or filtering function to test if the event
* references at least one node that should trigger the subscription
* callback.
*
* Selector string filters will trigger the callback if the event originated
* from a node that matches it or is contained in a node that matches it.
* Function filters are called for each Node up the parent axis to the
* subscribing container node, and receive at each level the Node and the event
* object. The function should return true (or a truthy value) if that Node
* should trigger the subscription callback. Note, it is possible for filters
* to match multiple Nodes for a single event. In this case, the delegate
* callback will be executed for each matching Node.
*
* For each matching Node, the callback will be executed with its 'this'
* object set to the Node matched by the filter (unless a specific context was
* provided during subscription), and the provided event's
* currentTarget
will also be set to the matching Node. The
* containing Node from which the subscription was originally made can be
* referenced as e.container
.
*
* @method delegate
* @param type {String} the event type to delegate
* @param fn {Function} the callback function to execute. This function
* will be provided the event object for the delegated event.
* @param el {String|node} the element that is the delegation container
* @param filter {string|Function} a selector that must match the target of the
* event or a function to test target and its parents for a match
* @param context optional argument that specifies what 'this' refers to.
* @param args* 0..n additional arguments to pass on to the callback function.
* These arguments will be added after the event object.
* @return {EventHandle} the detach handle
* @static
* @for Event
*/
function delegate(type, fn, el, filter) {
var args = toArray(arguments, 0, true),
query = isString(el) ? el : null,
typeBits, synth, container, categories, cat, i, len, handles, handle;
// Support Y.delegate({ click: fnA, key: fnB }, el, filter, ...);
// and Y.delegate(['click', 'key'], fn, el, filter, ...);
if (isObject(type)) {
handles = [];
if (isArray(type)) {
for (i = 0, len = type.length; i < len; ++i) {
args[0] = type[i];
handles.push(Y.delegate.apply(Y, args));
}
} else {
// Y.delegate({'click', fn}, el, filter) =>
// Y.delegate('click', fn, el, filter)
args.unshift(null); // one arg becomes two; need to make space
for (i in type) {
if (type.hasOwnProperty(i)) {
args[0] = i;
args[1] = type[i];
handles.push(Y.delegate.apply(Y, args));
}
}
}
return new Y.EventHandle(handles);
}
typeBits = type.split(/\|/);
if (typeBits.length > 1) {
cat = typeBits.shift();
args[0] = type = typeBits.shift();
}
synth = Y.Node.DOM_EVENTS[type];
if (isObject(synth) && synth.delegate) {
handle = synth.delegate.apply(synth, arguments);
}
if (!handle) {
if (!type || !fn || !el || !filter) {
return;
}
container = (query) ? Y.Selector.query(query, null, true) : el;
if (!container && isString(el)) {
handle = Y.on('available', function () {
Y.mix(handle, Y.delegate.apply(Y, args), true);
}, el);
}
if (!handle && container) {
args.splice(2, 2, container); // remove the filter
handle = Y.Event._attach(args, { facade: false });
handle.sub.filter = filter;
handle.sub._notify = delegate.notifySub;
}
}
if (handle && cat) {
categories = detachCategories[cat] || (detachCategories[cat] = {});
categories = categories[type] || (categories[type] = []);
categories.push(handle);
}
return handle;
}
/**
Overrides the _notify
method on the normal DOM subscription to
inject the filtering logic and only proceed in the case of a match.
This method is hosted as a private property of the `delegate` method
(e.g. `Y.delegate.notifySub`)
@method notifySub
@param thisObj {Object} default 'this' object for the callback
@param args {Array} arguments passed to the event's fire()
@param ce {CustomEvent} the custom event managing the DOM subscriptions for
the subscribed event on the subscribing node.
@return {Boolean} false if the event was stopped
@private
@static
@since 3.2.0
**/
delegate.notifySub = function (thisObj, args, ce) {
// Preserve args for other subscribers
args = args.slice();
if (this.args) {
args.push.apply(args, this.args);
}
// Only notify subs if the event occurred on a targeted element
var currentTarget = delegate._applyFilter(this.filter, args, ce),
//container = e.currentTarget,
e, i, len, ret;
if (currentTarget) {
// Support multiple matches up the the container subtree
currentTarget = toArray(currentTarget);
// The second arg is the currentTarget, but we'll be reusing this
// facade, replacing the currentTarget for each use, so it doesn't
// matter what element we seed it with.
e = args[0] = new Y.DOMEventFacade(args[0], ce.el, ce);
e.container = Y.one(ce.el);
for (i = 0, len = currentTarget.length; i < len && !e.stopped; ++i) {
e.currentTarget = Y.one(currentTarget[i]);
ret = this.fn.apply(this.context || e.currentTarget, args);
if (ret === false) { // stop further notifications
break;
}
}
return ret;
}
};
/**
Compiles a selector string into a filter function to identify whether
Nodes along the parent axis of an event's target should trigger event
notification.
This function is memoized, so previously compiled filter functions are
returned if the same selector string is provided.
This function may be useful when defining synthetic events for delegate
handling.
Hosted as a property of the `delegate` method (e.g. `Y.delegate.compileFilter`).
@method compileFilter
@param selector {String} the selector string to base the filtration on
@return {Function}
@since 3.2.0
@static
**/
delegate.compileFilter = Y.cached(function (selector) {
return function (target, e) {
return selectorTest(target._node, selector,
(e.currentTarget === e.target) ? null : e.currentTarget._node);
};
});
/**
Regex to test for disabled elements during filtering. This is only relevant to
IE to normalize behavior with other browsers, which swallow events that occur
to disabled elements. IE fires the event from the parent element instead of the
original target, though it does preserve `event.srcElement` as the disabled
element. IE also supports disabled on ``, but the event still bubbles, so it
acts more like `e.preventDefault()` plus styling. That issue is not handled here
because other browsers fire the event on the ``, so delegate is supported in
both cases.
@property _disabledRE
@type {RegExp}
@protected
@since 3.8.1
**/
delegate._disabledRE = /^(?:button|input|select|textarea)$/i;
/**
Walks up the parent axis of an event's target, and tests each element
against a supplied filter function. If any Nodes, including the container,
satisfy the filter, the delegated callback will be triggered for each.
Hosted as a protected property of the `delegate` method (e.g.
`Y.delegate._applyFilter`).
@method _applyFilter
@param filter {Function} boolean function to test for inclusion in event
notification
@param args {Array} the arguments that would be passed to subscribers
@param ce {CustomEvent} the DOM event wrapper
@return {Node|Node[]|undefined} The Node or Nodes that satisfy the filter
@protected
**/
delegate._applyFilter = function (filter, args, ce) {
var e = args[0],
container = ce.el, // facadeless events in IE, have no e.currentTarget
target = e.target || e.srcElement,
match = [],
isContainer = false;
// Resolve text nodes to their containing element
if (target.nodeType === 3) {
target = target.parentNode;
}
// For IE. IE propagates events from the parent element of disabled
// elements, where other browsers swallow the event entirely. To normalize
// this in IE, filtering for matching elements should abort if the target
// is a disabled form control.
if (target.disabled && delegate._disabledRE.test(target.nodeName)) {
return match;
}
// passing target as the first arg rather than leaving well enough alone
// making 'this' in the filter function refer to the target. This is to
// support bound filter functions.
args.unshift(target);
if (isString(filter)) {
while (target) {
isContainer = (target === container);
if (selectorTest(target, filter, (isContainer ? null: container))) {
match.push(target);
}
if (isContainer) {
break;
}
target = target.parentNode;
}
} else {
// filter functions are implementer code and should receive wrappers
args[0] = Y.one(target);
args[1] = new Y.DOMEventFacade(e, container, ce);
while (target) {
// filter(target, e, extra args...) - this === target
if (filter.apply(args[0], args)) {
match.push(target);
}
if (target === container) {
break;
}
target = target.parentNode;
args[0] = Y.one(target);
}
args[1] = e; // restore the raw DOM event
}
if (match.length <= 1) {
match = match[0]; // single match or undefined
}
// remove the target
args.shift();
return match;
};
/**
* Sets up event delegation on a container element. The delegated event
* will use a supplied filter to test if the callback should be executed.
* This filter can be either a selector string or a function that returns
* a Node to use as the currentTarget for the event.
*
* The event object for the delegated event is supplied to the callback
* function. It is modified slightly in order to support all properties
* that may be needed for event delegation. 'currentTarget' is set to
* the element that matched the selector string filter or the Node returned
* from the filter function. 'container' is set to the element that the
* listener is delegated from (this normally would be the 'currentTarget').
*
* Filter functions will be called with the arguments that would be passed to
* the callback function, including the event object as the first parameter.
* The function should return false (or a falsey value) if the success criteria
* aren't met, and the Node to use as the event's currentTarget and 'this'
* object if they are.
*
* @method delegate
* @param type {string} the event type to delegate
* @param fn {function} the callback function to execute. This function
* will be provided the event object for the delegated event.
* @param el {string|node} the element that is the delegation container
* @param filter {string|function} a selector that must match the target of the
* event or a function that returns a Node or false.
* @param context optional argument that specifies what 'this' refers to.
* @param args* 0..n additional arguments to pass on to the callback function.
* These arguments will be added after the event object.
* @return {EventHandle} the detach handle
* @for YUI
*/
Y.delegate = Y.Event.delegate = delegate;
}, '3.9.1', {"requires": ["node-base"]});
YUI.add('node-event-delegate', function (Y, NAME) {
/**
* Functionality to make the node a delegated event container
* @module node
* @submodule node-event-delegate
*/
/**
* Sets up a delegation listener for an event occurring inside the Node.
* The delegated event will be verified against a supplied selector or
* filtering function to test if the event references at least one node that
* should trigger the subscription callback.
*
* Selector string filters will trigger the callback if the event originated
* from a node that matches it or is contained in a node that matches it.
* Function filters are called for each Node up the parent axis to the
* subscribing container node, and receive at each level the Node and the event
* object. The function should return true (or a truthy value) if that Node
* should trigger the subscription callback. Note, it is possible for filters
* to match multiple Nodes for a single event. In this case, the delegate
* callback will be executed for each matching Node.
*
* For each matching Node, the callback will be executed with its 'this'
* object set to the Node matched by the filter (unless a specific context was
* provided during subscription), and the provided event's
* currentTarget
will also be set to the matching Node. The
* containing Node from which the subscription was originally made can be
* referenced as e.container
.
*
* @method delegate
* @param type {String} the event type to delegate
* @param fn {Function} the callback function to execute. This function
* will be provided the event object for the delegated event.
* @param spec {String|Function} a selector that must match the target of the
* event or a function to test target and its parents for a match
* @param context {Object} optional argument that specifies what 'this' refers to.
* @param args* {any} 0..n additional arguments to pass on to the callback function.
* These arguments will be added after the event object.
* @return {EventHandle} the detach handle
* @for Node
*/
Y.Node.prototype.delegate = function(type) {
var args = Y.Array(arguments, 0, true),
index = (Y.Lang.isObject(type) && !Y.Lang.isArray(type)) ? 1 : 2;
args.splice(index, 0, this._node);
return Y.delegate.apply(Y, args);
};
}, '3.9.1', {"requires": ["node-base", "event-delegate"]});
YUI.add('node-pluginhost', function (Y, NAME) {
/**
* @module node
* @submodule node-pluginhost
*/
/**
* Registers plugins to be instantiated at the class level (plugins
* which should be plugged into every instance of Node by default).
*
* @method plug
* @static
* @for Node
* @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
* @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
*/
Y.Node.plug = function() {
var args = Y.Array(arguments);
args.unshift(Y.Node);
Y.Plugin.Host.plug.apply(Y.Base, args);
return Y.Node;
};
/**
* Unregisters any class level plugins which have been registered by the Node
*
* @method unplug
* @static
*
* @param {Function | Array} plugin The plugin class, or an array of plugin classes
*/
Y.Node.unplug = function() {
var args = Y.Array(arguments);
args.unshift(Y.Node);
Y.Plugin.Host.unplug.apply(Y.Base, args);
return Y.Node;
};
Y.mix(Y.Node, Y.Plugin.Host, false, null, 1);
// allow batching of plug/unplug via NodeList
// doesn't use NodeList.importMethod because we need real Nodes (not tmpNode)
/**
* Adds a plugin to each node in the NodeList.
* This will instantiate the plugin and attach it to the configured namespace on each node
* @method plug
* @for NodeList
* @param P {Function | Object |Array} Accepts the plugin class, or an
* object with a "fn" property specifying the plugin class and
* a "cfg" property specifying the configuration for the Plugin.
*
* Additionally an Array can also be passed in, with the above function or
* object values, allowing the user to add multiple plugins in a single call.
*
* @param config (Optional) If the first argument is the plugin class, the second argument
* can be the configuration for the plugin.
* @chainable
*/
Y.NodeList.prototype.plug = function() {
var args = arguments;
Y.NodeList.each(this, function(node) {
Y.Node.prototype.plug.apply(Y.one(node), args);
});
return this;
};
/**
* Removes a plugin from all nodes in the NodeList. This will destroy the
* plugin instance and delete the namespace each node.
* @method unplug
* @for NodeList
* @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided,
* all registered plugins are unplugged.
* @chainable
*/
Y.NodeList.prototype.unplug = function() {
var args = arguments;
Y.NodeList.each(this, function(node) {
Y.Node.prototype.unplug.apply(Y.one(node), args);
});
return this;
};
}, '3.9.1', {"requires": ["node-base", "pluginhost"]});
YUI.add('node-screen', function (Y, NAME) {
/**
* Extended Node interface for managing regions and screen positioning.
* Adds support for positioning elements and normalizes window size and scroll detection.
* @module node
* @submodule node-screen
*/
// these are all "safe" returns, no wrapping required
Y.each([
/**
* Returns the inner width of the viewport (exludes scrollbar).
* @config winWidth
* @for Node
* @type {Int}
*/
'winWidth',
/**
* Returns the inner height of the viewport (exludes scrollbar).
* @config winHeight
* @type {Int}
*/
'winHeight',
/**
* Document width
* @config docWidth
* @type {Int}
*/
'docWidth',
/**
* Document height
* @config docHeight
* @type {Int}
*/
'docHeight',
/**
* Pixel distance the page has been scrolled horizontally
* @config docScrollX
* @type {Int}
*/
'docScrollX',
/**
* Pixel distance the page has been scrolled vertically
* @config docScrollY
* @type {Int}
*/
'docScrollY'
],
function(name) {
Y.Node.ATTRS[name] = {
getter: function() {
var args = Array.prototype.slice.call(arguments);
args.unshift(Y.Node.getDOMNode(this));
return Y.DOM[name].apply(this, args);
}
};
}
);
Y.Node.ATTRS.scrollLeft = {
getter: function() {
var node = Y.Node.getDOMNode(this);
return ('scrollLeft' in node) ? node.scrollLeft : Y.DOM.docScrollX(node);
},
setter: function(val) {
var node = Y.Node.getDOMNode(this);
if (node) {
if ('scrollLeft' in node) {
node.scrollLeft = val;
} else if (node.document || node.nodeType === 9) {
Y.DOM._getWin(node).scrollTo(val, Y.DOM.docScrollY(node)); // scroll window if win or doc
}
} else {
}
}
};
Y.Node.ATTRS.scrollTop = {
getter: function() {
var node = Y.Node.getDOMNode(this);
return ('scrollTop' in node) ? node.scrollTop : Y.DOM.docScrollY(node);
},
setter: function(val) {
var node = Y.Node.getDOMNode(this);
if (node) {
if ('scrollTop' in node) {
node.scrollTop = val;
} else if (node.document || node.nodeType === 9) {
Y.DOM._getWin(node).scrollTo(Y.DOM.docScrollX(node), val); // scroll window if win or doc
}
} else {
}
}
};
Y.Node.importMethod(Y.DOM, [
/**
* Gets the current position of the node in page coordinates.
* @method getXY
* @for Node
* @return {Array} The XY position of the node
*/
'getXY',
/**
* Set the position of the node in page coordinates, regardless of how the node is positioned.
* @method setXY
* @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
* @chainable
*/
'setXY',
/**
* Gets the current position of the node in page coordinates.
* @method getX
* @return {Int} The X position of the node
*/
'getX',
/**
* Set the position of the node in page coordinates, regardless of how the node is positioned.
* @method setX
* @param {Int} x X value for new position (coordinates are page-based)
* @chainable
*/
'setX',
/**
* Gets the current position of the node in page coordinates.
* @method getY
* @return {Int} The Y position of the node
*/
'getY',
/**
* Set the position of the node in page coordinates, regardless of how the node is positioned.
* @method setY
* @param {Int} y Y value for new position (coordinates are page-based)
* @chainable
*/
'setY',
/**
* Swaps the XY position of this node with another node.
* @method swapXY
* @param {Node | HTMLElement} otherNode The node to swap with.
* @chainable
*/
'swapXY'
]);
/**
* @module node
* @submodule node-screen
*/
/**
* Returns a region object for the node
* @config region
* @for Node
* @type Node
*/
Y.Node.ATTRS.region = {
getter: function() {
var node = this.getDOMNode(),
region;
if (node && !node.tagName) {
if (node.nodeType === 9) { // document
node = node.documentElement;
}
}
if (Y.DOM.isWindow(node)) {
region = Y.DOM.viewportRegion(node);
} else {
region = Y.DOM.region(node);
}
return region;
}
};
/**
* Returns a region object for the node's viewport
* @config viewportRegion
* @type Node
*/
Y.Node.ATTRS.viewportRegion = {
getter: function() {
return Y.DOM.viewportRegion(Y.Node.getDOMNode(this));
}
};
Y.Node.importMethod(Y.DOM, 'inViewportRegion');
// these need special treatment to extract 2nd node arg
/**
* Compares the intersection of the node with another node or region
* @method intersect
* @for Node
* @param {Node|Object} node2 The node or region to compare with.
* @param {Object} altRegion An alternate region to use (rather than this node's).
* @return {Object} An object representing the intersection of the regions.
*/
Y.Node.prototype.intersect = function(node2, altRegion) {
var node1 = Y.Node.getDOMNode(this);
if (Y.instanceOf(node2, Y.Node)) { // might be a region object
node2 = Y.Node.getDOMNode(node2);
}
return Y.DOM.intersect(node1, node2, altRegion);
};
/**
* Determines whether or not the node is within the giving region.
* @method inRegion
* @param {Node|Object} node2 The node or region to compare with.
* @param {Boolean} all Whether or not all of the node must be in the region.
* @param {Object} altRegion An alternate region to use (rather than this node's).
* @return {Object} An object representing the intersection of the regions.
*/
Y.Node.prototype.inRegion = function(node2, all, altRegion) {
var node1 = Y.Node.getDOMNode(this);
if (Y.instanceOf(node2, Y.Node)) { // might be a region object
node2 = Y.Node.getDOMNode(node2);
}
return Y.DOM.inRegion(node1, node2, all, altRegion);
};
}, '3.9.1', {"requires": ["dom-screen", "node-base"]});
YUI.add('node-style', function (Y, NAME) {
(function(Y) {
/**
* Extended Node interface for managing node styles.
* @module node
* @submodule node-style
*/
Y.mix(Y.Node.prototype, {
/**
* Sets a style property of the node.
* Use camelCase (e.g. 'backgroundColor') for multi-word properties.
* @method setStyle
* @param {String} attr The style attribute to set.
* @param {String|Number} val The value.
* @chainable
*/
setStyle: function(attr, val) {
Y.DOM.setStyle(this._node, attr, val);
return this;
},
/**
* Sets multiple style properties on the node.
* Use camelCase (e.g. 'backgroundColor') for multi-word properties.
* @method setStyles
* @param {Object} hash An object literal of property:value pairs.
* @chainable
*/
setStyles: function(hash) {
Y.DOM.setStyles(this._node, hash);
return this;
},
/**
* Returns the style's current value.
* Use camelCase (e.g. 'backgroundColor') for multi-word properties.
* @method getStyle
* @for Node
* @param {String} attr The style attribute to retrieve.
* @return {String} The current value of the style property for the element.
*/
getStyle: function(attr) {
return Y.DOM.getStyle(this._node, attr);
},
/**
* Returns the computed value for the given style property.
* Use camelCase (e.g. 'backgroundColor') for multi-word properties.
* @method getComputedStyle
* @param {String} attr The style attribute to retrieve.
* @return {String} The computed value of the style property for the element.
*/
getComputedStyle: function(attr) {
return Y.DOM.getComputedStyle(this._node, attr);
}
});
/**
* Returns an array of values for each node.
* Use camelCase (e.g. 'backgroundColor') for multi-word properties.
* @method getStyle
* @for NodeList
* @see Node.getStyle
* @param {String} attr The style attribute to retrieve.
* @return {Array} The current values of the style property for the element.
*/
/**
* Returns an array of the computed value for each node.
* Use camelCase (e.g. 'backgroundColor') for multi-word properties.
* @method getComputedStyle
* @see Node.getComputedStyle
* @param {String} attr The style attribute to retrieve.
* @return {Array} The computed values for each node.
*/
/**
* Sets a style property on each node.
* Use camelCase (e.g. 'backgroundColor') for multi-word properties.
* @method setStyle
* @see Node.setStyle
* @param {String} attr The style attribute to set.
* @param {String|Number} val The value.
* @chainable
*/
/**
* Sets multiple style properties on each node.
* Use camelCase (e.g. 'backgroundColor') for multi-word properties.
* @method setStyles
* @see Node.setStyles
* @param {Object} hash An object literal of property:value pairs.
* @chainable
*/
// These are broken out to handle undefined return (avoid false positive for
// chainable)
Y.NodeList.importMethod(Y.Node.prototype, ['getStyle', 'getComputedStyle', 'setStyle', 'setStyles']);
})(Y);
}, '3.9.1', {"requires": ["dom-style", "node-base"]});
YUI.add('querystring-stringify-simple', function (Y, NAME) {
/*global Y */
/**
* Provides Y.QueryString.stringify method for converting objects to Query Strings.
* This is a subset implementation of the full querystring-stringify.
* This module provides the bare minimum functionality (encoding a hash of simple values),
* without the additional support for nested data structures. Every key-value pair is
* encoded by encodeURIComponent.
* This module provides a minimalistic way for io to handle single-level objects
* as transaction data.
*
* @module querystring
* @submodule querystring-stringify-simple
*/
var QueryString = Y.namespace("QueryString"),
EUC = encodeURIComponent;
QueryString.stringify = function (obj, c) {
var qs = [],
// Default behavior is false; standard key notation.
s = c && c.arrayKey ? true : false,
key, i, l;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if (Y.Lang.isArray(obj[key])) {
for (i = 0, l = obj[key].length; i < l; i++) {
qs.push(EUC(s ? key + '[]' : key) + '=' + EUC(obj[key][i]));
}
}
else {
qs.push(EUC(key) + '=' + EUC(obj[key]));
}
}
}
return qs.join('&');
};
}, '3.9.1', {"requires": ["yui-base"]});
YUI.add('io-base', function (Y, NAME) {
/**
Base IO functionality. Provides basic XHR transport support.
@module io
@submodule io-base
@for IO
**/
var // List of events that comprise the IO event lifecycle.
EVENTS = ['start', 'complete', 'end', 'success', 'failure', 'progress'],
// Whitelist of used XHR response object properties.
XHR_PROPS = ['status', 'statusText', 'responseText', 'responseXML'],
win = Y.config.win,
uid = 0;
/**
The IO class is a utility that brokers HTTP requests through a simplified
interface. Specifically, it allows JavaScript to make HTTP requests to
a resource without a page reload. The underlying transport for making
same-domain requests is the XMLHttpRequest object. IO can also use
Flash, if specified as a transport, for cross-domain requests.
@class IO
@constructor
@param {Object} config Object of EventTarget's publish method configurations
used to configure IO's events.
**/
function IO (config) {
var io = this;
io._uid = 'io:' + uid++;
io._init(config);
Y.io._map[io._uid] = io;
}
IO.prototype = {
//--------------------------------------
// Properties
//--------------------------------------
/**
* A counter that increments for each transaction.
*
* @property _id
* @private
* @type {Number}
*/
_id: 0,
/**
* Object of IO HTTP headers sent with each transaction.
*
* @property _headers
* @private
* @type {Object}
*/
_headers: {
'X-Requested-With' : 'XMLHttpRequest'
},
/**
* Object that stores timeout values for any transaction with a defined
* "timeout" configuration property.
*
* @property _timeout
* @private
* @type {Object}
*/
_timeout: {},
//--------------------------------------
// Methods
//--------------------------------------
_init: function(config) {
var io = this, i, len;
io.cfg = config || {};
Y.augment(io, Y.EventTarget);
for (i = 0, len = EVENTS.length; i < len; ++i) {
// Publish IO global events with configurations, if any.
// IO global events are set to broadcast by default.
// These events use the "io:" namespace.
io.publish('io:' + EVENTS[i], Y.merge({ broadcast: 1 }, config));
// Publish IO transaction events with configurations, if
// any. These events use the "io-trn:" namespace.
io.publish('io-trn:' + EVENTS[i], config);
}
},
/**
* Method that creates a unique transaction object for each request.
*
* @method _create
* @private
* @param {Object} cfg Configuration object subset to determine if
* the transaction is an XDR or file upload,
* requiring an alternate transport.
* @param {Number} id Transaction id
* @return {Object} The transaction object
*/
_create: function(config, id) {
var io = this,
transaction = {
id : Y.Lang.isNumber(id) ? id : io._id++,
uid: io._uid
},
alt = config.xdr ? config.xdr.use : null,
form = config.form && config.form.upload ? 'iframe' : null,
use;
if (alt === 'native') {
// Non-IE and IE >= 10 can use XHR level 2 and not rely on an
// external transport.
alt = Y.UA.ie && !SUPPORTS_CORS ? 'xdr' : null;
// Prevent "pre-flight" OPTIONS request by removing the
// `X-Requested-With` HTTP header from CORS requests. This header
// can be added back on a per-request basis, if desired.
io.setHeader('X-Requested-With');
}
use = alt || form;
transaction = use ? Y.merge(Y.IO.customTransport(use), transaction) :
Y.merge(Y.IO.defaultTransport(), transaction);
if (transaction.notify) {
config.notify = function (e, t, c) { io.notify(e, t, c); };
}
if (!use) {
if (win && win.FormData && config.data instanceof win.FormData) {
transaction.c.upload.onprogress = function (e) {
io.progress(transaction, e, config);
};
transaction.c.onload = function (e) {
io.load(transaction, e, config);
};
transaction.c.onerror = function (e) {
io.error(transaction, e, config);
};
transaction.upload = true;
}
}
return transaction;
},
_destroy: function(transaction) {
if (win && !transaction.notify && !transaction.xdr) {
if (XHR && !transaction.upload) {
transaction.c.onreadystatechange = null;
} else if (transaction.upload) {
transaction.c.upload.onprogress = null;
transaction.c.onload = null;
transaction.c.onerror = null;
} else if (Y.UA.ie && !transaction.e) {
// IE, when using XMLHttpRequest as an ActiveX Object, will throw
// a "Type Mismatch" error if the event handler is set to "null".
transaction.c.abort();
}
}
transaction = transaction.c = null;
},
/**
* Method for creating and firing events.
*
* @method _evt
* @private
* @param {String} eventName Event to be published.
* @param {Object} transaction Transaction object.
* @param {Object} config Configuration data subset for event subscription.
*/
_evt: function(eventName, transaction, config) {
var io = this, params,
args = config['arguments'],
emitFacade = io.cfg.emitFacade,
globalEvent = "io:" + eventName,
trnEvent = "io-trn:" + eventName;
// Workaround for #2532107
this.detach(trnEvent);
if (transaction.e) {
transaction.c = { status: 0, statusText: transaction.e };
}
// Fire event with parameters or an Event Facade.
params = [ emitFacade ?
{
id: transaction.id,
data: transaction.c,
cfg: config,
'arguments': args
} :
transaction.id
];
if (!emitFacade) {
if (eventName === EVENTS[0] || eventName === EVENTS[2]) {
if (args) {
params.push(args);
}
} else {
if (transaction.evt) {
params.push(transaction.evt);
} else {
params.push(transaction.c);
}
if (args) {
params.push(args);
}
}
}
params.unshift(globalEvent);
// Fire global events.
io.fire.apply(io, params);
// Fire transaction events, if receivers are defined.
if (config.on) {
params[0] = trnEvent;
io.once(trnEvent, config.on[eventName], config.context || Y);
io.fire.apply(io, params);
}
},
/**
* Fires event "io:start" and creates, fires a transaction-specific
* start event, if `config.on.start` is defined.
*
* @method start
* @param {Object} transaction Transaction object.
* @param {Object} config Configuration object for the transaction.
*/
start: function(transaction, config) {
/**
* Signals the start of an IO request.
* @event io:start
*/
this._evt(EVENTS[0], transaction, config);
},
/**
* Fires event "io:complete" and creates, fires a
* transaction-specific "complete" event, if config.on.complete is
* defined.
*
* @method complete
* @param {Object} transaction Transaction object.
* @param {Object} config Configuration object for the transaction.
*/
complete: function(transaction, config) {
/**
* Signals the completion of the request-response phase of a
* transaction. Response status and data are accessible, if
* available, in this event.
* @event io:complete
*/
this._evt(EVENTS[1], transaction, config);
},
/**
* Fires event "io:end" and creates, fires a transaction-specific "end"
* event, if config.on.end is defined.
*
* @method end
* @param {Object} transaction Transaction object.
* @param {Object} config Configuration object for the transaction.
*/
end: function(transaction, config) {
/**
* Signals the end of the transaction lifecycle.
* @event io:end
*/
this._evt(EVENTS[2], transaction, config);
this._destroy(transaction);
},
/**
* Fires event "io:success" and creates, fires a transaction-specific
* "success" event, if config.on.success is defined.
*
* @method success
* @param {Object} transaction Transaction object.
* @param {Object} config Configuration object for the transaction.
*/
success: function(transaction, config) {
/**
* Signals an HTTP response with status in the 2xx range.
* Fires after io:complete.
* @event io:success
*/
this._evt(EVENTS[3], transaction, config);
this.end(transaction, config);
},
/**
* Fires event "io:failure" and creates, fires a transaction-specific
* "failure" event, if config.on.failure is defined.
*
* @method failure
* @param {Object} transaction Transaction object.
* @param {Object} config Configuration object for the transaction.
*/
failure: function(transaction, config) {
/**
* Signals an HTTP response with status outside of the 2xx range.
* Fires after io:complete.
* @event io:failure
*/
this._evt(EVENTS[4], transaction, config);
this.end(transaction, config);
},
/**
* Fires event "io:progress" and creates, fires a transaction-specific
* "progress" event -- for XMLHttpRequest file upload -- if
* config.on.progress is defined.
*
* @method progress
* @param {Object} transaction Transaction object.
* @param {Object} progress event.
* @param {Object} config Configuration object for the transaction.
*/
progress: function(transaction, e, config) {
/**
* Signals the interactive state during a file upload transaction.
* This event fires after io:start and before io:complete.
* @event io:progress
*/
transaction.evt = e;
this._evt(EVENTS[5], transaction, config);
},
/**
* Fires event "io:complete" and creates, fires a transaction-specific
* "complete" event -- for XMLHttpRequest file upload -- if
* config.on.complete is defined.
*
* @method load
* @param {Object} transaction Transaction object.
* @param {Object} load event.
* @param {Object} config Configuration object for the transaction.
*/
load: function (transaction, e, config) {
transaction.evt = e.target;
this._evt(EVENTS[1], transaction, config);
},
/**
* Fires event "io:failure" and creates, fires a transaction-specific
* "failure" event -- for XMLHttpRequest file upload -- if
* config.on.failure is defined.
*
* @method error
* @param {Object} transaction Transaction object.
* @param {Object} error event.
* @param {Object} config Configuration object for the transaction.
*/
error: function (transaction, e, config) {
transaction.evt = e;
this._evt(EVENTS[4], transaction, config);
},
/**
* Retry an XDR transaction, using the Flash tranport, if the native
* transport fails.
*
* @method _retry
* @private
* @param {Object} transaction Transaction object.
* @param {String} uri Qualified path to transaction resource.
* @param {Object} config Configuration object for the transaction.
*/
_retry: function(transaction, uri, config) {
this._destroy(transaction);
config.xdr.use = 'flash';
return this.send(uri, config, transaction.id);
},
/**
* Method that concatenates string data for HTTP GET transactions.
*
* @method _concat
* @private
* @param {String} uri URI or root data.
* @param {String} data Data to be concatenated onto URI.
* @return {String}
*/
_concat: function(uri, data) {
uri += (uri.indexOf('?') === -1 ? '?' : '&') + data;
return uri;
},
/**
* Stores default client headers for all transactions. If a label is
* passed with no value argument, the header will be deleted.
*
* @method setHeader
* @param {String} name HTTP header
* @param {String} value HTTP header value
*/
setHeader: function(name, value) {
if (value) {
this._headers[name] = value;
} else {
delete this._headers[name];
}
},
/**
* Method that sets all HTTP headers to be sent in a transaction.
*
* @method _setHeaders
* @private
* @param {Object} transaction - XHR instance for the specific transaction.
* @param {Object} headers - HTTP headers for the specific transaction, as
* defined in the configuration object passed to YUI.io().
*/
_setHeaders: function(transaction, headers) {
headers = Y.merge(this._headers, headers);
Y.Object.each(headers, function(value, name) {
if (value !== 'disable') {
transaction.setRequestHeader(name, headers[name]);
}
});
},
/**
* Starts timeout count if the configuration object has a defined
* timeout property.
*
* @method _startTimeout
* @private
* @param {Object} transaction Transaction object generated by _create().
* @param {Object} timeout Timeout in milliseconds.
*/
_startTimeout: function(transaction, timeout) {
var io = this;
io._timeout[transaction.id] = setTimeout(function() {
io._abort(transaction, 'timeout');
}, timeout);
},
/**
* Clears the timeout interval started by _startTimeout().
*
* @method _clearTimeout
* @private
* @param {Number} id - Transaction id.
*/
_clearTimeout: function(id) {
clearTimeout(this._timeout[id]);
delete this._timeout[id];
},
/**
* Method that determines if a transaction response qualifies as success
* or failure, based on the response HTTP status code, and fires the
* appropriate success or failure events.
*
* @method _result
* @private
* @static
* @param {Object} transaction Transaction object generated by _create().
* @param {Object} config Configuration object passed to io().
*/
_result: function(transaction, config) {
var status;
// Firefox will throw an exception if attempting to access
// an XHR object's status property, after a request is aborted.
try {
status = transaction.c.status;
} catch(e) {
status = 0;
}
// IE reports HTTP 204 as HTTP 1223.
if (status >= 200 && status < 300 || status === 304 || status === 1223) {
this.success(transaction, config);
} else {
this.failure(transaction, config);
}
},
/**
* Event handler bound to onreadystatechange.
*
* @method _rS
* @private
* @param {Object} transaction Transaction object generated by _create().
* @param {Object} config Configuration object passed to YUI.io().
*/
_rS: function(transaction, config) {
var io = this;
if (transaction.c.readyState === 4) {
if (config.timeout) {
io._clearTimeout(transaction.id);
}
// Yield in the event of request timeout or abort.
setTimeout(function() {
io.complete(transaction, config);
io._result(transaction, config);
}, 0);
}
},
/**
* Terminates a transaction due to an explicit abort or timeout.
*
* @method _abort
* @private
* @param {Object} transaction Transaction object generated by _create().
* @param {String} type Identifies timed out or aborted transaction.
*/
_abort: function(transaction, type) {
if (transaction && transaction.c) {
transaction.e = type;
transaction.c.abort();
}
},
/**
* Requests a transaction. `send()` is implemented as `Y.io()`. Each
* transaction may include a configuration object. Its properties are:
*
*
* - method
* - HTTP method verb (e.g., GET or POST). If this property is not
* not defined, the default value will be GET.
*
* - data
* - This is the name-value string that will be sent as the
* transaction data. If the request is HTTP GET, the data become
* part of querystring. If HTTP POST, the data are sent in the
* message body.
*
* - xdr
* - Defines the transport to be used for cross-domain requests.
* By setting this property, the transaction will use the specified
* transport instead of XMLHttpRequest. The properties of the
* transport object are:
*
* - use
* - The transport to be used: 'flash' or 'native'
* - dataType
* - Set the value to 'XML' if that is the expected response
* content type.
*
*
* - form
* - Form serialization configuration object. Its properties are:
*
* - id
* - Node object or id of HTML form
* - useDisabled
* - `true` to also serialize disabled form field values
* (defaults to `false`)
*
*
* - on
* - Assigns transaction event subscriptions. Available events are:
*
* - start
* - Fires when a request is sent to a resource.
* - complete
* - Fires when the transaction is complete.
* - success
* - Fires when the HTTP response status is within the 2xx
* range.
* - failure
* - Fires when the HTTP response status is outside the 2xx
* range, if an exception occurs, if the transation is aborted,
* or if the transaction exceeds a configured `timeout`.
* - end
* - Fires at the conclusion of the transaction
* lifecycle, after `success` or `failure`.
*
*
* Callback functions for `start` and `end` receive the id of the
* transaction as a first argument. For `complete`, `success`, and
* `failure`, callbacks receive the id and the response object
* (usually the XMLHttpRequest instance). If the `arguments`
* property was included in the configuration object passed to
* `Y.io()`, the configured data will be passed to all callbacks as
* the last argument.
*
*
* - sync
* - Pass `true` to make a same-domain transaction synchronous.
* CAVEAT: This will negatively impact the user
* experience. Have a very good reason if you intend to use
* this.
*
* - context
* - The "`this'" object for all configured event handlers. If a
* specific context is needed for individual callbacks, bind the
* callback to a context using `Y.bind()`.
*
* - headers
* - Object map of transaction headers to send to the server. The
* object keys are the header names and the values are the header
* values.
*
* - timeout
* - Millisecond threshold for the transaction before being
* automatically aborted.
*
* - arguments
* - User-defined data passed to all registered event handlers.
* This value is available as the second argument in the "start" and
* "end" event handlers. It is the third argument in the "complete",
* "success", and "failure" event handlers. Be sure to quote
* this property name in the transaction configuration as
* "arguments" is a reserved word in JavaScript (e.g.
* `Y.io({ ..., "arguments": stuff })`).
*
*
* @method send
* @public
* @param {String} uri Qualified path to transaction resource.
* @param {Object} config Configuration object for the transaction.
* @param {Number} id Transaction id, if already set.
* @return {Object}
*/
send: function(uri, config, id) {
var transaction, method, i, len, sync, data,
io = this,
u = uri,
response = {};
config = config ? Y.Object(config) : {};
transaction = io._create(config, id);
method = config.method ? config.method.toUpperCase() : 'GET';
sync = config.sync;
data = config.data;
// Serialize a map object into a key-value string using
// querystring-stringify-simple.
if ((Y.Lang.isObject(data) && !data.nodeType) && !transaction.upload) {
if (Y.QueryString && Y.QueryString.stringify) {
config.data = data = Y.QueryString.stringify(data);
} else {
}
}
if (config.form) {
if (config.form.upload) {
// This is a file upload transaction, calling
// upload() in io-upload-iframe.
return io.upload(transaction, uri, config);
} else {
// Serialize HTML form data into a key-value string.
data = io._serialize(config.form, data);
}
}
// Convert falsy values to an empty string. This way IE can't be
// rediculous and translate `undefined` to "undefined".
data || (data = '');
if (data) {
switch (method) {
case 'GET':
case 'HEAD':
case 'DELETE':
u = io._concat(u, data);
data = '';
break;
case 'POST':
case 'PUT':
// If Content-Type is defined in the configuration object, or
// or as a default header, it will be used instead of
// 'application/x-www-form-urlencoded; charset=UTF-8'
config.headers = Y.merge({
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}, config.headers);
break;
}
}
if (transaction.xdr) {
// Route data to io-xdr module for flash and XDomainRequest.
return io.xdr(u, transaction, config);
}
else if (transaction.notify) {
// Route data to custom transport
return transaction.c.send(transaction, uri, config);
}
if (!sync && !transaction.upload) {
transaction.c.onreadystatechange = function() {
io._rS(transaction, config);
};
}
try {
// Determine if request is to be set as
// synchronous or asynchronous.
transaction.c.open(method, u, !sync, config.username || null, config.password || null);
io._setHeaders(transaction.c, config.headers || {});
io.start(transaction, config);
// Will work only in browsers that implement the
// Cross-Origin Resource Sharing draft.
if (config.xdr && config.xdr.credentials && SUPPORTS_CORS) {
transaction.c.withCredentials = true;
}
// Using "null" with HTTP POST will result in a request
// with no Content-Length header defined.
transaction.c.send(data);
if (sync) {
// Create a response object for synchronous transactions,
// mixing id and arguments properties with the xhr
// properties whitelist.
for (i = 0, len = XHR_PROPS.length; i < len; ++i) {
response[XHR_PROPS[i]] = transaction.c[XHR_PROPS[i]];
}
response.getAllResponseHeaders = function() {
return transaction.c.getAllResponseHeaders();
};
response.getResponseHeader = function(name) {
return transaction.c.getResponseHeader(name);
};
io.complete(transaction, config);
io._result(transaction, config);
return response;
}
} catch(e) {
if (transaction.xdr) {
// This exception is usually thrown by browsers
// that do not support XMLHttpRequest Level 2.
// Retry the request with the XDR transport set
// to 'flash'. If the Flash transport is not
// initialized or available, the transaction
// will resolve to a transport error.
return io._retry(transaction, uri, config);
} else {
io.complete(transaction, config);
io._result(transaction, config);
}
}
// If config.timeout is defined, and the request is standard XHR,
// initialize timeout polling.
if (config.timeout) {
io._startTimeout(transaction, config.timeout);
}
return {
id: transaction.id,
abort: function() {
return transaction.c ? io._abort(transaction, 'abort') : false;
},
isInProgress: function() {
return transaction.c ? (transaction.c.readyState % 4) : false;
},
io: io
};
}
};
/**
Method for initiating an ajax call. The first argument is the url end
point for the call. The second argument is an object to configure the
transaction and attach event subscriptions. The configuration object
supports the following properties:
- method
- HTTP method verb (e.g., GET or POST). If this property is not
not defined, the default value will be GET.
- data
- This is the name-value string that will be sent as the
transaction data. If the request is HTTP GET, the data become
part of querystring. If HTTP POST, the data are sent in the
message body.
- xdr
- Defines the transport to be used for cross-domain requests.
By setting this property, the transaction will use the specified
transport instead of XMLHttpRequest. The properties of the
transport object are:
- use
- The transport to be used: 'flash' or 'native'
- dataType
- Set the value to 'XML' if that is the expected response
content type.
- form
- Form serialization configuration object. Its properties are:
- id
- Node object or id of HTML form
- useDisabled
- `true` to also serialize disabled form field values
(defaults to `false`)
- on
- Assigns transaction event subscriptions. Available events are:
- start
- Fires when a request is sent to a resource.
- complete
- Fires when the transaction is complete.
- success
- Fires when the HTTP response status is within the 2xx
range.
- failure
- Fires when the HTTP response status is outside the 2xx
range, if an exception occurs, if the transation is aborted,
or if the transaction exceeds a configured `timeout`.
- end
- Fires at the conclusion of the transaction
lifecycle, after `success` or `failure`.
Callback functions for `start` and `end` receive the id of the
transaction as a first argument. For `complete`, `success`, and
`failure`, callbacks receive the id and the response object
(usually the XMLHttpRequest instance). If the `arguments`
property was included in the configuration object passed to
`Y.io()`, the configured data will be passed to all callbacks as
the last argument.
- sync
- Pass `true` to make a same-domain transaction synchronous.
CAVEAT: This will negatively impact the user
experience. Have a very good reason if you intend to use
this.
- context
- The "`this'" object for all configured event handlers. If a
specific context is needed for individual callbacks, bind the
callback to a context using `Y.bind()`.
- headers
- Object map of transaction headers to send to the server. The
object keys are the header names and the values are the header
values.
- timeout
- Millisecond threshold for the transaction before being
automatically aborted.
- arguments
- User-defined data passed to all registered event handlers.
This value is available as the second argument in the "start" and
"end" event handlers. It is the third argument in the "complete",
"success", and "failure" event handlers. Be sure to quote
this property name in the transaction configuration as
"arguments" is a reserved word in JavaScript (e.g.
`Y.io({ ..., "arguments": stuff })`).
@method io
@static
@param {String} url qualified path to transaction resource.
@param {Object} config configuration object for the transaction.
@return {Object}
@for YUI
**/
Y.io = function(url, config) {
// Calling IO through the static interface will use and reuse
// an instance of IO.
var transaction = Y.io._map['io:0'] || new IO();
return transaction.send.apply(transaction, [url, config]);
};
/**
Method for setting and deleting IO HTTP headers to be sent with every
request.
Hosted as a property on the `io` function (e.g. `Y.io.header`).
@method header
@param {String} name HTTP header
@param {String} value HTTP header value
@static
**/
Y.io.header = function(name, value) {
// Calling IO through the static interface will use and reuse
// an instance of IO.
var transaction = Y.io._map['io:0'] || new IO();
transaction.setHeader(name, value);
};
Y.IO = IO;
// Map of all IO instances created.
Y.io._map = {};
var XHR = win && win.XMLHttpRequest,
XDR = win && win.XDomainRequest,
AX = win && win.ActiveXObject,
// Checks for the presence of the `withCredentials` in an XHR instance
// object, which will be present if the environment supports CORS.
SUPPORTS_CORS = XHR && 'withCredentials' in (new XMLHttpRequest());
Y.mix(Y.IO, {
/**
* The ID of the default IO transport, defaults to `xhr`
* @property _default
* @type {String}
* @static
*/
_default: 'xhr',
/**
*
* @method defaultTransport
* @static
* @param {String} [id] The transport to set as the default, if empty a new transport is created.
* @return {Object} The transport object with a `send` method
*/
defaultTransport: function(id) {
if (id) {
Y.IO._default = id;
} else {
var o = {
c: Y.IO.transports[Y.IO._default](),
notify: Y.IO._default === 'xhr' ? false : true
};
return o;
}
},
/**
* An object hash of custom transports available to IO
* @property transports
* @type {Object}
* @static
*/
transports: {
xhr: function () {
return XHR ? new XMLHttpRequest() :
AX ? new ActiveXObject('Microsoft.XMLHTTP') : null;
},
xdr: function () {
return XDR ? new XDomainRequest() : null;
},
iframe: function () { return {}; },
flash: null,
nodejs: null
},
/**
* Create a custom transport of type and return it's object
* @method customTransport
* @param {String} id The id of the transport to create.
* @static
*/
customTransport: function(id) {
var o = { c: Y.IO.transports[id]() };
o[(id === 'xdr' || id === 'flash') ? 'xdr' : 'notify'] = true;
return o;
}
});
Y.mix(Y.IO.prototype, {
/**
* Fired from the notify method of the transport which in turn fires
* the event on the IO object.
* @method notify
* @param {String} event The name of the event
* @param {Object} transaction The transaction object
* @param {Object} config The configuration object for this transaction
*/
notify: function(event, transaction, config) {
var io = this;
switch (event) {
case 'timeout':
case 'abort':
case 'transport error':
transaction.c = { status: 0, statusText: event };
event = 'failure';
default:
io[event].apply(io, [transaction, config]);
}
}
});
}, '3.9.1', {"requires": ["event-custom-base", "querystring-stringify-simple"]});
YUI.add('json-parse', function (Y, NAME) {
var _JSON = Y.config.global.JSON;
Y.namespace('JSON').parse = function (obj, reviver, space) {
return _JSON.parse((typeof obj === 'string' ? obj : obj + ''), reviver, space);
};
}, '3.9.1', {"requires": ["yui-base"]});
YUI.add('transition', function (Y, NAME) {
/**
* Provides the transition method for Node.
* Transition has no API of its own, but adds the transition method to Node.
*
* @module transition
* @requires node-style
*/
var CAMEL_VENDOR_PREFIX = '',
VENDOR_PREFIX = '',
DOCUMENT = Y.config.doc,
DOCUMENT_ELEMENT = 'documentElement',
DOCUMENT_STYLE = DOCUMENT[DOCUMENT_ELEMENT].style,
TRANSITION_CAMEL = 'transition',
TRANSITION_PROPERTY_CAMEL = 'transitionProperty',
TRANSITION_PROPERTY,
TRANSITION_DURATION,
TRANSITION_TIMING_FUNCTION,
TRANSITION_DELAY,
TRANSITION_END,
ON_TRANSITION_END,
EMPTY_OBJ = {},
VENDORS = [
'Webkit',
'Moz'
],
VENDOR_TRANSITION_END = {
Webkit: 'webkitTransitionEnd'
},
/**
* A class for constructing transition instances.
* Adds the "transition" method to Node.
* @class Transition
* @constructor
*/
Transition = function() {
this.init.apply(this, arguments);
};
// One off handling of transform-prefixing.
Transition._TRANSFORM = 'transform';
Transition._toCamel = function(property) {
property = property.replace(/-([a-z])/gi, function(m0, m1) {
return m1.toUpperCase();
});
return property;
};
Transition._toHyphen = function(property) {
property = property.replace(/([A-Z]?)([a-z]+)([A-Z]?)/g, function(m0, m1, m2, m3) {
var str = ((m1) ? '-' + m1.toLowerCase() : '') + m2;
if (m3) {
str += '-' + m3.toLowerCase();
}
return str;
});
return property;
};
Transition.SHOW_TRANSITION = 'fadeIn';
Transition.HIDE_TRANSITION = 'fadeOut';
Transition.useNative = false;
// Map transition properties to vendor-specific versions.
if ('transition' in DOCUMENT_STYLE
&& 'transitionProperty' in DOCUMENT_STYLE
&& 'transitionDuration' in DOCUMENT_STYLE
&& 'transitionTimingFunction' in DOCUMENT_STYLE
&& 'transitionDelay' in DOCUMENT_STYLE) {
Transition.useNative = true;
Transition.supported = true; // TODO: remove
} else {
Y.Array.each(VENDORS, function(val) { // then vendor specific
var property = val + 'Transition';
if (property in DOCUMENT[DOCUMENT_ELEMENT].style) {
CAMEL_VENDOR_PREFIX = val;
VENDOR_PREFIX = Transition._toHyphen(val) + '-';
Transition.useNative = true;
Transition.supported = true; // TODO: remove
Transition._VENDOR_PREFIX = val;
}
});
}
// Map transform property to vendor-specific versions.
// One-off required for cssText injection.
if (typeof DOCUMENT_STYLE.transform === 'undefined') {
Y.Array.each(VENDORS, function(val) { // then vendor specific
var property = val + 'Transform';
if (typeof DOCUMENT_STYLE[property] !== 'undefined') {
Transition._TRANSFORM = property;
}
});
}
if (CAMEL_VENDOR_PREFIX) {
TRANSITION_CAMEL = CAMEL_VENDOR_PREFIX + 'Transition';
TRANSITION_PROPERTY_CAMEL = CAMEL_VENDOR_PREFIX + 'TransitionProperty';
}
TRANSITION_PROPERTY = VENDOR_PREFIX + 'transition-property';
TRANSITION_DURATION = VENDOR_PREFIX + 'transition-duration';
TRANSITION_TIMING_FUNCTION = VENDOR_PREFIX + 'transition-timing-function';
TRANSITION_DELAY = VENDOR_PREFIX + 'transition-delay';
TRANSITION_END = 'transitionend';
ON_TRANSITION_END = 'on' + CAMEL_VENDOR_PREFIX.toLowerCase() + 'transitionend';
TRANSITION_END = VENDOR_TRANSITION_END[CAMEL_VENDOR_PREFIX] || TRANSITION_END;
Transition.fx = {};
Transition.toggles = {};
Transition._hasEnd = {};
Transition._reKeywords = /^(?:node|duration|iterations|easing|delay|on|onstart|onend)$/i;
Y.Node.DOM_EVENTS[TRANSITION_END] = 1;
Transition.NAME = 'transition';
Transition.DEFAULT_EASING = 'ease';
Transition.DEFAULT_DURATION = 0.5;
Transition.DEFAULT_DELAY = 0;
Transition._nodeAttrs = {};
Transition.prototype = {
constructor: Transition,
init: function(node, config) {
var anim = this;
anim._node = node;
if (!anim._running && config) {
anim._config = config;
node._transition = anim; // cache for reuse
anim._duration = ('duration' in config) ?
config.duration: anim.constructor.DEFAULT_DURATION;
anim._delay = ('delay' in config) ?
config.delay: anim.constructor.DEFAULT_DELAY;
anim._easing = config.easing || anim.constructor.DEFAULT_EASING;
anim._count = 0; // track number of animated properties
anim._running = false;
}
return anim;
},
addProperty: function(prop, config) {
var anim = this,
node = this._node,
uid = Y.stamp(node),
nodeInstance = Y.one(node),
attrs = Transition._nodeAttrs[uid],
computed,
compareVal,
dur,
attr,
val;
if (!attrs) {
attrs = Transition._nodeAttrs[uid] = {};
}
attr = attrs[prop];
// might just be a value
if (config && config.value !== undefined) {
val = config.value;
} else if (config !== undefined) {
val = config;
config = EMPTY_OBJ;
}
if (typeof val === 'function') {
val = val.call(nodeInstance, nodeInstance);
}
if (attr && attr.transition) {
// take control if another transition owns this property
if (attr.transition !== anim) {
attr.transition._count--; // remapping attr to this transition
}
}
anim._count++; // properties per transition
// make 0 async and fire events
dur = ((typeof config.duration !== 'undefined') ? config.duration :
anim._duration) || 0.0001;
attrs[prop] = {
value: val,
duration: dur,
delay: (typeof config.delay !== 'undefined') ? config.delay :
anim._delay,
easing: config.easing || anim._easing,
transition: anim
};
// native end event doesnt fire when setting to same value
// supplementing with timer
// val may be a string or number (height: 0, etc), but computedStyle is always string
computed = Y.DOM.getComputedStyle(node, prop);
compareVal = (typeof val === 'string') ? computed : parseFloat(computed);
if (Transition.useNative && compareVal === val) {
setTimeout(function() {
anim._onNativeEnd.call(node, {
propertyName: prop,
elapsedTime: dur
});
}, dur * 1000);
}
},
removeProperty: function(prop) {
var anim = this,
attrs = Transition._nodeAttrs[Y.stamp(anim._node)];
if (attrs && attrs[prop]) {
delete attrs[prop];
anim._count--;
}
},
initAttrs: function(config) {
var attr,
node = this._node;
if (config.transform && !config[Transition._TRANSFORM]) {
config[Transition._TRANSFORM] = config.transform;
delete config.transform; // TODO: copy
}
for (attr in config) {
if (config.hasOwnProperty(attr) && !Transition._reKeywords.test(attr)) {
this.addProperty(attr, config[attr]);
// when size is auto or % webkit starts from zero instead of computed
// (https://bugs.webkit.org/show_bug.cgi?id=16020)
// TODO: selective set
if (node.style[attr] === '') {
Y.DOM.setStyle(node, attr, Y.DOM.getComputedStyle(node, attr));
}
}
}
},
/**
* Starts or an animation.
* @method run
* @chainable
* @private
*/
run: function(callback) {
var anim = this,
node = anim._node,
config = anim._config,
data = {
type: 'transition:start',
config: config
};
if (!anim._running) {
anim._running = true;
if (config.on && config.on.start) {
config.on.start.call(Y.one(node), data);
}
anim.initAttrs(anim._config);
anim._callback = callback;
anim._start();
}
return anim;
},
_start: function() {
this._runNative();
},
_prepDur: function(dur) {
dur = parseFloat(dur) * 1000;
return dur + 'ms';
},
_runNative: function() {
var anim = this,
node = anim._node,
uid = Y.stamp(node),
style = node.style,
computed = node.ownerDocument.defaultView.getComputedStyle(node),
attrs = Transition._nodeAttrs[uid],
cssText = '',
cssTransition = computed[Transition._toCamel(TRANSITION_PROPERTY)],
transitionText = TRANSITION_PROPERTY + ': ',
duration = TRANSITION_DURATION + ': ',
easing = TRANSITION_TIMING_FUNCTION + ': ',
delay = TRANSITION_DELAY + ': ',
hyphy,
attr,
name;
// preserve existing transitions
if (cssTransition !== 'all') {
transitionText += cssTransition + ',';
duration += computed[Transition._toCamel(TRANSITION_DURATION)] + ',';
easing += computed[Transition._toCamel(TRANSITION_TIMING_FUNCTION)] + ',';
delay += computed[Transition._toCamel(TRANSITION_DELAY)] + ',';
}
// run transitions mapped to this instance
for (name in attrs) {
hyphy = Transition._toHyphen(name);
attr = attrs[name];
if ((attr = attrs[name]) && attr.transition === anim) {
if (name in node.style) { // only native styles allowed
duration += anim._prepDur(attr.duration) + ',';
delay += anim._prepDur(attr.delay) + ',';
easing += (attr.easing) + ',';
transitionText += hyphy + ',';
cssText += hyphy + ': ' + attr.value + '; ';
} else {
this.removeProperty(name);
}
}
}
transitionText = transitionText.replace(/,$/, ';');
duration = duration.replace(/,$/, ';');
easing = easing.replace(/,$/, ';');
delay = delay.replace(/,$/, ';');
// only one native end event per node
if (!Transition._hasEnd[uid]) {
node.addEventListener(TRANSITION_END, anim._onNativeEnd, '');
Transition._hasEnd[uid] = true;
}
style.cssText += transitionText + duration + easing + delay + cssText;
},
_end: function(elapsed) {
var anim = this,
node = anim._node,
callback = anim._callback,
config = anim._config,
data = {
type: 'transition:end',
config: config,
elapsedTime: elapsed
},
nodeInstance = Y.one(node);
anim._running = false;
anim._callback = null;
if (node) {
if (config.on && config.on.end) {
setTimeout(function() { // IE: allow previous update to finish
config.on.end.call(nodeInstance, data);
// nested to ensure proper fire order
if (callback) {
callback.call(nodeInstance, data);
}
}, 1);
} else if (callback) {
setTimeout(function() { // IE: allow previous update to finish
callback.call(nodeInstance, data);
}, 1);
}
}
},
_endNative: function(name) {
var node = this._node,
value = node.ownerDocument.defaultView.getComputedStyle(node, '')[Transition._toCamel(TRANSITION_PROPERTY)];
name = Transition._toHyphen(name);
if (typeof value === 'string') {
value = value.replace(new RegExp('(?:^|,\\s)' + name + ',?'), ',');
value = value.replace(/^,|,$/, '');
node.style[TRANSITION_CAMEL] = value;
}
},
_onNativeEnd: function(e) {
var node = this,
uid = Y.stamp(node),
event = e,//e._event,
name = Transition._toCamel(event.propertyName),
elapsed = event.elapsedTime,
attrs = Transition._nodeAttrs[uid],
attr = attrs[name],
anim = (attr) ? attr.transition : null,
data,
config;
if (anim) {
anim.removeProperty(name);
anim._endNative(name);
config = anim._config[name];
data = {
type: 'propertyEnd',
propertyName: name,
elapsedTime: elapsed,
config: config
};
if (config && config.on && config.on.end) {
config.on.end.call(Y.one(node), data);
}
if (anim._count <= 0) { // after propertyEnd fires
anim._end(elapsed);
node.style[TRANSITION_PROPERTY_CAMEL] = ''; // clean up style
}
}
},
destroy: function() {
var anim = this,
node = anim._node;
if (node) {
node.removeEventListener(TRANSITION_END, anim._onNativeEnd, false);
anim._node = null;
}
}
};
Y.Transition = Transition;
Y.TransitionNative = Transition; // TODO: remove
/**
* Animate one or more css properties to a given value. Requires the "transition" module.
* example usage:
* Y.one('#demo').transition({
* duration: 1, // in seconds, default is 0.5
* easing: 'ease-out', // default is 'ease'
* delay: '1', // delay start for 1 second, default is 0
*
* height: '10px',
* width: '10px',
*
* opacity: { // per property
* value: 0,
* duration: 2,
* delay: 2,
* easing: 'ease-in'
* }
* });
*
* @for Node
* @method transition
* @param {Object} config An object containing one or more style properties, a duration and an easing.
* @param {Function} callback A function to run after the transition has completed.
* @chainable
*/
Y.Node.prototype.transition = function(name, config, callback) {
var
transitionAttrs = Transition._nodeAttrs[Y.stamp(this._node)],
anim = (transitionAttrs) ? transitionAttrs.transition || null : null,
fxConfig,
prop;
if (typeof name === 'string') { // named effect, pull config from registry
if (typeof config === 'function') {
callback = config;
config = null;
}
fxConfig = Transition.fx[name];
if (config && typeof config !== 'boolean') {
config = Y.clone(config);
for (prop in fxConfig) {
if (fxConfig.hasOwnProperty(prop)) {
if (! (prop in config)) {
config[prop] = fxConfig[prop];
}
}
}
} else {
config = fxConfig;
}
} else { // name is a config, config is a callback or undefined
callback = config;
config = name;
}
if (anim && !anim._running) {
anim.init(this, config);
} else {
anim = new Transition(this._node, config);
}
anim.run(callback);
return this;
};
Y.Node.prototype.show = function(name, config, callback) {
this._show(); // show prior to transition
if (name && Y.Transition) {
if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
if (typeof config === 'function') {
callback = config;
config = name;
}
name = Transition.SHOW_TRANSITION;
}
this.transition(name, config, callback);
}
return this;
};
Y.NodeList.prototype.show = function(name, config, callback) {
var nodes = this._nodes,
i = 0,
node;
while ((node = nodes[i++])) {
Y.one(node).show(name, config, callback);
}
return this;
};
var _wrapCallBack = function(anim, fn, callback) {
return function() {
if (fn) {
fn.call(anim);
}
if (callback && typeof callback === 'function') {
callback.apply(anim._node, arguments);
}
};
};
Y.Node.prototype.hide = function(name, config, callback) {
if (name && Y.Transition) {
if (typeof config === 'function') {
callback = config;
config = null;
}
callback = _wrapCallBack(this, this._hide, callback); // wrap with existing callback
if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
if (typeof config === 'function') {
callback = config;
config = name;
}
name = Transition.HIDE_TRANSITION;
}
this.transition(name, config, callback);
} else {
this._hide();
}
return this;
};
Y.NodeList.prototype.hide = function(name, config, callback) {
var nodes = this._nodes,
i = 0,
node;
while ((node = nodes[i++])) {
Y.one(node).hide(name, config, callback);
}
return this;
};
/**
* Animate one or more css properties to a given value. Requires the "transition" module.
* example usage:
* Y.all('.demo').transition({
* duration: 1, // in seconds, default is 0.5
* easing: 'ease-out', // default is 'ease'
* delay: '1', // delay start for 1 second, default is 0
*
* height: '10px',
* width: '10px',
*
* opacity: { // per property
* value: 0,
* duration: 2,
* delay: 2,
* easing: 'ease-in'
* }
* });
*
* @for NodeList
* @method transition
* @param {Object} config An object containing one or more style properties, a duration and an easing.
* @param {Function} callback A function to run after the transition has completed. The callback fires
* once per item in the NodeList.
* @chainable
*/
Y.NodeList.prototype.transition = function(config, callback) {
var nodes = this._nodes,
i = 0,
node;
while ((node = nodes[i++])) {
Y.one(node).transition(config, callback);
}
return this;
};
Y.Node.prototype.toggleView = function(name, on, callback) {
this._toggles = this._toggles || [];
callback = arguments[arguments.length - 1];
if (typeof name !== 'string') { // no transition, just toggle
on = name;
this._toggleView(on, callback); // call original _toggleView in Y.Node
return;
}
if (typeof on === 'function') { // Ignore "on" if used for callback argument.
on = undefined;
}
if (typeof on === 'undefined' && name in this._toggles) { // reverse current toggle
on = ! this._toggles[name];
}
on = (on) ? 1 : 0;
if (on) {
this._show();
} else {
callback = _wrapCallBack(this, this._hide, callback);
}
this._toggles[name] = on;
this.transition(Y.Transition.toggles[name][on], callback);
return this;
};
Y.NodeList.prototype.toggleView = function(name, on, callback) {
var nodes = this._nodes,
i = 0,
node;
while ((node = nodes[i++])) {
node = Y.one(node);
node.toggleView.apply(node, arguments);
}
return this;
};
Y.mix(Transition.fx, {
fadeOut: {
opacity: 0,
duration: 0.5,
easing: 'ease-out'
},
fadeIn: {
opacity: 1,
duration: 0.5,
easing: 'ease-in'
},
sizeOut: {
height: 0,
width: 0,
duration: 0.75,
easing: 'ease-out'
},
sizeIn: {
height: function(node) {
return node.get('scrollHeight') + 'px';
},
width: function(node) {
return node.get('scrollWidth') + 'px';
},
duration: 0.5,
easing: 'ease-in',
on: {
start: function() {
var overflow = this.getStyle('overflow');
if (overflow !== 'hidden') { // enable scrollHeight/Width
this.setStyle('overflow', 'hidden');
this._transitionOverflow = overflow;
}
},
end: function() {
if (this._transitionOverflow) { // revert overridden value
this.setStyle('overflow', this._transitionOverflow);
delete this._transitionOverflow;
}
}
}
}
});
Y.mix(Transition.toggles, {
size: ['sizeOut', 'sizeIn'],
fade: ['fadeOut', 'fadeIn']
});
}, '3.9.1', {"requires": ["node-style"]});
YUI.add('selector-css2', function (Y, NAME) {
/**
* The selector module provides helper methods allowing CSS2 Selectors to be used with DOM elements.
* @module dom
* @submodule selector-css2
* @for Selector
*/
/*
* Provides helper methods for collecting and filtering DOM elements.
*/
var PARENT_NODE = 'parentNode',
TAG_NAME = 'tagName',
ATTRIBUTES = 'attributes',
COMBINATOR = 'combinator',
PSEUDOS = 'pseudos',
Selector = Y.Selector,
SelectorCSS2 = {
_reRegExpTokens: /([\^\$\?\[\]\*\+\-\.\(\)\|\\])/,
SORT_RESULTS: true,
// TODO: better detection, document specific
_isXML: (function() {
var isXML = (Y.config.doc.createElement('div').tagName !== 'DIV');
return isXML;
}()),
/**
* Mapping of shorthand tokens to corresponding attribute selector
* @property shorthand
* @type object
*/
shorthand: {
'\\#(-?[_a-z0-9]+[-\\w\\uE000]*)': '[id=$1]',
'\\.(-?[_a-z]+[-\\w\\uE000]*)': '[className~=$1]'
},
/**
* List of operators and corresponding boolean functions.
* These functions are passed the attribute and the current node's value of the attribute.
* @property operators
* @type object
*/
operators: {
'': function(node, attr) { return Y.DOM.getAttribute(node, attr) !== ''; }, // Just test for existence of attribute
'~=': '(?:^|\\s+){val}(?:\\s+|$)', // space-delimited
'|=': '^{val}-?' // optional hyphen-delimited
},
pseudos: {
'first-child': function(node) {
return Y.DOM._children(node[PARENT_NODE])[0] === node;
}
},
_bruteQuery: function(selector, root, firstOnly) {
var ret = [],
nodes = [],
tokens = Selector._tokenize(selector),
token = tokens[tokens.length - 1],
rootDoc = Y.DOM._getDoc(root),
child,
id,
className,
tagName;
if (token) {
// prefilter nodes
id = token.id;
className = token.className;
tagName = token.tagName || '*';
if (root.getElementsByTagName) { // non-IE lacks DOM api on doc frags
// try ID first, unless no root.all && root not in document
// (root.all works off document, but not getElementById)
if (id && (root.all || (root.nodeType === 9 || Y.DOM.inDoc(root)))) {
nodes = Y.DOM.allById(id, root);
// try className
} else if (className) {
nodes = root.getElementsByClassName(className);
} else { // default to tagName
nodes = root.getElementsByTagName(tagName);
}
} else { // brute getElementsByTagName()
child = root.firstChild;
while (child) {
// only collect HTMLElements
// match tag to supplement missing getElementsByTagName
if (child.tagName && (tagName === '*' || child.tagName === tagName)) {
nodes.push(child);
}
child = child.nextSibling || child.firstChild;
}
}
if (nodes.length) {
ret = Selector._filterNodes(nodes, tokens, firstOnly);
}
}
return ret;
},
_filterNodes: function(nodes, tokens, firstOnly) {
var i = 0,
j,
len = tokens.length,
n = len - 1,
result = [],
node = nodes[0],
tmpNode = node,
getters = Y.Selector.getters,
operator,
combinator,
token,
path,
pass,
value,
tests,
test;
for (i = 0; (tmpNode = node = nodes[i++]);) {
n = len - 1;
path = null;
testLoop:
while (tmpNode && tmpNode.tagName) {
token = tokens[n];
tests = token.tests;
j = tests.length;
if (j && !pass) {
while ((test = tests[--j])) {
operator = test[1];
if (getters[test[0]]) {
value = getters[test[0]](tmpNode, test[0]);
} else {
value = tmpNode[test[0]];
if (test[0] === 'tagName' && !Selector._isXML) {
value = value.toUpperCase();
}
if (typeof value != 'string' && value !== undefined && value.toString) {
value = value.toString(); // coerce for comparison
} else if (value === undefined && tmpNode.getAttribute) {
// use getAttribute for non-standard attributes
value = tmpNode.getAttribute(test[0], 2); // 2 === force string for IE
}
}
if ((operator === '=' && value !== test[2]) || // fast path for equality
(typeof operator !== 'string' && // protect against String.test monkey-patch (Moo)
operator.test && !operator.test(value)) || // regex test
(!operator.test && // protect against RegExp as function (webkit)
typeof operator === 'function' && !operator(tmpNode, test[0], test[2]))) { // function test
// skip non element nodes or non-matching tags
if ((tmpNode = tmpNode[path])) {
while (tmpNode &&
(!tmpNode.tagName ||
(token.tagName && token.tagName !== tmpNode.tagName))
) {
tmpNode = tmpNode[path];
}
}
continue testLoop;
}
}
}
n--; // move to next token
// now that we've passed the test, move up the tree by combinator
if (!pass && (combinator = token.combinator)) {
path = combinator.axis;
tmpNode = tmpNode[path];
// skip non element nodes
while (tmpNode && !tmpNode.tagName) {
tmpNode = tmpNode[path];
}
if (combinator.direct) { // one pass only
path = null;
}
} else { // success if we made it this far
result.push(node);
if (firstOnly) {
return result;
}
break;
}
}
}
node = tmpNode = null;
return result;
},
combinators: {
' ': {
axis: 'parentNode'
},
'>': {
axis: 'parentNode',
direct: true
},
'+': {
axis: 'previousSibling',
direct: true
}
},
_parsers: [
{
name: ATTRIBUTES,
re: /^\uE003(-?[a-z]+[\w\-]*)+([~\|\^\$\*!=]=?)?['"]?([^\uE004'"]*)['"]?\uE004/i,
fn: function(match, token) {
var operator = match[2] || '',
operators = Selector.operators,
escVal = (match[3]) ? match[3].replace(/\\/g, '') : '',
test;
// add prefiltering for ID and CLASS
if ((match[1] === 'id' && operator === '=') ||
(match[1] === 'className' &&
Y.config.doc.documentElement.getElementsByClassName &&
(operator === '~=' || operator === '='))) {
token.prefilter = match[1];
match[3] = escVal;
// escape all but ID for prefilter, which may run through QSA (via Dom.allById)
token[match[1]] = (match[1] === 'id') ? match[3] : escVal;
}
// add tests
if (operator in operators) {
test = operators[operator];
if (typeof test === 'string') {
match[3] = escVal.replace(Selector._reRegExpTokens, '\\$1');
test = new RegExp(test.replace('{val}', match[3]));
}
match[2] = test;
}
if (!token.last || token.prefilter !== match[1]) {
return match.slice(1);
}
}
},
{
name: TAG_NAME,
re: /^((?:-?[_a-z]+[\w-]*)|\*)/i,
fn: function(match, token) {
var tag = match[1];
if (!Selector._isXML) {
tag = tag.toUpperCase();
}
token.tagName = tag;
if (tag !== '*' && (!token.last || token.prefilter)) {
return [TAG_NAME, '=', tag];
}
if (!token.prefilter) {
token.prefilter = 'tagName';
}
}
},
{
name: COMBINATOR,
re: /^\s*([>+~]|\s)\s*/,
fn: function(match, token) {
}
},
{
name: PSEUDOS,
re: /^:([\-\w]+)(?:\uE005['"]?([^\uE005]*)['"]?\uE006)*/i,
fn: function(match, token) {
var test = Selector[PSEUDOS][match[1]];
if (test) { // reorder match array and unescape special chars for tests
if (match[2]) {
match[2] = match[2].replace(/\\/g, '');
}
return [match[2], test];
} else { // selector token not supported (possibly missing CSS3 module)
return false;
}
}
}
],
_getToken: function(token) {
return {
tagName: null,
id: null,
className: null,
attributes: {},
combinator: null,
tests: []
};
},
/*
Break selector into token units per simple selector.
Combinator is attached to the previous token.
*/
_tokenize: function(selector) {
selector = selector || '';
selector = Selector._parseSelector(Y.Lang.trim(selector));
var token = Selector._getToken(), // one token per simple selector (left selector holds combinator)
query = selector, // original query for debug report
tokens = [], // array of tokens
found = false, // whether or not any matches were found this pass
match, // the regex match
test,
i, parser;
/*
Search for selector patterns, store, and strip them from the selector string
until no patterns match (invalid selector) or we run out of chars.
Multiple attributes and pseudos are allowed, in any order.
for example:
'form:first-child[type=button]:not(button)[lang|=en]'
*/
outer:
do {
found = false; // reset after full pass
for (i = 0; (parser = Selector._parsers[i++]);) {
if ( (match = parser.re.exec(selector)) ) { // note assignment
if (parser.name !== COMBINATOR ) {
token.selector = selector;
}
selector = selector.replace(match[0], ''); // strip current match from selector
if (!selector.length) {
token.last = true;
}
if (Selector._attrFilters[match[1]]) { // convert class to className, etc.
match[1] = Selector._attrFilters[match[1]];
}
test = parser.fn(match, token);
if (test === false) { // selector not supported
found = false;
break outer;
} else if (test) {
token.tests.push(test);
}
if (!selector.length || parser.name === COMBINATOR) {
tokens.push(token);
token = Selector._getToken(token);
if (parser.name === COMBINATOR) {
token.combinator = Y.Selector.combinators[match[1]];
}
}
found = true;
}
}
} while (found && selector.length);
if (!found || selector.length) { // not fully parsed
tokens = [];
}
return tokens;
},
_replaceMarkers: function(selector) {
selector = selector.replace(/\[/g, '\uE003');
selector = selector.replace(/\]/g, '\uE004');
selector = selector.replace(/\(/g, '\uE005');
selector = selector.replace(/\)/g, '\uE006');
return selector;
},
_replaceShorthand: function(selector) {
var shorthand = Y.Selector.shorthand,
re;
for (re in shorthand) {
if (shorthand.hasOwnProperty(re)) {
selector = selector.replace(new RegExp(re, 'gi'), shorthand[re]);
}
}
return selector;
},
_parseSelector: function(selector) {
var replaced = Y.Selector._replaceSelector(selector),
selector = replaced.selector;
// replace shorthand (".foo, #bar") after pseudos and attrs
// to avoid replacing unescaped chars
selector = Y.Selector._replaceShorthand(selector);
selector = Y.Selector._restore('attr', selector, replaced.attrs);
selector = Y.Selector._restore('pseudo', selector, replaced.pseudos);
// replace braces and parens before restoring escaped chars
// to avoid replacing ecaped markers
selector = Y.Selector._replaceMarkers(selector);
selector = Y.Selector._restore('esc', selector, replaced.esc);
return selector;
},
_attrFilters: {
'class': 'className',
'for': 'htmlFor'
},
getters: {
href: function(node, attr) {
return Y.DOM.getAttribute(node, attr);
},
id: function(node, attr) {
return Y.DOM.getId(node);
}
}
};
Y.mix(Y.Selector, SelectorCSS2, true);
Y.Selector.getters.src = Y.Selector.getters.rel = Y.Selector.getters.href;
// IE wants class with native queries
if (Y.Selector.useNative && Y.config.doc.querySelector) {
Y.Selector.shorthand['\\.(-?[_a-z]+[-\\w]*)'] = '[class~=$1]';
}
}, '3.9.1', {"requires": ["selector-native"]});
YUI.add('selector-css3', function (Y, NAME) {
/**
* The selector css3 module provides support for css3 selectors.
* @module dom
* @submodule selector-css3
* @for Selector
*/
/*
an+b = get every _a_th node starting at the _b_th
0n+b = no repeat ("0" and "n" may both be omitted (together) , e.g. "0n+1" or "1", not "0+1"), return only the _b_th element
1n+b = get every element starting from b ("1" may may be omitted, e.g. "1n+0" or "n+0" or "n")
an+0 = get every _a_th element, "0" may be omitted
*/
Y.Selector._reNth = /^(?:([\-]?\d*)(n){1}|(odd|even)$)*([\-+]?\d*)$/;
Y.Selector._getNth = function(node, expr, tag, reverse) {
Y.Selector._reNth.test(expr);
var a = parseInt(RegExp.$1, 10), // include every _a_ elements (zero means no repeat, just first _a_)
n = RegExp.$2, // "n"
oddeven = RegExp.$3, // "odd" or "even"
b = parseInt(RegExp.$4, 10) || 0, // start scan from element _b_
result = [],
siblings = Y.DOM._children(node.parentNode, tag),
op;
if (oddeven) {
a = 2; // always every other
op = '+';
n = 'n';
b = (oddeven === 'odd') ? 1 : 0;
} else if ( isNaN(a) ) {
a = (n) ? 1 : 0; // start from the first or no repeat
}
if (a === 0) { // just the first
if (reverse) {
b = siblings.length - b + 1;
}
if (siblings[b - 1] === node) {
return true;
} else {
return false;
}
} else if (a < 0) {
reverse = !!reverse;
a = Math.abs(a);
}
if (!reverse) {
for (var i = b - 1, len = siblings.length; i < len; i += a) {
if ( i >= 0 && siblings[i] === node ) {
return true;
}
}
} else {
for (var i = siblings.length - b, len = siblings.length; i >= 0; i -= a) {
if ( i < len && siblings[i] === node ) {
return true;
}
}
}
return false;
};
Y.mix(Y.Selector.pseudos, {
'root': function(node) {
return node === node.ownerDocument.documentElement;
},
'nth-child': function(node, expr) {
return Y.Selector._getNth(node, expr);
},
'nth-last-child': function(node, expr) {
return Y.Selector._getNth(node, expr, null, true);
},
'nth-of-type': function(node, expr) {
return Y.Selector._getNth(node, expr, node.tagName);
},
'nth-last-of-type': function(node, expr) {
return Y.Selector._getNth(node, expr, node.tagName, true);
},
'last-child': function(node) {
var children = Y.DOM._children(node.parentNode);
return children[children.length - 1] === node;
},
'first-of-type': function(node) {
return Y.DOM._children(node.parentNode, node.tagName)[0] === node;
},
'last-of-type': function(node) {
var children = Y.DOM._children(node.parentNode, node.tagName);
return children[children.length - 1] === node;
},
'only-child': function(node) {
var children = Y.DOM._children(node.parentNode);
return children.length === 1 && children[0] === node;
},
'only-of-type': function(node) {
var children = Y.DOM._children(node.parentNode, node.tagName);
return children.length === 1 && children[0] === node;
},
'empty': function(node) {
return node.childNodes.length === 0;
},
'not': function(node, expr) {
return !Y.Selector.test(node, expr);
},
'contains': function(node, expr) {
var text = node.innerText || node.textContent || '';
return text.indexOf(expr) > -1;
},
'checked': function(node) {
return (node.checked === true || node.selected === true);
},
enabled: function(node) {
return (node.disabled !== undefined && !node.disabled);
},
disabled: function(node) {
return (node.disabled);
}
});
Y.mix(Y.Selector.operators, {
'^=': '^{val}', // Match starts with value
'$=': '{val}$', // Match ends with value
'*=': '{val}' // Match contains value as substring
});
Y.Selector.combinators['~'] = {
axis: 'previousSibling'
};
}, '3.9.1', {"requires": ["selector-native", "selector-css2"]});
YUI.add('yui-log', function (Y, NAME) {
/**
* Provides console log capability and exposes a custom event for
* console implementations. This module is a `core` YUI module,
* it's documentation is located under the YUI class.
*
* @module yui
* @submodule yui-log
*/
var INSTANCE = Y,
LOGEVENT = 'yui:log',
UNDEFINED = 'undefined',
LEVELS = { debug: 1,
info: 1,
warn: 1,
error: 1 };
/**
* If the 'debug' config is true, a 'yui:log' event will be
* dispatched, which the Console widget and anything else
* can consume. If the 'useBrowserConsole' config is true, it will
* write to the browser console if available. YUI-specific log
* messages will only be present in the -debug versions of the
* JS files. The build system is supposed to remove log statements
* from the raw and minified versions of the files.
*
* @method log
* @for YUI
* @param {String} msg The message to log.
* @param {String} cat The log category for the message. Default
* categories are "info", "warn", "error", time".
* Custom categories can be used as well. (opt).
* @param {String} src The source of the the message (opt).
* @param {boolean} silent If true, the log event won't fire.
* @return {YUI} YUI instance.
*/
INSTANCE.log = function(msg, cat, src, silent) {
var bail, excl, incl, m, f,
Y = INSTANCE,
c = Y.config,
publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
// suppress log message if the config is off or the event stack
// or the event call stack contains a consumer of the yui:log event
if (c.debug) {
// apply source filters
src = src || "";
if (typeof src !== "undefined") {
excl = c.logExclude;
incl = c.logInclude;
if (incl && !(src in incl)) {
bail = 1;
} else if (incl && (src in incl)) {
bail = !incl[src];
} else if (excl && (src in excl)) {
bail = excl[src];
}
}
if (!bail) {
if (c.useBrowserConsole) {
m = (src) ? src + ': ' + msg : msg;
if (Y.Lang.isFunction(c.logFn)) {
c.logFn.call(Y, msg, cat, src);
} else if (typeof console !== UNDEFINED && console.log) {
f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
console[f](m);
} else if (typeof opera !== UNDEFINED) {
opera.postError(m);
}
}
if (publisher && !silent) {
if (publisher === Y && (!publisher.getEvent(LOGEVENT))) {
publisher.publish(LOGEVENT, {
broadcast: 2
});
}
publisher.fire(LOGEVENT, {
msg: msg,
cat: cat,
src: src
});
}
}
}
return Y;
};
/**
* Write a system message. This message will be preserved in the
* minified and raw versions of the YUI files, unlike log statements.
* @method message
* @for YUI
* @param {String} msg The message to log.
* @param {String} cat The log category for the message. Default
* categories are "info", "warn", "error", time".
* Custom categories can be used as well. (opt).
* @param {String} src The source of the the message (opt).
* @param {boolean} silent If true, the log event won't fire.
* @return {YUI} YUI instance.
*/
INSTANCE.message = function() {
return INSTANCE.log.apply(INSTANCE, arguments);
};
}, '3.9.1', {"requires": ["yui-base"]});
YUI.add('dump', function (Y, NAME) {
/**
* Returns a simple string representation of the object or array.
* Other types of objects will be returned unprocessed. Arrays
* are expected to be indexed. Use object notation for
* associative arrays.
*
* If included, the dump method is added to the YUI instance.
*
* @module dump
*/
var L = Y.Lang,
OBJ = '{...}',
FUN = 'f(){...}',
COMMA = ', ',
ARROW = ' => ',
/**
* Returns a simple string representation of the object or array.
* Other types of objects will be returned unprocessed. Arrays
* are expected to be indexed.
*
* @method dump
* @param {Object} o The object to dump.
* @param {Number} d How deep to recurse child objects, default 3.
* @return {String} the dump result.
* @for YUI
*/
dump = function(o, d) {
var i, len, s = [], type = L.type(o);
// Cast non-objects to string
// Skip dates because the std toString is what we want
// Skip HTMLElement-like objects because trying to dump
// an element will cause an unhandled exception in FF 2.x
if (!L.isObject(o)) {
return o + '';
} else if (type == 'date') {
return o;
} else if (o.nodeType && o.tagName) {
return o.tagName + '#' + o.id;
} else if (o.document && o.navigator) {
return 'window';
} else if (o.location && o.body) {
return 'document';
} else if (type == 'function') {
return FUN;
}
// dig into child objects the depth specifed. Default 3
d = (L.isNumber(d)) ? d : 3;
// arrays [1, 2, 3]
if (type == 'array') {
s.push('[');
for (i = 0, len = o.length; i < len; i = i + 1) {
if (L.isObject(o[i])) {
s.push((d > 0) ? L.dump(o[i], d - 1) : OBJ);
} else {
s.push(o[i]);
}
s.push(COMMA);
}
if (s.length > 1) {
s.pop();
}
s.push(']');
// regexp /foo/
} else if (type == 'regexp') {
s.push(o.toString());
// objects {k1 => v1, k2 => v2}
} else {
s.push('{');
for (i in o) {
if (o.hasOwnProperty(i)) {
try {
s.push(i + ARROW);
if (L.isObject(o[i])) {
s.push((d > 0) ? L.dump(o[i], d - 1) : OBJ);
} else {
s.push(o[i]);
}
s.push(COMMA);
} catch (e) {
s.push('Error: ' + e.message);
}
}
}
if (s.length > 1) {
s.pop();
}
s.push('}');
}
return s.join('');
};
Y.dump = dump;
L.dump = dump;
}, '3.9.1', {"requires": ["yui-base"]});
YUI.add('transition-timer', function (Y, NAME) {
/**
* Provides the base Transition class, for animating numeric properties.
*
* @module transition
* @submodule transition-timer
*/
var Transition = Y.Transition;
Y.mix(Transition.prototype, {
_start: function() {
if (Transition.useNative) {
this._runNative();
} else {
this._runTimer();
}
},
_runTimer: function() {
var anim = this;
anim._initAttrs();
Transition._running[Y.stamp(anim)] = anim;
anim._startTime = new Date();
Transition._startTimer();
},
_endTimer: function() {
var anim = this;
delete Transition._running[Y.stamp(anim)];
anim._startTime = null;
},
_runFrame: function() {
var t = new Date() - this._startTime;
this._runAttrs(t);
},
_runAttrs: function(time) {
var anim = this,
node = anim._node,
config = anim._config,
uid = Y.stamp(node),
attrs = Transition._nodeAttrs[uid],
customAttr = Transition.behaviors,
done = false,
allDone = false,
data,
name,
attribute,
setter,
elapsed,
delay,
d,
t,
i;
for (name in attrs) {
if ((attribute = attrs[name]) && attribute.transition === anim) {
d = attribute.duration;
delay = attribute.delay;
elapsed = (time - delay) / 1000;
t = time;
data = {
type: 'propertyEnd',
propertyName: name,
config: config,
elapsedTime: elapsed
};
setter = (i in customAttr && 'set' in customAttr[i]) ?
customAttr[i].set : Transition.DEFAULT_SETTER;
done = (t >= d);
if (t > d) {
t = d;
}
if (!delay || time >= delay) {
setter(anim, name, attribute.from, attribute.to, t - delay, d - delay,
attribute.easing, attribute.unit);
if (done) {
delete attrs[name];
anim._count--;
if (config[name] && config[name].on && config[name].on.end) {
config[name].on.end.call(Y.one(node), data);
}
//node.fire('transition:propertyEnd', data);
if (!allDone && anim._count <= 0) {
allDone = true;
anim._end(elapsed);
anim._endTimer();
}
}
}
}
}
},
_initAttrs: function() {
var anim = this,
customAttr = Transition.behaviors,
uid = Y.stamp(anim._node),
attrs = Transition._nodeAttrs[uid],
attribute,
duration,
delay,
easing,
val,
name,
mTo,
mFrom,
unit, begin, end;
for (name in attrs) {
if ((attribute = attrs[name]) && attribute.transition === anim) {
duration = attribute.duration * 1000;
delay = attribute.delay * 1000;
easing = attribute.easing;
val = attribute.value;
// only allow supported properties
if (name in anim._node.style || name in Y.DOM.CUSTOM_STYLES) {
begin = (name in customAttr && 'get' in customAttr[name]) ?
customAttr[name].get(anim, name) : Transition.DEFAULT_GETTER(anim, name);
mFrom = Transition.RE_UNITS.exec(begin);
mTo = Transition.RE_UNITS.exec(val);
begin = mFrom ? mFrom[1] : begin;
end = mTo ? mTo[1] : val;
unit = mTo ? mTo[2] : mFrom ? mFrom[2] : ''; // one might be zero TODO: mixed units
if (!unit && Transition.RE_DEFAULT_UNIT.test(name)) {
unit = Transition.DEFAULT_UNIT;
}
if (typeof easing === 'string') {
if (easing.indexOf('cubic-bezier') > -1) {
easing = easing.substring(13, easing.length - 1).split(',');
} else if (Transition.easings[easing]) {
easing = Transition.easings[easing];
}
}
attribute.from = Number(begin);
attribute.to = Number(end);
attribute.unit = unit;
attribute.easing = easing;
attribute.duration = duration + delay;
attribute.delay = delay;
} else {
delete attrs[name];
anim._count--;
}
}
}
},
destroy: function() {
this.detachAll();
this._node = null;
}
}, true);
Y.mix(Y.Transition, {
_runtimeAttrs: {},
/*
* Regex of properties that should use the default unit.
*
* @property RE_DEFAULT_UNIT
* @static
*/
RE_DEFAULT_UNIT: /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i,
/*
* The default unit to use with properties that pass the RE_DEFAULT_UNIT test.
*
* @property DEFAULT_UNIT
* @static
*/
DEFAULT_UNIT: 'px',
/*
* Time in milliseconds passed to setInterval for frame processing
*
* @property intervalTime
* @default 20
* @static
*/
intervalTime: 20,
/*
* Bucket for custom getters and setters
*
* @property behaviors
* @static
*/
behaviors: {
left: {
get: function(anim, attr) {
return Y.DOM._getAttrOffset(anim._node, attr);
}
}
},
/*
* The default setter to use when setting object properties.
*
* @property DEFAULT_SETTER
* @static
*/
DEFAULT_SETTER: function(anim, att, from, to, elapsed, duration, fn, unit) {
from = Number(from);
to = Number(to);
var node = anim._node,
val = Transition.cubicBezier(fn, elapsed / duration);
val = from + val[0] * (to - from);
if (node) {
if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
unit = unit || '';
Y.DOM.setStyle(node, att, val + unit);
}
} else {
anim._end();
}
},
/*
* The default getter to use when getting object properties.
*
* @property DEFAULT_GETTER
* @static
*/
DEFAULT_GETTER: function(anim, att) {
var node = anim._node,
val = '';
if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
val = Y.DOM.getComputedStyle(node, att);
}
return val;
},
_startTimer: function() {
if (!Transition._timer) {
Transition._timer = setInterval(Transition._runFrame, Transition.intervalTime);
}
},
_stopTimer: function() {
clearInterval(Transition._timer);
Transition._timer = null;
},
/*
* Called per Interval to handle each animation frame.
* @method _runFrame
* @private
* @static
*/
_runFrame: function() {
var done = true,
anim;
for (anim in Transition._running) {
if (Transition._running[anim]._runFrame) {
done = false;
Transition._running[anim]._runFrame();
}
}
if (done) {
Transition._stopTimer();
}
},
cubicBezier: function(p, t) {
var x0 = 0,
y0 = 0,
x1 = p[0],
y1 = p[1],
x2 = p[2],
y2 = p[3],
x3 = 1,
y3 = 0,
A = x3 - 3 * x2 + 3 * x1 - x0,
B = 3 * x2 - 6 * x1 + 3 * x0,
C = 3 * x1 - 3 * x0,
D = x0,
E = y3 - 3 * y2 + 3 * y1 - y0,
F = 3 * y2 - 6 * y1 + 3 * y0,
G = 3 * y1 - 3 * y0,
H = y0,
x = (((A*t) + B)*t + C)*t + D,
y = (((E*t) + F)*t + G)*t + H;
return [x, y];
},
easings: {
ease: [0.25, 0, 1, 0.25],
linear: [0, 0, 1, 1],
'ease-in': [0.42, 0, 1, 1],
'ease-out': [0, 0, 0.58, 1],
'ease-in-out': [0.42, 0, 0.58, 1]
},
_running: {},
_timer: null,
RE_UNITS: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/
}, true);
Transition.behaviors.top = Transition.behaviors.bottom = Transition.behaviors.right = Transition.behaviors.left;
Y.Transition = Transition;
}, '3.9.1', {"requires": ["transition"]});
YUI.add('yui', function (Y, NAME) {
// empty
}, '3.9.1', {
"use": [
"yui",
"oop",
"dom",
"event-custom-base",
"event-base",
"pluginhost",
"node",
"event-delegate",
"io-base",
"json-parse",
"transition",
"selector-css3",
"dom-style-ie",
"querystring-stringify-simple"
]
});
var Y = YUI().use('*');
/* YUI 3.9.1 (build 5852) Copyright 2013 Yahoo! Inc. http://yuilibrary.com/license/ */
YUI.add('loader-base', function (Y, NAME) {
/**
* The YUI loader core
* @module loader
* @submodule loader-base
*/
if (!YUI.Env[Y.version]) {
(function() {
var VERSION = Y.version,
BUILD = '/build/',
ROOT = VERSION + BUILD,
CDN_BASE = Y.Env.base,
GALLERY_VERSION = 'gallery-2013.02.27-21-03',
TNT = '2in3',
TNT_VERSION = '4',
YUI2_VERSION = '2.9.0',
COMBO_BASE = CDN_BASE + 'combo?',
META = { version: VERSION,
root: ROOT,
base: Y.Env.base,
comboBase: COMBO_BASE,
skin: { defaultSkin: 'sam',
base: 'assets/skins/',
path: 'skin.css',
after: ['cssreset',
'cssfonts',
'cssgrids',
'cssbase',
'cssreset-context',
'cssfonts-context']},
groups: {},
patterns: {} },
groups = META.groups,
yui2Update = function(tnt, yui2, config) {
var root = TNT + '.' +
(tnt || TNT_VERSION) + '/' +
(yui2 || YUI2_VERSION) + BUILD,
base = (config && config.base) ? config.base : CDN_BASE,
combo = (config && config.comboBase) ? config.comboBase : COMBO_BASE;
groups.yui2.base = base + root;
groups.yui2.root = root;
groups.yui2.comboBase = combo;
},
galleryUpdate = function(tag, config) {
var root = (tag || GALLERY_VERSION) + BUILD,
base = (config && config.base) ? config.base : CDN_BASE,
combo = (config && config.comboBase) ? config.comboBase : COMBO_BASE;
groups.gallery.base = base + root;
groups.gallery.root = root;
groups.gallery.comboBase = combo;
};
groups[VERSION] = {};
groups.gallery = {
ext: false,
combine: true,
comboBase: COMBO_BASE,
update: galleryUpdate,
patterns: { 'gallery-': { },
'lang/gallery-': {},
'gallerycss-': { type: 'css' } }
};
groups.yui2 = {
combine: true,
ext: false,
comboBase: COMBO_BASE,
update: yui2Update,
patterns: {
'yui2-': {
configFn: function(me) {
if (/-skin|reset|fonts|grids|base/.test(me.name)) {
me.type = 'css';
me.path = me.path.replace(/\.js/, '.css');
// this makes skins in builds earlier than
// 2.6.0 work as long as combine is false
me.path = me.path.replace(/\/yui2-skin/,
'/assets/skins/sam/yui2-skin');
}
}
}
}
};
galleryUpdate();
yui2Update();
YUI.Env[VERSION] = META;
}());
}
/*jslint forin: true, maxlen: 350 */
/**
* Loader dynamically loads script and css files. It includes the dependency
* information for the version of the library in use, and will automatically pull in
* dependencies for the modules requested. It can also 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
* @main loader
* @submodule loader-base
*/
var NOT_FOUND = {},
NO_REQUIREMENTS = [],
MAX_URL_LENGTH = 1024,
GLOBAL_ENV = YUI.Env,
GLOBAL_LOADED = GLOBAL_ENV._loaded,
CSS = 'css',
JS = 'js',
INTL = 'intl',
DEFAULT_SKIN = 'sam',
VERSION = Y.version,
ROOT_LANG = '',
YObject = Y.Object,
oeach = YObject.each,
yArray = Y.Array,
_queue = GLOBAL_ENV._loaderQueue,
META = GLOBAL_ENV[VERSION],
SKIN_PREFIX = 'skin-',
L = Y.Lang,
ON_PAGE = GLOBAL_ENV.mods,
modulekey,
_path = function(dir, file, type, nomin) {
var path = dir + '/' + file;
if (!nomin) {
path += '-min';
}
path += '.' + (type || CSS);
return path;
};
if (!YUI.Env._cssLoaded) {
YUI.Env._cssLoaded = {};
}
/**
* The component metadata is stored in Y.Env.meta.
* Part of the loader module.
* @property meta
* @for YUI
*/
Y.Env.meta = META;
/**
* 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 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. You can also specify an external, custom combo service to host
* your modules as well.
var Y = YUI();
var loader = new Y.Loader({
filter: 'debug',
base: '../../',
root: 'build/',
combine: true,
require: ['node', 'dd', 'console']
});
var out = loader.resolve(true);
* @constructor
* @class Loader
* @param {Object} config an optional set of configuration options.
* @param {String} config.base The base dir which to fetch this module from
* @param {String} config.comboBase The Combo service base path. Ex: `http://yui.yahooapis.com/combo?`
* @param {String} config.root The root path to prepend to module names for the combo service. Ex: `2.5.2/build/`
* @param {String|Object} config.filter A filter to apply to result urls. See filter property
* @param {Object} config.filters Per-component filter specification. If specified for a given component, this overrides the filter config.
* @param {Boolean} config.combine Use a combo service to reduce the number of http connections required to load your dependencies
* @param {Boolean} [config.async=true] Fetch files in async
* @param {Array} config.ignore: A list of modules that should never be dynamically loaded
* @param {Array} config.force A list of modules that should always be loaded when required, even if already present on the page
* @param {HTMLElement|String} config.insertBefore Node or id for a node that should be used as the insertion point for new nodes
* @param {Object} config.jsAttributes Object literal containing attributes to add to script nodes
* @param {Object} config.cssAttributes Object literal containing attributes to add to link nodes
* @param {Number} config.timeout The number of milliseconds before a timeout occurs when dynamically loading nodes. If not set, there is no timeout
* @param {Object} config.context Execution context for all callbacks
* @param {Function} config.onSuccess Callback for the 'success' event
* @param {Function} config.onFailure Callback for the 'failure' event
* @param {Function} config.onCSS Callback for the 'CSSComplete' event. When loading YUI components with CSS the CSS is loaded first, then the script. This provides a moment you can tie into to improve the presentation of the page while the script is loading.
* @param {Function} config.onTimeout Callback for the 'timeout' event
* @param {Function} config.onProgress Callback executed each time a script or css file is loaded
* @param {Object} config.modules A list of module definitions. See Loader.addModule for the supported module metadata
* @param {Object} config.groups A list of group definitions. Each group can contain specific definitions for `base`, `comboBase`, `combine`, and accepts a list of `modules`.
* @param {String} config.2in3 The version of the YUI 2 in 3 wrapper to use. The intrinsic support for YUI 2 modules in YUI 3 relies on versions of the YUI 2 components inside YUI 3 module wrappers. These wrappers change over time to accomodate the issues that arise from running YUI 2 in a YUI 3 sandbox.
* @param {String} config.yui2 When using the 2in3 project, you can select the version of YUI 2 to use. Valid values are `2.2.2`, `2.3.1`, `2.4.1`, `2.5.2`, `2.6.0`, `2.7.0`, `2.8.0`, `2.8.1` and `2.9.0` [default] -- plus all versions of YUI 2 going forward.
*/
Y.Loader = function(o) {
var self = this;
//Catch no config passed.
o = o || {};
modulekey = META.md5;
/**
* Internal callback to handle multiple internal insert() calls
* so that css is inserted prior to js
* @property _internalCallback
* @private
*/
// self._internalCallback = null;
/**
* Callback that will be executed when the loader is finished
* with an insert
* @method onSuccess
* @type function
*/
// self.onSuccess = null;
/**
* Callback that will be executed if there is a failure
* @method onFailure
* @type function
*/
// self.onFailure = null;
/**
* Callback for the 'CSSComplete' event. When loading YUI components
* with CSS the CSS is loaded first, then the script. This provides
* a moment you can tie into to improve the presentation of the page
* while the script is loading.
* @method onCSS
* @type function
*/
// self.onCSS = null;
/**
* Callback executed each time a script or css file is loaded
* @method onProgress
* @type function
*/
// self.onProgress = null;
/**
* Callback that will be executed if a timeout occurs
* @method onTimeout
* @type function
*/
// self.onTimeout = null;
/**
* The execution context for all callbacks
* @property context
* @default {YUI} the YUI instance
*/
self.context = Y;
/**
* Data that is passed to all callbacks
* @property data
*/
// self.data = null;
/**
* Node reference or id where new nodes should be inserted before
* @property insertBefore
* @type string|HTMLElement
*/
// self.insertBefore = null;
/**
* The charset attribute for inserted nodes
* @property charset
* @type string
* @deprecated , use cssAttributes or jsAttributes.
*/
// self.charset = null;
/**
* An object literal containing attributes to add to link nodes
* @property cssAttributes
* @type object
*/
// self.cssAttributes = null;
/**
* An object literal containing attributes to add to script nodes
* @property jsAttributes
* @type object
*/
// self.jsAttributes = null;
/**
* The base directory.
* @property base
* @type string
* @default http://yui.yahooapis.com/[YUI VERSION]/build/
*/
self.base = Y.Env.meta.base + Y.Env.meta.root;
/**
* Base path for the combo service
* @property comboBase
* @type string
* @default http://yui.yahooapis.com/combo?
*/
self.comboBase = Y.Env.meta.comboBase;
/*
* Base path for language packs.
*/
// self.langBase = Y.Env.meta.langBase;
// self.lang = "";
/**
* If configured, the loader will attempt to use the combo
* service for YUI resources and configured external resources.
* @property combine
* @type boolean
* @default true if a base dir isn't in the config
*/
self.combine = o.base &&
(o.base.indexOf(self.comboBase.substr(0, 20)) > -1);
/**
* The default seperator to use between files in a combo URL
* @property comboSep
* @type {String}
* @default Ampersand
*/
self.comboSep = '&';
/**
* Max url length for combo urls. The default is 1024. This is the URL
* limit for the Yahoo! hosted combo servers. If consuming
* a different combo service that has a different URL limit
* it is possible to override this default by supplying
* the maxURLLength config option. The config option will
* only take effect if lower than the default.
*
* @property maxURLLength
* @type int
*/
self.maxURLLength = MAX_URL_LENGTH;
/**
* Ignore modules registered on the YUI global
* @property ignoreRegistered
* @default false
*/
self.ignoreRegistered = o.ignoreRegistered;
/**
* Root path to prepend to module path for the combo
* service
* @property root
* @type string
* @default [YUI VERSION]/build/
*/
self.root = Y.Env.meta.root;
/**
* Timeout value in milliseconds. If set, self value will be used by
* the get utility. the timeout event will fire if
* a timeout occurs.
* @property timeout
* @type int
*/
self.timeout = 0;
/**
* A list of modules that should not be loaded, even if
* they turn up in the dependency tree
* @property ignore
* @type string[]
*/
// self.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[]
*/
// self.force = null;
self.forceMap = {};
/**
* Should we allow rollups
* @property allowRollup
* @type boolean
* @default false
*/
self.allowRollup = false;
/**
* 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}
*/
// self.filter = null;
/**
* per-component filter specification. If specified for a given
* component, this overrides the filter config.
* @property filters
* @type object
*/
self.filters = {};
/**
* The list of requested modules
* @property required
* @type {string: boolean}
*/
self.required = {};
/**
* If a module name is predefined when requested, it is checked againsts
* the patterns provided in this property. If there is a match, the
* module is added with the default configuration.
*
* At the moment only supporting module prefixes, but anticipate
* supporting at least regular expressions.
* @property patterns
* @type Object
*/
// self.patterns = Y.merge(Y.Env.meta.patterns);
self.patterns = {};
/**
* The library metadata
* @property moduleInfo
*/
// self.moduleInfo = Y.merge(Y.Env.meta.moduleInfo);
self.moduleInfo = {};
self.groups = Y.merge(Y.Env.meta.groups);
/**
* 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/',
*
* // 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
* @type {Object}
*/
self.skin = Y.merge(Y.Env.meta.skin);
/*
* Map of conditional modules
* @since 3.2.0
*/
self.conditions = {};
// map of modules with a hash of modules that meet the requirement
// self.provides = {};
self.config = o;
self._internal = true;
self._populateCache();
/**
* 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.
* @property loaded
* @type {string: boolean}
*/
self.loaded = GLOBAL_LOADED[VERSION];
/**
* Should Loader fetch scripts in `async`, defaults to `true`
* @property async
*/
self.async = true;
self._inspectPage();
self._internal = false;
self._config(o);
self.forceMap = (self.force) ? Y.Array.hash(self.force) : {};
self.testresults = null;
if (Y.config.tests) {
self.testresults = Y.config.tests;
}
/**
* List of rollup files found in the library metadata
* @property rollups
*/
// self.rollups = null;
/**
* Whether or not to load optional dependencies for
* the requested modules
* @property loadOptional
* @type boolean
* @default false
*/
// self.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[]
*/
self.sorted = [];
/*
* A list of modules to attach to the YUI instance when complete.
* If not supplied, the sorted list of dependencies are applied.
* @property attaching
*/
// self.attaching = null;
/**
* Flag to indicate the dependency tree needs to be recomputed
* if insert is called again.
* @property dirty
* @type boolean
* @default true
*/
self.dirty = true;
/**
* List of modules inserted by the utility
* @property inserted
* @type {string: boolean}
*/
self.inserted = {};
/**
* List of skipped modules during insert() because the module
* was not defined
* @property skipped
*/
self.skipped = {};
// Y.on('yui:load', self.loadNext, self);
self.tested = {};
/*
* Cached sorted calculate results
* @property results
* @since 3.2.0
*/
//self.results = {};
if (self.ignoreRegistered) {
//Clear inpage already processed modules.
self._resetModules();
}
};
Y.Loader.prototype = {
/**
* Checks the cache for modules and conditions, if they do not exist
* process the default metadata and populate the local moduleInfo hash.
* @method _populateCache
* @private
*/
_populateCache: function() {
var self = this,
defaults = META.modules,
cache = GLOBAL_ENV._renderedMods,
i;
if (cache && !self.ignoreRegistered) {
for (i in cache) {
if (cache.hasOwnProperty(i)) {
self.moduleInfo[i] = Y.merge(cache[i]);
}
}
cache = GLOBAL_ENV._conditions;
for (i in cache) {
if (cache.hasOwnProperty(i)) {
self.conditions[i] = Y.merge(cache[i]);
}
}
} else {
for (i in defaults) {
if (defaults.hasOwnProperty(i)) {
self.addModule(defaults[i], i);
}
}
}
},
/**
* Reset modules in the module cache to a pre-processed state so additional
* computations with a different skin or language will work as expected.
* @method _resetModules
* @private
*/
_resetModules: function() {
var self = this, i, o,
mod, name, details;
for (i in self.moduleInfo) {
if (self.moduleInfo.hasOwnProperty(i)) {
mod = self.moduleInfo[i];
name = mod.name;
details = (YUI.Env.mods[name] ? YUI.Env.mods[name].details : null);
if (details) {
self.moduleInfo[name]._reset = true;
self.moduleInfo[name].requires = details.requires || [];
self.moduleInfo[name].optional = details.optional || [];
self.moduleInfo[name].supersedes = details.supercedes || [];
}
if (mod.defaults) {
for (o in mod.defaults) {
if (mod.defaults.hasOwnProperty(o)) {
if (mod[o]) {
mod[o] = mod.defaults[o];
}
}
}
}
delete mod.langCache;
delete mod.skinCache;
if (mod.skinnable) {
self._addSkin(self.skin.defaultSkin, mod.name);
}
}
}
},
/**
Regex that matches a CSS URL. Used to guess the file type when it's not
specified.
@property REGEX_CSS
@type RegExp
@final
@protected
@since 3.5.0
**/
REGEX_CSS: /\.css(?:[?;].*)?$/i,
/**
* Default filters for raw and debug
* @property FILTER_DEFS
* @type Object
* @final
* @protected
*/
FILTER_DEFS: {
RAW: {
'searchExp': '-min\\.js',
'replaceStr': '.js'
},
DEBUG: {
'searchExp': '-min\\.js',
'replaceStr': '-debug.js'
},
COVERAGE: {
'searchExp': '-min\\.js',
'replaceStr': '-coverage.js'
}
},
/*
* Check the pages meta-data and cache the result.
* @method _inspectPage
* @private
*/
_inspectPage: function() {
var self = this, v, m, req, mr, i;
//Inspect the page for CSS only modules and mark them as loaded.
for (i in self.moduleInfo) {
if (self.moduleInfo.hasOwnProperty(i)) {
v = self.moduleInfo[i];
if (v.type && v.type === CSS) {
if (self.isCSSLoaded(v.name)) {
self.loaded[i] = true;
}
}
}
}
for (i in ON_PAGE) {
if (ON_PAGE.hasOwnProperty(i)) {
v = ON_PAGE[i];
if (v.details) {
m = self.moduleInfo[v.name];
req = v.details.requires;
mr = m && m.requires;
if (m) {
if (!m._inspected && req && mr.length !== req.length) {
// console.log('deleting ' + m.name);
delete m.expanded;
}
} else {
m = self.addModule(v.details, i);
}
m._inspected = true;
}
}
}
},
/*
* returns true if b is not loaded, and is required directly or by means of modules it supersedes.
* @private
* @method _requires
* @param {String} mod1 The first module to compare
* @param {String} mod2 The second module to compare
*/
_requires: function(mod1, mod2) {
var i, rm, after_map, s,
info = this.moduleInfo,
m = info[mod1],
other = info[mod2];
if (!m || !other) {
return false;
}
rm = m.expanded_map;
after_map = m.after_map;
// check if this module should be sorted after the other
// do this first to short circut circular deps
if (after_map && (mod2 in after_map)) {
return true;
}
after_map = other.after_map;
// and vis-versa
if (after_map && (mod1 in after_map)) {
return false;
}
// check if this module requires one the other supersedes
s = info[mod2] && info[mod2].supersedes;
if (s) {
for (i = 0; i < s.length; i++) {
if (this._requires(mod1, s[i])) {
return true;
}
}
}
s = info[mod1] && info[mod1].supersedes;
if (s) {
for (i = 0; i < s.length; i++) {
if (this._requires(mod2, s[i])) {
return false;
}
}
}
// check if this module requires the other directly
// if (r && yArray.indexOf(r, mod2) > -1) {
if (rm && (mod2 in rm)) {
return true;
}
// external css files should be sorted below yui css
if (m.ext && m.type === CSS && !other.ext && other.type === CSS) {
return true;
}
return false;
},
/**
* Apply a new config to the Loader instance
* @method _config
* @private
* @param {Object} o The new configuration
*/
_config: function(o) {
var i, j, val, a, f, group, groupName, self = this,
mods = [], mod;
// apply config values
if (o) {
for (i in o) {
if (o.hasOwnProperty(i)) {
val = o[i];
//TODO This should be a case
if (i === 'require') {
self.require(val);
} else if (i === 'skin') {
//If the config.skin is a string, format to the expected object
if (typeof val === 'string') {
self.skin.defaultSkin = o.skin;
val = {
defaultSkin: val
};
}
Y.mix(self.skin, val, true);
} else if (i === 'groups') {
for (j in val) {
if (val.hasOwnProperty(j)) {
groupName = j;
group = val[j];
self.addGroup(group, groupName);
if (group.aliases) {
for (a in group.aliases) {
if (group.aliases.hasOwnProperty(a)) {
self.addAlias(group.aliases[a], a);
}
}
}
}
}
} else if (i === 'modules') {
// add a hash of module definitions
for (j in val) {
if (val.hasOwnProperty(j)) {
self.addModule(val[j], j);
}
}
} else if (i === 'aliases') {
for (j in val) {
if (val.hasOwnProperty(j)) {
self.addAlias(val[j], j);
}
}
} else if (i === 'gallery') {
if (this.groups.gallery.update) {
this.groups.gallery.update(val, o);
}
} else if (i === 'yui2' || i === '2in3') {
if (this.groups.yui2.update) {
this.groups.yui2.update(o['2in3'], o.yui2, o);
}
} else {
self[i] = val;
}
}
}
}
// fix filter
f = self.filter;
if (L.isString(f)) {
f = f.toUpperCase();
self.filterName = f;
self.filter = self.FILTER_DEFS[f];
if (f === 'DEBUG') {
self.require('yui-log', 'dump');
}
}
if (self.filterName && self.coverage) {
if (self.filterName === 'COVERAGE' && L.isArray(self.coverage) && self.coverage.length) {
for (i = 0; i < self.coverage.length; i++) {
mod = self.coverage[i];
if (self.moduleInfo[mod] && self.moduleInfo[mod].use) {
mods = [].concat(mods, self.moduleInfo[mod].use);
} else {
mods.push(mod);
}
}
self.filters = self.filters || {};
Y.Array.each(mods, function(mod) {
self.filters[mod] = self.FILTER_DEFS.COVERAGE;
});
self.filterName = 'RAW';
self.filter = self.FILTER_DEFS[self.filterName];
}
}
},
/**
* 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 {string} skin the name of the skin.
* @param {string} mod optional: the name of a module to skin.
* @return {string} the full skin module name.
*/
formatSkin: function(skin, mod) {
var s = SKIN_PREFIX + skin;
if (mod) {
s = s + '-' + mod;
}
return s;
},
/**
* Adds the skin def to the module info
* @method _addSkin
* @param {string} skin the name of the skin.
* @param {string} mod the name of the module.
* @param {string} parent 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 mdef, pkg, name, nmod,
info = this.moduleInfo,
sinf = this.skin,
ext = info[mod] && info[mod].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;
nmod = {
skin: true,
name: name,
group: mdef.group,
type: 'css',
after: sinf.after,
path: (parent || pkg) + '/' + sinf.base + skin +
'/' + mod + '.css',
ext: ext
};
if (mdef.base) {
nmod.base = mdef.base;
}
if (mdef.configFn) {
nmod.configFn = mdef.configFn;
}
this.addModule(nmod, name);
}
}
return name;
},
/**
* Adds an alias module to the system
* @method addAlias
* @param {Array} use An array of modules that makes up this alias
* @param {String} name The name of the alias
* @example
* var loader = new Y.Loader({});
* loader.addAlias([ 'node', 'yql' ], 'davglass');
* loader.require(['davglass']);
* var out = loader.resolve(true);
*
* //out.js will contain Node and YQL modules
*/
addAlias: function(use, name) {
YUI.Env.aliases[name] = use;
this.addModule({
name: name,
use: use
});
},
/**
* Add a new module group
* @method addGroup
* @param {Object} config An object containing the group configuration data
* @param {String} config.name required, the group name
* @param {String} config.base The base directory for this module group
* @param {String} config.root The root path to add to each combo resource path
* @param {Boolean} config.combine Should the request be combined
* @param {String} config.comboBase Combo service base path
* @param {Object} config.modules The group of modules
* @param {String} name the group name.
* @example
* var loader = new Y.Loader({});
* loader.addGroup({
* name: 'davglass',
* combine: true,
* comboBase: '/combo?',
* root: '',
* modules: {
* //Module List here
* }
* }, 'davglass');
*/
addGroup: function(o, name) {
var mods = o.modules,
self = this, i, v;
name = name || o.name;
o.name = name;
self.groups[name] = o;
if (o.patterns) {
for (i in o.patterns) {
if (o.patterns.hasOwnProperty(i)) {
o.patterns[i].group = name;
self.patterns[i] = o.patterns[i];
}
}
}
if (mods) {
for (i in mods) {
if (mods.hasOwnProperty(i)) {
v = mods[i];
if (typeof v === 'string') {
v = { name: i, fullpath: v };
}
v.group = name;
self.addModule(v, i);
}
}
}
},
/**
* Add a new module to the component metadata.
* @method addModule
* @param {Object} config An object containing the module data.
* @param {String} config.name Required, the component name
* @param {String} config.type Required, the component type (js or css)
* @param {String} config.path Required, the path to the script from `base`
* @param {Array} config.requires Array of modules required by this component
* @param {Array} [config.optional] Array of optional modules for this component
* @param {Array} [config.supersedes] Array of the modules this component replaces
* @param {Array} [config.after] Array of modules the components which, if present, should be sorted above this one
* @param {Object} [config.after_map] Faster alternative to 'after' -- supply a hash instead of an array
* @param {Number} [config.rollup] The number of superseded modules required for automatic rollup
* @param {String} [config.fullpath] If `fullpath` is specified, this is used instead of the configured `base + path`
* @param {Boolean} [config.skinnable] Flag to determine if skin assets should automatically be pulled in
* @param {Object} [config.submodules] Hash of submodules
* @param {String} [config.group] The group the module belongs to -- this is set automatically when it is added as part of a group configuration.
* @param {Array} [config.lang] Array of BCP 47 language tags of languages for which this module has localized resource bundles, e.g., `["en-GB", "zh-Hans-CN"]`
* @param {Object} [config.condition] Specifies that the module should be loaded automatically if a condition is met. This is an object with up to three fields:
* @param {String} [config.condition.trigger] The name of a module that can trigger the auto-load
* @param {Function} [config.condition.test] A function that returns true when the module is to be loaded.
* @param {String} [config.condition.when] Specifies the load order of the conditional module
* with regard to the position of the trigger module.
* This should be one of three values: `before`, `after`, or `instead`. The default is `after`.
* @param {Object} [config.testresults] A hash of test results from `Y.Features.all()`
* @param {Function} [config.configFn] A function to exectute when configuring this module
* @param {Object} config.configFn.mod The module config, modifying this object will modify it's config. Returning false will delete the module's config.
* @param {String} [name] The module name, required if not in the module data.
* @return {Object} the module definition or null if the object passed in did not provide all required attributes.
*/
addModule: function(o, name) {
name = name || o.name;
if (typeof o === 'string') {
o = { name: name, fullpath: o };
}
var subs, i, l, t, sup, s, smod, plugins, plug,
j, langs, packName, supName, flatSup, flatLang, lang, ret,
overrides, skinname, when, g, p,
conditions = this.conditions, trigger;
//Only merge this data if the temp flag is set
//from an earlier pass from a pattern or else
//an override module (YUI_config) can not be used to
//replace a default module.
if (this.moduleInfo[name] && this.moduleInfo[name].temp) {
//This catches temp modules loaded via a pattern
// The module will be added twice, once from the pattern and
// Once from the actual add call, this ensures that properties
// that were added to the module the first time around (group: gallery)
// are also added the second time around too.
o = Y.merge(this.moduleInfo[name], o);
}
o.name = name;
if (!o || !o.name) {
return null;
}
if (!o.type) {
//Always assume it's javascript unless the CSS pattern is matched.
o.type = JS;
p = o.path || o.fullpath;
if (p && this.REGEX_CSS.test(p)) {
o.type = CSS;
}
}
if (!o.path && !o.fullpath) {
o.path = _path(name, name, o.type);
}
o.supersedes = o.supersedes || o.use;
o.ext = ('ext' in o) ? o.ext : (this._internal) ? false : true;
// Handle submodule logic
subs = o.submodules;
this.moduleInfo[name] = o;
o.requires = o.requires || [];
/*
Only allowing the cascade of requires information, since
optional and supersedes are far more fine grained than
a blanket requires is.
*/
if (this.requires) {
for (i = 0; i < this.requires.length; i++) {
o.requires.push(this.requires[i]);
}
}
if (o.group && this.groups && this.groups[o.group]) {
g = this.groups[o.group];
if (g.requires) {
for (i = 0; i < g.requires.length; i++) {
o.requires.push(g.requires[i]);
}
}
}
if (!o.defaults) {
o.defaults = {
requires: o.requires ? [].concat(o.requires) : null,
supersedes: o.supersedes ? [].concat(o.supersedes) : null,
optional: o.optional ? [].concat(o.optional) : null
};
}
if (o.skinnable && o.ext && o.temp) {
skinname = this._addSkin(this.skin.defaultSkin, name);
o.requires.unshift(skinname);
}
if (o.requires.length) {
o.requires = this.filterRequires(o.requires) || [];
}
if (!o.langPack && o.lang) {
langs = yArray(o.lang);
for (j = 0; j < langs.length; j++) {
lang = langs[j];
packName = this.getLangPackName(lang, name);
smod = this.moduleInfo[packName];
if (!smod) {
smod = this._addLangPack(lang, o, packName);
}
}
}
if (subs) {
sup = o.supersedes || [];
l = 0;
for (i in subs) {
if (subs.hasOwnProperty(i)) {
s = subs[i];
s.path = s.path || _path(name, i, o.type);
s.pkg = name;
s.group = o.group;
if (s.supersedes) {
sup = sup.concat(s.supersedes);
}
smod = this.addModule(s, i);
sup.push(i);
if (smod.skinnable) {
o.skinnable = true;
overrides = this.skin.overrides;
if (overrides && overrides[i]) {
for (j = 0; j < overrides[i].length; j++) {
skinname = this._addSkin(overrides[i][j],
i, name);
sup.push(skinname);
}
}
skinname = this._addSkin(this.skin.defaultSkin,
i, name);
sup.push(skinname);
}
// looks like we are expected to work out the metadata
// for the parent module language packs from what is
// specified in the child modules.
if (s.lang && s.lang.length) {
langs = yArray(s.lang);
for (j = 0; j < langs.length; j++) {
lang = langs[j];
packName = this.getLangPackName(lang, name);
supName = this.getLangPackName(lang, i);
smod = this.moduleInfo[packName];
if (!smod) {
smod = this._addLangPack(lang, o, packName);
}
flatSup = flatSup || yArray.hash(smod.supersedes);
if (!(supName in flatSup)) {
smod.supersedes.push(supName);
}
o.lang = o.lang || [];
flatLang = flatLang || yArray.hash(o.lang);
if (!(lang in flatLang)) {
o.lang.push(lang);
}
// Add rollup file, need to add to supersedes list too
// default packages
packName = this.getLangPackName(ROOT_LANG, name);
supName = this.getLangPackName(ROOT_LANG, i);
smod = this.moduleInfo[packName];
if (!smod) {
smod = this._addLangPack(lang, o, packName);
}
if (!(supName in flatSup)) {
smod.supersedes.push(supName);
}
// Add rollup file, need to add to supersedes list too
}
}
l++;
}
}
//o.supersedes = YObject.keys(yArray.hash(sup));
o.supersedes = yArray.dedupe(sup);
if (this.allowRollup) {
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.pkg = name;
plug.path = plug.path || _path(name, i, o.type);
plug.requires = plug.requires || [];
plug.group = o.group;
this.addModule(plug, i);
if (o.skinnable) {
this._addSkin(this.skin.defaultSkin, i, name);
}
}
}
}
if (o.condition) {
t = o.condition.trigger;
if (YUI.Env.aliases[t]) {
t = YUI.Env.aliases[t];
}
if (!Y.Lang.isArray(t)) {
t = [t];
}
for (i = 0; i < t.length; i++) {
trigger = t[i];
when = o.condition.when;
conditions[trigger] = conditions[trigger] || {};
conditions[trigger][name] = o.condition;
// the 'when' attribute can be 'before', 'after', or 'instead'
// the default is after.
if (when && when !== 'after') {
if (when === 'instead') { // replace the trigger
o.supersedes = o.supersedes || [];
o.supersedes.push(trigger);
}
// before the trigger
// the trigger requires the conditional mod,
// so it should appear before the conditional
// mod if we do not intersede.
} else { // after the trigger
o.after = o.after || [];
o.after.push(trigger);
}
}
}
if (o.supersedes) {
o.supersedes = this.filterRequires(o.supersedes);
}
if (o.after) {
o.after = this.filterRequires(o.after);
o.after_map = yArray.hash(o.after);
}
// this.dirty = true;
if (o.configFn) {
ret = o.configFn(o);
if (ret === false) {
delete this.moduleInfo[name];
delete GLOBAL_ENV._renderedMods[name];
o = null;
}
}
//Add to global cache
if (o) {
if (!GLOBAL_ENV._renderedMods) {
GLOBAL_ENV._renderedMods = {};
}
GLOBAL_ENV._renderedMods[name] = Y.mix(GLOBAL_ENV._renderedMods[name] || {}, o);
GLOBAL_ENV._conditions = conditions;
}
return o;
},
/**
* Add a requirement for one or more module
* @method require
* @param {string[] | string*} what the modules to load.
*/
require: function(what) {
var a = (typeof what === 'string') ? yArray(arguments) : what;
this.dirty = true;
this.required = Y.merge(this.required, yArray.hash(this.filterRequires(a)));
this._explodeRollups();
},
/**
* Grab all the items that were asked for, check to see if the Loader
* meta-data contains a "use" array. If it doesm remove the asked item and replace it with
* the content of the "use".
* This will make asking for: "dd"
* Actually ask for: "dd-ddm-base,dd-ddm,dd-ddm-drop,dd-drag,dd-proxy,dd-constrain,dd-drop,dd-scroll,dd-drop-plugin"
* @private
* @method _explodeRollups
*/
_explodeRollups: function() {
var self = this, m, m2, i, a, v, len, len2,
r = self.required;
if (!self.allowRollup) {
for (i in r) {
if (r.hasOwnProperty(i)) {
m = self.getModule(i);
if (m && m.use) {
len = m.use.length;
for (a = 0; a < len; a++) {
m2 = self.getModule(m.use[a]);
if (m2 && m2.use) {
len2 = m2.use.length;
for (v = 0; v < len2; v++) {
r[m2.use[v]] = true;
}
} else {
r[m.use[a]] = true;
}
}
}
}
}
self.required = r;
}
},
/**
* Explodes the required array to remove aliases and replace them with real modules
* @method filterRequires
* @param {Array} r The original requires array
* @return {Array} The new array of exploded requirements
*/
filterRequires: function(r) {
if (r) {
if (!Y.Lang.isArray(r)) {
r = [r];
}
r = Y.Array(r);
var c = [], i, mod, o, m;
for (i = 0; i < r.length; i++) {
mod = this.getModule(r[i]);
if (mod && mod.use) {
for (o = 0; o < mod.use.length; o++) {
//Must walk the other modules in case a module is a rollup of rollups (datatype)
m = this.getModule(mod.use[o]);
if (m && m.use && (m.name !== mod.name)) {
c = Y.Array.dedupe([].concat(c, this.filterRequires(m.use)));
} else {
c.push(mod.use[o]);
}
}
} else {
c.push(r[i]);
}
}
r = c;
}
return r;
},
/**
* Returns an object containing properties for all modules required
* in order to load the requested module
* @method getRequires
* @param {object} mod The module definition from moduleInfo.
* @return {array} the expanded requirement list.
*/
getRequires: function(mod) {
if (!mod) {
//console.log('returning no reqs for ' + mod.name);
return NO_REQUIREMENTS;
}
if (mod._parsed) {
//console.log('returning requires for ' + mod.name, mod.requires);
return mod.expanded || NO_REQUIREMENTS;
}
//TODO add modue cache here out of scope..
var i, m, j, add, packName, lang, testresults = this.testresults,
name = mod.name, cond,
adddef = ON_PAGE[name] && ON_PAGE[name].details,
d, go, def,
r, old_mod,
o, skinmod, skindef, skinpar, skinname,
intl = mod.lang || mod.intl,
info = this.moduleInfo,
ftests = Y.Features && Y.Features.tests.load,
hash, reparse;
// console.log(name);
// pattern match leaves module stub that needs to be filled out
if (mod.temp && adddef) {
old_mod = mod;
mod = this.addModule(adddef, name);
mod.group = old_mod.group;
mod.pkg = old_mod.pkg;
delete mod.expanded;
}
// console.log('cache: ' + mod.langCache + ' == ' + this.lang);
//If a skin or a lang is different, reparse..
reparse = !((!this.lang || mod.langCache === this.lang) && (mod.skinCache === this.skin.defaultSkin));
if (mod.expanded && !reparse) {
return mod.expanded;
}
d = [];
hash = {};
r = this.filterRequires(mod.requires);
if (mod.lang) {
//If a module has a lang attribute, auto add the intl requirement.
d.unshift('intl');
r.unshift('intl');
intl = true;
}
o = this.filterRequires(mod.optional);
mod._parsed = true;
mod.langCache = this.lang;
mod.skinCache = this.skin.defaultSkin;
for (i = 0; i < r.length; i++) {
if (!hash[r[i]]) {
d.push(r[i]);
hash[r[i]] = true;
m = this.getModule(r[i]);
if (m) {
add = this.getRequires(m);
intl = intl || (m.expanded_map &&
(INTL in m.expanded_map));
for (j = 0; j < add.length; j++) {
d.push(add[j]);
}
}
}
}
// get the requirements from superseded modules, if any
r = this.filterRequires(mod.supersedes);
if (r) {
for (i = 0; i < r.length; i++) {
if (!hash[r[i]]) {
// if this module has submodules, the requirements list is
// expanded to include the submodules. This is so we can
// prevent dups when a submodule is already loaded and the
// parent is requested.
if (mod.submodules) {
d.push(r[i]);
}
hash[r[i]] = true;
m = this.getModule(r[i]);
if (m) {
add = this.getRequires(m);
intl = intl || (m.expanded_map &&
(INTL in m.expanded_map));
for (j = 0; j < add.length; j++) {
d.push(add[j]);
}
}
}
}
}
if (o && this.loadOptional) {
for (i = 0; i < o.length; i++) {
if (!hash[o[i]]) {
d.push(o[i]);
hash[o[i]] = true;
m = info[o[i]];
if (m) {
add = this.getRequires(m);
intl = intl || (m.expanded_map &&
(INTL in m.expanded_map));
for (j = 0; j < add.length; j++) {
d.push(add[j]);
}
}
}
}
}
cond = this.conditions[name];
if (cond) {
//Set the module to not parsed since we have conditionals and this could change the dependency tree.
mod._parsed = false;
if (testresults && ftests) {
oeach(testresults, function(result, id) {
var condmod = ftests[id].name;
if (!hash[condmod] && ftests[id].trigger === name) {
if (result && ftests[id]) {
hash[condmod] = true;
d.push(condmod);
}
}
});
} else {
for (i in cond) {
if (cond.hasOwnProperty(i)) {
if (!hash[i]) {
def = cond[i];
//first see if they've specfied a ua check
//then see if they've got a test fn & if it returns true
//otherwise just having a condition block is enough
go = def && ((!def.ua && !def.test) || (def.ua && Y.UA[def.ua]) ||
(def.test && def.test(Y, r)));
if (go) {
hash[i] = true;
d.push(i);
m = this.getModule(i);
if (m) {
add = this.getRequires(m);
for (j = 0; j < add.length; j++) {
d.push(add[j]);
}
}
}
}
}
}
}
}
// Create skin modules
if (mod.skinnable) {
skindef = this.skin.overrides;
for (i in YUI.Env.aliases) {
if (YUI.Env.aliases.hasOwnProperty(i)) {
if (Y.Array.indexOf(YUI.Env.aliases[i], name) > -1) {
skinpar = i;
}
}
}
if (skindef && (skindef[name] || (skinpar && skindef[skinpar]))) {
skinname = name;
if (skindef[skinpar]) {
skinname = skinpar;
}
for (i = 0; i < skindef[skinname].length; i++) {
skinmod = this._addSkin(skindef[skinname][i], name);
if (!this.isCSSLoaded(skinmod, this._boot)) {
d.push(skinmod);
}
}
} else {
skinmod = this._addSkin(this.skin.defaultSkin, name);
if (!this.isCSSLoaded(skinmod, this._boot)) {
d.push(skinmod);
}
}
}
mod._parsed = false;
if (intl) {
if (mod.lang && !mod.langPack && Y.Intl) {
lang = Y.Intl.lookupBestLang(this.lang || ROOT_LANG, mod.lang);
packName = this.getLangPackName(lang, name);
if (packName) {
d.unshift(packName);
}
}
d.unshift(INTL);
}
mod.expanded_map = yArray.hash(d);
mod.expanded = YObject.keys(mod.expanded_map);
return mod.expanded;
},
/**
* Check to see if named css module is already loaded on the page
* @method isCSSLoaded
* @param {String} name The name of the css file
* @return Boolean
*/
isCSSLoaded: function(name, skip) {
//TODO - Make this call a batching call with name being an array
if (!name || !YUI.Env.cssStampEl || (!skip && this.ignoreRegistered)) {
return false;
}
var el = YUI.Env.cssStampEl,
ret = false,
mod = YUI.Env._cssLoaded[name],
style = el.currentStyle; //IE
if (mod !== undefined) {
return mod;
}
//Add the classname to the element
el.className = name;
if (!style) {
style = Y.config.doc.defaultView.getComputedStyle(el, null);
}
if (style && style.display === 'none') {
ret = true;
}
el.className = ''; //Reset the classname to ''
YUI.Env._cssLoaded[name] = ret;
return ret;
},
/**
* Returns a hash of module names the supplied module satisfies.
* @method getProvides
* @param {string} name The name of the module.
* @return {object} what this module provides.
*/
getProvides: function(name) {
var m = this.getModule(name), o, s;
// supmap = this.provides;
if (!m) {
return NOT_FOUND;
}
if (m && !m.provides) {
o = {};
s = m.supersedes;
if (s) {
yArray.each(s, function(v) {
Y.mix(o, this.getProvides(v));
}, this);
}
o[name] = true;
m.provides = o;
}
return m.provides;
},
/**
* Calculates the dependency tree, the result is stored in the sorted
* property.
* @method calculate
* @param {object} o optional options object.
* @param {string} type optional argument to prune modules.
*/
calculate: function(o, type) {
if (o || type || this.dirty) {
if (o) {
this._config(o);
}
if (!this._init) {
this._setup();
}
this._explode();
if (this.allowRollup) {
this._rollup();
} else {
this._explodeRollups();
}
this._reduce();
this._sort();
}
},
/**
* Creates a "psuedo" package for languages provided in the lang array
* @method _addLangPack
* @private
* @param {String} lang The language to create
* @param {Object} m The module definition to create the language pack around
* @param {String} packName The name of the package (e.g: lang/datatype-date-en-US)
* @return {Object} The module definition
*/
_addLangPack: function(lang, m, packName) {
var name = m.name,
packPath, conf,
existing = this.moduleInfo[packName];
if (!existing) {
packPath = _path((m.pkg || name), packName, JS, true);
conf = {
path: packPath,
intl: true,
langPack: true,
ext: m.ext,
group: m.group,
supersedes: []
};
if (m.root) {
conf.root = m.root;
}
if (m.base) {
conf.base = m.base;
}
if (m.configFn) {
conf.configFn = m.configFn;
}
this.addModule(conf, packName);
if (lang) {
Y.Env.lang = Y.Env.lang || {};
Y.Env.lang[lang] = Y.Env.lang[lang] || {};
Y.Env.lang[lang][name] = true;
}
}
return this.moduleInfo[packName];
},
/**
* Investigates the current YUI configuration on the page. By default,
* modules already detected will not be loaded again unless a force
* option is encountered. Called by calculate()
* @method _setup
* @private
*/
_setup: function() {
var info = this.moduleInfo, name, i, j, m, l,
packName;
for (name in info) {
if (info.hasOwnProperty(name)) {
m = info[name];
if (m) {
// remove dups
//m.requires = YObject.keys(yArray.hash(m.requires));
m.requires = yArray.dedupe(m.requires);
// Create lang pack modules
//if (m.lang && m.lang.length) {
if (m.lang) {
// Setup root package if the module has lang defined,
// it needs to provide a root language pack
packName = this.getLangPackName(ROOT_LANG, name);
this._addLangPack(null, m, packName);
}
}
}
}
//l = Y.merge(this.inserted);
l = {};
// available modules
if (!this.ignoreRegistered) {
Y.mix(l, GLOBAL_ENV.mods);
}
// add the ignore list to the list of loaded packages
if (this.ignore) {
Y.mix(l, yArray.hash(this.ignore));
}
// expand the list to include superseded modules
for (j in l) {
if (l.hasOwnProperty(j)) {
Y.mix(l, this.getProvides(j));
}
}
// remove modules on the force list from the loaded list
if (this.force) {
for (i = 0; i < this.force.length; i++) {
if (this.force[i] in l) {
delete l[this.force[i]];
}
}
}
Y.mix(this.loaded, l);
this._init = true;
},
/**
* Builds a module name for a language pack
* @method getLangPackName
* @param {string} lang the language code.
* @param {string} mname the module to build it for.
* @return {string} the language pack module name.
*/
getLangPackName: function(lang, mname) {
return ('lang/' + mname + ((lang) ? '_' + lang : ''));
},
/**
* Inspects the required modules list looking for additional
* dependencies. Expands the required list to include all
* required modules. Called by calculate()
* @method _explode
* @private
*/
_explode: function() {
//TODO Move done out of scope
var r = this.required, m, reqs, done = {},
self = this, name, expound;
// the setup phase is over, all modules have been created
self.dirty = false;
self._explodeRollups();
r = self.required;
for (name in r) {
if (r.hasOwnProperty(name)) {
if (!done[name]) {
done[name] = true;
m = self.getModule(name);
if (m) {
expound = m.expound;
if (expound) {
r[expound] = self.getModule(expound);
reqs = self.getRequires(r[expound]);
Y.mix(r, yArray.hash(reqs));
}
reqs = self.getRequires(m);
Y.mix(r, yArray.hash(reqs));
}
}
}
}
},
/**
* The default method used to test a module against a pattern
* @method _patternTest
* @private
* @param {String} mname The module being tested
* @param {String} pname The pattern to match
*/
_patternTest: function(mname, pname) {
return (mname.indexOf(pname) > -1);
},
/**
* Get's the loader meta data for the requested module
* @method getModule
* @param {String} mname The module name to get
* @return {Object} The module metadata
*/
getModule: function(mname) {
//TODO: Remove name check - it's a quick hack to fix pattern WIP
if (!mname) {
return null;
}
var p, found, pname,
m = this.moduleInfo[mname],
patterns = this.patterns;
// check the patterns library to see if we should automatically add
// the module with defaults
if (!m || (m && m.ext)) {
for (pname in patterns) {
if (patterns.hasOwnProperty(pname)) {
p = patterns[pname];
//There is no test method, create a default one that tests
// the pattern against the mod name
if (!p.test) {
p.test = this._patternTest;
}
if (p.test(mname, pname)) {
// use the metadata supplied for the pattern
// as the module definition.
found = p;
break;
}
}
}
}
if (!m) {
if (found) {
if (p.action) {
p.action.call(this, mname, pname);
} else {
// ext true or false?
m = this.addModule(Y.merge(found), mname);
if (found.configFn) {
m.configFn = found.configFn;
}
m.temp = true;
}
}
} else {
if (found && m && found.configFn && !m.configFn) {
m.configFn = found.configFn;
m.configFn(m);
}
}
return m;
},
// impl in rollup submodule
_rollup: function() { },
/**
* Remove superceded modules and loaded modules. Called by
* calculate() after we have the mega list of all dependencies
* @method _reduce
* @return {object} the reduced dependency hash.
* @private
*/
_reduce: function(r) {
r = r || this.required;
var i, j, s, m, type = this.loadType,
ignore = this.ignore ? yArray.hash(this.ignore) : false;
for (i in r) {
if (r.hasOwnProperty(i)) {
m = this.getModule(i);
// remove if already loaded
if (((this.loaded[i] || ON_PAGE[i]) &&
!this.forceMap[i] && !this.ignoreRegistered) ||
(type && m && m.type !== type)) {
delete r[i];
}
if (ignore && ignore[i]) {
delete r[i];
}
// remove anything this module supersedes
s = m && m.supersedes;
if (s) {
for (j = 0; j < s.length; j++) {
if (s[j] in r) {
delete r[s[j]];
}
}
}
}
}
return r;
},
/**
* Handles the queue when a module has been loaded for all cases
* @method _finish
* @private
* @param {String} msg The message from Loader
* @param {Boolean} success A boolean denoting success or failure
*/
_finish: function(msg, success) {
_queue.running = false;
var onEnd = this.onEnd;
if (onEnd) {
onEnd.call(this.context, {
msg: msg,
data: this.data,
success: success
});
}
this._continue();
},
/**
* The default Loader onSuccess handler, calls this.onSuccess with a payload
* @method _onSuccess
* @private
*/
_onSuccess: function() {
var self = this, skipped = Y.merge(self.skipped), fn,
failed = [], rreg = self.requireRegistration,
success, msg, i, mod;
for (i in skipped) {
if (skipped.hasOwnProperty(i)) {
delete self.inserted[i];
}
}
self.skipped = {};
for (i in self.inserted) {
if (self.inserted.hasOwnProperty(i)) {
mod = self.getModule(i);
if (mod && rreg && mod.type === JS && !(i in YUI.Env.mods)) {
failed.push(i);
} else {
Y.mix(self.loaded, self.getProvides(i));
}
}
}
fn = self.onSuccess;
msg = (failed.length) ? 'notregistered' : 'success';
success = !(failed.length);
if (fn) {
fn.call(self.context, {
msg: msg,
data: self.data,
success: success,
failed: failed,
skipped: skipped
});
}
self._finish(msg, success);
},
/**
* The default Loader onProgress handler, calls this.onProgress with a payload
* @method _onProgress
* @private
*/
_onProgress: function(e) {
var self = this, i;
//set the internal cache to what just came in.
if (e.data && e.data.length) {
for (i = 0; i < e.data.length; i++) {
e.data[i] = self.getModule(e.data[i].name);
}
}
if (self.onProgress) {
self.onProgress.call(self.context, {
name: e.url,
data: e.data
});
}
},
/**
* The default Loader onFailure handler, calls this.onFailure with a payload
* @method _onFailure
* @private
*/
_onFailure: function(o) {
var f = this.onFailure, msg = [], i = 0, len = o.errors.length;
for (i; i < len; i++) {
msg.push(o.errors[i].error);
}
msg = msg.join(',');
if (f) {
f.call(this.context, {
msg: msg,
data: this.data,
success: false
});
}
this._finish(msg, false);
},
/**
* The default Loader onTimeout handler, calls this.onTimeout with a payload
* @method _onTimeout
* @param {Get.Transaction} transaction The Transaction object from `Y.Get`
* @private
*/
_onTimeout: function(transaction) {
var f = this.onTimeout;
if (f) {
f.call(this.context, {
msg: 'timeout',
data: this.data,
success: false,
transaction: transaction
});
}
},
/**
* Sorts the dependency tree. The last step of calculate()
* @method _sort
* @private
*/
_sort: function() {
// create an indexed list
var s = YObject.keys(this.required),
// loaded = this.loaded,
//TODO Move this out of scope
done = {},
p = 0, l, a, b, j, k, moved, doneKey;
// keep going until we make a pass without moving anything
for (;;) {
l = s.length;
moved = false;
// start the loop after items that are already sorted
for (j = p; j < l; j++) {
// check the next module on the list to see if its
// dependencies have been met
a = s[j];
// check everything below current item and move if we
// find a requirement for the current item
for (k = j + 1; k < l; k++) {
doneKey = a + s[k];
if (!done[doneKey] && this._requires(a, s[k])) {
// extract the dependency so we can move it up
b = s.splice(k, 1);
// insert the dependency above the item that
// requires it
s.splice(j, 0, b[0]);
// only swap two dependencies once to short circut
// circular dependencies
done[doneKey] = true;
// keep working
moved = true;
break;
}
}
// jump out of loop if we moved something
if (moved) {
break;
// this item is sorted, move our pointer and keep going
} else {
p++;
}
}
// when we make it here and moved is false, we are
// finished sorting
if (!moved) {
break;
}
}
this.sorted = s;
},
/**
* Handles the actual insertion of script/link tags
* @method _insert
* @private
* @param {Object} source The YUI instance the request came from
* @param {Object} o The metadata to include
* @param {String} type JS or CSS
* @param {Boolean} [skipcalc=false] Do a Loader.calculate on the meta
*/
_insert: function(source, o, type, skipcalc) {
// restore the state at the time of the request
if (source) {
this._config(source);
}
// build the dependency list
// don't include type so we can process CSS and script in
// one pass when the type is not specified.
var modules = this.resolve(!skipcalc),
self = this, comp = 0, actions = 0,
mods = {}, deps, complete;
self._refetch = [];
if (type) {
//Filter out the opposite type and reset the array so the checks later work
modules[((type === JS) ? CSS : JS)] = [];
}
if (!self.fetchCSS) {
modules.css = [];
}
if (modules.js.length) {
comp++;
}
if (modules.css.length) {
comp++;
}
//console.log('Resolved Modules: ', modules);
complete = function(d) {
actions++;
var errs = {}, i = 0, o = 0, u = '', fn,
modName, resMods;
if (d && d.errors) {
for (i = 0; i < d.errors.length; i++) {
if (d.errors[i].request) {
u = d.errors[i].request.url;
} else {
u = d.errors[i];
}
errs[u] = u;
}
}
if (d && d.data && d.data.length && (d.type === 'success')) {
for (i = 0; i < d.data.length; i++) {
self.inserted[d.data[i].name] = true;
//If the external module has a skin or a lang, reprocess it
if (d.data[i].lang || d.data[i].skinnable) {
delete self.inserted[d.data[i].name];
self._refetch.push(d.data[i].name);
}
}
}
if (actions === comp) {
self._loading = null;
if (self._refetch.length) {
//Get the deps for the new meta-data and reprocess
for (i = 0; i < self._refetch.length; i++) {
deps = self.getRequires(self.getModule(self._refetch[i]));
for (o = 0; o < deps.length; o++) {
if (!self.inserted[deps[o]]) {
//We wouldn't be to this point without the module being here
mods[deps[o]] = deps[o];
}
}
}
mods = Y.Object.keys(mods);
if (mods.length) {
self.require(mods);
resMods = self.resolve(true);
if (resMods.cssMods.length) {
for (i=0; i < resMods.cssMods.length; i++) {
modName = resMods.cssMods[i].name;
delete YUI.Env._cssLoaded[modName];
if (self.isCSSLoaded(modName)) {
self.inserted[modName] = true;
delete self.required[modName];
}
}
self.sorted = [];
self._sort();
}
d = null; //bail
self._insert(); //insert the new deps
}
}
if (d && d.fn) {
fn = d.fn;
delete d.fn;
fn.call(self, d);
}
}
};
this._loading = true;
if (!modules.js.length && !modules.css.length) {
actions = -1;
complete({
fn: self._onSuccess
});
return;
}
if (modules.css.length) { //Load CSS first
Y.Get.css(modules.css, {
data: modules.cssMods,
attributes: self.cssAttributes,
insertBefore: self.insertBefore,
charset: self.charset,
timeout: self.timeout,
context: self,
onProgress: function(e) {
self._onProgress.call(self, e);
},
onTimeout: function(d) {
self._onTimeout.call(self, d);
},
onSuccess: function(d) {
d.type = 'success';
d.fn = self._onSuccess;
complete.call(self, d);
},
onFailure: function(d) {
d.type = 'failure';
d.fn = self._onFailure;
complete.call(self, d);
}
});
}
if (modules.js.length) {
Y.Get.js(modules.js, {
data: modules.jsMods,
insertBefore: self.insertBefore,
attributes: self.jsAttributes,
charset: self.charset,
timeout: self.timeout,
autopurge: false,
context: self,
async: self.async,
onProgress: function(e) {
self._onProgress.call(self, e);
},
onTimeout: function(d) {
self._onTimeout.call(self, d);
},
onSuccess: function(d) {
d.type = 'success';
d.fn = self._onSuccess;
complete.call(self, d);
},
onFailure: function(d) {
d.type = 'failure';
d.fn = self._onFailure;
complete.call(self, d);
}
});
}
},
/**
* Once a loader operation is completely finished, process any additional queued items.
* @method _continue
* @private
*/
_continue: function() {
if (!(_queue.running) && _queue.size() > 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 {object} o optional options object.
* @param {string} type the type of dependency to insert.
*/
insert: function(o, type, skipsort) {
var self = this, copy = Y.merge(this);
delete copy.require;
delete copy.dirty;
_queue.add(function() {
self._insert(copy, o, type, skipsort);
});
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
* @deprecated
* @param {string} mname optional the name of the module that has
* been loaded (which is usually why it is time to load the next
* one).
*/
loadNext: function() {
return;
},
/**
* Apply filter defined for this instance to a url/path
* @method _filter
* @param {string} u the string to filter.
* @param {string} name the name of the module, if we are processing
* a single module as opposed to a combined url.
* @return {string} the filtered string.
* @private
*/
_filter: function(u, name, group) {
var f = this.filter,
hasFilter = name && (name in this.filters),
modFilter = hasFilter && this.filters[name],
groupName = group || (this.moduleInfo[name] ? this.moduleInfo[name].group : null);
if (groupName && this.groups[groupName] && this.groups[groupName].filter) {
modFilter = this.groups[groupName].filter;
hasFilter = true;
}
if (u) {
if (hasFilter) {
f = (L.isString(modFilter)) ? this.FILTER_DEFS[modFilter.toUpperCase()] || null : modFilter;
}
if (f) {
u = u.replace(new RegExp(f.searchExp, 'g'), f.replaceStr);
}
}
return u;
},
/**
* Generates the full url for a module
* @method _url
* @param {string} path the path fragment.
* @param {String} name The name of the module
* @param {String} [base=self.base] The base url to use
* @return {string} the full url.
* @private
*/
_url: function(path, name, base) {
return this._filter((base || this.base || '') + path, name);
},
/**
* Returns an Object hash of file arrays built from `loader.sorted` or from an arbitrary list of sorted modules.
* @method resolve
* @param {Boolean} [calc=false] Perform a loader.calculate() before anything else
* @param {Array} [s=loader.sorted] An override for the loader.sorted array
* @return {Object} Object hash (js and css) of two arrays of file lists
* @example This method can be used as an off-line dep calculator
*
* var Y = YUI();
* var loader = new Y.Loader({
* filter: 'debug',
* base: '../../',
* root: 'build/',
* combine: true,
* require: ['node', 'dd', 'console']
* });
* var out = loader.resolve(true);
*
*/
resolve: function(calc, s) {
var len, i, m, url, group, groupName, j, frag,
comboSource, comboSources, mods, comboBase,
base, urls, u = [], tmpBase, baseLen, resCombos = {},
self = this, comboSep, maxURLLength,
inserted = (self.ignoreRegistered) ? {} : self.inserted,
resolved = { js: [], jsMods: [], css: [], cssMods: [] },
type = self.loadType || 'js', addSingle;
if (self.skin.overrides || self.skin.defaultSkin !== DEFAULT_SKIN || self.ignoreRegistered) {
self._resetModules();
}
if (calc) {
self.calculate();
}
s = s || self.sorted;
addSingle = function(m) {
if (m) {
group = (m.group && self.groups[m.group]) || NOT_FOUND;
//Always assume it's async
if (group.async === false) {
m.async = group.async;
}
url = (m.fullpath) ? self._filter(m.fullpath, s[i]) :
self._url(m.path, s[i], group.base || m.base);
if (m.attributes || m.async === false) {
url = {
url: url,
async: m.async
};
if (m.attributes) {
url.attributes = m.attributes;
}
}
resolved[m.type].push(url);
resolved[m.type + 'Mods'].push(m);
} else {
}
};
len = s.length;
// the default combo base
comboBase = self.comboBase;
url = comboBase;
comboSources = {};
for (i = 0; i < len; i++) {
comboSource = comboBase;
m = self.getModule(s[i]);
groupName = m && m.group;
group = self.groups[groupName];
if (groupName && group) {
if (!group.combine || m.fullpath) {
//This is not a combo module, skip it and load it singly later.
addSingle(m);
continue;
}
m.combine = true;
if (group.comboBase) {
comboSource = group.comboBase;
}
if ("root" in group && L.isValue(group.root)) {
m.root = group.root;
}
m.comboSep = group.comboSep || self.comboSep;
m.maxURLLength = group.maxURLLength || self.maxURLLength;
} else {
if (!self.combine) {
//This is not a combo module, skip it and load it singly later.
addSingle(m);
continue;
}
}
comboSources[comboSource] = comboSources[comboSource] || [];
comboSources[comboSource].push(m);
}
for (j in comboSources) {
if (comboSources.hasOwnProperty(j)) {
resCombos[j] = resCombos[j] || { js: [], jsMods: [], css: [], cssMods: [] };
url = j;
mods = comboSources[j];
len = mods.length;
if (len) {
for (i = 0; i < len; i++) {
if (inserted[mods[i]]) {
continue;
}
m = mods[i];
// Do not try to combine non-yui JS unless combo def
// is found
if (m && (m.combine || !m.ext)) {
resCombos[j].comboSep = m.comboSep;
resCombos[j].group = m.group;
resCombos[j].maxURLLength = m.maxURLLength;
frag = ((L.isValue(m.root)) ? m.root : self.root) + (m.path || m.fullpath);
frag = self._filter(frag, m.name);
resCombos[j][m.type].push(frag);
resCombos[j][m.type + 'Mods'].push(m);
} else {
//Add them to the next process..
if (mods[i]) {
addSingle(mods[i]);
}
}
}
}
}
}
for (j in resCombos) {
if (resCombos.hasOwnProperty(j)) {
base = j;
comboSep = resCombos[base].comboSep || self.comboSep;
maxURLLength = resCombos[base].maxURLLength || self.maxURLLength;
for (type in resCombos[base]) {
if (type === JS || type === CSS) {
urls = resCombos[base][type];
mods = resCombos[base][type + 'Mods'];
len = urls.length;
tmpBase = base + urls.join(comboSep);
baseLen = tmpBase.length;
if (maxURLLength <= base.length) {
maxURLLength = MAX_URL_LENGTH;
}
if (len) {
if (baseLen > maxURLLength) {
u = [];
for (s = 0; s < len; s++) {
u.push(urls[s]);
tmpBase = base + u.join(comboSep);
if (tmpBase.length > maxURLLength) {
m = u.pop();
tmpBase = base + u.join(comboSep);
resolved[type].push(self._filter(tmpBase, null, resCombos[base].group));
u = [];
if (m) {
u.push(m);
}
}
}
if (u.length) {
tmpBase = base + u.join(comboSep);
resolved[type].push(self._filter(tmpBase, null, resCombos[base].group));
}
} else {
resolved[type].push(self._filter(tmpBase, null, resCombos[base].group));
}
}
resolved[type + 'Mods'] = resolved[type + 'Mods'].concat(mods);
}
}
}
}
resCombos = null;
return resolved;
},
/**
Shortcut to calculate, resolve and load all modules.
var loader = new Y.Loader({
ignoreRegistered: true,
modules: {
mod: {
path: 'mod.js'
}
},
requires: [ 'mod' ]
});
loader.load(function() {
console.log('All modules have loaded..');
});
@method load
@param {Callback} cb Executed after all load operations are complete
*/
load: function(cb) {
if (!cb) {
return;
}
var self = this,
out = self.resolve(true);
self.data = out;
self.onEnd = function() {
cb.apply(self.context || self, arguments);
};
self.insert();
}
};
}, '3.9.1', {"requires": ["get", "features"]});
YUI.add('loader-rollup', function (Y, NAME) {
/**
* Optional automatic rollup logic for reducing http connections
* when not using a combo service.
* @module loader
* @submodule rollup
*/
/**
* Look for rollup packages to determine if all of the modules a
* rollup supersedes are required. If so, include the rollup to
* help reduce the total number of connections required. Called
* by calculate(). This is an optional feature, and requires the
* appropriate submodule to function.
* @method _rollup
* @for Loader
* @private
*/
Y.Loader.prototype._rollup = function() {
var i, j, m, s, r = this.required, roll,
info = this.moduleInfo, rolled, c, smod;
// find and cache rollup modules
if (this.dirty || !this.rollups) {
this.rollups = {};
for (i in info) {
if (info.hasOwnProperty(i)) {
m = this.getModule(i);
// if (m && m.rollup && m.supersedes) {
if (m && m.rollup) {
this.rollups[i] = m;
}
}
}
}
// make as many passes as needed to pick up rollup rollups
for (;;) {
rolled = false;
// go through the rollup candidates
for (i in this.rollups) {
if (this.rollups.hasOwnProperty(i)) {
// there can be only one, unless forced
if (!r[i] && ((!this.loaded[i]) || this.forceMap[i])) {
m = this.getModule(i);
s = m.supersedes || [];
roll = false;
// @TODO remove continue
if (!m.rollup) {
continue;
}
c = 0;
// check the threshold
for (j = 0; j < s.length; j++) {
smod = info[s[j]];
// if the superseded module is loaded, we can't
// load the rollup unless it has been forced.
if (this.loaded[s[j]] && !this.forceMap[s[j]]) {
roll = false;
break;
// increment the counter if this module is required.
// if we are beyond the rollup threshold, we will
// use the rollup module
} else if (r[s[j]] && m.type === smod.type) {
c++;
roll = (c >= 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;
}
}
};
}, '3.9.1', {"requires": ["loader-base"]});
YUI.add('loader-yui3', function (Y, NAME) {
/* This file is auto-generated by (yogi loader --yes --mix --start ../) */
/*jshint maxlen:900, eqeqeq: false */
/**
* YUI 3 module metadata
* @module loader
* @submodule loader-yui3
*/
YUI.Env[Y.version].modules = YUI.Env[Y.version].modules || {};
Y.mix(YUI.Env[Y.version].modules, {
"align-plugin": {
"requires": [
"node-screen",
"node-pluginhost"
]
},
"anim": {
"use": [
"anim-base",
"anim-color",
"anim-curve",
"anim-easing",
"anim-node-plugin",
"anim-scroll",
"anim-xy"
]
},
"anim-base": {
"requires": [
"base-base",
"node-style"
]
},
"anim-color": {
"requires": [
"anim-base"
]
},
"anim-curve": {
"requires": [
"anim-xy"
]
},
"anim-easing": {
"requires": [
"anim-base"
]
},
"anim-node-plugin": {
"requires": [
"node-pluginhost",
"anim-base"
]
},
"anim-scroll": {
"requires": [
"anim-base"
]
},
"anim-shape": {
"requires": [
"anim-base",
"anim-easing",
"anim-color",
"matrix"
]
},
"anim-shape-transform": {
"use": [
"anim-shape"
]
},
"anim-xy": {
"requires": [
"anim-base",
"node-screen"
]
},
"app": {
"use": [
"app-base",
"app-content",
"app-transitions",
"lazy-model-list",
"model",
"model-list",
"model-sync-rest",
"router",
"view",
"view-node-map"
]
},
"app-base": {
"requires": [
"classnamemanager",
"pjax-base",
"router",
"view"
]
},
"app-content": {
"requires": [
"app-base",
"pjax-content"
]
},
"app-transitions": {
"requires": [
"app-base"
]
},
"app-transitions-css": {
"type": "css"
},
"app-transitions-native": {
"condition": {
"name": "app-transitions-native",
"test": function (Y) {
var doc = Y.config.doc,
node = doc ? doc.documentElement : null;
if (node && node.style) {
return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
}
return false;
},
"trigger": "app-transitions"
},
"requires": [
"app-transitions",
"app-transitions-css",
"parallel",
"transition"
]
},
"array-extras": {
"requires": [
"yui-base"
]
},
"array-invoke": {
"requires": [
"yui-base"
]
},
"arraylist": {
"requires": [
"yui-base"
]
},
"arraylist-add": {
"requires": [
"arraylist"
]
},
"arraylist-filter": {
"requires": [
"arraylist"
]
},
"arraysort": {
"requires": [
"yui-base"
]
},
"async-queue": {
"requires": [
"event-custom"
]
},
"attribute": {
"use": [
"attribute-base",
"attribute-complex"
]
},
"attribute-base": {
"requires": [
"attribute-core",
"attribute-observable",
"attribute-extras"
]
},
"attribute-complex": {
"requires": [
"attribute-base"
]
},
"attribute-core": {
"requires": [
"oop"
]
},
"attribute-events": {
"use": [
"attribute-observable"
]
},
"attribute-extras": {
"requires": [
"oop"
]
},
"attribute-observable": {
"requires": [
"event-custom"
]
},
"autocomplete": {
"use": [
"autocomplete-base",
"autocomplete-sources",
"autocomplete-list",
"autocomplete-plugin"
]
},
"autocomplete-base": {
"optional": [
"autocomplete-sources"
],
"requires": [
"array-extras",
"base-build",
"escape",
"event-valuechange",
"node-base"
]
},
"autocomplete-filters": {
"requires": [
"array-extras",
"text-wordbreak"
]
},
"autocomplete-filters-accentfold": {
"requires": [
"array-extras",
"text-accentfold",
"text-wordbreak"
]
},
"autocomplete-highlighters": {
"requires": [
"array-extras",
"highlight-base"
]
},
"autocomplete-highlighters-accentfold": {
"requires": [
"array-extras",
"highlight-accentfold"
]
},
"autocomplete-list": {
"after": [
"autocomplete-sources"
],
"lang": [
"en",
"es"
],
"requires": [
"autocomplete-base",
"event-resize",
"node-screen",
"selector-css3",
"shim-plugin",
"widget",
"widget-position",
"widget-position-align"
],
"skinnable": true
},
"autocomplete-list-keys": {
"condition": {
"name": "autocomplete-list-keys",
"test": function (Y) {
// Only add keyboard support to autocomplete-list if this doesn't appear to
// be an iOS or Android-based mobile device.
//
// There's currently no feasible way to actually detect whether a device has
// a hardware keyboard, so this sniff will have to do. It can easily be
// overridden by manually loading the autocomplete-list-keys module.
//
// Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
// doesn't fire the keyboard events used by AutoCompleteList, so there's
// no point loading the -keys module even when a bluetooth keyboard may be
// available.
return !(Y.UA.ios || Y.UA.android);
},
"trigger": "autocomplete-list"
},
"requires": [
"autocomplete-list",
"base-build"
]
},
"autocomplete-plugin": {
"requires": [
"autocomplete-list",
"node-pluginhost"
]
},
"autocomplete-sources": {
"optional": [
"io-base",
"json-parse",
"jsonp",
"yql"
],
"requires": [
"autocomplete-base"
]
},
"axes": {
"use": [
"axis-numeric",
"axis-category",
"axis-time",
"axis-stacked"
]
},
"axes-base": {
"use": [
"axis-numeric-base",
"axis-category-base",
"axis-time-base",
"axis-stacked-base"
]
},
"axis": {
"requires": [
"dom",
"widget",
"widget-position",
"widget-stack",
"graphics",
"axis-base"
]
},
"axis-base": {
"requires": [
"classnamemanager",
"datatype-number",
"datatype-date",
"base",
"event-custom"
]
},
"axis-category": {
"requires": [
"axis",
"axis-category-base"
]
},
"axis-category-base": {
"requires": [
"axis-base"
]
},
"axis-numeric": {
"requires": [
"axis",
"axis-numeric-base"
]
},
"axis-numeric-base": {
"requires": [
"axis-base"
]
},
"axis-stacked": {
"requires": [
"axis-numeric",
"axis-stacked-base"
]
},
"axis-stacked-base": {
"requires": [
"axis-numeric-base"
]
},
"axis-time": {
"requires": [
"axis",
"axis-time-base"
]
},
"axis-time-base": {
"requires": [
"axis-base"
]
},
"base": {
"use": [
"base-base",
"base-pluginhost",
"base-build"
]
},
"base-base": {
"requires": [
"attribute-base",
"base-core",
"base-observable"
]
},
"base-build": {
"requires": [
"base-base"
]
},
"base-core": {
"requires": [
"attribute-core"
]
},
"base-observable": {
"requires": [
"attribute-observable"
]
},
"base-pluginhost": {
"requires": [
"base-base",
"pluginhost"
]
},
"button": {
"requires": [
"button-core",
"cssbutton",
"widget"
]
},
"button-core": {
"requires": [
"attribute-core",
"classnamemanager",
"node-base"
]
},
"button-group": {
"requires": [
"button-plugin",
"cssbutton",
"widget"
]
},
"button-plugin": {
"requires": [
"button-core",
"cssbutton",
"node-pluginhost"
]
},
"cache": {
"use": [
"cache-base",
"cache-offline",
"cache-plugin"
]
},
"cache-base": {
"requires": [
"base"
]
},
"cache-offline": {
"requires": [
"cache-base",
"json"
]
},
"cache-plugin": {
"requires": [
"plugin",
"cache-base"
]
},
"calendar": {
"lang": [
"de",
"en",
"es",
"es-AR",
"fr",
"it",
"ja",
"nb-NO",
"nl",
"pt-BR",
"ru",
"zh-HANT-TW"
],
"requires": [
"calendar-base",
"calendarnavigator"
],
"skinnable": true
},
"calendar-base": {
"lang": [
"de",
"en",
"es",
"es-AR",
"fr",
"it",
"ja",
"nb-NO",
"nl",
"pt-BR",
"ru",
"zh-HANT-TW"
],
"requires": [
"widget",
"datatype-date",
"datatype-date-math",
"cssgrids"
],
"skinnable": true
},
"calendarnavigator": {
"requires": [
"plugin",
"classnamemanager",
"datatype-date",
"node"
],
"skinnable": true
},
"charts": {
"use": [
"charts-base"
]
},
"charts-base": {
"requires": [
"dom",
"event-mouseenter",
"event-touch",
"graphics-group",
"axes",
"series-pie",
"series-line",
"series-marker",
"series-area",
"series-spline",
"series-column",
"series-bar",
"series-areaspline",
"series-combo",
"series-combospline",
"series-line-stacked",
"series-marker-stacked",
"series-area-stacked",
"series-spline-stacked",
"series-column-stacked",
"series-bar-stacked",
"series-areaspline-stacked",
"series-combo-stacked",
"series-combospline-stacked"
]
},
"charts-legend": {
"requires": [
"charts-base"
]
},
"classnamemanager": {
"requires": [
"yui-base"
]
},
"clickable-rail": {
"requires": [
"slider-base"
]
},
"collection": {
"use": [
"array-extras",
"arraylist",
"arraylist-add",
"arraylist-filter",
"array-invoke"
]
},
"color": {
"use": [
"color-base",
"color-hsl",
"color-harmony"
]
},
"color-base": {
"requires": [
"yui-base"
]
},
"color-harmony": {
"requires": [
"color-hsl"
]
},
"color-hsl": {
"requires": [
"color-base"
]
},
"color-hsv": {
"requires": [
"color-base"
]
},
"console": {
"lang": [
"en",
"es",
"ja"
],
"requires": [
"yui-log",
"widget"
],
"skinnable": true
},
"console-filters": {
"requires": [
"plugin",
"console"
],
"skinnable": true
},
"controller": {
"use": [
"router"
]
},
"cookie": {
"requires": [
"yui-base"
]
},
"createlink-base": {
"requires": [
"editor-base"
]
},
"cssbase": {
"after": [
"cssreset",
"cssfonts",
"cssgrids",
"cssreset-context",
"cssfonts-context",
"cssgrids-context"
],
"type": "css"
},
"cssbase-context": {
"after": [
"cssreset",
"cssfonts",
"cssgrids",
"cssreset-context",
"cssfonts-context",
"cssgrids-context"
],
"type": "css"
},
"cssbutton": {
"type": "css"
},
"cssfonts": {
"type": "css"
},
"cssfonts-context": {
"type": "css"
},
"cssgrids": {
"optional": [
"cssreset",
"cssfonts"
],
"type": "css"
},
"cssgrids-base": {
"optional": [
"cssreset",
"cssfonts"
],
"type": "css"
},
"cssgrids-responsive": {
"optional": [
"cssreset",
"cssfonts"
],
"requires": [
"cssgrids",
"cssgrids-responsive-base"
],
"type": "css"
},
"cssgrids-units": {
"optional": [
"cssreset",
"cssfonts"
],
"requires": [
"cssgrids-base"
],
"type": "css"
},
"cssnormalize": {
"type": "css"
},
"cssnormalize-context": {
"type": "css"
},
"cssreset": {
"type": "css"
},
"cssreset-context": {
"type": "css"
},
"dataschema": {
"use": [
"dataschema-base",
"dataschema-json",
"dataschema-xml",
"dataschema-array",
"dataschema-text"
]
},
"dataschema-array": {
"requires": [
"dataschema-base"
]
},
"dataschema-base": {
"requires": [
"base"
]
},
"dataschema-json": {
"requires": [
"dataschema-base",
"json"
]
},
"dataschema-text": {
"requires": [
"dataschema-base"
]
},
"dataschema-xml": {
"requires": [
"dataschema-base"
]
},
"datasource": {
"use": [
"datasource-local",
"datasource-io",
"datasource-get",
"datasource-function",
"datasource-cache",
"datasource-jsonschema",
"datasource-xmlschema",
"datasource-arrayschema",
"datasource-textschema",
"datasource-polling"
]
},
"datasource-arrayschema": {
"requires": [
"datasource-local",
"plugin",
"dataschema-array"
]
},
"datasource-cache": {
"requires": [
"datasource-local",
"plugin",
"cache-base"
]
},
"datasource-function": {
"requires": [
"datasource-local"
]
},
"datasource-get": {
"requires": [
"datasource-local",
"get"
]
},
"datasource-io": {
"requires": [
"datasource-local",
"io-base"
]
},
"datasource-jsonschema": {
"requires": [
"datasource-local",
"plugin",
"dataschema-json"
]
},
"datasource-local": {
"requires": [
"base"
]
},
"datasource-polling": {
"requires": [
"datasource-local"
]
},
"datasource-textschema": {
"requires": [
"datasource-local",
"plugin",
"dataschema-text"
]
},
"datasource-xmlschema": {
"requires": [
"datasource-local",
"plugin",
"datatype-xml",
"dataschema-xml"
]
},
"datatable": {
"use": [
"datatable-core",
"datatable-table",
"datatable-head",
"datatable-body",
"datatable-base",
"datatable-column-widths",
"datatable-message",
"datatable-mutable",
"datatable-sort",
"datatable-datasource"
]
},
"datatable-base": {
"requires": [
"datatable-core",
"datatable-table",
"datatable-head",
"datatable-body",
"base-build",
"widget"
],
"skinnable": true
},
"datatable-body": {
"requires": [
"datatable-core",
"view",
"classnamemanager"
]
},
"datatable-column-widths": {
"requires": [
"datatable-base"
]
},
"datatable-core": {
"requires": [
"escape",
"model-list",
"node-event-delegate"
]
},
"datatable-datasource": {
"requires": [
"datatable-base",
"plugin",
"datasource-local"
]
},
"datatable-formatters": {
"requires": [
"datatable-body",
"datatype-number-format",
"datatype-date-format",
"escape"
]
},
"datatable-head": {
"requires": [
"datatable-core",
"view",
"classnamemanager"
]
},
"datatable-message": {
"lang": [
"en",
"fr",
"es"
],
"requires": [
"datatable-base"
],
"skinnable": true
},
"datatable-mutable": {
"requires": [
"datatable-base"
]
},
"datatable-scroll": {
"requires": [
"datatable-base",
"datatable-column-widths",
"dom-screen"
],
"skinnable": true
},
"datatable-sort": {
"lang": [
"en",
"fr",
"es"
],
"requires": [
"datatable-base"
],
"skinnable": true
},
"datatable-table": {
"requires": [
"datatable-core",
"datatable-head",
"datatable-body",
"view",
"classnamemanager"
]
},
"datatype": {
"use": [
"datatype-date",
"datatype-number",
"datatype-xml"
]
},
"datatype-date": {
"use": [
"datatype-date-parse",
"datatype-date-format",
"datatype-date-math"
]
},
"datatype-date-format": {
"lang": [
"ar",
"ar-JO",
"ca",
"ca-ES",
"da",
"da-DK",
"de",
"de-AT",
"de-DE",
"el",
"el-GR",
"en",
"en-AU",
"en-CA",
"en-GB",
"en-IE",
"en-IN",
"en-JO",
"en-MY",
"en-NZ",
"en-PH",
"en-SG",
"en-US",
"es",
"es-AR",
"es-BO",
"es-CL",
"es-CO",
"es-EC",
"es-ES",
"es-MX",
"es-PE",
"es-PY",
"es-US",
"es-UY",
"es-VE",
"fi",
"fi-FI",
"fr",
"fr-BE",
"fr-CA",
"fr-FR",
"hi",
"hi-IN",
"id",
"id-ID",
"it",
"it-IT",
"ja",
"ja-JP",
"ko",
"ko-KR",
"ms",
"ms-MY",
"nb",
"nb-NO",
"nl",
"nl-BE",
"nl-NL",
"pl",
"pl-PL",
"pt",
"pt-BR",
"ro",
"ro-RO",
"ru",
"ru-RU",
"sv",
"sv-SE",
"th",
"th-TH",
"tr",
"tr-TR",
"vi",
"vi-VN",
"zh-Hans",
"zh-Hans-CN",
"zh-Hant",
"zh-Hant-HK",
"zh-Hant-TW"
]
},
"datatype-date-math": {
"requires": [
"yui-base"
]
},
"datatype-date-parse": {},
"datatype-number": {
"use": [
"datatype-number-parse",
"datatype-number-format"
]
},
"datatype-number-format": {},
"datatype-number-parse": {},
"datatype-xml": {
"use": [
"datatype-xml-parse",
"datatype-xml-format"
]
},
"datatype-xml-format": {},
"datatype-xml-parse": {},
"dd": {
"use": [
"dd-ddm-base",
"dd-ddm",
"dd-ddm-drop",
"dd-drag",
"dd-proxy",
"dd-constrain",
"dd-drop",
"dd-scroll",
"dd-delegate"
]
},
"dd-constrain": {
"requires": [
"dd-drag"
]
},
"dd-ddm": {
"requires": [
"dd-ddm-base",
"event-resize"
]
},
"dd-ddm-base": {
"requires": [
"node",
"base",
"yui-throttle",
"classnamemanager"
]
},
"dd-ddm-drop": {
"requires": [
"dd-ddm"
]
},
"dd-delegate": {
"requires": [
"dd-drag",
"dd-drop-plugin",
"event-mouseenter"
]
},
"dd-drag": {
"requires": [
"dd-ddm-base"
]
},
"dd-drop": {
"requires": [
"dd-drag",
"dd-ddm-drop"
]
},
"dd-drop-plugin": {
"requires": [
"dd-drop"
]
},
"dd-gestures": {
"condition": {
"name": "dd-gestures",
"trigger": "dd-drag",
"ua": "touchEnabled"
},
"requires": [
"dd-drag",
"event-synthetic",
"event-gestures"
]
},
"dd-plugin": {
"optional": [
"dd-constrain",
"dd-proxy"
],
"requires": [
"dd-drag"
]
},
"dd-proxy": {
"requires": [
"dd-drag"
]
},
"dd-scroll": {
"requires": [
"dd-drag"
]
},
"dial": {
"lang": [
"en",
"es"
],
"requires": [
"widget",
"dd-drag",
"event-mouseenter",
"event-move",
"event-key",
"transition",
"intl"
],
"skinnable": true
},
"dom": {
"use": [
"dom-base",
"dom-screen",
"dom-style",
"selector-native",
"selector"
]
},
"dom-base": {
"requires": [
"dom-core"
]
},
"dom-core": {
"requires": [
"oop",
"features"
]
},
"dom-deprecated": {
"requires": [
"dom-base"
]
},
"dom-screen": {
"requires": [
"dom-base",
"dom-style"
]
},
"dom-style": {
"requires": [
"dom-base"
]
},
"dom-style-ie": {
"condition": {
"name": "dom-style-ie",
"test": function (Y) {
var testFeature = Y.Features.test,
addFeature = Y.Features.add,
WINDOW = Y.config.win,
DOCUMENT = Y.config.doc,
DOCUMENT_ELEMENT = 'documentElement',
ret = false;
addFeature('style', 'computedStyle', {
test: function() {
return WINDOW && 'getComputedStyle' in WINDOW;
}
});
addFeature('style', 'opacity', {
test: function() {
return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
}
});
ret = (!testFeature('style', 'opacity') &&
!testFeature('style', 'computedStyle'));
return ret;
},
"trigger": "dom-style"
},
"requires": [
"dom-style"
]
},
"dump": {
"requires": [
"yui-base"
]
},
"editor": {
"use": [
"frame",
"editor-selection",
"exec-command",
"editor-base",
"editor-para",
"editor-br",
"editor-bidi",
"editor-tab",
"createlink-base"
]
},
"editor-base": {
"requires": [
"base",
"frame",
"node",
"exec-command",
"editor-selection"
]
},
"editor-bidi": {
"requires": [
"editor-base"
]
},
"editor-br": {
"requires": [
"editor-base"
]
},
"editor-lists": {
"requires": [
"editor-base"
]
},
"editor-para": {
"requires": [
"editor-para-base"
]
},
"editor-para-base": {
"requires": [
"editor-base"
]
},
"editor-para-ie": {
"condition": {
"name": "editor-para-ie",
"trigger": "editor-para",
"ua": "ie",
"when": "instead"
},
"requires": [
"editor-para-base"
]
},
"editor-selection": {
"requires": [
"node"
]
},
"editor-tab": {
"requires": [
"editor-base"
]
},
"escape": {
"requires": [
"yui-base"
]
},
"event": {
"after": [
"node-base"
],
"use": [
"event-base",
"event-delegate",
"event-synthetic",
"event-mousewheel",
"event-mouseenter",
"event-key",
"event-focus",
"event-resize",
"event-hover",
"event-outside",
"event-touch",
"event-move",
"event-flick",
"event-valuechange",
"event-tap"
]
},
"event-base": {
"after": [
"node-base"
],
"requires": [
"event-custom-base"
]
},
"event-base-ie": {
"after": [
"event-base"
],
"condition": {
"name": "event-base-ie",
"test": function(Y) {
var imp = Y.config.doc && Y.config.doc.implementation;
return (imp && (!imp.hasFeature('Events', '2.0')));
},
"trigger": "node-base"
},
"requires": [
"node-base"
]
},
"event-contextmenu": {
"requires": [
"event-synthetic",
"dom-screen"
]
},
"event-custom": {
"use": [
"event-custom-base",
"event-custom-complex"
]
},
"event-custom-base": {
"requires": [
"oop"
]
},
"event-custom-complex": {
"requires": [
"event-custom-base"
]
},
"event-delegate": {
"requires": [
"node-base"
]
},
"event-flick": {
"requires": [
"node-base",
"event-touch",
"event-synthetic"
]
},
"event-focus": {
"requires": [
"event-synthetic"
]
},
"event-gestures": {
"use": [
"event-flick",
"event-move"
]
},
"event-hover": {
"requires": [
"event-mouseenter"
]
},
"event-key": {
"requires": [
"event-synthetic"
]
},
"event-mouseenter": {
"requires": [
"event-synthetic"
]
},
"event-mousewheel": {
"requires": [
"node-base"
]
},
"event-move": {
"requires": [
"node-base",
"event-touch",
"event-synthetic"
]
},
"event-outside": {
"requires": [
"event-synthetic"
]
},
"event-resize": {
"requires": [
"node-base",
"event-synthetic"
]
},
"event-simulate": {
"requires": [
"event-base"
]
},
"event-synthetic": {
"requires": [
"node-base",
"event-custom-complex"
]
},
"event-tap": {
"requires": [
"node-base",
"event-base",
"event-touch",
"event-synthetic"
]
},
"event-touch": {
"requires": [
"node-base"
]
},
"event-valuechange": {
"requires": [
"event-focus",
"event-synthetic"
]
},
"exec-command": {
"requires": [
"frame"
]
},
"features": {
"requires": [
"yui-base"
]
},
"file": {
"requires": [
"file-flash",
"file-html5"
]
},
"file-flash": {
"requires": [
"base"
]
},
"file-html5": {
"requires": [
"base"
]
},
"frame": {
"requires": [
"base",
"node",
"selector-css3",
"yui-throttle"
]
},
"gesture-simulate": {
"requires": [
"async-queue",
"event-simulate",
"node-screen"
]
},
"get": {
"requires": [
"yui-base"
]
},
"graphics": {
"requires": [
"node",
"event-custom",
"pluginhost",
"matrix",
"classnamemanager"
]
},
"graphics-canvas": {
"condition": {
"name": "graphics-canvas",
"test": function(Y) {
var DOCUMENT = Y.config.doc,
useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
},
"trigger": "graphics"
},
"requires": [
"graphics"
]
},
"graphics-canvas-default": {
"condition": {
"name": "graphics-canvas-default",
"test": function(Y) {
var DOCUMENT = Y.config.doc,
useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
},
"trigger": "graphics"
}
},
"graphics-group": {
"requires": [
"graphics"
]
},
"graphics-svg": {
"condition": {
"name": "graphics-svg",
"test": function(Y) {
var DOCUMENT = Y.config.doc,
useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
return svg && (useSVG || !canvas);
},
"trigger": "graphics"
},
"requires": [
"graphics"
]
},
"graphics-svg-default": {
"condition": {
"name": "graphics-svg-default",
"test": function(Y) {
var DOCUMENT = Y.config.doc,
useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
return svg && (useSVG || !canvas);
},
"trigger": "graphics"
}
},
"graphics-vml": {
"condition": {
"name": "graphics-vml",
"test": function(Y) {
var DOCUMENT = Y.config.doc,
canvas = DOCUMENT && DOCUMENT.createElement("canvas");
return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
},
"trigger": "graphics"
},
"requires": [
"graphics"
]
},
"graphics-vml-default": {
"condition": {
"name": "graphics-vml-default",
"test": function(Y) {
var DOCUMENT = Y.config.doc,
canvas = DOCUMENT && DOCUMENT.createElement("canvas");
return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
},
"trigger": "graphics"
}
},
"handlebars": {
"use": [
"handlebars-compiler"
]
},
"handlebars-base": {
"requires": []
},
"handlebars-compiler": {
"requires": [
"handlebars-base"
]
},
"highlight": {
"use": [
"highlight-base",
"highlight-accentfold"
]
},
"highlight-accentfold": {
"requires": [
"highlight-base",
"text-accentfold"
]
},
"highlight-base": {
"requires": [
"array-extras",
"classnamemanager",
"escape",
"text-wordbreak"
]
},
"history": {
"use": [
"history-base",
"history-hash",
"history-hash-ie",
"history-html5"
]
},
"history-base": {
"requires": [
"event-custom-complex"
]
},
"history-hash": {
"after": [
"history-html5"
],
"requires": [
"event-synthetic",
"history-base",
"yui-later"
]
},
"history-hash-ie": {
"condition": {
"name": "history-hash-ie",
"test": function (Y) {
var docMode = Y.config.doc && Y.config.doc.documentMode;
return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
!docMode || docMode < 8);
},
"trigger": "history-hash"
},
"requires": [
"history-hash",
"node-base"
]
},
"history-html5": {
"optional": [
"json"
],
"requires": [
"event-base",
"history-base",
"node-base"
]
},
"imageloader": {
"requires": [
"base-base",
"node-style",
"node-screen"
]
},
"intl": {
"requires": [
"intl-base",
"event-custom"
]
},
"intl-base": {
"requires": [
"yui-base"
]
},
"io": {
"use": [
"io-base",
"io-xdr",
"io-form",
"io-upload-iframe",
"io-queue"
]
},
"io-base": {
"requires": [
"event-custom-base",
"querystring-stringify-simple"
]
},
"io-form": {
"requires": [
"io-base",
"node-base"
]
},
"io-nodejs": {
"condition": {
"name": "io-nodejs",
"trigger": "io-base",
"ua": "nodejs"
},
"requires": [
"io-base"
]
},
"io-queue": {
"requires": [
"io-base",
"queue-promote"
]
},
"io-upload-iframe": {
"requires": [
"io-base",
"node-base"
]
},
"io-xdr": {
"requires": [
"io-base",
"datatype-xml-parse"
]
},
"json": {
"use": [
"json-parse",
"json-stringify"
]
},
"json-parse": {
"requires": [
"yui-base"
]
},
"json-parse-shim": {
"condition": {
"name": "json-parse-shim",
"test": function (Y) {
var _JSON = Y.config.global.JSON,
Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
nativeSupport = Y.config.useNativeJSONParse !== false && !!Native;
function workingNative( k, v ) {
return k === "ok" ? true : v;
}
// Double check basic functionality. This is mainly to catch early broken
// implementations of the JSON API in Firefox 3.1 beta1 and beta2
if ( nativeSupport ) {
try {
nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
}
catch ( e ) {
nativeSupport = false;
}
}
return !nativeSupport;
},
"trigger": "json-parse"
},
"requires": [
"json-parse"
]
},
"json-stringify": {
"requires": [
"yui-base"
]
},
"json-stringify-shim": {
"condition": {
"name": "json-stringify-shim",
"test": function (Y) {
var _JSON = Y.config.global.JSON,
Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native;
// Double check basic native functionality. This is primarily to catch broken
// early JSON API implementations in Firefox 3.1 beta1 and beta2.
if ( nativeSupport ) {
try {
nativeSupport = ( '0' === Native.stringify(0) );
} catch ( e ) {
nativeSupport = false;
}
}
return !nativeSupport;
},
"trigger": "json-stringify"
},
"requires": [
"json-stringify"
]
},
"jsonp": {
"requires": [
"get",
"oop"
]
},
"jsonp-url": {
"requires": [
"jsonp"
]
},
"lazy-model-list": {
"requires": [
"model-list"
]
},
"loader": {
"use": [
"loader-base",
"loader-rollup",
"loader-yui3"
]
},
"loader-base": {
"requires": [
"get",
"features"
]
},
"loader-rollup": {
"requires": [
"loader-base"
]
},
"loader-yui3": {
"requires": [
"loader-base"
]
},
"matrix": {
"requires": [
"yui-base"
]
},
"model": {
"requires": [
"base-build",
"escape",
"json-parse"
]
},
"model-list": {
"requires": [
"array-extras",
"array-invoke",
"arraylist",
"base-build",
"escape",
"json-parse",
"model"
]
},
"model-sync-rest": {
"requires": [
"model",
"io-base",
"json-stringify"
]
},
"node": {
"use": [
"node-base",
"node-event-delegate",
"node-pluginhost",
"node-screen",
"node-style"
]
},
"node-base": {
"requires": [
"event-base",
"node-core",
"dom-base"
]
},
"node-core": {
"requires": [
"dom-core",
"selector"
]
},
"node-deprecated": {
"requires": [
"node-base"
]
},
"node-event-delegate": {
"requires": [
"node-base",
"event-delegate"
]
},
"node-event-html5": {
"requires": [
"node-base"
]
},
"node-event-simulate": {
"requires": [
"node-base",
"event-simulate",
"gesture-simulate"
]
},
"node-flick": {
"requires": [
"classnamemanager",
"transition",
"event-flick",
"plugin"
],
"skinnable": true
},
"node-focusmanager": {
"requires": [
"attribute",
"node",
"plugin",
"node-event-simulate",
"event-key",
"event-focus"
]
},
"node-load": {
"requires": [
"node-base",
"io-base"
]
},
"node-menunav": {
"requires": [
"node",
"classnamemanager",
"plugin",
"node-focusmanager"
],
"skinnable": true
},
"node-pluginhost": {
"requires": [
"node-base",
"pluginhost"
]
},
"node-screen": {
"requires": [
"dom-screen",
"node-base"
]
},
"node-scroll-info": {
"requires": [
"base-build",
"dom-screen",
"event-resize",
"node-pluginhost",
"plugin"
]
},
"node-style": {
"requires": [
"dom-style",
"node-base"
]
},
"oop": {
"requires": [
"yui-base"
]
},
"overlay": {
"requires": [
"widget",
"widget-stdmod",
"widget-position",
"widget-position-align",
"widget-stack",
"widget-position-constrain"
],
"skinnable": true
},
"panel": {
"requires": [
"widget",
"widget-autohide",
"widget-buttons",
"widget-modality",
"widget-position",
"widget-position-align",
"widget-position-constrain",
"widget-stack",
"widget-stdmod"
],
"skinnable": true
},
"parallel": {
"requires": [
"yui-base"
]
},
"pjax": {
"requires": [
"pjax-base",
"pjax-content"
]
},
"pjax-base": {
"requires": [
"classnamemanager",
"node-event-delegate",
"router"
]
},
"pjax-content": {
"requires": [
"io-base",
"node-base",
"router"
]
},
"pjax-plugin": {
"requires": [
"node-pluginhost",
"pjax",
"plugin"
]
},
"plugin": {
"requires": [
"base-base"
]
},
"pluginhost": {
"use": [
"pluginhost-base",
"pluginhost-config"
]
},
"pluginhost-base": {
"requires": [
"yui-base"
]
},
"pluginhost-config": {
"requires": [
"pluginhost-base"
]
},
"profiler": {
"requires": [
"yui-base"
]
},
"promise": {
"requires": [
"timers"
]
},
"querystring": {
"use": [
"querystring-parse",
"querystring-stringify"
]
},
"querystring-parse": {
"requires": [
"yui-base",
"array-extras"
]
},
"querystring-parse-simple": {
"requires": [
"yui-base"
]
},
"querystring-stringify": {
"requires": [
"yui-base"
]
},
"querystring-stringify-simple": {
"requires": [
"yui-base"
]
},
"queue-promote": {
"requires": [
"yui-base"
]
},
"range-slider": {
"requires": [
"slider-base",
"slider-value-range",
"clickable-rail"
]
},
"recordset": {
"use": [
"recordset-base",
"recordset-sort",
"recordset-filter",
"recordset-indexer"
]
},
"recordset-base": {
"requires": [
"base",
"arraylist"
]
},
"recordset-filter": {
"requires": [
"recordset-base",
"array-extras",
"plugin"
]
},
"recordset-indexer": {
"requires": [
"recordset-base",
"plugin"
]
},
"recordset-sort": {
"requires": [
"arraysort",
"recordset-base",
"plugin"
]
},
"resize": {
"use": [
"resize-base",
"resize-proxy",
"resize-constrain"
]
},
"resize-base": {
"requires": [
"base",
"widget",
"event",
"oop",
"dd-drag",
"dd-delegate",
"dd-drop"
],
"skinnable": true
},
"resize-constrain": {
"requires": [
"plugin",
"resize-base"
]
},
"resize-plugin": {
"optional": [
"resize-constrain"
],
"requires": [
"resize-base",
"plugin"
]
},
"resize-proxy": {
"requires": [
"plugin",
"resize-base"
]
},
"router": {
"optional": [
"querystring-parse"
],
"requires": [
"array-extras",
"base-build",
"history"
]
},
"scrollview": {
"requires": [
"scrollview-base",
"scrollview-scrollbars"
]
},
"scrollview-base": {
"requires": [
"widget",
"event-gestures",
"event-mousewheel",
"transition"
],
"skinnable": true
},
"scrollview-base-ie": {
"condition": {
"name": "scrollview-base-ie",
"trigger": "scrollview-base",
"ua": "ie"
},
"requires": [
"scrollview-base"
]
},
"scrollview-list": {
"requires": [
"plugin",
"classnamemanager"
],
"skinnable": true
},
"scrollview-paginator": {
"requires": [
"plugin",
"classnamemanager"
]
},
"scrollview-scrollbars": {
"requires": [
"classnamemanager",
"transition",
"plugin"
],
"skinnable": true
},
"selector": {
"requires": [
"selector-native"
]
},
"selector-css2": {
"condition": {
"name": "selector-css2",
"test": function (Y) {
var DOCUMENT = Y.config.doc,
ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
return ret;
},
"trigger": "selector"
},
"requires": [
"selector-native"
]
},
"selector-css3": {
"requires": [
"selector-native",
"selector-css2"
]
},
"selector-native": {
"requires": [
"dom-base"
]
},
"series-area": {
"requires": [
"series-cartesian",
"series-fill-util"
]
},
"series-area-stacked": {
"requires": [
"series-stacked",
"series-area"
]
},
"series-areaspline": {
"requires": [
"series-area",
"series-curve-util"
]
},
"series-areaspline-stacked": {
"requires": [
"series-stacked",
"series-areaspline"
]
},
"series-bar": {
"requires": [
"series-marker",
"series-histogram-base"
]
},
"series-bar-stacked": {
"requires": [
"series-stacked",
"series-bar"
]
},
"series-base": {
"requires": [
"graphics",
"axis-base"
]
},
"series-candlestick": {
"requires": [
"series-range"
]
},
"series-cartesian": {
"requires": [
"series-base"
]
},
"series-column": {
"requires": [
"series-marker",
"series-histogram-base"
]
},
"series-column-stacked": {
"requires": [
"series-stacked",
"series-column"
]
},
"series-combo": {
"requires": [
"series-cartesian",
"series-line-util",
"series-plot-util",
"series-fill-util"
]
},
"series-combo-stacked": {
"requires": [
"series-stacked",
"series-combo"
]
},
"series-combospline": {
"requires": [
"series-combo",
"series-curve-util"
]
},
"series-combospline-stacked": {
"requires": [
"series-combo-stacked",
"series-curve-util"
]
},
"series-curve-util": {},
"series-fill-util": {},
"series-histogram-base": {
"requires": [
"series-cartesian",
"series-plot-util"
]
},
"series-line": {
"requires": [
"series-cartesian",
"series-line-util"
]
},
"series-line-stacked": {
"requires": [
"series-stacked",
"series-line"
]
},
"series-line-util": {},
"series-marker": {
"requires": [
"series-cartesian",
"series-plot-util"
]
},
"series-marker-stacked": {
"requires": [
"series-stacked",
"series-marker"
]
},
"series-ohlc": {
"requires": [
"series-range"
]
},
"series-pie": {
"requires": [
"series-base",
"series-plot-util"
]
},
"series-plot-util": {},
"series-range": {
"requires": [
"series-cartesian"
]
},
"series-spline": {
"requires": [
"series-line",
"series-curve-util"
]
},
"series-spline-stacked": {
"requires": [
"series-stacked",
"series-spline"
]
},
"series-stacked": {
"requires": [
"axis-stacked"
]
},
"shim-plugin": {
"requires": [
"node-style",
"node-pluginhost"
]
},
"slider": {
"use": [
"slider-base",
"slider-value-range",
"clickable-rail",
"range-slider"
]
},
"slider-base": {
"requires": [
"widget",
"dd-constrain",
"event-key"
],
"skinnable": true
},
"slider-value-range": {
"requires": [
"slider-base"
]
},
"sortable": {
"requires": [
"dd-delegate",
"dd-drop-plugin",
"dd-proxy"
]
},
"sortable-scroll": {
"requires": [
"dd-scroll",
"sortable"
]
},
"stylesheet": {
"requires": [
"yui-base"
]
},
"substitute": {
"optional": [
"dump"
],
"requires": [
"yui-base"
]
},
"swf": {
"requires": [
"event-custom",
"node",
"swfdetect",
"escape"
]
},
"swfdetect": {
"requires": [
"yui-base"
]
},
"tabview": {
"requires": [
"widget",
"widget-parent",
"widget-child",
"tabview-base",
"node-pluginhost",
"node-focusmanager"
],
"skinnable": true
},
"tabview-base": {
"requires": [
"node-event-delegate",
"classnamemanager",
"skin-sam-tabview"
]
},
"tabview-plugin": {
"requires": [
"tabview-base"
]
},
"template": {
"use": [
"template-base",
"template-micro"
]
},
"template-base": {
"requires": [
"yui-base"
]
},
"template-micro": {
"requires": [
"escape"
]
},
"test": {
"requires": [
"event-simulate",
"event-custom",
"json-stringify"
]
},
"test-console": {
"requires": [
"console-filters",
"test",
"array-extras"
],
"skinnable": true
},
"text": {
"use": [
"text-accentfold",
"text-wordbreak"
]
},
"text-accentfold": {
"requires": [
"array-extras",
"text-data-accentfold"
]
},
"text-data-accentfold": {
"requires": [
"yui-base"
]
},
"text-data-wordbreak": {
"requires": [
"yui-base"
]
},
"text-wordbreak": {
"requires": [
"array-extras",
"text-data-wordbreak"
]
},
"timers": {
"requires": [
"yui-base"
]
},
"transition": {
"requires": [
"node-style"
]
},
"transition-timer": {
"condition": {
"name": "transition-timer",
"test": function (Y) {
var DOCUMENT = Y.config.doc,
node = (DOCUMENT) ? DOCUMENT.documentElement: null,
ret = true;
if (node && node.style) {
ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
}
return ret;
},
"trigger": "transition"
},
"requires": [
"transition"
]
},
"tree": {
"requires": [
"base-build",
"tree-node"
]
},
"tree-labelable": {
"requires": [
"tree"
]
},
"tree-lazy": {
"requires": [
"base-pluginhost",
"plugin",
"tree"
]
},
"tree-node": {},
"tree-openable": {
"requires": [
"tree"
]
},
"tree-selectable": {
"requires": [
"tree"
]
},
"uploader": {
"requires": [
"uploader-html5",
"uploader-flash"
]
},
"uploader-flash": {
"requires": [
"swf",
"widget",
"base",
"cssbutton",
"node",
"event-custom",
"file-flash",
"uploader-queue"
]
},
"uploader-html5": {
"requires": [
"widget",
"node-event-simulate",
"file-html5",
"uploader-queue"
]
},
"uploader-queue": {
"requires": [
"base"
]
},
"view": {
"requires": [
"base-build",
"node-event-delegate"
]
},
"view-node-map": {
"requires": [
"view"
]
},
"widget": {
"use": [
"widget-base",
"widget-htmlparser",
"widget-skin",
"widget-uievents"
]
},
"widget-anim": {
"requires": [
"anim-base",
"plugin",
"widget"
]
},
"widget-autohide": {
"requires": [
"base-build",
"event-key",
"event-outside",
"widget"
]
},
"widget-base": {
"requires": [
"attribute",
"base-base",
"base-pluginhost",
"classnamemanager",
"event-focus",
"node-base",
"node-style"
],
"skinnable": true
},
"widget-base-ie": {
"condition": {
"name": "widget-base-ie",
"trigger": "widget-base",
"ua": "ie"
},
"requires": [
"widget-base"
]
},
"widget-buttons": {
"requires": [
"button-plugin",
"cssbutton",
"widget-stdmod"
]
},
"widget-child": {
"requires": [
"base-build",
"widget"
]
},
"widget-htmlparser": {
"requires": [
"widget-base"
]
},
"widget-locale": {
"requires": [
"widget-base"
]
},
"widget-modality": {
"requires": [
"base-build",
"event-outside",
"widget"
],
"skinnable": true
},
"widget-parent": {
"requires": [
"arraylist",
"base-build",
"widget"
]
},
"widget-position": {
"requires": [
"base-build",
"node-screen",
"widget"
]
},
"widget-position-align": {
"requires": [
"widget-position"
]
},
"widget-position-constrain": {
"requires": [
"widget-position"
]
},
"widget-skin": {
"requires": [
"widget-base"
]
},
"widget-stack": {
"requires": [
"base-build",
"widget"
],
"skinnable": true
},
"widget-stdmod": {
"requires": [
"base-build",
"widget"
]
},
"widget-uievents": {
"requires": [
"node-event-delegate",
"widget-base"
]
},
"yql": {
"requires": [
"oop"
]
},
"yql-jsonp": {
"condition": {
"name": "yql-jsonp",
"test": function (Y) {
/* Only load the JSONP module when not in nodejs or winjs
TODO Make the winjs module a CORS module
*/
return (!Y.UA.nodejs && !Y.UA.winjs);
},
"trigger": "yql",
"when": "after"
},
"requires": [
"jsonp",
"jsonp-url"
]
},
"yql-nodejs": {
"condition": {
"name": "yql-nodejs",
"trigger": "yql",
"ua": "nodejs",
"when": "after"
}
},
"yql-winjs": {
"condition": {
"name": "yql-winjs",
"trigger": "yql",
"ua": "winjs",
"when": "after"
}
},
"yui": {},
"yui-base": {},
"yui-later": {
"requires": [
"yui-base"
]
},
"yui-log": {
"requires": [
"yui-base"
]
},
"yui-throttle": {
"requires": [
"yui-base"
]
}
});
YUI.Env[Y.version].md5 = '660f328e92276f36e9abfafb02169183';
}, '3.9.1', {"requires": ["loader-base"]});
YUI.add('loader', function (Y, NAME) {}, '3.9.1', {"use": ["loader-base", "loader-rollup", "loader-yui3"]});