/* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html version: 3.3.0 build: 3167 */ /** * The YUI module contains the components required for building the YUI seed * file. This includes the script loading mechanism, a simple queue, and * the core utilities for the library. * @module yui * @submodule yui-base */ if (typeof YUI != 'undefined') { YUI._YUI = YUI; } /** * The YUI global namespace object. If YUI is already defined, the * existing YUI object will not be overwritten so that defined * namespaces are preserved. It is the constructor for the object * the end user interacts with. As indicated below, each instance * has full custom event support, but only if the event system * is available. This is a self-instantiable factory function. You * can invoke it directly like this: * * YUI().use('*', function(Y) { * // ready * }); * * But it also works like this: * * var Y = YUI(); * * @class YUI * @constructor * @global * @uses EventTarget * @param o* {object} 0..n optional configuration objects. these values * are store in Y.config. See config for the list of supported * properties. */ /*global YUI*/ /*global YUI_config*/ var YUI = function() { var i = 0, Y = this, args = arguments, l = args.length, instanceOf = function(o, type) { return (o && o.hasOwnProperty && (o instanceof type)); }, gconf = (typeof YUI_config !== 'undefined') && YUI_config; if (!(instanceOf(Y, YUI))) { Y = new YUI(); } else { // set up the core environment Y._init(); // YUI.GlobalConfig is a master configuration that might span // multiple contexts in a non-browser environment. It is applied // first to all instances in all contexts. if (YUI.GlobalConfig) { Y.applyConfig(YUI.GlobalConfig); } // YUI_Config is a page-level config. It is applied to all // instances created on the page. This is applied after // YUI.GlobalConfig, and before the instance level configuration // objects. if (gconf) { Y.applyConfig(gconf); } // bind the specified additional modules for this instance if (!l) { Y._setup(); } } if (l) { // Each instance can accept one or more configuration objects. // These are applied after YUI.GlobalConfig and YUI_Config, // overriding values set in those config files if there is a ' // matching property. for (; i < l; i++) { Y.applyConfig(args[i]); } Y._setup(); } Y.instanceOf = instanceOf; return Y; }; (function() { var proto, prop, VERSION = '3.3.0', PERIOD = '.', BASE = 'http://yui.yahooapis.com/', DOC_LABEL = 'yui3-js-enabled', NOOP = function() {}, SLICE = Array.prototype.slice, APPLY_TO_AUTH = { 'io.xdrReady': 1, // the functions applyTo 'io.xdrResponse': 1, // can call. this should 'SWF.eventHandler': 1 }, // be done at build time hasWin = (typeof window != 'undefined'), win = (hasWin) ? window : null, doc = (hasWin) ? win.document : null, docEl = doc && doc.documentElement, docClass = docEl && docEl.className, instances = {}, time = new Date().getTime(), add = function(el, type, fn, capture) { if (el && el.addEventListener) { el.addEventListener(type, fn, capture); } else if (el && el.attachEvent) { el.attachEvent('on' + type, fn); } }, remove = function(el, type, fn, capture) { if (el && el.removeEventListener) { // this can throw an uncaught exception in FF try { el.removeEventListener(type, fn, capture); } catch (ex) {} } else if (el && el.detachEvent) { el.detachEvent('on' + type, fn); } }, handleLoad = function() { YUI.Env.windowLoaded = true; YUI.Env.DOMReady = true; if (hasWin) { remove(window, 'load', handleLoad); } }, getLoader = function(Y, o) { var loader = Y.Env._loader; if (loader) { loader.ignoreRegistered = false; loader.onEnd = null; loader.data = null; loader.required = []; loader.loadType = null; } else { loader = new Y.Loader(Y.config); Y.Env._loader = loader; } return loader; }, clobber = function(r, s) { for (var i in s) { if (s.hasOwnProperty(i)) { r[i] = s[i]; } } }, ALREADY_DONE = { success: true }; // Stamp the documentElement (HTML) with a class of "yui-loaded" to // enable styles that need to key off of JS being enabled. if (docEl && docClass.indexOf(DOC_LABEL) == -1) { if (docClass) { docClass += ' '; } docClass += DOC_LABEL; docEl.className = docClass; } if (VERSION.indexOf('@') > -1) { VERSION = '3.2.0'; // dev time hack for cdn test } proto = { /** * Applies a new configuration object to the YUI instance config. * This will merge new group/module definitions, and will also * update the loader cache if necessary. Updating Y.config directly * will not update the cache. * @method applyConfig * @param {object} the configuration object. * @since 3.2.0 */ applyConfig: function(o) { o = o || NOOP; var attr, name, // detail, config = this.config, mods = config.modules, groups = config.groups, rls = config.rls, loader = this.Env._loader; for (name in o) { if (o.hasOwnProperty(name)) { attr = o[name]; if (mods && name == 'modules') { clobber(mods, attr); } else if (groups && name == 'groups') { clobber(groups, attr); } else if (rls && name == 'rls') { clobber(rls, attr); } else if (name == 'win') { config[name] = attr.contentWindow || attr; config.doc = config[name].document; } else if (name == '_yuid') { // preserve the guid } else { config[name] = attr; } } } if (loader) { loader._config(o); } }, _config: function(o) { this.applyConfig(o); }, /** * Initialize this YUI instance * @private */ _init: function() { var filter, Y = this, G_ENV = YUI.Env, Env = Y.Env, prop; /** * The version number of the YUI instance. * @property version * @type string */ Y.version = VERSION; if (!Env) { Y.Env = { mods: {}, // flat module map versions: {}, // version module map base: BASE, cdn: BASE + VERSION + '/build/', // bootstrapped: false, _idx: 0, _used: {}, _attached: {}, _yidx: 0, _uidx: 0, _guidp: 'y', _loaded: {}, serviced: {}, getBase: G_ENV && G_ENV.getBase || function(srcPattern, comboPattern) { var b, nodes, i, src, match; // get from querystring nodes = (doc && doc.getElementsByTagName('script')) || []; for (i = 0; i < nodes.length; i = i + 1) { src = nodes[i].src; if (src) { match = src.match(srcPattern); b = match && match[1]; if (b) { // this is to set up the path to the loader. The file // filter for loader should match the yui include. filter = match[2]; if (filter) { match = filter.indexOf('js'); if (match > -1) { filter = filter.substr(0, match); } } // extract correct path for mixed combo urls // http://yuilibrary.com/projects/yui3/ticket/2528423 match = src.match(comboPattern); if (match && match[3]) { b = match[1] + match[3]; } break; } } } // use CDN default return b || Env.cdn; } }; Env = Y.Env; Env._loaded[VERSION] = {}; if (G_ENV && Y !== YUI) { Env._yidx = ++G_ENV._yidx; Env._guidp = ('yui_' + VERSION + '_' + Env._yidx + '_' + time).replace(/\./g, '_'); } else if (YUI._YUI) { G_ENV = YUI._YUI.Env; Env._yidx += G_ENV._yidx; Env._uidx += G_ENV._uidx; for (prop in G_ENV) { if (!(prop in Env)) { Env[prop] = G_ENV[prop]; } } delete YUI._YUI; } Y.id = Y.stamp(Y); instances[Y.id] = Y; } Y.constructor = YUI; // configuration defaults Y.config = Y.config || { win: win, doc: doc, debug: true, useBrowserConsole: true, throwFail: true, bootstrap: true, cacheUse: true, fetchCSS: true }; Y.config.base = YUI.config.base || Y.Env.getBase(/^(.*)yui\/yui([\.\-].*)js(\?.*)?$/, /^(.*\?)(.*\&)(.*)yui\/yui[\.\-].*js(\?.*)?$/); if (!filter || (!('-min.-debug.').indexOf(filter))) { filter = '-min.'; } Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + (filter || '-min.') + 'js'; }, /** * Finishes the instance setup. Attaches whatever modules were defined * when the yui modules was registered. * @method _setup * @private */ _setup: function(o) { var i, Y = this, core = [], mods = YUI.Env.mods, extras = Y.config.core || ['get', 'rls', 'intl-base', 'loader', 'yui-log', 'yui-later', 'yui-throttle']; for (i = 0; i < extras.length; i++) { if (mods[extras[i]]) { core.push(extras[i]); } } Y._attach(['yui-base']); Y._attach(core); }, /** * Executes a method on a YUI instance with * the specified id if the specified method is whitelisted. * @method applyTo * @param id {string} the YUI instance id. * @param method {string} the name of the method to exectute. * Ex: 'Object.keys'. * @param args {Array} the arguments to apply to the method. * @return {object} the return value from the applied method or null. */ applyTo: function(id, method, args) { if (!(method in APPLY_TO_AUTH)) { this.log(method + ': applyTo not allowed', 'warn', 'yui'); return null; } var instance = instances[id], nest, m, i; if (instance) { nest = method.split('.'); m = instance; for (i = 0; i < nest.length; i = i + 1) { m = m[nest[i]]; if (!m) { this.log('applyTo not found: ' + method, 'warn', 'yui'); } } return m.apply(instance, args); } return null; }, /** * Registers a module with the YUI global. The easiest way to create a * first-class YUI module is to use the YUI component build tool. * * http://yuilibrary.com/projects/builder * * The build system will produce the YUI.add wrapper for you module, along * with any configuration info required for the module. * @method add * @param name {string} module name. * @param fn {Function} entry point into the module that * is used to bind module to the YUI instance. * @param version {string} version string. * @param details {object} optional config data: * requires: features that must be present before this module can be * attached. * optional: optional features that should be present if loadOptional * is defined. Note: modules are not often loaded this way in YUI 3, * but this field is still useful to inform the user that certain * features in the component will require additional dependencies. * use: features that are included within this module which need to * be attached automatically when this module is attached. This * supports the YUI 3 rollup system -- a module with submodules * defined will need to have the submodules listed in the 'use' * config. The YUI component build tool does this for you. * @return {YUI} the YUI instance. * */ add: function(name, fn, version, details) { details = details || {}; var env = YUI.Env, mod = { name: name, fn: fn, version: version, details: details }, loader, i, versions = env.versions; env.mods[name] = mod; versions[version] = versions[version] || {}; versions[version][name] = mod; for (i in instances) { if (instances.hasOwnProperty(i)) { loader = instances[i].Env._loader; if (loader) { if (!loader.moduleInfo[name]) { loader.addModule(details, name); } } } } return this; }, /** * Executes the function associated with each required * module, binding the module to the YUI instance. * @method _attach * @private */ _attach: function(r, fromLoader) { var i, name, mod, details, req, use, after, mods = YUI.Env.mods, Y = this, j, done = Y.Env._attached, len = r.length, loader; for (i = 0; i < len; i++) { if (!done[r[i]]) { name = r[i]; mod = mods[name]; if (!mod) { loader = Y.Env._loader; if (!loader || !loader.moduleInfo[name]) { Y.message('NOT loaded: ' + name, 'warn', 'yui'); } } else { done[name] = true; details = mod.details; req = details.requires; use = details.use; after = details.after; if (req) { for (j = 0; j < req.length; j++) { if (!done[req[j]]) { if (!Y._attach(req)) { return false; } break; } } } if (after) { for (j = 0; j < after.length; j++) { if (!done[after[j]]) { if (!Y._attach(after)) { return false; } break; } } } if (use) { for (j = 0; j < use.length; j++) { if (!done[use[j]]) { if (!Y._attach(use)) { return false; } break; } } } if (mod.fn) { try { mod.fn(Y, name); } catch (e) { Y.error('Attach error: ' + name, e, name); return false; } } } } } return true; }, /** * Attaches one or more modules to the YUI instance. When this * is executed, the requirements are analyzed, and one of * several things can happen: * * - All requirements are available on the page -- The modules * are attached to the instance. If supplied, the use callback * is executed synchronously. * * - Modules are missing, the Get utility is not available OR * the 'bootstrap' config is false -- A warning is issued about * the missing modules and all available modules are attached. * * - Modules are missing, the Loader is not available but the Get * utility is and boostrap is not false -- The loader is bootstrapped * before doing the following.... * * - Modules are missing and the Loader is available -- The loader * expands the dependency tree and fetches missing modules. When * the loader is finshed the callback supplied to use is executed * asynchronously. * * @param modules* {string} 1-n modules to bind (uses arguments array). * @param *callback {function} callback function executed when * the instance has the required functionality. If included, it * must be the last parameter. * * // loads and attaches drag and drop and its dependencies * YUI().use('dd', function(Y) {}); * // attaches all modules that are available on the page * YUI().use('*', function(Y) {}); * // intrinsic YUI gallery support (since 3.1.0) * YUI().use('gallery-yql', function(Y) {}); * // intrinsic YUI 2in3 support (since 3.1.0) * YUI().use('yui2-datatable', function(Y) {});. * * * @return {YUI} the YUI instance. */ use: function() { var args = SLICE.call(arguments, 0), callback = args[args.length - 1], Y = this, key; // The last argument supplied to use can be a load complete callback if (Y.Lang.isFunction(callback)) { args.pop(); } else { callback = null; } if (Y._loading) { Y._useQueue = Y._useQueue || new Y.Queue(); Y._useQueue.add([args, callback]); } else { key = args.join(); if (Y.config.cacheUse && Y.Env.serviced[key]) { Y._notify(callback, ALREADY_DONE, args); } else { Y._use(args, function(Y, response) { if (Y.config.cacheUse) { Y.Env.serviced[key] = true; } Y._notify(callback, response, args); }); } } return Y; }, _notify: function(callback, response, args) { if (!response.success && this.config.loadErrorFn) { this.config.loadErrorFn.call(this, this, callback, response, args); } else if (callback) { try { callback(this, response); } catch (e) { this.error('use callback error', e, args); } } }, _use: function(args, callback) { if (!this.Array) { this._attach(['yui-base']); } var len, loader, handleBoot, Y = this, G_ENV = YUI.Env, mods = G_ENV.mods, Env = Y.Env, used = Env._used, queue = G_ENV._loaderQueue, firstArg = args[0], YArray = Y.Array, config = Y.config, boot = config.bootstrap, missing = [], r = [], ret = true, fetchCSS = config.fetchCSS, process = function(names, skip) { if (!names.length) { return; } YArray.each(names, function(name) { // add this module to full list of things to attach if (!skip) { r.push(name); } // only attach a module once if (used[name]) { return; } var m = mods[name], req, use; if (m) { used[name] = true; req = m.details.requires; use = m.details.use; } else { // CSS files don't register themselves, see if it has // been loaded if (!G_ENV._loaded[VERSION][name]) { missing.push(name); } else { used[name] = true; // probably css } } // make sure requirements are attached if (req && req.length) { process(req); } // make sure we grab the submodule dependencies too if (use && use.length) { process(use, 1); } }); }, handleLoader = function(fromLoader) { var response = fromLoader || { success: true, msg: 'not dynamic' }, redo, origMissing, ret = true, data = response.data; Y._loading = false; if (data) { origMissing = missing; missing = []; r = []; process(data); redo = missing.length; if (redo) { if (missing.sort().join() == origMissing.sort().join()) { redo = false; } } } if (redo && data) { Y._loading = false; Y._use(args, function() { if (Y._attach(data)) { Y._notify(callback, response, data); } }); } else { if (data) { ret = Y._attach(data); } if (ret) { Y._notify(callback, response, args); } } if (Y._useQueue && Y._useQueue.size() && !Y._loading) { Y._use.apply(Y, Y._useQueue.next()); } }; // YUI().use('*'); // bind everything available if (firstArg === '*') { ret = Y._attach(Y.Object.keys(mods)); if (ret) { handleLoader(); } return Y; } // use loader to expand dependencies and sort the // requirements if it is available. if (boot && Y.Loader && args.length) { loader = getLoader(Y); loader.require(args); loader.ignoreRegistered = true; loader.calculate(null, (fetchCSS) ? null : 'js'); args = loader.sorted; } // process each requirement and any additional requirements // the module metadata specifies process(args); len = missing.length; if (len) { missing = Y.Object.keys(YArray.hash(missing)); len = missing.length; } // dynamic load if (boot && len && Y.Loader) { Y._loading = true; loader = getLoader(Y); loader.onEnd = handleLoader; loader.context = Y; loader.data = args; loader.ignoreRegistered = false; loader.require(args); loader.insert(null, (fetchCSS) ? null : 'js'); // loader.partial(missing, (fetchCSS) ? null : 'js'); } else if (len && Y.config.use_rls) { // server side loader service Y.Get.script(Y._rls(args), { onEnd: function(o) { handleLoader(o); }, data: args }); } else if (boot && len && Y.Get && !Env.bootstrapped) { Y._loading = true; handleBoot = function() { Y._loading = false; queue.running = false; Env.bootstrapped = true; if (Y._attach(['loader'])) { Y._use(args, callback); } }; if (G_ENV._bootstrapping) { queue.add(handleBoot); } else { G_ENV._bootstrapping = true; Y.Get.script(config.base + config.loaderPath, { onEnd: handleBoot }); } } else { ret = Y._attach(args); if (ret) { handleLoader(); } } return Y; }, /** * Returns the namespace specified and creates it if it doesn't exist *
     * YUI.namespace("property.package");
     * YUI.namespace("YAHOO.property.package");
     * 
* Either of the above would create YUI.property, then * YUI.property.package (YAHOO is scrubbed out, this is * to remain compatible with YUI2) * * Be careful when naming packages. Reserved words may work in some browsers * and not others. For instance, the following will fail in Safari: *
     * YUI.namespace("really.long.nested.namespace");
     * 
* This fails because "long" is a future reserved word in ECMAScript * * @method namespace * @param {string*} arguments 1-n namespaces to create. * @return {object} A reference to the last namespace object created. */ namespace: function() { var a = arguments, o = this, i = 0, j, d, arg; for (; i < a.length; i++) { // d = ('' + a[i]).split('.'); arg = a[i]; if (arg.indexOf(PERIOD)) { d = arg.split(PERIOD); for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) { o[d[j]] = o[d[j]] || {}; o = o[d[j]]; } } else { o[arg] = o[arg] || {}; } } return o; }, // this is replaced if the log module is included log: NOOP, message: NOOP, /** * Report an error. The reporting mechanism is controled by * the 'throwFail' configuration attribute. If throwFail is * not specified, the message is written to the Logger, otherwise * a JS error is thrown * @method error * @param msg {string} the error message. * @param e {Error|string} Optional JS error that was caught, or an error string. * @param data Optional additional info * and throwFail is specified, this error will be re-thrown. * @return {YUI} this YUI instance. */ error: function(msg, e, data) { var Y = this, ret; if (Y.config.errorFn) { ret = Y.config.errorFn.apply(Y, arguments); } if (Y.config.throwFail && !ret) { throw (e || new Error(msg)); } else { Y.message(msg, 'error'); // don't scrub this one } return Y; }, /** * Generate an id that is unique among all YUI instances * @method guid * @param pre {string} optional guid prefix. * @return {string} the guid. */ guid: function(pre) { var id = this.Env._guidp + (++this.Env._uidx); return (pre) ? (pre + id) : id; }, /** * Returns a guid associated with an object. If the object * does not have one, a new one is created unless readOnly * is specified. * @method stamp * @param o The object to stamp. * @param readOnly {boolean} if true, a valid guid will only * be returned if the object has one assigned to it. * @return {string} The object's guid or null. */ stamp: function(o, readOnly) { var uid; if (!o) { return o; } // IE generates its own unique ID for dom nodes // The uniqueID property of a document node returns a new ID if (o.uniqueID && o.nodeType && o.nodeType !== 9) { uid = o.uniqueID; } else { uid = (typeof o === 'string') ? o : o._yuid; } if (!uid) { uid = this.guid(); if (!readOnly) { try { o._yuid = uid; } catch (e) { uid = null; } } } return uid; }, /** * Destroys the YUI instance * @method destroy * @since 3.3.0 */ destroy: function() { var Y = this; if (Y.Event) { Y.Event._unload(); } delete instances[Y.id]; delete Y.Env; delete Y.config; } /** * instanceof check for objects that works around * memory leak in IE when the item tested is * window/document * @method instanceOf * @since 3.3.0 */ }; YUI.prototype = proto; // inheritance utilities are not available yet for (prop in proto) { if (proto.hasOwnProperty(prop)) { YUI[prop] = proto[prop]; } } // set up the environment YUI._init(); if (hasWin) { // add a window load event at load time so we can capture // the case where it fires before dynamic loading is // complete. add(window, 'load', handleLoad); } else { handleLoad(); } YUI.Env.add = add; YUI.Env.remove = remove; /*global exports*/ // Support the CommonJS method for exporting our single global if (typeof exports == 'object') { exports.YUI = YUI; } }()); /** * The config object contains all of the configuration options for * the YUI instance. This object is supplied by the implementer * when instantiating a YUI instance. Some properties have default * values if they are not supplied by the implementer. This should * not be updated directly because some values are cached. Use * applyConfig() to update the config object on a YUI instance that * has already been configured. * * @class config * @static */ /** * Allows the YUI seed file to fetch the loader component and library * metadata to dynamically load additional dependencies. * * @property bootstrap * @type boolean * @default true */ /** * Log to the browser console if debug is on and the browser has a * supported console. * * @property useBrowserConsole * @type boolean * @default true */ /** * A hash of log sources that should be logged. If specified, only * log messages from these sources will be logged. * * @property logInclude * @type object */ /** * A hash of log sources that should be not be logged. If specified, * all sources are logged if not on this list. * * @property logExclude * @type object */ /** * Set to true if the yui seed file was dynamically loaded in * order to bootstrap components relying on the window load event * and the 'domready' custom event. * * @property injected * @type boolean * @default false */ /** * If throwFail is set, Y.error will generate or re-throw a JS Error. * Otherwise the failure is logged. * * @property throwFail * @type boolean * @default true */ /** * The window/frame that this instance should operate in. * * @property win * @type Window * @default the window hosting YUI */ /** * The document associated with the 'win' configuration. * * @property doc * @type Document * @default the document hosting YUI */ /** * A list of modules that defines the YUI core (overrides the default). * * @property core * @type string[] */ /** * A list of languages in order of preference. This list is matched against * the list of available languages in modules that the YUI instance uses to * determine the best possible localization of language sensitive modules. * Languages are represented using BCP 47 language tags, such as "en-GB" for * English as used in the United Kingdom, or "zh-Hans-CN" for simplified * Chinese as used in China. The list can be provided as a comma-separated * list or as an array. * * @property lang * @type string|string[] */ /** * The default date format * @property dateFormat * @type string * @deprecated use configuration in DataType.Date.format() instead. */ /** * The default locale * @property locale * @type string * @deprecated use config.lang instead. */ /** * The default interval when polling in milliseconds. * @property pollInterval * @type int * @default 20 */ /** * The number of dynamic nodes to insert by default before * automatically removing them. This applies to script nodes * because remove the node will not make the evaluated script * unavailable. Dynamic CSS is not auto purged, because removing * a linked style sheet will also remove the style definitions. * @property purgethreshold * @type int * @default 20 */ /** * The default interval when polling in milliseconds. * @property windowResizeDelay * @type int * @default 40 */ /** * Base directory for dynamic loading * @property base * @type string */ /* * The secure base dir (not implemented) * For dynamic loading. * @property secureBase * @type string */ /** * The YUI combo service base dir. Ex: http://yui.yahooapis.com/combo? * For dynamic loading. * @property comboBase * @type string */ /** * The root path to prepend to module path for the combo service. * Ex: 3.0.0b1/build/ * For dynamic loading. * @property root * @type string */ /** * 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"
 *  }
 * 
* * For dynamic loading. * * @property filter * @type string|object */ /** * The 'skin' config let's you configure application level skin * customizations. It contains the following attributes which * can be specified to override the defaults: * * // 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. * 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: { * slider: ['capsule', 'round'] * } * * For dynamic loading. * * @property skin */ /** * Hash of per-component filter specification. If specified for a given * component, this overrides the filter config. * * For dynamic loading. * * @property filters */ /** * Use the YUI combo service to reduce the number of http connections * required to load your dependencies. Turning this off will * disable combo handling for YUI and all module groups configured * with a combo service. * * For dynamic loading. * * @property combine * @type boolean * @default true if 'base' is not supplied, false if it is. */ /** * A list of modules that should never be dynamically loaded * * @property ignore * @type string[] */ /** * A list of modules that should always be loaded when required, even if already * present on the page. * * @property force * @type string[] */ /** * Node or id for a node that should be used as the insertion point for new * nodes. For dynamic loading. * * @property insertBefore * @type string */ /** * Object literal containing attributes to add to dynamically loaded script * nodes. * @property jsAttributes * @type string */ /** * Object literal containing attributes to add to dynamically loaded link * nodes. * @property cssAttributes * @type string */ /** * Number of milliseconds before a timeout occurs when dynamically * loading nodes. If not set, there is no timeout. * @property timeout * @type int */ /** * Callback for the 'CSSComplete' event. When dynamically loading YUI * components with CSS, this property fires when the CSS is finished * loading but script loading is still ongoing. This provides an * opportunity to enhance the presentation of a loading page a little * bit before the entire loading process is done. * * @property onCSS * @type function */ /** * A hash of module definitions to add to the list of YUI components. * These components can then be dynamically loaded side by side with * YUI via the use() method. This is a hash, the key is the module * name, and the value is an object literal specifying the metdata * for the module. * See Loader.addModule for the supported module * metadata fields. Also @see groups, which provides a way to * configure the base and combo spec for a set of modules. * * modules: { *   mymod1: { *   requires: ['node'], *   fullpath: 'http://myserver.mydomain.com/mymod1/mymod1.js' *   }, *   mymod2: { *   requires: ['mymod1'], *   fullpath: 'http://myserver.mydomain.com/mymod2/mymod2.js' *   } * } * * * @property modules * @type object */ /** * A hash of module group definitions. It for each group you * can specify a list of modules and the base path and * combo spec to use when dynamically loading the modules. @see * @see modules for the details about the modules part of the * group definition. * *   groups: { *   yui2: { *   // specify whether or not this group has a combo service *   combine: true, *   *   // the base path for non-combo paths *   base: 'http://yui.yahooapis.com/2.8.0r4/build/', *   *   // the path to the combo service *   comboBase: 'http://yui.yahooapis.com/combo?', *   *   // a fragment to prepend to the path attribute when *   // when building combo urls *   root: '2.8.0r4/build/', *   *   // the module definitions *   modules: { *   yui2_yde: { *   path: "yahoo-dom-event/yahoo-dom-event.js" *   }, *   yui2_anim: { *   path: "animation/animation.js", *   requires: ['yui2_yde'] *   } *   } *   } *   } * * @property modules * @type object */ /** * The loader 'path' attribute to the loader itself. This is combined * with the 'base' attribute to dynamically load the loader component * when boostrapping with the get utility alone. * * @property loaderPath * @type string * @default loader/loader-min.js */ /** * Specifies whether or not YUI().use(...) will attempt to load CSS * resources at all. Any truthy value will cause CSS dependencies * to load when fetching script. The special value 'force' will * cause CSS dependencies to be loaded even if no script is needed. * * @property fetchCSS * @type boolean|string * @default true */ /** * The default gallery version to build gallery module urls * @property gallery * @type string * @since 3.1.0 */ /** * The default YUI 2 version to build yui2 module urls. This is for * intrinsic YUI 2 support via the 2in3 project. Also @see the '2in3' * config for pulling different revisions of the wrapped YUI 2 * modules. * @since 3.1.0 * @property yui2 * @type string * @default 2.8.1 */ /** * The 2in3 project is a deployment of the various versions of YUI 2 * deployed as first-class YUI 3 modules. Eventually, the wrapper * for the modules will change (but the underlying YUI 2 code will * be the same), and you can select a particular version of * the wrapper modules via this config. * @since 3.1.0 * @property 2in3 * @type string * @default 1 */ /** * Alternative console log function for use in environments without * a supported native console. The function is executed in the * YUI instance context. * @since 3.1.0 * @property logFn * @type Function */ /** * A callback to execute when Y.error is called. It receives the * error message and an javascript error object if Y.error was * executed because a javascript error was caught. The function * is executed in the YUI instance context. * * @since 3.2.0 * @property errorFn * @type Function */ /** * A callback to execute when the loader fails to load one or * more resource. This could be because of a script load * failure. It can also fail if a javascript module fails * to register itself, but only when the 'requireRegistration' * is true. If this function is defined, the use() callback will * only be called when the loader succeeds, otherwise it always * executes unless there was a javascript error when attaching * a module. * * @since 3.3.0 * @property loadErrorFn * @type Function */ /** * When set to true, the YUI loader will expect that all modules * it is responsible for loading will be first-class YUI modules * that register themselves with the YUI global. If this is * set to true, loader will fail if the module registration fails * to happen after the script is loaded. * * @since 3.3.0 * @property requireRegistration * @type boolean * @default false */ /** * Cache serviced use() requests. * @since 3.3.0 * @property cacheUse * @type boolean * @default true */ /** * The parameter defaults for the remote loader service. * Requires the rls submodule. The properties that are * supported: *
 * m: comma separated list of module requirements.  This
 *    must be the param name even for custom implemetations.
 * v: the version of YUI to load.  Defaults to the version
 *    of YUI that is being used.
 * gv: the version of the gallery to load (@see the gallery config)
 * env: comma separated list of modules already on the page.
 *      this must be the param name even for custom implemetations.
 * lang: the languages supported on the page (@see the lang config)
 * '2in3v':  the version of the 2in3 wrapper to use (@see the 2in3 config).
 * '2v': the version of yui2 to use in the yui 2in3 wrappers
 *       (@see the yui2 config)
 * filt: a filter def to apply to the urls (@see the filter config).
 * filts: a list of custom filters to apply per module
 *        (@see the filters config).
 * tests: this is a map of conditional module test function id keys
 * with the values of 1 if the test passes, 0 if not.  This must be
 * the name of the querystring param in custom templates.
 *
* * @since 3.2.0 * @property rls */ /** * The base path to the remote loader service * * @since 3.2.0 * @property rls_base */ /** * The template to use for building the querystring portion * of the remote loader service url. The default is determined * by the rls config -- each property that has a value will be * represented. * * ex: m={m}&v={v}&env={env}&lang={lang}&filt={filt}&tests={tests} * * * @since 3.2.0 * @property rls_tmpl */ /** * Configure the instance to use a remote loader service instead of * the client loader. * * @since 3.2.0 * @property use_rls */ YUI.add('yui-base', function(Y) { /* * YUI stub * @module yui * @submodule yui-base */ /** * The YUI module contains the components required for building the YUI * seed file. This includes the script loading mechanism, a simple queue, * and the core utilities for the library. * @module yui * @submodule yui-base */ /** * Provides the language utilites and extensions used by the library * @class Lang * @static */ Y.Lang = Y.Lang || {}; var L = Y.Lang, ARRAY = 'array', BOOLEAN = 'boolean', DATE = 'date', ERROR = 'error', FUNCTION = 'function', NUMBER = 'number', NULL = 'null', OBJECT = 'object', REGEX = 'regexp', STRING = 'string', STRING_PROTO = String.prototype, TOSTRING = Object.prototype.toString, UNDEFINED = 'undefined', TYPES = { 'undefined' : UNDEFINED, 'number' : NUMBER, 'boolean' : BOOLEAN, 'string' : STRING, '[object Function]' : FUNCTION, '[object RegExp]' : REGEX, '[object Array]' : ARRAY, '[object Date]' : DATE, '[object Error]' : ERROR }, TRIMREGEX = /^\s+|\s+$/g, EMPTYSTRING = '', SUBREGEX = /\{\s*([^\|\}]+?)\s*(?:\|([^\}]*))?\s*\}/g; /** * Determines whether or not the provided item is an array. * Returns false for array-like collections such as the * function arguments collection or HTMLElement collection * will return false. Use Y.Array.test if you * want to test for an array-like collection. * @method isArray * @static * @param o The object to test. * @return {boolean} true if o is an array. */ // L.isArray = Array.isArray || function(o) { // return L.type(o) === ARRAY; // }; L.isArray = function(o) { return L.type(o) === ARRAY; }; /** * Determines whether or not the provided item is a boolean. * @method isBoolean * @static * @param o The object to test. * @return {boolean} true if o is a boolean. */ L.isBoolean = function(o) { return typeof o === BOOLEAN; }; /** *

* Determines whether or not the provided item is a function. * Note: Internet Explorer thinks certain functions are objects: *

* *
 * var obj = document.createElement("object");
 * Y.Lang.isFunction(obj.getAttribute) // reports false in IE
 *  
 * var input = document.createElement("input"); // append to body
 * Y.Lang.isFunction(input.focus) // reports false in IE
 * 
* *

* You will have to implement additional tests if these functions * matter to you. *

* * @method isFunction * @static * @param o The object to test. * @return {boolean} true if o is a function. */ L.isFunction = function(o) { return L.type(o) === FUNCTION; }; /** * Determines whether or not the supplied item is a date instance. * @method isDate * @static * @param o The object to test. * @return {boolean} true if o is a date. */ L.isDate = function(o) { // return o instanceof Date; return L.type(o) === DATE && o.toString() !== 'Invalid Date' && !isNaN(o); }; /** * Determines whether or not the provided item is null. * @method isNull * @static * @param o The object to test. * @return {boolean} true if o is null. */ L.isNull = function(o) { return o === null; }; /** * Determines whether or not the provided item is a legal number. * @method isNumber * @static * @param o The object to test. * @return {boolean} true if o is a number. */ L.isNumber = function(o) { return typeof o === NUMBER && isFinite(o); }; /** * Determines whether or not the provided item is of type object * or function. Note that arrays are also objects, so * Y.Lang.isObject([]) === true. * @method isObject * @static * @param o The object to test. * @param failfn {boolean} fail if the input is a function. * @return {boolean} true if o is an object. */ L.isObject = function(o, failfn) { var t = typeof o; return (o && (t === OBJECT || (!failfn && (t === FUNCTION || L.isFunction(o))))) || false; }; /** * Determines whether or not the provided item is a string. * @method isString * @static * @param o The object to test. * @return {boolean} true if o is a string. */ L.isString = function(o) { return typeof o === STRING; }; /** * Determines whether or not the provided item is undefined. * @method isUndefined * @static * @param o The object to test. * @return {boolean} true if o is undefined. */ L.isUndefined = function(o) { return typeof o === UNDEFINED; }; /** * Returns a string without any leading or trailing whitespace. If * the input is not a string, the input will be returned untouched. * @method trim * @static * @param s {string} the string to trim. * @return {string} the trimmed string. */ L.trim = STRING_PROTO.trim ? function(s) { return (s && s.trim) ? s.trim() : s; } : function (s) { try { return s.replace(TRIMREGEX, EMPTYSTRING); } catch (e) { return s; } }; /** * Returns a string without any leading whitespace. * @method trimLeft * @static * @param s {string} the string to trim. * @return {string} the trimmed string. */ L.trimLeft = STRING_PROTO.trimLeft ? function (s) { return s.trimLeft(); } : function (s) { return s.replace(/^\s+/, ''); }; /** * Returns a string without any trailing whitespace. * @method trimRight * @static * @param s {string} the string to trim. * @return {string} the trimmed string. */ L.trimRight = STRING_PROTO.trimRight ? function (s) { return s.trimRight(); } : function (s) { return s.replace(/\s+$/, ''); }; /** * A convenience method for detecting a legitimate non-null value. * Returns false for null/undefined/NaN, true for other values, * including 0/false/'' * @method isValue * @static * @param o The item to test. * @return {boolean} true if it is not null/undefined/NaN || false. */ L.isValue = function(o) { var t = L.type(o); switch (t) { case NUMBER: return isFinite(o); case NULL: case UNDEFINED: return false; default: return !!(t); } }; /** *

* Returns a string representing the type of the item passed in. *

* *

* Known issues: *

* * * * @method type * @param o the item to test. * @return {string} the detected type. * @static */ L.type = function(o) { return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? OBJECT : NULL); }; /** * Lightweight version of Y.substitute. Uses the same template * structure as Y.substitute, but doesn't support recursion, * auto-object coersion, or formats. * @method sub * @param {string} s String to be modified. * @param {object} o Object containing replacement values. * @return {string} the substitute result. * @static * @since 3.2.0 */ L.sub = function(s, o) { return ((s.replace) ? s.replace(SUBREGEX, function(match, key) { return (!L.isUndefined(o[key])) ? o[key] : match; }) : s); }; /** * Returns the current time in milliseconds. * @method now * @return {int} the current date * @since 3.3.0 */ L.now = Date.now || function () { return new Date().getTime(); }; /** * The YUI module contains the components required for building the YUI seed * file. This includes the script loading mechanism, a simple queue, and the * core utilities for the library. * @module yui * @submodule yui-base */ var Native = Array.prototype, LENGTH = 'length', /** * Adds the following array utilities to the YUI instance. Additional * array helpers can be found in the collection component. * @class Array */ /** * Y.Array(o) returns an array: * - Arrays are return unmodified unless the start position is specified. * - "Array-like" collections (@see Array.test) are converted to arrays * - For everything else, a new array is created with the input as the sole * item. * - The start position is used if the input is or is like an array to return * a subset of the collection. * * @todo this will not automatically convert elements that are also * collections such as forms and selects. Passing true as the third * param will force a conversion. * * @method () * @static * @param {object} o the item to arrayify. * @param {int} startIdx if an array or array-like, this is the start index. * @param {boolean} arraylike if true, it forces the array-like fork. This * can be used to avoid multiple Array.test calls. * @return {Array} the resulting array. */ YArray = function(o, startIdx, arraylike) { var t = (arraylike) ? 2 : YArray.test(o), l, a, start = startIdx || 0; if (t) { // IE errors when trying to slice HTMLElement collections try { return Native.slice.call(o, start); } catch (e) { a = []; l = o.length; for (; start < l; start++) { a.push(o[start]); } return a; } } else { return [o]; } }; Y.Array = YArray; /** * Evaluates the input to determine if it is an array, array-like, or * something else. This is used to handle the arguments collection * available within functions, and HTMLElement collections * * @method test * @static * * @todo current implementation (intenionally) will not implicitly * handle html elements that are array-like (forms, selects, etc). * * @param {object} o the object to test. * * @return {int} a number indicating the results: * 0: Not an array or an array-like collection * 1: A real array. * 2: array-like collection. */ YArray.test = function(o) { var r = 0; if (Y.Lang.isObject(o)) { if (Y.Lang.isArray(o)) { r = 1; } else { try { // indexed, but no tagName (element) or alert (window), // or functions without apply/call (Safari // HTMLElementCollection bug). if ((LENGTH in o) && !o.tagName && !o.alert && !o.apply) { r = 2; } } catch (e) {} } } return r; }; /** * Executes the supplied function on each item in the array. * @method each * @param {Array} a the array to iterate. * @param {Function} f the function to execute on each item. The * function receives three arguments: the value, the index, the full array. * @param {object} o Optional context object. * @static * @return {YUI} the YUI instance. */ YArray.each = (Native.forEach) ? function(a, f, o) { Native.forEach.call(a || [], f, o || Y); return Y; } : function(a, f, o) { var l = (a && a.length) || 0, i; for (i = 0; i < l; i = i + 1) { f.call(o || Y, a[i], i, a); } return Y; }; /** * Returns an object using the first array as keys, and * the second as values. If the second array is not * provided the value is set to true for each. * @method hash * @static * @param {Array} k keyset. * @param {Array} v optional valueset. * @return {object} the hash. */ YArray.hash = function(k, v) { var o = {}, l = k.length, vl = v && v.length, i; for (i = 0; i < l; i = i + 1) { o[k[i]] = (vl && vl > i) ? v[i] : true; } return o; }; /** * Returns the index of the first item in the array * that contains the specified value, -1 if the * value isn't found. * @method indexOf * @static * @param {Array} a the array to search. * @param {any} val the value to search for. * @return {int} the index of the item that contains the value or -1. */ YArray.indexOf = (Native.indexOf) ? function(a, val) { return Native.indexOf.call(a, val); } : function(a, val) { for (var i = 0; i < a.length; i = i + 1) { if (a[i] === val) { return i; } } return -1; }; /** * Numeric sort convenience function. * Y.ArrayAssert.itemsAreEqual([1,2,3], [3,1,2].sort(Y.Array.numericSort)); * @method numericSort * @static * @param {number} a a number. * @param {number} b a number. */ YArray.numericSort = function(a, b) { return (a - b); }; /** * Executes the supplied function on each item in the array. * Returning true from the processing function will stop the * processing of the remaining items. * @method some * @param {Array} a the array to iterate. * @param {Function} f the function to execute on each item. The function * receives three arguments: the value, the index, the full array. * @param {object} o Optional context object. * @static * @return {boolean} true if the function returns true on * any of the items in the array. */ YArray.some = (Native.some) ? function(a, f, o) { return Native.some.call(a, f, o); } : function(a, f, o) { var l = a.length, i; for (i = 0; i < l; i = i + 1) { if (f.call(o, a[i], i, a)) { return true; } } return false; }; /** * The YUI module contains the components required for building the YUI * seed file. This includes the script loading mechanism, a simple queue, * and the core utilities for the library. * @module yui * @submodule yui-base */ /** * A simple FIFO queue. Items are added to the Queue with add(1..n items) and * removed using next(). * * @class Queue * @constructor * @param {MIXED} item* 0..n items to seed the queue. */ function Queue() { this._init(); this.add.apply(this, arguments); } Queue.prototype = { /** * Initialize the queue * * @method _init * @protected */ _init: function() { /** * The collection of enqueued items * * @property _q * @type Array * @protected */ this._q = []; }, /** * Get the next item in the queue. FIFO support * * @method next * @return {MIXED} the next item in the queue. */ next: function() { return this._q.shift(); }, /** * Get the last in the queue. LIFO support. * * @method last * @return {MIXED} the last item in the queue. */ last: function() { return this._q.pop(); }, /** * Add 0..n items to the end of the queue. * * @method add * @param {MIXED} item* 0..n items. * @return {object} this queue. */ add: function() { this._q.push.apply(this._q, arguments); return this; }, /** * Returns the current number of queued items. * * @method size * @return {Number} The size. */ size: function() { return this._q.length; } }; Y.Queue = Queue; YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue(); /** * The YUI module contains the components required for building the YUI * seed file. This includes the script loading mechanism, a simple queue, * and the core utilities for the library. * @module yui * @submodule yui-base */ var CACHED_DELIMITER = '__', /* * IE will not enumerate native functions in a derived object even if the * function was overridden. This is a workaround for specific functions * we care about on the Object prototype. * @property _iefix * @for YUI * @param {Function} r the object to receive the augmentation * @param {Function} s the object that supplies the properties to augment * @private */ _iefix = function(r, s) { var fn = s.toString; if (Y.Lang.isFunction(fn) && fn != Object.prototype.toString) { r.toString = fn; } }; /** * Returns a new object containing all of the properties of * all the supplied objects. The properties from later objects * will overwrite those in earlier objects. Passing in a * single object will create a shallow copy of it. For a deep * copy, use clone. * @method merge * @for YUI * @param arguments {Object*} the objects to merge. * @return {object} the new merged object. */ Y.merge = function() { var a = arguments, o = {}, i, l = a.length; for (i = 0; i < l; i = i + 1) { Y.mix(o, a[i], true); } return o; }; /** * Applies the supplier's properties to the receiver. By default * all prototype and static propertes on the supplier are applied * to the corresponding spot on the receiver. By default all * properties are applied, and a property that is already on the * reciever will not be overwritten. The default behavior can * be modified by supplying the appropriate parameters. * * @todo add constants for the modes * * @method mix * @param {Function} r the object to receive the augmentation. * @param {Function} s the object that supplies the properties to augment. * @param ov {boolean} if true, properties already on the receiver * will be overwritten if found on the supplier. * @param wl {string[]} a whitelist. If supplied, only properties in * this list will be applied to the receiver. * @param {int} mode what should be copies, and to where * default(0): object to object * 1: prototype to prototype (old augment) * 2: prototype to prototype and object props (new augment) * 3: prototype to object * 4: object to prototype. * @param merge {boolean/int} merge objects instead of overwriting/ignoring. * A value of 2 will skip array merge * Used by Y.aggregate. * @return {object} the augmented object. */ Y.mix = function(r, s, ov, wl, mode, merge) { if (!s || !r) { return r || Y; } if (mode) { switch (mode) { case 1: // proto to proto return Y.mix(r.prototype, s.prototype, ov, wl, 0, merge); case 2: // object to object and proto to proto Y.mix(r.prototype, s.prototype, ov, wl, 0, merge); break; // pass through case 3: // proto to static return Y.mix(r, s.prototype, ov, wl, 0, merge); case 4: // static to proto return Y.mix(r.prototype, s, ov, wl, 0, merge); default: // object to object is what happens below } } // Maybe don't even need this wl && wl.length check anymore?? var i, l, p, type; if (wl && wl.length) { for (i = 0, l = wl.length; i < l; ++i) { p = wl[i]; type = Y.Lang.type(r[p]); if (s.hasOwnProperty(p)) { if (merge && type == 'object') { Y.mix(r[p], s[p]); } else if (ov || !(p in r)) { r[p] = s[p]; } } } } else { for (i in s) { // if (s.hasOwnProperty(i) && !(i in FROZEN)) { if (s.hasOwnProperty(i)) { // check white list if it was supplied // if the receiver has this property, it is an object, // and merge is specified, merge the two objects. if (merge && Y.Lang.isObject(r[i], true)) { Y.mix(r[i], s[i], ov, wl, 0, true); // recursive // otherwise apply the property only if overwrite // is specified or the receiver doesn't have one. } else if (ov || !(i in r)) { r[i] = s[i]; } // if merge is specified and the receiver is an array, // append the array item // } else if (arr) { // r.push(s[i]); // } } } if (Y.UA.ie) { _iefix(r, s); } } return r; }; /** * Returns a wrapper for a function which caches the * return value of that function, keyed off of the combined * argument values. * @method cached * @param source {function} the function to memoize. * @param cache an optional cache seed. * @param refetch if supplied, this value is tested against the cached * value. If the values are equal, the wrapped function is executed again. * @return {Function} the wrapped function. */ Y.cached = function(source, cache, refetch) { cache = cache || {}; return function(arg1) { var k = (arguments.length > 1) ? Array.prototype.join.call(arguments, CACHED_DELIMITER) : arg1; if (!(k in cache) || (refetch && cache[k] == refetch)) { cache[k] = source.apply(source, arguments); } return cache[k]; }; }; /** * The YUI module contains the components required for building the YUI * seed file. This includes the script loading mechanism, a simple queue, * and the core utilities for the library. * @module yui * @submodule yui-base */ /** * Adds the following Object utilities to the YUI instance * @class Object */ /** * Y.Object(o) returns a new object based upon the supplied object. * @method () * @static * @param o the supplier object. * @return {Object} the new object. */ var F = function() {}, // O = Object.create || function(o) { // F.prototype = o; // return new F(); // }, O = function(o) { F.prototype = o; return new F(); }, owns = function(o, k) { return o && o.hasOwnProperty && o.hasOwnProperty(k); // return Object.prototype.hasOwnProperty.call(o, k); }, UNDEF, /** * Extracts the keys, values, or size from an object * * @method _extract * @param o the object. * @param what what to extract (0: keys, 1: values, 2: size). * @return {boolean|Array} the extracted info. * @static * @private */ _extract = function(o, what) { var count = (what === 2), out = (count) ? 0 : [], i; for (i in o) { if (owns(o, i)) { if (count) { out++; } else { out.push((what) ? o[i] : i); } } } return out; }; Y.Object = O; /** * Returns an array containing the object's keys * @method keys * @static * @param o an object. * @return {string[]} the keys. */ // O.keys = Object.keys || function(o) { // return _extract(o); // }; O.keys = function(o) { return _extract(o); }; /** * Returns an array containing the object's values * @method values * @static * @param o an object. * @return {Array} the values. */ // O.values = Object.values || function(o) { // return _extract(o, 1); // }; O.values = function(o) { return _extract(o, 1); }; /** * Returns the size of an object * @method size * @static * @param o an object. * @return {int} the size. */ O.size = Object.size || function(o) { return _extract(o, 2); }; /** * Returns true if the object contains a given key * @method hasKey * @static * @param o an object. * @param k the key to query. * @return {boolean} true if the object contains the key. */ O.hasKey = owns; /** * Returns true if the object contains a given value * @method hasValue * @static * @param o an object. * @param v the value to query. * @return {boolean} true if the object contains the value. */ O.hasValue = function(o, v) { return (Y.Array.indexOf(O.values(o), v) > -1); }; /** * Determines whether or not the property was added * to the object instance. Returns false if the property is not present * in the object, or was inherited from the prototype. * * @method owns * @static * @param o {any} The object being testing. * @param p {string} the property to look for. * @return {boolean} true if the object has the property on the instance. */ O.owns = owns; /** * Executes a function on each item. The function * receives the value, the key, and the object * as parameters (in that order). * @method each * @static * @param o the object to iterate. * @param f {Function} the function to execute on each item. The function * receives three arguments: the value, the the key, the full object. * @param c the execution context. * @param proto {boolean} include proto. * @return {YUI} the YUI instance. */ O.each = function(o, f, c, proto) { var s = c || Y, i; for (i in o) { if (proto || owns(o, i)) { f.call(s, o[i], i, o); } } return Y; }; /** * Executes a function on each item, but halts if the * function returns true. The function * receives the value, the key, and the object * as paramters (in that order). * @method some * @static * @param o the object to iterate. * @param f {Function} the function to execute on each item. The function * receives three arguments: the value, the the key, the full object. * @param c the execution context. * @param proto {boolean} include proto. * @return {boolean} true if any execution of the function returns true, * false otherwise. */ O.some = function(o, f, c, proto) { var s = c || Y, i; for (i in o) { if (proto || owns(o, i)) { if (f.call(s, o[i], i, o)) { return true; } } } return false; }; /** * Retrieves the sub value at the provided path, * from the value object provided. * * @method getValue * @static * @param o The object from which to extract the property value. * @param path {Array} A path array, specifying the object traversal path * from which to obtain the sub value. * @return {Any} The value stored in the path, undefined if not found, * undefined if the source is not an object. Returns the source object * if an empty path is provided. */ O.getValue = function(o, path) { if (!Y.Lang.isObject(o)) { return UNDEF; } var i, p = Y.Array(path), l = p.length; for (i = 0; o !== UNDEF && i < l; i++) { o = o[p[i]]; } return o; }; /** * Sets the sub-attribute value at the provided path on the * value object. Returns the modified value object, or * undefined if the path is invalid. * * @method setValue * @static * @param o The object on which to set the sub value. * @param path {Array} A path array, specifying the object traversal path * at which to set the sub value. * @param val {Any} The new value for the sub-attribute. * @return {Object} The modified object, with the new sub value set, or * undefined, if the path was invalid. */ O.setValue = function(o, path, val) { var i, p = Y.Array(path), leafIdx = p.length - 1, ref = o; if (leafIdx >= 0) { for (i = 0; ref !== UNDEF && i < leafIdx; i++) { ref = ref[p[i]]; } if (ref !== UNDEF) { ref[p[i]] = val; } else { return UNDEF; } } return o; }; /** * Returns true if the object has no properties of its own * @method isEmpty * @static * @return {boolean} true if the object is empty. * @since 3.2.0 */ O.isEmpty = function(o) { for (var i in o) { if (owns(o, i)) { return false; } } return true; }; /** * The YUI module contains the components required for building the YUI seed * file. This includes the script loading mechanism, a simple queue, and the * core utilities for the library. * @module yui * @submodule yui-base */ /** * YUI user agent detection. * Do not fork for a browser if it can be avoided. Use feature detection when * you can. Use the user agent as a last resort. UA stores a version * number for the browser engine, 0 otherwise. This value may or may not map * to the version number of the browser using the engine. The value is * presented as a float so that it can easily be used for boolean evaluation * as well as for looking for a particular range of versions. Because of this, * some of the granularity of the version info may be lost (e.g., Gecko 1.8.0.9 * reports 1.8). * @class UA * @static */ /** * Static method for parsing the UA string. Defaults to assigning it's value to Y.UA * @static * @method Env.parseUA * @param {String} subUA Parse this UA string instead of navigator.userAgent * @returns {Object} The Y.UA object */ YUI.Env.parseUA = function(subUA) { var numberify = function(s) { var c = 0; return parseFloat(s.replace(/\./g, function() { return (c++ == 1) ? '' : '.'; })); }, win = Y.config.win, nav = win && win.navigator, o = { /** * Internet Explorer version number or 0. Example: 6 * @property ie * @type float * @static */ ie: 0, /** * Opera version number or 0. Example: 9.2 * @property opera * @type float * @static */ opera: 0, /** * Gecko engine revision number. Will evaluate to 1 if Gecko * is detected but the revision could not be found. Other browsers * will be 0. Example: 1.8 *
         * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
         * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
         * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
         * Firefox 3.0   <-- 1.9
         * Firefox 3.5   <-- 1.91
         * 
* @property gecko * @type float * @static */ gecko: 0, /** * AppleWebKit version. KHTML browsers that are not WebKit browsers * will evaluate to 1, other browsers 0. Example: 418.9 *
         * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
         *                                   latest available for Mac OSX 10.3.
         * Safari 2.0.2:         416     <-- hasOwnProperty introduced
         * Safari 2.0.4:         418     <-- preventDefault fixed
         * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
         *                                   different versions of webkit
         * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
         *                                   updated, but not updated
         *                                   to the latest patch.
         * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native
         * SVG and many major issues fixed).
         * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic
         * update from 2.x via the 10.4.11 OS patch.
         * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
         *                                   yahoo.com user agent hack removed.
         * 
* http://en.wikipedia.org/wiki/Safari_version_history * @property webkit * @type float * @static */ webkit: 0, /** * Chrome will be detected as webkit, but this property will also * be populated with the Chrome version number * @property chrome * @type float * @static */ chrome: 0, /** * The mobile property will be set to a string containing any relevant * user agent information when a modern mobile browser is detected. * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series * devices with the WebKit-based browser, and Opera Mini. * @property mobile * @type string * @static */ mobile: null, /** * Adobe AIR version number or 0. Only populated if webkit is detected. * Example: 1.0 * @property air * @type float */ air: 0, /** * Detects Apple iPad's OS version * @property ipad * @type float * @static */ ipad: 0, /** * Detects Apple iPhone's OS version * @property iphone * @type float * @static */ iphone: 0, /** * Detects Apples iPod's OS version * @property ipod * @type float * @static */ ipod: 0, /** * General truthy check for iPad, iPhone or iPod * @property ios * @type float * @static */ ios: null, /** * Detects Googles Android OS version * @property android * @type float * @static */ android: 0, /** * Detects Palms WebOS version * @property webos * @type float * @static */ webos: 0, /** * Google Caja version number or 0. * @property caja * @type float */ caja: nav && nav.cajaVersion, /** * Set to true if the page appears to be in SSL * @property secure * @type boolean * @static */ secure: false, /** * The operating system. Currently only detecting windows or macintosh * @property os * @type string * @static */ os: null }, ua = subUA || nav && nav.userAgent, loc = win && win.location, href = loc && loc.href, m; o.secure = href && (href.toLowerCase().indexOf('https') === 0); if (ua) { if ((/windows|win32/i).test(ua)) { o.os = 'windows'; } else if ((/macintosh/i).test(ua)) { o.os = 'macintosh'; } else if ((/rhino/i).test(ua)) { o.os = 'rhino'; } // Modern KHTML browsers should qualify as Safari X-Grade if ((/KHTML/).test(ua)) { o.webkit = 1; } // Modern WebKit browsers are at least X-Grade m = ua.match(/AppleWebKit\/([^\s]*)/); if (m && m[1]) { o.webkit = numberify(m[1]); // Mobile browser check if (/ Mobile\//.test(ua)) { o.mobile = 'Apple'; // iPhone or iPod Touch m = ua.match(/OS ([^\s]*)/); if (m && m[1]) { m = numberify(m[1].replace('_', '.')); } o.ios = m; o.ipad = o.ipod = o.iphone = 0; m = ua.match(/iPad|iPod|iPhone/); if (m && m[0]) { o[m[0].toLowerCase()] = o.ios; } } else { m = ua.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/); if (m) { // Nokia N-series, Android, webOS, ex: NokiaN95 o.mobile = m[0]; } if (/webOS/.test(ua)) { o.mobile = 'WebOS'; m = ua.match(/webOS\/([^\s]*);/); if (m && m[1]) { o.webos = numberify(m[1]); } } if (/ Android/.test(ua)) { o.mobile = 'Android'; m = ua.match(/Android ([^\s]*);/); if (m && m[1]) { o.android = numberify(m[1]); } } } m = ua.match(/Chrome\/([^\s]*)/); if (m && m[1]) { o.chrome = numberify(m[1]); // Chrome } else { m = ua.match(/AdobeAIR\/([^\s]*)/); if (m) { o.air = m[0]; // Adobe AIR 1.0 or better } } } if (!o.webkit) { // not webkit // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr) m = ua.match(/Opera[\s\/]([^\s]*)/); if (m && m[1]) { o.opera = numberify(m[1]); m = ua.match(/Opera Mini[^;]*/); if (m) { o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316 } } else { // not opera or webkit m = ua.match(/MSIE\s([^;]*)/); if (m && m[1]) { o.ie = numberify(m[1]); } else { // not opera, webkit, or ie m = ua.match(/Gecko\/([^\s]*)/); if (m) { o.gecko = 1; // Gecko detected, look for revision m = ua.match(/rv:([^\s\)]*)/); if (m && m[1]) { o.gecko = numberify(m[1]); } } } } } } YUI.Env.UA = o; return o; }; Y.UA = YUI.Env.UA || YUI.Env.parseUA(); }, '3.3.0' );