/* Copyright (c) 2011, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html version: 2.9.0 */ /** * The YAHOO object is the single global object used by YUI Library. It * contains utility function for setting up namespaces, inheritance, and * logging. YAHOO.util, YAHOO.widget, and YAHOO.example are namespaces * created automatically for and used by the library. * @module yahoo * @title YAHOO Global */ /** * YAHOO_config is not included as part of the library. Instead it is an * object that can be defined by the implementer immediately before * including the YUI library. The properties included in this object * will be used to configure global properties needed as soon as the * library begins to load. * @class YAHOO_config * @static */ /** * A reference to a function that will be executed every time a YAHOO module * is loaded. As parameter, this function will receive the version * information for the module. See * YAHOO.env.getVersion for the description of the version data structure. * @property listener * @type Function * @static * @default undefined */ /** * Set to true if the library will be dynamically loaded after window.onload. * Defaults to false * @property injecting * @type boolean * @static * @default undefined */ /** * Instructs the yuiloader component to dynamically load yui components and * their dependencies. See the yuiloader documentation for more information * about dynamic loading * @property load * @static * @default undefined * @see yuiloader */ /** * Forces the use of the supplied locale where applicable in the library * @property locale * @type string * @static * @default undefined */ if (typeof YAHOO == "undefined" || !YAHOO) { /** * The YAHOO global namespace object. If YAHOO is already defined, the * existing YAHOO object will not be overwritten so that defined * namespaces are preserved. * @class YAHOO * @static */ var YAHOO = {}; } /** * Returns the namespace specified and creates it if it doesn't exist *
* YAHOO.namespace("property.package");
* YAHOO.namespace("YAHOO.property.package");
*
* Either of the above would create YAHOO.property, then
* YAHOO.property.package
*
* Be careful when naming packages. Reserved words may work in some browsers
* and not others. For instance, the following will fail in Safari:
*
* YAHOO.namespace("really.long.nested.namespace");
*
* This fails because "long" is a future reserved word in ECMAScript
*
* For implementation code that uses YUI, do not create your components
* in the namespaces defined by YUI (
* YAHOO.util,
* YAHOO.widget,
* YAHOO.lang,
* YAHOO.tool,
* YAHOO.example,
* YAHOO.env) -- create your own namespace (e.g., 'companyname').
*
* @method namespace
* @static
* @param {String*} arguments 1-n namespaces to create
* @return {Object} A reference to the last namespace object created
*/
YAHOO.namespace = function() {
var a=arguments, o=null, i, j, d;
for (i=0; i
* 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 = agent || (navigator && navigator.userAgent),
loc = window && window.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(/Version\/([^\s]*)/);
if (m && m[1]) {
o.opera = numberify(m[1]); // opera 10+
}
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]);
}
}
}
}
}
}
return o;
};
YAHOO.env.ua = YAHOO.env.parseUA();
/*
* Initializes the global by creating the default namespaces and applying
* any new configuration information that is detected. This is the setup
* for env.
* @method init
* @static
* @private
*/
(function() {
YAHOO.namespace("util", "widget", "example");
/*global YAHOO_config*/
if ("undefined" !== typeof YAHOO_config) {
var l=YAHOO_config.listener, ls=YAHOO.env.listeners,unique=true, i;
if (l) {
// if YAHOO is loaded multiple times we need to check to see if
// this is a new config object. If it is, add the new component
// load listener to the stack
for (i=0; i& < > " ' / `
*
*
*
* This implementation is based on the
* OWASP
* HTML escaping recommendations. In addition to the characters
* in the OWASP recommendation, we also escape the `
* character, since IE interprets it as an attribute delimiter when used in
* innerHTML.
*
Usage: var myAnim = new YAHOO.util.Anim(el, { width: { from: 10, to: 100 } }, 1, YAHOO.util.Easing.easeOut);
* @class Anim * @namespace YAHOO.util * @requires YAHOO.util.AnimMgr * @requires YAHOO.util.Easing * @requires YAHOO.util.Dom * @requires YAHOO.util.Event * @requires YAHOO.util.CustomEvent * @constructor * @param {String | HTMLElement} el Reference to the element that will be animated * @param {Object} attributes The attribute(s) to be animated. * Each attribute is an object with at minimum a "to" or "by" member defined. * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). * All attribute names use camelCase. * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) */ var Anim = function(el, attributes, duration, method) { if (!el) { YAHOO.log('element required to create Anim instance', 'error', 'Anim'); } this.init(el, attributes, duration, method); }; Anim.NAME = 'Anim'; Anim.prototype = { /** * Provides a readable name for the Anim instance. * @method toString * @return {String} */ toString: function() { var el = this.getEl() || {}; var id = el.id || el.tagName; return (this.constructor.NAME + ': ' + id); }, patterns: { // cached for performance noNegatives: /width|height|opacity|padding/i, // keep at zero or above offsetAttribute: /^((width|height)|(top|left))$/, // use offsetValue as default defaultUnit: /width|height|top$|bottom$|left$|right$/i, // use 'px' by default offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i // IE may return these, so convert these to offset }, /** * Returns the value computed by the animation's "method". * @method doMethod * @param {String} attr The name of the attribute. * @param {Number} start The value this attribute should start from for this animation. * @param {Number} end The value this attribute should end at for this animation. * @return {Number} The Value to be applied to the attribute. */ doMethod: function(attr, start, end) { return this.method(this.currentFrame, start, end - start, this.totalFrames); }, /** * Applies a value to an attribute. * @method setAttribute * @param {String} attr The name of the attribute. * @param {Number} val The value to be applied to the attribute. * @param {String} unit The unit ('px', '%', etc.) of the value. */ setAttribute: function(attr, val, unit) { var el = this.getEl(); if ( this.patterns.noNegatives.test(attr) ) { val = (val > 0) ? val : 0; } if (attr in el && !('style' in el && attr in el.style)) { el[attr] = val; } else { Y.Dom.setStyle(el, attr, val + unit); } }, /** * Returns current value of the attribute. * @method getAttribute * @param {String} attr The name of the attribute. * @return {Number} val The current value of the attribute. */ getAttribute: function(attr) { var el = this.getEl(); var val = Y.Dom.getStyle(el, attr); if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) { return parseFloat(val); } var a = this.patterns.offsetAttribute.exec(attr) || []; var pos = !!( a[3] ); // top or left var box = !!( a[2] ); // width or height if ('style' in el) { // use offsets for width/height and abs pos top/left if ( box || (Y.Dom.getStyle(el, 'position') == 'absolute' && pos) ) { val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)]; } else { // default to zero for other 'auto' val = 0; } } else if (attr in el) { val = el[attr]; } return val; }, /** * Returns the unit to use when none is supplied. * @method getDefaultUnit * @param {attr} attr The name of the attribute. * @return {String} The default unit to be used. */ getDefaultUnit: function(attr) { if ( this.patterns.defaultUnit.test(attr) ) { return 'px'; } return ''; }, /** * Sets the actual values to be used during the animation. Should only be needed for subclass use. * @method setRuntimeAttribute * @param {Object} attr The attribute object * @private */ setRuntimeAttribute: function(attr) { var start; var end; var attributes = this.attributes; this.runtimeAttributes[attr] = {}; var isset = function(prop) { return (typeof prop !== 'undefined'); }; if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) { return false; // note return; nothing to animate to } start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr); // To beats by, per SMIL 2.1 spec if ( isset(attributes[attr]['to']) ) { end = attributes[attr]['to']; } else if ( isset(attributes[attr]['by']) ) { if (start.constructor == Array) { end = []; for (var i = 0, len = start.length; i < len; ++i) { end[i] = start[i] + attributes[attr]['by'][i] * 1; // times 1 to cast "by" } } else { end = start + attributes[attr]['by'] * 1; } } this.runtimeAttributes[attr].start = start; this.runtimeAttributes[attr].end = end; // set units if needed this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr); return true; }, /** * Constructor for Anim instance. * @method init * @param {String | HTMLElement} el Reference to the element that will be animated * @param {Object} attributes The attribute(s) to be animated. * Each attribute is an object with at minimum a "to" or "by" member defined. * Additional optional members are "from" (defaults to current value), "units" (defaults to "px"). * All attribute names use camelCase. * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method) */ init: function(el, attributes, duration, method) { /** * Whether or not the animation is running. * @property isAnimated * @private * @type Boolean */ var isAnimated = false; /** * A Date object that is created when the animation begins. * @property startTime * @private * @type Date */ var startTime = null; /** * The number of frames this animation was able to execute. * @property actualFrames * @private * @type Int */ var actualFrames = 0; /** * The element to be animated. * @property el * @private * @type HTMLElement */ el = Y.Dom.get(el); /** * The collection of attributes to be animated. * Each attribute must have at least a "to" or "by" defined in order to animate. * If "to" is supplied, the animation will end with the attribute at that value. * If "by" is supplied, the animation will end at that value plus its starting value. * If both are supplied, "to" is used, and "by" is ignored. * Optional additional member include "from" (the value the attribute should start animating from, defaults to current value), and "unit" (the units to apply to the values). * @property attributes * @type Object */ this.attributes = attributes || {}; /** * The length of the animation. Defaults to "1" (second). * @property duration * @type Number */ this.duration = !YAHOO.lang.isUndefined(duration) ? duration : 1; /** * The method that will provide values to the attribute(s) during the animation. * Defaults to "YAHOO.util.Easing.easeNone". * @property method * @type Function */ this.method = method || Y.Easing.easeNone; /** * Whether or not the duration should be treated as seconds. * Defaults to true. * @property useSeconds * @type Boolean */ this.useSeconds = true; // default to seconds /** * The location of the current animation on the timeline. * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time. * @property currentFrame * @type Int */ this.currentFrame = 0; /** * The total number of frames to be executed. * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time. * @property totalFrames * @type Int */ this.totalFrames = Y.AnimMgr.fps; /** * Changes the animated element * @method setEl */ this.setEl = function(element) { el = Y.Dom.get(element); }; /** * Returns a reference to the animated element. * @method getEl * @return {HTMLElement} */ this.getEl = function() { return el; }; /** * Checks whether the element is currently animated. * @method isAnimated * @return {Boolean} current value of isAnimated. */ this.isAnimated = function() { return isAnimated; }; /** * Returns the animation start time. * @method getStartTime * @return {Date} current value of startTime. */ this.getStartTime = function() { return startTime; }; this.runtimeAttributes = {}; var logger = {}; logger.log = function() {YAHOO.log.apply(window, arguments)}; logger.log('creating new instance of ' + this); /** * Starts the animation by registering it with the animation manager. * @method animate */ this.animate = function() { if ( this.isAnimated() ) { return false; } this.currentFrame = 0; this.totalFrames = ( this.useSeconds ) ? Math.ceil(Y.AnimMgr.fps * this.duration) : this.duration; if (this.duration === 0 && this.useSeconds) { // jump to last frame if zero second duration this.totalFrames = 1; } Y.AnimMgr.registerElement(this); return true; }; /** * Stops the animation. Normally called by AnimMgr when animation completes. * @method stop * @param {Boolean} finish (optional) If true, animation will jump to final frame. */ this.stop = function(finish) { if (!this.isAnimated()) { // nothing to stop return false; } if (finish) { this.currentFrame = this.totalFrames; this._onTween.fire(); } Y.AnimMgr.stop(this); }; this._handleStart = function() { this.onStart.fire(); this.runtimeAttributes = {}; for (var attr in this.attributes) { if (this.attributes.hasOwnProperty(attr)) { this.setRuntimeAttribute(attr); } } isAnimated = true; actualFrames = 0; startTime = new Date(); }; /** * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s). * @private */ this._handleTween = function() { var data = { duration: new Date() - this.getStartTime(), currentFrame: this.currentFrame }; data.toString = function() { return ( 'duration: ' + data.duration + ', currentFrame: ' + data.currentFrame ); }; this.onTween.fire(data); var runtimeAttributes = this.runtimeAttributes; for (var attr in runtimeAttributes) { if (runtimeAttributes.hasOwnProperty(attr)) { this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit); } } this.afterTween.fire(data); actualFrames += 1; }; this._handleComplete = function() { var actual_duration = (new Date() - startTime) / 1000 ; var data = { duration: actual_duration, frames: actualFrames, fps: actualFrames / actual_duration }; data.toString = function() { return ( 'duration: ' + data.duration + ', frames: ' + data.frames + ', fps: ' + data.fps ); }; isAnimated = false; actualFrames = 0; this.onComplete.fire(data); }; /** * Custom event that fires after onStart, useful in subclassing * @private */ this._onStart = new Y.CustomEvent('_start', this, true); /** * Custom event that fires when animation begins * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction) * @event onStart */ this.onStart = new Y.CustomEvent('start', this); /** * Custom event that fires between each frame * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction) * @event onTween */ this.onTween = new Y.CustomEvent('tween', this); /** * Custom event that fires between each frame * Listen via subscribe method (e.g. myAnim.afterTween.subscribe(someFunction) * @event afterTween */ this.afterTween = new Y.CustomEvent('afterTween', this); /** * Custom event that fires after onTween * @private */ this._onTween = new Y.CustomEvent('_tween', this, true); /** * Custom event that fires when animation ends * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction) * @event onComplete */ this.onComplete = new Y.CustomEvent('complete', this); /** * Custom event that fires after onComplete * @private */ this._onComplete = new Y.CustomEvent('_complete', this, true); this._onStart.subscribe(this._handleStart); this._onTween.subscribe(this._handleTween); this._onComplete.subscribe(this._handleComplete); } }; Y.Anim = Anim; })(); /** * Handles animation queueing and threading. * Used by Anim and subclasses. * @class AnimMgr * @namespace YAHOO.util */ YAHOO.util.AnimMgr = new function() { /** * Reference to the animation Interval. * @property thread * @private * @type Int */ var thread = null; /** * The current queue of registered animation objects. * @property queue * @private * @type Array */ var queue = []; /** * The number of active animations. * @property tweenCount * @private * @type Int */ var tweenCount = 0; /** * Base frame rate (frames per second). * Arbitrarily high for better x-browser calibration (slower browsers drop more frames). * @property fps * @type Int * */ this.fps = 1000; /** * Interval delay in milliseconds, defaults to fastest possible. * @property delay * @type Int * */ this.delay = 20; /** * Adds an animation instance to the animation queue. * All animation instances must be registered in order to animate. * @method registerElement * @param {object} tween The Anim instance to be be registered */ this.registerElement = function(tween) { queue[queue.length] = tween; tweenCount += 1; tween._onStart.fire(); this.start(); }; var _unregisterQueue = []; var _unregistering = false; var doUnregister = function() { var next_args = _unregisterQueue.shift(); unRegister.apply(YAHOO.util.AnimMgr,next_args); if (_unregisterQueue.length) { arguments.callee(); } }; var unRegister = function(tween, index) { index = index || getIndex(tween); if (!tween.isAnimated() || index === -1) { return false; } tween._onComplete.fire(); queue.splice(index, 1); tweenCount -= 1; if (tweenCount <= 0) { this.stop(); } return true; }; /** * removes an animation instance from the animation queue. * All animation instances must be registered in order to animate. * @method unRegister * @param {object} tween The Anim instance to be be registered * @param {Int} index The index of the Anim instance * @private */ this.unRegister = function() { _unregisterQueue.push(arguments); if (!_unregistering) { _unregistering = true; doUnregister(); _unregistering = false; } } /** * Starts the animation thread. * Only one thread can run at a time. * @method start */ this.start = function() { if (thread === null) { thread = setInterval(this.run, this.delay); } }; /** * Stops the animation thread or a specific animation instance. * @method stop * @param {object} tween A specific Anim instance to stop (optional) * If no instance given, Manager stops thread and all animations. */ this.stop = function(tween) { if (!tween) { clearInterval(thread); for (var i = 0, len = queue.length; i < len; ++i) { this.unRegister(queue[0], 0); } queue = []; thread = null; tweenCount = 0; } else { this.unRegister(tween); } }; /** * Called per Interval to handle each animation frame. * @method run */ this.run = function() { for (var i = 0, len = queue.length; i < len; ++i) { var tween = queue[i]; if ( !tween || !tween.isAnimated() ) { continue; } if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null) { tween.currentFrame += 1; if (tween.useSeconds) { correctFrame(tween); } tween._onTween.fire(); } else { YAHOO.util.AnimMgr.stop(tween, i); } } }; var getIndex = function(anim) { for (var i = 0, len = queue.length; i < len; ++i) { if (queue[i] === anim) { return i; // note return; } } return -1; }; /** * On the fly frame correction to keep animation on time. * @method correctFrame * @private * @param {Object} tween The Anim instance being corrected. */ var correctFrame = function(tween) { var frames = tween.totalFrames; var frame = tween.currentFrame; var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames); var elapsed = (new Date() - tween.getStartTime()); var tweak = 0; if (elapsed < tween.duration * 1000) { // check if falling behind tweak = Math.round((elapsed / expected - 1) * tween.currentFrame); } else { // went over duration, so jump to end tweak = frames - (frame + 1); } if (tweak > 0 && isFinite(tweak)) { // adjust if needed if (tween.currentFrame + tweak >= frames) {// dont go past last frame tweak = frames - (frame + 1); } tween.currentFrame += tweak; } }; this._queue = queue; this._getIndex = getIndex; }; /** * Used to calculate Bezier splines for any number of control points. * @class Bezier * @namespace YAHOO.util * */ YAHOO.util.Bezier = new function() { /** * Get the current position of the animated element based on t. * Each point is an array of "x" and "y" values (0 = x, 1 = y) * At least 2 points are required (start and end). * First point is start. Last point is end. * Additional control points are optional. * @method getPosition * @param {Array} points An array containing Bezier points * @param {Number} t A number between 0 and 1 which is the basis for determining current position * @return {Array} An array containing int x and y member data */ this.getPosition = function(points, t) { var n = points.length; var tmp = []; for (var i = 0; i < n; ++i){ tmp[i] = [points[i][0], points[i][1]]; // save input } for (var j = 1; j < n; ++j) { for (i = 0; i < n - j; ++i) { tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0]; tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1]; } } return [ tmp[0][0], tmp[0][1] ]; }; }; (function() { /** * Anim subclass for color transitions. *Usage: var myAnim = new Y.ColorAnim(el, { backgroundColor: { from: '#FF0000', to: '#FFFFFF' } }, 1, Y.Easing.easeOut); Color values can be specified with either 112233, #112233,
* [255,255,255], or rgb(255,255,255)
Usage: var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);
Usage: var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);
* YAHOO.util.DragDropMgr.refreshCache({group1:true, group2:true});
*
* @TODO this really should be an indexed array. Alternatively this
* method could accept both.
* @method refreshCache
* @param {Object} groups an associative array of groups to refresh
* @static
*/
refreshCache: function(groups) {
YAHOO.log("refreshing element location cache", "info", "DragDropMgr");
// refresh everything if group array is not provided
var g = groups || this.ids;
for (var sGroup in g) {
if ("string" != typeof sGroup) {
continue;
}
for (var i in this.ids[sGroup]) {
var oDD = this.ids[sGroup][i];
if (this.isTypeOfDD(oDD)) {
var loc = this.getLocation(oDD);
if (loc) {
this.locationCache[oDD.id] = loc;
} else {
delete this.locationCache[oDD.id];
YAHOO.log("Could not get the loc for " + oDD.id, "warn", "DragDropMgr");
}
}
}
}
},
/**
* This checks to make sure an element exists and is in the DOM. The
* main purpose is to handle cases where innerHTML is used to remove
* drag and drop objects from the DOM. IE provides an 'unspecified
* error' when trying to access the offsetParent of such an element
* @method verifyEl
* @param {HTMLElement} el the element to check
* @return {boolean} true if the element looks usable
* @static
*/
verifyEl: function(el) {
try {
if (el) {
var parent = el.offsetParent;
if (parent) {
return true;
}
}
} catch(e) {
YAHOO.log("detected problem with an element", "info", "DragDropMgr");
}
return false;
},
/**
* Returns a Region object containing the drag and drop element's position
* and size, including the padding configured for it
* @method getLocation
* @param {DragDrop} oDD the drag and drop object to get the
* location for
* @return {YAHOO.util.Region} a Region object representing the total area
* the element occupies, including any padding
* the instance is configured for.
* @static
*/
getLocation: function(oDD) {
if (! this.isTypeOfDD(oDD)) {
YAHOO.log(oDD + " is not a DD obj", "info", "DragDropMgr");
return null;
}
var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
try {
pos= YAHOO.util.Dom.getXY(el);
} catch (e) { }
if (!pos) {
YAHOO.log("getXY failed", "info", "DragDropMgr");
return null;
}
x1 = pos[0];
x2 = x1 + el.offsetWidth;
y1 = pos[1];
y2 = y1 + el.offsetHeight;
t = y1 - oDD.padding[0];
r = x2 + oDD.padding[1];
b = y2 + oDD.padding[2];
l = x1 - oDD.padding[3];
return new YAHOO.util.Region( t, r, b, l );
},
/**
* Checks the cursor location to see if it over the target
* @method isOverTarget
* @param {YAHOO.util.Point} pt The point to evaluate
* @param {DragDrop} oTarget the DragDrop object we are inspecting
* @param {boolean} intersect true if we are in intersect mode
* @param {YAHOO.util.Region} pre-cached location of the dragged element
* @return {boolean} true if the mouse is over the target
* @private
* @static
*/
isOverTarget: function(pt, oTarget, intersect, curRegion) {
// use cache if available
var loc = this.locationCache[oTarget.id];
if (!loc || !this.useCache) {
YAHOO.log("cache not populated", "info", "DragDropMgr");
loc = this.getLocation(oTarget);
this.locationCache[oTarget.id] = loc;
YAHOO.log("cache: " + loc, "info", "DragDropMgr");
}
if (!loc) {
YAHOO.log("could not get the location of the element", "info", "DragDropMgr");
return false;
}
//YAHOO.log("loc: " + loc + ", pt: " + pt);
oTarget.cursorIsOver = loc.contains( pt );
// DragDrop is using this as a sanity check for the initial mousedown
// in this case we are done. In POINT mode, if the drag obj has no
// contraints, we are done. Otherwise we need to evaluate the
// region the target as occupies to determine if the dragged element
// overlaps with it.
var dc = this.dragCurrent;
if (!dc || (!intersect && !dc.constrainX && !dc.constrainY)) {
//if (oTarget.cursorIsOver) {
//YAHOO.log("over " + oTarget + ", " + loc + ", " + pt, "warn");
//}
return oTarget.cursorIsOver;
}
oTarget.overlap = null;
// Get the current location of the drag element, this is the
// location of the mouse event less the delta that represents
// where the original mousedown happened on the element. We
// need to consider constraints and ticks as well.
if (!curRegion) {
var pos = dc.getTargetCoord(pt.x, pt.y);
var el = dc.getDragEl();
curRegion = new YAHOO.util.Region( pos.y,
pos.x + el.offsetWidth,
pos.y + el.offsetHeight,
pos.x );
}
var overlap = curRegion.intersect(loc);
if (overlap) {
oTarget.overlap = overlap;
return (intersect) ? true : oTarget.cursorIsOver;
} else {
return false;
}
},
/**
* unload event handler
* @method _onUnload
* @private
* @static
*/
_onUnload: function(e, me) {
this.unregAll();
},
/**
* Cleans up the drag and drop events and objects.
* @method unregAll
* @private
* @static
*/
unregAll: function() {
YAHOO.log("unregister all", "info", "DragDropMgr");
if (this.dragCurrent) {
this.stopDrag();
this.dragCurrent = null;
}
this._execOnAll("unreg", []);
//for (var i in this.elementCache) {
//delete this.elementCache[i];
//}
//this.elementCache = {};
this.ids = {};
},
/**
* A cache of DOM elements
* @property elementCache
* @private
* @static
* @deprecated elements are not cached now
*/
elementCache: {},
/**
* Get the wrapper for the DOM element specified
* @method getElWrapper
* @param {String} id the id of the element to get
* @return {YAHOO.util.DDM.ElementWrapper} the wrapped element
* @private
* @deprecated This wrapper isn't that useful
* @static
*/
getElWrapper: function(id) {
var oWrapper = this.elementCache[id];
if (!oWrapper || !oWrapper.el) {
oWrapper = this.elementCache[id] =
new this.ElementWrapper(YAHOO.util.Dom.get(id));
}
return oWrapper;
},
/**
* Returns the actual DOM element
* @method getElement
* @param {String} id the id of the elment to get
* @return {Object} The element
* @deprecated use YAHOO.util.Dom.get instead
* @static
*/
getElement: function(id) {
return YAHOO.util.Dom.get(id);
},
/**
* Returns the style property for the DOM element (i.e.,
* document.getElById(id).style)
* @method getCss
* @param {String} id the id of the elment to get
* @return {Object} The style property of the element
* @deprecated use YAHOO.util.Dom instead
* @static
*/
getCss: function(id) {
var el = YAHOO.util.Dom.get(id);
return (el) ? el.style : null;
},
/**
* Inner class for cached elements
* @class DragDropMgr.ElementWrapper
* @for DragDropMgr
* @private
* @deprecated
*/
ElementWrapper: function(el) {
/**
* The element
* @property el
*/
this.el = el || null;
/**
* The element id
* @property id
*/
this.id = this.el && el.id;
/**
* A reference to the style property
* @property css
*/
this.css = this.el && el.style;
},
/**
* Returns the X position of an html element
* @method getPosX
* @param el the element for which to get the position
* @return {int} the X coordinate
* @for DragDropMgr
* @deprecated use YAHOO.util.Dom.getX instead
* @static
*/
getPosX: function(el) {
return YAHOO.util.Dom.getX(el);
},
/**
* Returns the Y position of an html element
* @method getPosY
* @param el the element for which to get the position
* @return {int} the Y coordinate
* @deprecated use YAHOO.util.Dom.getY instead
* @static
*/
getPosY: function(el) {
return YAHOO.util.Dom.getY(el);
},
/**
* Swap two nodes. In IE, we use the native method, for others we
* emulate the IE behavior
* @method swapNode
* @param n1 the first node to swap
* @param n2 the other node to swap
* @static
*/
swapNode: function(n1, n2) {
if (n1.swapNode) {
n1.swapNode(n2);
} else {
var p = n2.parentNode;
var s = n2.nextSibling;
if (s == n1) {
p.insertBefore(n1, n2);
} else if (n2 == n1.nextSibling) {
p.insertBefore(n2, n1);
} else {
n1.parentNode.replaceChild(n2, n1);
p.insertBefore(n1, s);
}
}
},
/**
* Returns the current scroll position
* @method getScroll
* @private
* @static
*/
getScroll: function () {
var t, l, dde=document.documentElement, db=document.body;
if (dde && (dde.scrollTop || dde.scrollLeft)) {
t = dde.scrollTop;
l = dde.scrollLeft;
} else if (db) {
t = db.scrollTop;
l = db.scrollLeft;
} else {
YAHOO.log("could not get scroll property", "info", "DragDropMgr");
}
return { top: t, left: l };
},
/**
* Returns the specified element style property
* @method getStyle
* @param {HTMLElement} el the element
* @param {string} styleProp the style property
* @return {string} The value of the style property
* @deprecated use YAHOO.util.Dom.getStyle
* @static
*/
getStyle: function(el, styleProp) {
return YAHOO.util.Dom.getStyle(el, styleProp);
},
/**
* Gets the scrollTop
* @method getScrollTop
* @return {int} the document's scrollTop
* @static
*/
getScrollTop: function () { return this.getScroll().top; },
/**
* Gets the scrollLeft
* @method getScrollLeft
* @return {int} the document's scrollTop
* @static
*/
getScrollLeft: function () { return this.getScroll().left; },
/**
* Sets the x/y position of an element to the location of the
* target element.
* @method moveToEl
* @param {HTMLElement} moveEl The element to move
* @param {HTMLElement} targetEl The position reference element
* @static
*/
moveToEl: function (moveEl, targetEl) {
var aCoord = YAHOO.util.Dom.getXY(targetEl);
YAHOO.log("moveToEl: " + aCoord, "info", "DragDropMgr");
YAHOO.util.Dom.setXY(moveEl, aCoord);
},
/**
* Gets the client height
* @method getClientHeight
* @return {int} client height in px
* @deprecated use YAHOO.util.Dom.getViewportHeight instead
* @static
*/
getClientHeight: function() {
return YAHOO.util.Dom.getViewportHeight();
},
/**
* Gets the client width
* @method getClientWidth
* @return {int} client width in px
* @deprecated use YAHOO.util.Dom.getViewportWidth instead
* @static
*/
getClientWidth: function() {
return YAHOO.util.Dom.getViewportWidth();
},
/**
* Numeric array sort function
* @method numericSort
* @static
*/
numericSort: function(a, b) { return (a - b); },
/**
* Internal counter
* @property _timeoutCount
* @private
* @static
*/
_timeoutCount: 0,
/**
* Trying to make the load order less important. Without this we get
* an error if this file is loaded before the Event Utility.
* @method _addListeners
* @private
* @static
*/
_addListeners: function() {
var DDM = YAHOO.util.DDM;
if ( YAHOO.util.Event && document ) {
DDM._onLoad();
} else {
if (DDM._timeoutCount > 2000) {
YAHOO.log("DragDrop requires the Event Utility", "error", "DragDropMgr");
} else {
setTimeout(DDM._addListeners, 10);
if (document && document.body) {
DDM._timeoutCount += 1;
}
}
}
},
/**
* Recursively searches the immediate parent and all child nodes for
* the handle element in order to determine wheter or not it was
* clicked.
* @method handleWasClicked
* @param node the html element to inspect
* @static
*/
handleWasClicked: function(node, id) {
if (this.isHandle(id, node.id)) {
YAHOO.log("clicked node is a handle", "info", "DragDropMgr");
return true;
} else {
// check to see if this is a text node child of the one we want
var p = node.parentNode;
// YAHOO.log("p: " + p);
while (p) {
if (this.isHandle(id, p.id)) {
return true;
} else {
YAHOO.log(p.id + " is not a handle", "info", "DragDropMgr");
p = p.parentNode;
}
}
}
return false;
}
};
}();
// shorter alias, save a few bytes
YAHOO.util.DDM = YAHOO.util.DragDropMgr;
YAHOO.util.DDM._addListeners();
}
(function() {
var Event=YAHOO.util.Event;
var Dom=YAHOO.util.Dom;
/**
* Defines the interface and base operation of items that that can be
* dragged or can be drop targets. It was designed to be extended, overriding
* the event handlers for startDrag, onDrag, onDragOver, onDragOut.
* Up to three html elements can be associated with a DragDrop instance:
*
* dd = new YAHOO.util.DragDrop("div1", "group1");
*
* Since none of the event handlers have been implemented, nothing would
* actually happen if you were to run the code above. Normally you would
* override this class or one of the default implementations, but you can
* also override the methods you want on an instance of the class...
*
* dd.onDragDrop = function(e, id) {
* alert("dd was dropped on " + id);
* }
*
* @namespace YAHOO.util
* @class DragDrop
* @constructor
* @param {String} id of the element that is linked to this instance
* @param {String} sGroup the group of related DragDrop objects
* @param {object} config an object containing configurable attributes
* Valid properties for DragDrop:
* padding, isTarget, maintainOffset, primaryButtonOnly,
*/
YAHOO.util.DragDrop = function(id, sGroup, config) {
if (id) {
this.init(id, sGroup, config);
}
};
YAHOO.util.DragDrop.prototype = {
/**
* An Object Literal containing the events that we will be using: mouseDown, b4MouseDown, mouseUp, b4StartDrag, startDrag, b4EndDrag, endDrag, mouseUp, drag, b4Drag, invalidDrop, b4DragOut, dragOut, dragEnter, b4DragOver, dragOver, b4DragDrop, dragDrop
* By setting any of these to false, then event will not be fired.
* @property events
* @type object
*/
events: null,
/**
* @method on
* @description Shortcut for EventProvider.subscribe, see YAHOO.util.EventProvider.subscribe
*/
on: function() {
this.subscribe.apply(this, arguments);
},
/**
* The id of the element associated with this object. This is what we
* refer to as the "linked element" because the size and position of
* this element is used to determine when the drag and drop objects have
* interacted.
* @property id
* @type String
*/
id: null,
/**
* Configuration attributes passed into the constructor
* @property config
* @type object
*/
config: null,
/**
* The id of the element that will be dragged. By default this is same
* as the linked element , but could be changed to another element. Ex:
* YAHOO.util.DDProxy
* @property dragElId
* @type String
* @private
*/
dragElId: null,
/**
* the id of the element that initiates the drag operation. By default
* this is the linked element, but could be changed to be a child of this
* element. This lets us do things like only starting the drag when the
* header element within the linked html element is clicked.
* @property handleElId
* @type String
* @private
*/
handleElId: null,
/**
* An associative array of HTML tags that will be ignored if clicked.
* @property invalidHandleTypes
* @type {string: string}
*/
invalidHandleTypes: null,
/**
* An associative array of ids for elements that will be ignored if clicked
* @property invalidHandleIds
* @type {string: string}
*/
invalidHandleIds: null,
/**
* An indexted array of css class names for elements that will be ignored
* if clicked.
* @property invalidHandleClasses
* @type string[]
*/
invalidHandleClasses: null,
/**
* The linked element's absolute X position at the time the drag was
* started
* @property startPageX
* @type int
* @private
*/
startPageX: 0,
/**
* The linked element's absolute X position at the time the drag was
* started
* @property startPageY
* @type int
* @private
*/
startPageY: 0,
/**
* The group defines a logical collection of DragDrop objects that are
* related. Instances only get events when interacting with other
* DragDrop object in the same group. This lets us define multiple
* groups using a single DragDrop subclass if we want.
* @property groups
* @type {string: string}
*/
groups: null,
/**
* Individual drag/drop instances can be locked. This will prevent
* onmousedown start drag.
* @property locked
* @type boolean
* @private
*/
locked: false,
/**
* Lock this instance
* @method lock
*/
lock: function() { this.locked = true; },
/**
* Unlock this instace
* @method unlock
*/
unlock: function() { this.locked = false; },
/**
* By default, all instances can be a drop target. This can be disabled by
* setting isTarget to false.
* @property isTarget
* @type boolean
*/
isTarget: true,
/**
* The padding configured for this drag and drop object for calculating
* the drop zone intersection with this object.
* @property padding
* @type int[]
*/
padding: null,
/**
* If this flag is true, do not fire drop events. The element is a drag only element (for movement not dropping)
* @property dragOnly
* @type Boolean
*/
dragOnly: false,
/**
* If this flag is true, a shim will be placed over the screen/viewable area to track mouse events. Should help with dragging elements over iframes and other controls.
* @property useShim
* @type Boolean
*/
useShim: false,
/**
* Cached reference to the linked element
* @property _domRef
* @private
*/
_domRef: null,
/**
* Internal typeof flag
* @property __ygDragDrop
* @private
*/
__ygDragDrop: true,
/**
* Set to true when horizontal contraints are applied
* @property constrainX
* @type boolean
* @private
*/
constrainX: false,
/**
* Set to true when vertical contraints are applied
* @property constrainY
* @type boolean
* @private
*/
constrainY: false,
/**
* The left constraint
* @property minX
* @type int
* @private
*/
minX: 0,
/**
* The right constraint
* @property maxX
* @type int
* @private
*/
maxX: 0,
/**
* The up constraint
* @property minY
* @type int
* @type int
* @private
*/
minY: 0,
/**
* The down constraint
* @property maxY
* @type int
* @private
*/
maxY: 0,
/**
* The difference between the click position and the source element's location
* @property deltaX
* @type int
* @private
*/
deltaX: 0,
/**
* The difference between the click position and the source element's location
* @property deltaY
* @type int
* @private
*/
deltaY: 0,
/**
* Maintain offsets when we resetconstraints. Set to true when you want
* the position of the element relative to its parent to stay the same
* when the page changes
*
* @property maintainOffset
* @type boolean
*/
maintainOffset: false,
/**
* Array of pixel locations the element will snap to if we specified a
* horizontal graduation/interval. This array is generated automatically
* when you define a tick interval.
* @property xTicks
* @type int[]
*/
xTicks: null,
/**
* Array of pixel locations the element will snap to if we specified a
* vertical graduation/interval. This array is generated automatically
* when you define a tick interval.
* @property yTicks
* @type int[]
*/
yTicks: null,
/**
* By default the drag and drop instance will only respond to the primary
* button click (left button for a right-handed mouse). Set to true to
* allow drag and drop to start with any mouse click that is propogated
* by the browser
* @property primaryButtonOnly
* @type boolean
*/
primaryButtonOnly: true,
/**
* The availabe property is false until the linked dom element is accessible.
* @property available
* @type boolean
*/
available: false,
/**
* By default, drags can only be initiated if the mousedown occurs in the
* region the linked element is. This is done in part to work around a
* bug in some browsers that mis-report the mousedown if the previous
* mouseup happened outside of the window. This property is set to true
* if outer handles are defined.
*
* @property hasOuterHandles
* @type boolean
* @default false
*/
hasOuterHandles: false,
/**
* Property that is assigned to a drag and drop object when testing to
* see if it is being targeted by another dd object. This property
* can be used in intersect mode to help determine the focus of
* the mouse interaction. DDM.getBestMatch uses this property first to
* determine the closest match in INTERSECT mode when multiple targets
* are part of the same interaction.
* @property cursorIsOver
* @type boolean
*/
cursorIsOver: false,
/**
* Property that is assigned to a drag and drop object when testing to
* see if it is being targeted by another dd object. This is a region
* that represents the area the draggable element overlaps this target.
* DDM.getBestMatch uses this property to compare the size of the overlap
* to that of other targets in order to determine the closest match in
* INTERSECT mode when multiple targets are part of the same interaction.
* @property overlap
* @type YAHOO.util.Region
*/
overlap: null,
/**
* Code that executes immediately before the startDrag event
* @method b4StartDrag
* @private
*/
b4StartDrag: function(x, y) { },
/**
* Abstract method called after a drag/drop object is clicked
* and the drag or mousedown time thresholds have beeen met.
* @method startDrag
* @param {int} X click location
* @param {int} Y click location
*/
startDrag: function(x, y) { /* override this */ },
/**
* Code that executes immediately before the onDrag event
* @method b4Drag
* @private
*/
b4Drag: function(e) { },
/**
* Abstract method called during the onMouseMove event while dragging an
* object.
* @method onDrag
* @param {Event} e the mousemove event
*/
onDrag: function(e) { /* override this */ },
/**
* Abstract method called when this element fist begins hovering over
* another DragDrop obj
* @method onDragEnter
* @param {Event} e the mousemove event
* @param {String|DragDrop[]} id In POINT mode, the element
* id this is hovering over. In INTERSECT mode, an array of one or more
* dragdrop items being hovered over.
*/
onDragEnter: function(e, id) { /* override this */ },
/**
* Code that executes immediately before the onDragOver event
* @method b4DragOver
* @private
*/
b4DragOver: function(e) { },
/**
* Abstract method called when this element is hovering over another
* DragDrop obj
* @method onDragOver
* @param {Event} e the mousemove event
* @param {String|DragDrop[]} id In POINT mode, the element
* id this is hovering over. In INTERSECT mode, an array of dd items
* being hovered over.
*/
onDragOver: function(e, id) { /* override this */ },
/**
* Code that executes immediately before the onDragOut event
* @method b4DragOut
* @private
*/
b4DragOut: function(e) { },
/**
* Abstract method called when we are no longer hovering over an element
* @method onDragOut
* @param {Event} e the mousemove event
* @param {String|DragDrop[]} id In POINT mode, the element
* id this was hovering over. In INTERSECT mode, an array of dd items
* that the mouse is no longer over.
*/
onDragOut: function(e, id) { /* override this */ },
/**
* Code that executes immediately before the onDragDrop event
* @method b4DragDrop
* @private
*/
b4DragDrop: function(e) { },
/**
* Abstract method called when this item is dropped on another DragDrop
* obj
* @method onDragDrop
* @param {Event} e the mouseup event
* @param {String|DragDrop[]} id In POINT mode, the element
* id this was dropped on. In INTERSECT mode, an array of dd items this
* was dropped on.
*/
onDragDrop: function(e, id) { /* override this */ },
/**
* Abstract method called when this item is dropped on an area with no
* drop target
* @method onInvalidDrop
* @param {Event} e the mouseup event
*/
onInvalidDrop: function(e) { /* override this */ },
/**
* Code that executes immediately before the endDrag event
* @method b4EndDrag
* @private
*/
b4EndDrag: function(e) { },
/**
* Fired when we are done dragging the object
* @method endDrag
* @param {Event} e the mouseup event
*/
endDrag: function(e) { /* override this */ },
/**
* Code executed immediately before the onMouseDown event
* @method b4MouseDown
* @param {Event} e the mousedown event
* @private
*/
b4MouseDown: function(e) { },
/**
* Event handler that fires when a drag/drop obj gets a mousedown
* @method onMouseDown
* @param {Event} e the mousedown event
*/
onMouseDown: function(e) { /* override this */ },
/**
* Event handler that fires when a drag/drop obj gets a mouseup
* @method onMouseUp
* @param {Event} e the mouseup event
*/
onMouseUp: function(e) { /* override this */ },
/**
* Override the onAvailable method to do what is needed after the initial
* position was determined.
* @method onAvailable
*/
onAvailable: function () {
//this.logger.log("onAvailable (base)");
},
/**
* Returns a reference to the linked element
* @method getEl
* @return {HTMLElement} the html element
*/
getEl: function() {
if (!this._domRef) {
this._domRef = Dom.get(this.id);
}
return this._domRef;
},
/**
* Returns a reference to the actual element to drag. By default this is
* the same as the html element, but it can be assigned to another
* element. An example of this can be found in YAHOO.util.DDProxy
* @method getDragEl
* @return {HTMLElement} the html element
*/
getDragEl: function() {
return Dom.get(this.dragElId);
},
/**
* Sets up the DragDrop object. Must be called in the constructor of any
* YAHOO.util.DragDrop subclass
* @method init
* @param id the id of the linked element
* @param {String} sGroup the group of related items
* @param {object} config configuration attributes
*/
init: function(id, sGroup, config) {
this.initTarget(id, sGroup, config);
Event.on(this._domRef || this.id, "mousedown",
this.handleMouseDown, this, true);
// Event.on(this.id, "selectstart", Event.preventDefault);
for (var i in this.events) {
this.createEvent(i + 'Event');
}
},
/**
* Initializes Targeting functionality only... the object does not
* get a mousedown handler.
* @method initTarget
* @param id the id of the linked element
* @param {String} sGroup the group of related items
* @param {object} config configuration attributes
*/
initTarget: function(id, sGroup, config) {
// configuration attributes
this.config = config || {};
this.events = {};
// create a local reference to the drag and drop manager
this.DDM = YAHOO.util.DDM;
// initialize the groups object
this.groups = {};
// assume that we have an element reference instead of an id if the
// parameter is not a string
if (typeof id !== "string") {
YAHOO.log("id is not a string, assuming it is an HTMLElement");
this._domRef = id;
id = Dom.generateId(id);
}
// set the id
this.id = id;
// add to an interaction group
this.addToGroup((sGroup) ? sGroup : "default");
// We don't want to register this as the handle with the manager
// so we just set the id rather than calling the setter.
this.handleElId = id;
Event.onAvailable(id, this.handleOnAvailable, this, true);
// create a logger instance
this.logger = (YAHOO.widget.LogWriter) ?
new YAHOO.widget.LogWriter(this.toString()) : YAHOO;
// the linked element is the element that gets dragged by default
this.setDragElId(id);
// by default, clicked anchors will not start drag operations.
// @TODO what else should be here? Probably form fields.
this.invalidHandleTypes = { A: "A" };
this.invalidHandleIds = {};
this.invalidHandleClasses = [];
this.applyConfig();
},
/**
* Applies the configuration parameters that were passed into the constructor.
* This is supposed to happen at each level through the inheritance chain. So
* a DDProxy implentation will execute apply config on DDProxy, DD, and
* DragDrop in order to get all of the parameters that are available in
* each object.
* @method applyConfig
*/
applyConfig: function() {
this.events = {
mouseDown: true,
b4MouseDown: true,
mouseUp: true,
b4StartDrag: true,
startDrag: true,
b4EndDrag: true,
endDrag: true,
drag: true,
b4Drag: true,
invalidDrop: true,
b4DragOut: true,
dragOut: true,
dragEnter: true,
b4DragOver: true,
dragOver: true,
b4DragDrop: true,
dragDrop: true
};
if (this.config.events) {
for (var i in this.config.events) {
if (this.config.events[i] === false) {
this.events[i] = false;
}
}
}
// configurable properties:
// padding, isTarget, maintainOffset, primaryButtonOnly
this.padding = this.config.padding || [0, 0, 0, 0];
this.isTarget = (this.config.isTarget !== false);
this.maintainOffset = (this.config.maintainOffset);
this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
this.dragOnly = ((this.config.dragOnly === true) ? true : false);
this.useShim = ((this.config.useShim === true) ? true : false);
},
/**
* Executed when the linked element is available
* @method handleOnAvailable
* @private
*/
handleOnAvailable: function() {
//this.logger.log("handleOnAvailable");
this.available = true;
this.resetConstraints();
this.onAvailable();
},
/**
* Configures the padding for the target zone in px. Effectively expands
* (or reduces) the virtual object size for targeting calculations.
* Supports css-style shorthand; if only one parameter is passed, all sides
* will have that padding, and if only two are passed, the top and bottom
* will have the first param, the left and right the second.
* @method setPadding
* @param {int} iTop Top pad
* @param {int} iRight Right pad
* @param {int} iBot Bot pad
* @param {int} iLeft Left pad
*/
setPadding: function(iTop, iRight, iBot, iLeft) {
// this.padding = [iLeft, iRight, iTop, iBot];
if (!iRight && 0 !== iRight) {
this.padding = [iTop, iTop, iTop, iTop];
} else if (!iBot && 0 !== iBot) {
this.padding = [iTop, iRight, iTop, iRight];
} else {
this.padding = [iTop, iRight, iBot, iLeft];
}
},
/**
* Stores the initial placement of the linked element.
* @method setInitialPosition
* @param {int} diffX the X offset, default 0
* @param {int} diffY the Y offset, default 0
* @private
*/
setInitPosition: function(diffX, diffY) {
var el = this.getEl();
if (!this.DDM.verifyEl(el)) {
if (el && el.style && (el.style.display == 'none')) {
this.logger.log(this.id + " can not get initial position, element style is display: none");
} else {
this.logger.log(this.id + " element is broken");
}
return;
}
var dx = diffX || 0;
var dy = diffY || 0;
var p = Dom.getXY( el );
this.initPageX = p[0] - dx;
this.initPageY = p[1] - dy;
this.lastPageX = p[0];
this.lastPageY = p[1];
this.logger.log(this.id + " initial position: " + this.initPageX +
", " + this.initPageY);
this.setStartPosition(p);
},
/**
* Sets the start position of the element. This is set when the obj
* is initialized, the reset when a drag is started.
* @method setStartPosition
* @param pos current position (from previous lookup)
* @private
*/
setStartPosition: function(pos) {
var p = pos || Dom.getXY(this.getEl());
this.deltaSetXY = null;
this.startPageX = p[0];
this.startPageY = p[1];
},
/**
* Add this instance to a group of related drag/drop objects. All
* instances belong to at least one group, and can belong to as many
* groups as needed.
* @method addToGroup
* @param sGroup {string} the name of the group
*/
addToGroup: function(sGroup) {
this.groups[sGroup] = true;
this.DDM.regDragDrop(this, sGroup);
},
/**
* Remove's this instance from the supplied interaction group
* @method removeFromGroup
* @param {string} sGroup The group to drop
*/
removeFromGroup: function(sGroup) {
this.logger.log("Removing from group: " + sGroup);
if (this.groups[sGroup]) {
delete this.groups[sGroup];
}
this.DDM.removeDDFromGroup(this, sGroup);
},
/**
* Allows you to specify that an element other than the linked element
* will be moved with the cursor during a drag
* @method setDragElId
* @param id {string} the id of the element that will be used to initiate the drag
*/
setDragElId: function(id) {
this.dragElId = id;
},
/**
* Allows you to specify a child of the linked element that should be
* used to initiate the drag operation. An example of this would be if
* you have a content div with text and links. Clicking anywhere in the
* content area would normally start the drag operation. Use this method
* to specify that an element inside of the content div is the element
* that starts the drag operation.
* @method setHandleElId
* @param id {string} the id of the element that will be used to
* initiate the drag.
*/
setHandleElId: function(id) {
if (typeof id !== "string") {
YAHOO.log("id is not a string, assuming it is an HTMLElement");
id = Dom.generateId(id);
}
this.handleElId = id;
this.DDM.regHandle(this.id, id);
},
/**
* Allows you to set an element outside of the linked element as a drag
* handle
* @method setOuterHandleElId
* @param id the id of the element that will be used to initiate the drag
*/
setOuterHandleElId: function(id) {
if (typeof id !== "string") {
YAHOO.log("id is not a string, assuming it is an HTMLElement");
id = Dom.generateId(id);
}
this.logger.log("Adding outer handle event: " + id);
Event.on(id, "mousedown",
this.handleMouseDown, this, true);
this.setHandleElId(id);
this.hasOuterHandles = true;
},
/**
* Remove all drag and drop hooks for this element
* @method unreg
*/
unreg: function() {
this.logger.log("DragDrop obj cleanup " + this.id);
Event.removeListener(this.id, "mousedown",
this.handleMouseDown);
this._domRef = null;
this.DDM._remove(this);
},
/**
* Returns true if this instance is locked, or the drag drop mgr is locked
* (meaning that all drag/drop is disabled on the page.)
* @method isLocked
* @return {boolean} true if this obj or all drag/drop is locked, else
* false
*/
isLocked: function() {
return (this.DDM.isLocked() || this.locked);
},
/**
* Fired when this object is clicked
* @method handleMouseDown
* @param {Event} e
* @param {YAHOO.util.DragDrop} oDD the clicked dd object (this dd obj)
* @private
*/
handleMouseDown: function(e, oDD) {
var button = e.which || e.button;
this.logger.log("button: " + button);
if (this.primaryButtonOnly && button > 1) {
this.logger.log("Mousedown was not produced by the primary button");
return;
}
if (this.isLocked()) {
this.logger.log("Drag and drop is disabled, aborting");
return;
}
this.logger.log("mousedown " + this.id);
this.logger.log("firing onMouseDown events");
// firing the mousedown events prior to calculating positions
var b4Return = this.b4MouseDown(e),
b4Return2 = true;
if (this.events.b4MouseDown) {
b4Return2 = this.fireEvent('b4MouseDownEvent', e);
}
var mDownReturn = this.onMouseDown(e),
mDownReturn2 = true;
if (this.events.mouseDown) {
if (mDownReturn === false) {
//Fixes #2528759 - Mousedown function returned false, don't fire the event and cancel everything.
mDownReturn2 = false;
} else {
mDownReturn2 = this.fireEvent('mouseDownEvent', e);
}
}
if ((b4Return === false) || (mDownReturn === false) || (b4Return2 === false) || (mDownReturn2 === false)) {
this.logger.log('b4MouseDown or onMouseDown returned false, exiting drag');
return;
}
this.DDM.refreshCache(this.groups);
// var self = this;
// setTimeout( function() { self.DDM.refreshCache(self.groups); }, 0);
// Only process the event if we really clicked within the linked
// element. The reason we make this check is that in the case that
// another element was moved between the clicked element and the
// cursor in the time between the mousedown and mouseup events. When
// this happens, the element gets the next mousedown event
// regardless of where on the screen it happened.
var pt = new YAHOO.util.Point(Event.getPageX(e), Event.getPageY(e));
if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) {
this.logger.log("Click was not over the element: " + this.id);
} else {
if (this.clickValidator(e)) {
this.logger.log("click was a valid handle");
// set the initial element position
this.setStartPosition();
// start tracking mousemove distance and mousedown time to
// determine when to start the actual drag
this.DDM.handleMouseDown(e, this);
// this mousedown is mine
this.DDM.stopEvent(e);
} else {
this.logger.log("clickValidator returned false, drag not initiated");
}
}
},
/**
* @method clickValidator
* @description Method validates that the clicked element
* was indeed the handle or a valid child of the handle
* @param {Event} e
*/
clickValidator: function(e) {
var target = YAHOO.util.Event.getTarget(e);
return ( this.isValidHandleChild(target) &&
(this.id == this.handleElId ||
this.DDM.handleWasClicked(target, this.id)) );
},
/**
* Finds the location the element should be placed if we want to move
* it to where the mouse location less the click offset would place us.
* @method getTargetCoord
* @param {int} iPageX the X coordinate of the click
* @param {int} iPageY the Y coordinate of the click
* @return an object that contains the coordinates (Object.x and Object.y)
* @private
*/
getTargetCoord: function(iPageX, iPageY) {
// this.logger.log("getTargetCoord: " + iPageX + ", " + iPageY);
var x = iPageX - this.deltaX;
var y = iPageY - this.deltaY;
if (this.constrainX) {
if (x < this.minX) { x = this.minX; }
if (x > this.maxX) { x = this.maxX; }
}
if (this.constrainY) {
if (y < this.minY) { y = this.minY; }
if (y > this.maxY) { y = this.maxY; }
}
x = this.getTick(x, this.xTicks);
y = this.getTick(y, this.yTicks);
// this.logger.log("getTargetCoord " +
// " iPageX: " + iPageX +
// " iPageY: " + iPageY +
// " x: " + x + ", y: " + y);
return {x:x, y:y};
},
/**
* Allows you to specify a tag name that should not start a drag operation
* when clicked. This is designed to facilitate embedding links within a
* drag handle that do something other than start the drag.
* @method addInvalidHandleType
* @param {string} tagName the type of element to exclude
*/
addInvalidHandleType: function(tagName) {
var type = tagName.toUpperCase();
this.invalidHandleTypes[type] = type;
},
/**
* Lets you to specify an element id for a child of a drag handle
* that should not initiate a drag
* @method addInvalidHandleId
* @param {string} id the element id of the element you wish to ignore
*/
addInvalidHandleId: function(id) {
if (typeof id !== "string") {
YAHOO.log("id is not a string, assuming it is an HTMLElement");
id = Dom.generateId(id);
}
this.invalidHandleIds[id] = id;
},
/**
* Lets you specify a css class of elements that will not initiate a drag
* @method addInvalidHandleClass
* @param {string} cssClass the class of the elements you wish to ignore
*/
addInvalidHandleClass: function(cssClass) {
this.invalidHandleClasses.push(cssClass);
},
/**
* Unsets an excluded tag name set by addInvalidHandleType
* @method removeInvalidHandleType
* @param {string} tagName the type of element to unexclude
*/
removeInvalidHandleType: function(tagName) {
var type = tagName.toUpperCase();
// this.invalidHandleTypes[type] = null;
delete this.invalidHandleTypes[type];
},
/**
* Unsets an invalid handle id
* @method removeInvalidHandleId
* @param {string} id the id of the element to re-enable
*/
removeInvalidHandleId: function(id) {
if (typeof id !== "string") {
YAHOO.log("id is not a string, assuming it is an HTMLElement");
id = Dom.generateId(id);
}
delete this.invalidHandleIds[id];
},
/**
* Unsets an invalid css class
* @method removeInvalidHandleClass
* @param {string} cssClass the class of the element(s) you wish to
* re-enable
*/
removeInvalidHandleClass: function(cssClass) {
for (var i=0, len=this.invalidHandleClasses.length; iSee: Element.addListener
*Event fields:
* <String> type available
* <HTMLElement>
* target the HTMLElement bound to this Element instance
*
Usage:
* var handler = function(e) {var target = e.target};
* myTabs.addListener('available', handler);
See: Element.addListener
*Event fields:
* <String> type contentReady
* <HTMLElement>
* target the HTMLElement bound to this Element instance
*
Usage:
* var handler = function(e) {var target = e.target};
* myTabs.addListener('contentReady', handler);
See: Element.addListener
*Event fields:
* <String> type beforeAppendTo
* <HTMLElement/Element>
* target the HTMLElement/Element being appended to
*
Usage:
* var handler = function(e) {var target = e.target};
* myTabs.addListener('beforeAppendTo', handler);
See: Element.addListener
*Event fields:
* <String> type appendTo
* <HTMLElement/Element>
* target the HTMLElement/Element being appended to
*
Usage:
* var handler = function(e) {var target = e.target};
* myTabs.addListener('appendTo', handler);
* // assumes yahoo, dom, and event are already on the page
* YAHOO.util.Get.script(
* ["http://yui.yahooapis.com/2.7.0/build/dragdrop/dragdrop-min.js",
* "http://yui.yahooapis.com/2.7.0/build/animation/animation-min.js"], {
* onSuccess: function(o) {
* YAHOO.log(o.data); // foo
* new YAHOO.util.DDProxy("dd1"); // also new o.reference("dd1"); would work
* this.log("won't cause error because YAHOO is the scope");
* this.log(o.nodes.length === 2) // true
* // o.purge(); // optionally remove the script nodes immediately
* },
* onFailure: function(o) {
* YAHOO.log("transaction failed");
* },
* data: "foo",
* timeout: 10000, // 10 second timeout
* scope: YAHOO,
* // win: otherframe // target another window/frame
* autopurge: true // allow the utility to choose when to remove the nodes
* });
*
* @return {tId: string} an object containing info about the transaction
*/
script: function(url, opts) { return _queue("script", url, opts); },
/**
* Fetches and inserts one or more css link nodes into the
* head of the current document or the document in a specified
* window.
* @method css
* @static
* @param url {string} the url or urls to the css file(s)
* @param opts Options:
*
* YAHOO.util.Get.css("http://yui.yahooapis.com/2.7.0/build/menu/assets/skins/sam/menu.css");
*
*
* YAHOO.util.Get.css(["http://yui.yahooapis.com/2.7.0/build/menu/assets/skins/sam/menu.css",
* "http://yui.yahooapis.com/2.7.0/build/logger/assets/skins/sam/logger.css"]);
*
* @return {tId: string} an object containing info about the transaction
*/
css: function(url, opts) {
return _queue("css", url, opts);
}
};
}();
YAHOO.register("get", YAHOO.util.Get, {version: "2.9.0", build: "2800"});
/*
Copyright (c) 2011, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 2.9.0
*/
/**
* The YAHOO object is the single global object used by YUI Library. It
* contains utility function for setting up namespaces, inheritance, and
* logging. YAHOO.util, YAHOO.widget, and YAHOO.example are namespaces
* created automatically for and used by the library.
* @module yahoo
* @title YAHOO Global
*/
/**
* YAHOO_config is not included as part of the library. Instead it is an
* object that can be defined by the implementer immediately before
* including the YUI library. The properties included in this object
* will be used to configure global properties needed as soon as the
* library begins to load.
* @class YAHOO_config
* @static
*/
/**
* A reference to a function that will be executed every time a YAHOO module
* is loaded. As parameter, this function will receive the version
* information for the module. See
* YAHOO.env.getVersion for the description of the version data structure.
* @property listener
* @type Function
* @static
* @default undefined
*/
/**
* Set to true if the library will be dynamically loaded after window.onload.
* Defaults to false
* @property injecting
* @type boolean
* @static
* @default undefined
*/
/**
* Instructs the yuiloader component to dynamically load yui components and
* their dependencies. See the yuiloader documentation for more information
* about dynamic loading
* @property load
* @static
* @default undefined
* @see yuiloader
*/
/**
* Forces the use of the supplied locale where applicable in the library
* @property locale
* @type string
* @static
* @default undefined
*/
if (typeof YAHOO == "undefined" || !YAHOO) {
/**
* The YAHOO global namespace object. If YAHOO is already defined, the
* existing YAHOO object will not be overwritten so that defined
* namespaces are preserved.
* @class YAHOO
* @static
*/
var YAHOO = {};
}
/**
* Returns the namespace specified and creates it if it doesn't exist
*
* YAHOO.namespace("property.package");
* YAHOO.namespace("YAHOO.property.package");
*
* Either of the above would create YAHOO.property, then
* YAHOO.property.package
*
* Be careful when naming packages. Reserved words may work in some browsers
* and not others. For instance, the following will fail in Safari:
*
* YAHOO.namespace("really.long.nested.namespace");
*
* This fails because "long" is a future reserved word in ECMAScript
*
* For implementation code that uses YUI, do not create your components
* in the namespaces defined by YUI (
* YAHOO.util,
* YAHOO.widget,
* YAHOO.lang,
* YAHOO.tool,
* YAHOO.example,
* YAHOO.env) -- create your own namespace (e.g., 'companyname').
*
* @method namespace
* @static
* @param {String*} arguments 1-n namespaces to create
* @return {Object} A reference to the last namespace object created
*/
YAHOO.namespace = function() {
var a=arguments, o=null, i, j, d;
for (i=0; i
* 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 = agent || (navigator && navigator.userAgent),
loc = window && window.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(/Version\/([^\s]*)/);
if (m && m[1]) {
o.opera = numberify(m[1]); // opera 10+
}
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]);
}
}
}
}
}
}
return o;
};
YAHOO.env.ua = YAHOO.env.parseUA();
/*
* Initializes the global by creating the default namespaces and applying
* any new configuration information that is detected. This is the setup
* for env.
* @method init
* @static
* @private
*/
(function() {
YAHOO.namespace("util", "widget", "example");
/*global YAHOO_config*/
if ("undefined" !== typeof YAHOO_config) {
var l=YAHOO_config.listener, ls=YAHOO.env.listeners,unique=true, i;
if (l) {
// if YAHOO is loaded multiple times we need to check to see if
// this is a new config object. If it is, add the new component
// load listener to the stack
for (i=0; i& < > " ' / `
*
*
*
* This implementation is based on the
* OWASP
* HTML escaping recommendations. In addition to the characters
* in the OWASP recommendation, we also escape the `
* character, since IE interprets it as an attribute delimiter when used in
* innerHTML.
*
* // assumes yahoo, dom, and event are already on the page
* YAHOO.util.Get.script(
* ["http://yui.yahooapis.com/2.7.0/build/dragdrop/dragdrop-min.js",
* "http://yui.yahooapis.com/2.7.0/build/animation/animation-min.js"], {
* onSuccess: function(o) {
* YAHOO.log(o.data); // foo
* new YAHOO.util.DDProxy("dd1"); // also new o.reference("dd1"); would work
* this.log("won't cause error because YAHOO is the scope");
* this.log(o.nodes.length === 2) // true
* // o.purge(); // optionally remove the script nodes immediately
* },
* onFailure: function(o) {
* YAHOO.log("transaction failed");
* },
* data: "foo",
* timeout: 10000, // 10 second timeout
* scope: YAHOO,
* // win: otherframe // target another window/frame
* autopurge: true // allow the utility to choose when to remove the nodes
* });
*
* @return {tId: string} an object containing info about the transaction
*/
script: function(url, opts) { return _queue("script", url, opts); },
/**
* Fetches and inserts one or more css link nodes into the
* head of the current document or the document in a specified
* window.
* @method css
* @static
* @param url {string} the url or urls to the css file(s)
* @param opts Options:
*
* YAHOO.util.Get.css("http://yui.yahooapis.com/2.7.0/build/menu/assets/skins/sam/menu.css");
*
*
* YAHOO.util.Get.css(["http://yui.yahooapis.com/2.7.0/build/menu/assets/skins/sam/menu.css",
* "http://yui.yahooapis.com/2.7.0/build/logger/assets/skins/sam/logger.css"]);
*
* @return {tId: string} an object containing info about the transaction
*/
css: function(url, opts) {
return _queue("css", url, opts);
}
};
}();
YAHOO.register("get", YAHOO.util.Get, {version: "2.9.0", build: "2800"});
/*jslint evil: true, strict: false, regexp: false*/
/**
* Provides dynamic loading for the YUI library. It includes the dependency
* info for the library, and will automatically pull in dependencies for
* the modules requested. It supports rollup files (such as utilities.js
* and yahoo-dom-event.js), and will automatically use these when
* appropriate in order to minimize the number of http connections
* required to load all of the dependencies.
*
* @module yuiloader
* @namespace YAHOO.util
*/
/**
* YUILoader provides dynamic loading for YUI.
* @class YAHOO.util.YUILoader
* @todo
* version management, automatic sandboxing
*/
(function() {
var Y = YAHOO,
util = Y.util,
lang = Y.lang,
env = Y.env,
PROV = "_provides",
SUPER = "_supersedes",
REQ = "expanded",
AFTER = "_after",
VERSION = "2.9.0";
// version hack for cdn testing
// if (/VERSION/.test(VERSION)) {
// VERSION = "2.8.2";
// }
var YUI = {
dupsAllowed: {'yahoo': true, 'get': true},
/*
* The library metadata for the current release The is the default
* value for YAHOO.util.YUILoader.moduleInfo
* @property YUIInfo
* @static
*/
info: {
// 'root': '2.5.2/build/',
// 'base': 'http://yui.yahooapis.com/2.5.2/build/',
'root': VERSION + '/build/',
'base': 'http://yui.yahooapis.com/' + VERSION + '/build/',
'comboBase': 'http://yui.yahooapis.com/combo?',
'skin': {
'defaultSkin': 'sam',
'base': 'assets/skins/',
'path': 'skin.css',
'after': ['reset', 'fonts', 'grids', 'base'],
'rollup': 3
},
dupsAllowed: ['yahoo', 'get'],
'moduleInfo': {
'animation': {
'type': 'js',
'path': 'animation/animation-min.js',
'requires': ['dom', 'event']
},
'autocomplete': {
'type': 'js',
'path': 'autocomplete/autocomplete-min.js',
'requires': ['dom', 'event', 'datasource'],
'optional': ['connection', 'animation'],
'skinnable': true
},
'base': {
'type': 'css',
'path': 'base/base-min.css',
'after': ['reset', 'fonts', 'grids']
},
'button': {
'type': 'js',
'path': 'button/button-min.js',
'requires': ['element'],
'optional': ['menu'],
'skinnable': true
},
'calendar': {
'type': 'js',
'path': 'calendar/calendar-min.js',
'requires': ['event', 'dom'],
supersedes: ['datemath'],
'skinnable': true
},
'carousel': {
'type': 'js',
'path': 'carousel/carousel-min.js',
'requires': ['element'],
'optional': ['animation'],
'skinnable': true
},
'charts': {
'type': 'js',
'path': 'charts/charts-min.js',
'requires': ['element', 'json', 'datasource', 'swf']
},
'colorpicker': {
'type': 'js',
'path': 'colorpicker/colorpicker-min.js',
'requires': ['slider', 'element'],
'optional': ['animation'],
'skinnable': true
},
'connection': {
'type': 'js',
'path': 'connection/connection-min.js',
'requires': ['event'],
'supersedes': ['connectioncore']
},
'connectioncore': {
'type': 'js',
'path': 'connection/connection_core-min.js',
'requires': ['event'],
'pkg': 'connection'
},
'container': {
'type': 'js',
'path': 'container/container-min.js',
'requires': ['dom', 'event'],
// button is also optional, but this creates a circular
// dependency when loadOptional is specified. button
// optionally includes menu, menu requires container.
'optional': ['dragdrop', 'animation', 'connection'],
'supersedes': ['containercore'],
'skinnable': true
},
'containercore': {
'type': 'js',
'path': 'container/container_core-min.js',
'requires': ['dom', 'event'],
'pkg': 'container'
},
'cookie': {
'type': 'js',
'path': 'cookie/cookie-min.js',
'requires': ['yahoo']
},
'datasource': {
'type': 'js',
'path': 'datasource/datasource-min.js',
'requires': ['event'],
'optional': ['connection']
},
'datatable': {
'type': 'js',
'path': 'datatable/datatable-min.js',
'requires': ['element', 'datasource'],
'optional': ['calendar', 'dragdrop', 'paginator'],
'skinnable': true
},
datemath: {
'type': 'js',
'path': 'datemath/datemath-min.js',
'requires': ['yahoo']
},
'dom': {
'type': 'js',
'path': 'dom/dom-min.js',
'requires': ['yahoo']
},
'dragdrop': {
'type': 'js',
'path': 'dragdrop/dragdrop-min.js',
'requires': ['dom', 'event']
},
'editor': {
'type': 'js',
'path': 'editor/editor-min.js',
'requires': ['menu', 'element', 'button'],
'optional': ['animation', 'dragdrop'],
'supersedes': ['simpleeditor'],
'skinnable': true
},
'element': {
'type': 'js',
'path': 'element/element-min.js',
'requires': ['dom', 'event'],
'optional': ['event-mouseenter', 'event-delegate']
},
'element-delegate': {
'type': 'js',
'path': 'element-delegate/element-delegate-min.js',
'requires': ['element']
},
'event': {
'type': 'js',
'path': 'event/event-min.js',
'requires': ['yahoo']
},
'event-simulate': {
'type': 'js',
'path': 'event-simulate/event-simulate-min.js',
'requires': ['event']
},
'event-delegate': {
'type': 'js',
'path': 'event-delegate/event-delegate-min.js',
'requires': ['event'],
'optional': ['selector']
},
'event-mouseenter': {
'type': 'js',
'path': 'event-mouseenter/event-mouseenter-min.js',
'requires': ['dom', 'event']
},
'fonts': {
'type': 'css',
'path': 'fonts/fonts-min.css'
},
'get': {
'type': 'js',
'path': 'get/get-min.js',
'requires': ['yahoo']
},
'grids': {
'type': 'css',
'path': 'grids/grids-min.css',
'requires': ['fonts'],
'optional': ['reset']
},
'history': {
'type': 'js',
'path': 'history/history-min.js',
'requires': ['event']
},
'imagecropper': {
'type': 'js',
'path': 'imagecropper/imagecropper-min.js',
'requires': ['dragdrop', 'element', 'resize'],
'skinnable': true
},
'imageloader': {
'type': 'js',
'path': 'imageloader/imageloader-min.js',
'requires': ['event', 'dom']
},
'json': {
'type': 'js',
'path': 'json/json-min.js',
'requires': ['yahoo']
},
'layout': {
'type': 'js',
'path': 'layout/layout-min.js',
'requires': ['element'],
'optional': ['animation', 'dragdrop', 'resize', 'selector'],
'skinnable': true
},
'logger': {
'type': 'js',
'path': 'logger/logger-min.js',
'requires': ['event', 'dom'],
'optional': ['dragdrop'],
'skinnable': true
},
'menu': {
'type': 'js',
'path': 'menu/menu-min.js',
'requires': ['containercore'],
'skinnable': true
},
'paginator': {
'type': 'js',
'path': 'paginator/paginator-min.js',
'requires': ['element'],
'skinnable': true
},
'profiler': {
'type': 'js',
'path': 'profiler/profiler-min.js',
'requires': ['yahoo']
},
'profilerviewer': {
'type': 'js',
'path': 'profilerviewer/profilerviewer-min.js',
'requires': ['profiler', 'yuiloader', 'element'],
'skinnable': true
},
'progressbar': {
'type': 'js',
'path': 'progressbar/progressbar-min.js',
'requires': ['element'],
'optional': ['animation'],
'skinnable': true
},
'reset': {
'type': 'css',
'path': 'reset/reset-min.css'
},
'reset-fonts-grids': {
'type': 'css',
'path': 'reset-fonts-grids/reset-fonts-grids.css',
'supersedes': ['reset', 'fonts', 'grids', 'reset-fonts'],
'rollup': 4
},
'reset-fonts': {
'type': 'css',
'path': 'reset-fonts/reset-fonts.css',
'supersedes': ['reset', 'fonts'],
'rollup': 2
},
'resize': {
'type': 'js',
'path': 'resize/resize-min.js',
'requires': ['dragdrop', 'element'],
'optional': ['animation'],
'skinnable': true
},
'selector': {
'type': 'js',
'path': 'selector/selector-min.js',
'requires': ['yahoo', 'dom']
},
'simpleeditor': {
'type': 'js',
'path': 'editor/simpleeditor-min.js',
'requires': ['element'],
'optional': ['containercore', 'menu', 'button', 'animation', 'dragdrop'],
'skinnable': true,
'pkg': 'editor'
},
'slider': {
'type': 'js',
'path': 'slider/slider-min.js',
'requires': ['dragdrop'],
'optional': ['animation'],
'skinnable': true
},
'storage': {
'type': 'js',
'path': 'storage/storage-min.js',
'requires': ['yahoo', 'event', 'cookie'],
'optional': ['swfstore']
},
'stylesheet': {
'type': 'js',
'path': 'stylesheet/stylesheet-min.js',
'requires': ['yahoo']
},
'swf': {
'type': 'js',
'path': 'swf/swf-min.js',
'requires': ['element'],
'supersedes': ['swfdetect']
},
'swfdetect': {
'type': 'js',
'path': 'swfdetect/swfdetect-min.js',
'requires': ['yahoo']
},
'swfstore': {
'type': 'js',
'path': 'swfstore/swfstore-min.js',
'requires': ['element', 'cookie', 'swf']
},
'tabview': {
'type': 'js',
'path': 'tabview/tabview-min.js',
'requires': ['element'],
'optional': ['connection'],
'skinnable': true
},
'treeview': {
'type': 'js',
'path': 'treeview/treeview-min.js',
'requires': ['event', 'dom'],
'optional': ['json', 'animation', 'calendar'],
'skinnable': true
},
'uploader': {
'type': 'js',
'path': 'uploader/uploader-min.js',
'requires': ['element']
},
'utilities': {
'type': 'js',
'path': 'utilities/utilities.js',
'supersedes': ['yahoo', 'event', 'dragdrop', 'animation', 'dom', 'connection', 'element', 'yahoo-dom-event', 'get', 'yuiloader', 'yuiloader-dom-event'],
'rollup': 8
},
'yahoo': {
'type': 'js',
'path': 'yahoo/yahoo-min.js'
},
'yahoo-dom-event': {
'type': 'js',
'path': 'yahoo-dom-event/yahoo-dom-event.js',
'supersedes': ['yahoo', 'event', 'dom'],
'rollup': 3
},
'yuiloader': {
'type': 'js',
'path': 'yuiloader/yuiloader-min.js',
'supersedes': ['yahoo', 'get']
},
'yuiloader-dom-event': {
'type': 'js',
'path': 'yuiloader-dom-event/yuiloader-dom-event.js',
'supersedes': ['yahoo', 'dom', 'event', 'get', 'yuiloader', 'yahoo-dom-event'],
'rollup': 5
},
'yuitest': {
'type': 'js',
'path': 'yuitest/yuitest-min.js',
'requires': ['logger'],
'optional': ['event-simulate'],
'skinnable': true
}
}
},
ObjectUtil: {
appendArray: function(o, a) {
if (a) {
for (var i=0; i
* myFilter: {
* 'searchExp': "-min\\.js",
* 'replaceStr': "-debug.js"
* }
*
* @property filter
* @type string|{searchExp: string, replaceStr: string}
*/
this.filter = null;
/**
* The list of requested modules
* @property required
* @type {string: boolean}
*/
this.required = {};
/**
* The library metadata
* @property moduleInfo
*/
this.moduleInfo = lang.merge(YUI.info.moduleInfo);
/**
* List of rollup files found in the library metadata
* @property rollups
*/
this.rollups = null;
/**
* Whether or not to load optional dependencies for
* the requested modules
* @property loadOptional
* @type boolean
* @default false
*/
this.loadOptional = false;
/**
* All of the derived dependencies in sorted order, which
* will be populated when either calculate() or insert()
* is called
* @property sorted
* @type string[]
*/
this.sorted = [];
/**
* Set when beginning to compute the dependency tree.
* Composed of what YAHOO reports to be loaded combined
* with what has been loaded by the tool
* @propery loaded
* @type {string: boolean}
*/
this.loaded = {};
/**
* Flag to indicate the dependency tree needs to be recomputed
* if insert is called again.
* @property dirty
* @type boolean
* @default true
*/
this.dirty = true;
/**
* List of modules inserted by the utility
* @property inserted
* @type {string: boolean}
*/
this.inserted = {};
/**
* Provides the information used to skin the skinnable components.
* The following skin definition would result in 'skin1' and 'skin2'
* being loaded for calendar (if calendar was requested), and
* 'sam' for all other skinnable components:
*
*
* skin: {
*
* // The default skin, which is automatically applied if not
* // overriden by a component-specific skin definition.
* // Change this in to apply a different skin globally
* defaultSkin: 'sam',
*
* // This is combined with the loader base property to get
* // the default root directory for a skin. ex:
* // http://yui.yahooapis.com/2.3.0/build/assets/skins/sam/
* base: 'assets/skins/',
*
* // The name of the rollup css file for the skin
* path: 'skin.css',
*
* // The number of skinnable components requested that are
* // required before using the rollup file rather than the
* // individual component css files
* rollup: 3,
*
* // Any component-specific overrides can be specified here,
* // making it possible to load different skins for different
* // components. It is possible to load more than one skin
* // for a given component as well.
* overrides: {
* calendar: ['skin1', 'skin2']
* }
* }
*
* @property skin
*/
var self = this;
env.listeners.push(function(m) {
if (self._useYahooListener) {
//Y.log("YAHOO listener: " + m.name);
self.loadNext(m.name);
}
});
this.skin = lang.merge(YUI.info.skin);
this._config(o);
};
Y.util.YUILoader.prototype = {
FILTERS: {
RAW: {
'searchExp': "-min\\.js",
'replaceStr': ".js"
},
DEBUG: {
'searchExp': "-min\\.js",
'replaceStr': "-debug.js"
}
},
SKIN_PREFIX: "skin-",
_config: function(o) {
// apply config values
if (o) {
for (var i in o) {
if (lang.hasOwnProperty(o, i)) {
if (i == "require") {
this.require(o[i]);
} else {
this[i] = o[i];
}
}
}
}
// fix filter
var f = this.filter;
if (lang.isString(f)) {
f = f.toUpperCase();
// the logger must be available in order to use the debug
// versions of the library
if (f === "DEBUG") {
this.require("logger");
}
// hack to handle a a bug where LogWriter is being instantiated
// at load time, and the loader has no way to sort above it
// at the moment.
if (!Y.widget.LogWriter) {
Y.widget.LogWriter = function() {
return Y;
};
}
this.filter = this.FILTERS[f];
}
},
/** Add a new module to the component metadata.
* type can be "js" or "css". Both script and
* css are inserted if type is not provided.
* @method insert
* @param o optional options object
* @param type {string} the type of dependency to insert
*/
insert: function(o, type) {
// if (o) {
// Y.log("insert: " + lang.dump(o, 1) + ", " + type);
// } else {
// Y.log("insert: " + this.toString() + ", " + type);
// }
// build the dependency list
this.calculate(o);
// set a flag to indicate the load has started
this._loading = true;
// flag to indicate we are done with the combo service
// and any additional files will need to be loaded
// individually
// this._combineComplete = false;
// keep the loadType (js, css or undefined) cached
this.loadType = type;
if (this.combine) {
return this._combine();
}
if (!type) {
// Y.log("trying to load css first");
var self = this;
this._internalCallback = function() {
self._internalCallback = null;
self.insert(null, "js");
};
this.insert(null, "css");
return;
}
// start the load
this.loadNext();
},
/**
* Interns the script for the requested modules. The callback is
* provided a reference to the sandboxed YAHOO object. This only
* applies to the script: css can not be sandboxed; css will be
* loaded into the page normally if specified.
* @method sandbox
* @param callback {Function} the callback to exectued when the load is
* complete.
*/
sandbox: function(o, type) {
// if (o) {
// YAHOO.log("sandbox: " + lang.dump(o, 1) + ", " + type);
// } else {
// YAHOO.log("sandbox: " + this.toString() + ", " + type);
// }
var self = this,
success = function(o) {
var idx=o.argument[0], name=o.argument[2];
// store the response in the position it was requested
self._scriptText[idx] = o.responseText;
// YAHOO.log("received: " + o.responseText.substr(0, 100) + ", " + idx);
if (self.onProgress) {
self.onProgress.call(self.scope, {
name: name,
scriptText: o.responseText,
xhrResponse: o,
data: self.data
});
}
// only generate the sandbox once everything is loaded
self._loadCount++;
if (self._loadCount >= self._stopCount) {
// the variable to find
var v = self.varName || "YAHOO";
// wrap the contents of the requested modules in an anonymous function
var t = "(function() {\n";
// return the locally scoped reference.
var b = "\nreturn " + v + ";\n})();";
var ref = eval(t + self._scriptText.join("\n") + b);
self._pushEvents(ref);
if (ref) {
self.onSuccess.call(self.scope, {
reference: ref,
data: self.data
});
} else {
self._onFailure.call(self.varName + " reference failure");
}
}
},
failure = function(o) {
self.onFailure.call(self.scope, {
msg: "XHR failure",
xhrResponse: o,
data: self.data
});
};
self._config(o);
if (!self.onSuccess) {
throw new Error("You must supply an onSuccess handler for your sandbox");
}
self._sandbox = true;
// take care of any css first (this can't be sandboxed)
if (!type || type !== "js") {
self._internalCallback = function() {
self._internalCallback = null;
self.sandbox(null, "js");
};
self.insert(null, "css");
return;
}
// get the connection manager if not on the page
if (!util.Connect) {
// get a new loader instance to load connection.
var ld = new YAHOO.util.YUILoader();
ld.insert({
base: self.base,
filter: self.filter,
require: "connection",
insertBefore: self.insertBefore,
charset: self.charset,
onSuccess: function() {
self.sandbox(null, "js");
},
scope: self
}, "js");
return;
}
self._scriptText = [];
self._loadCount = 0;
self._stopCount = self.sorted.length;
self._xhr = [];
self.calculate();
var s=self.sorted, l=s.length, i, m, url;
for (i=0; iParse a JSON string, returning the native JavaScript * representation.
* *When lang.JSON.useNativeParse is true, this will defer to the native * JSON.parse if the browser has a native implementation. Otherwise, a * JavaScript implementation based on http://www.json.org/json2.js * is used.
* * @method parse * @param s {string} JSON string data * @param reviver {function} (optional) function(k,v) passed each key:value * pair of object literals, allowing pruning or altering values * @return {MIXED} the native JavaScript representation of the JSON string * @throws SyntaxError * @static */ parse : function (s,reviver) { if (typeof s !== 'string') { s += ''; } return Native && YAHOO.lang.JSON.useNativeParse ? Native.parse(s,reviver) : _parse(s,reviver); }, /** *Converts an arbitrary value to a JSON string representation.
* *Objects with cyclical references will trigger an exception.
* *If a whitelist is provided, only matching object keys will be * included. Alternately, a replacer function may be passed as the * second parameter. This function is executed on every value in the * input, and its return value will be used in place of the original value. * This is useful to serialize specialized objects or class instances.
* *If a positive integer or non-empty string is passed as the third * parameter, the output will be formatted with carriage returns and * indentation for readability. If a String is passed (such as "\t") it * will be used once for each indentation level. If a number is passed, * that number of spaces will be used.
* *When lang.JSON.useNativeStringify is true, this will defer to the * native JSON.stringify if the browser has a native implementation. * Otherwise, a JavaScript implementation is used.
* * @method stringify * @param o {MIXED} any arbitrary object to convert to JSON string * @param w {Array|Function} (optional) whitelist of acceptable object keys * to include OR a function(value,key) to alter values * before serialization * @param space {Number|String} (optional) indentation character(s) or * depthy of spaces to format the output * @return {string} JSON string representation of the input * @throws Error * @static */ stringify : function (o,w,space) { return Native && YAHOO.lang.JSON.useNativeStringify ? Native.stringify(o,w,space) : _stringify(o,w,space); }, /** * Serializes a Date instance as a UTC date string. Used internally by * the JavaScript implementation of stringify. If you need a different * Date serialization format, override this method. If you change this, * you should also set useNativeStringify to false, since native JSON * implementations serialize Dates per the ECMAScript 5 spec. You've been * warned. * * @method dateToString * @param d {Date} The Date to serialize * @return {String} stringified Date in UTC format YYYY-MM-DDTHH:mm:SSZ * @static */ dateToString : function (d) { function _zeroPad(v) { return v < 10 ? '0' + v : v; } return d.getUTCFullYear() + '-' + _zeroPad(d.getUTCMonth() + 1) + '-' + _zeroPad(d.getUTCDate()) + 'T' + _zeroPad(d.getUTCHours()) + COLON + _zeroPad(d.getUTCMinutes()) + COLON + _zeroPad(d.getUTCSeconds()) + 'Z'; }, /** * Reconstitute Date instances from the default JSON UTC serialization. * Reference this from a reviver function to rebuild Dates during the * parse operation. * * @method stringToDate * @param str {String} String serialization of a Date * @return {Date} */ stringToDate : function (str) { var m = str.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{3}))?Z$/); if (m) { var d = new Date(); d.setUTCFullYear(m[1], m[2]-1, m[3]); d.setUTCHours(m[4], m[5], m[6], (m[7] || 0)); return d; } return str; } }; /** *Four step determination whether a string is safe to eval. In three steps, * escape sequences, safe values, and properly placed open square brackets * are replaced with placeholders or removed. Then in the final step, the * result of all these replacements is checked for invalid characters.
* *This is an alias for isSafe.
* * @method isValid * @param str {String} JSON string to be tested * @return {boolean} is the string safe for eval? * @static * @deprecated use isSafe */ YAHOO.lang.JSON.isValid = YAHOO.lang.JSON.isSafe; })(); YAHOO.register("json", YAHOO.lang.JSON, {version: "2.9.0", build: "2800"}); /* Copyright (c) 2011, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html version: 2.9.0 */ (function () { /** * Config is a utility used within an Object to allow the implementer to * maintain a list of local configuration properties and listen for changes * to those properties dynamically using CustomEvent. The initial values are * also maintained so that the configuration can be reset at any given point * to its initial state. * @namespace YAHOO.util * @class Config * @constructor * @param {Object} owner The owner Object to which this Config Object belongs */ YAHOO.util.Config = function (owner) { if (owner) { this.init(owner); } if (!owner) { YAHOO.log("No owner specified for Config object", "error", "Config"); } }; var Lang = YAHOO.lang, CustomEvent = YAHOO.util.CustomEvent, Config = YAHOO.util.Config; /** * Constant representing the CustomEvent type for the config changed event. * @property YAHOO.util.Config.CONFIG_CHANGED_EVENT * @private * @static * @final */ Config.CONFIG_CHANGED_EVENT = "configChanged"; /** * Constant representing the boolean type string * @property YAHOO.util.Config.BOOLEAN_TYPE * @private * @static * @final */ Config.BOOLEAN_TYPE = "boolean"; Config.prototype = { /** * Object reference to the owner of this Config Object * @property owner * @type Object */ owner: null, /** * Boolean flag that specifies whether a queue is currently * being executed * @property queueInProgress * @type Boolean */ queueInProgress: false, /** * Maintains the local collection of configuration property objects and * their specified values * @property config * @private * @type Object */ config: null, /** * Maintains the local collection of configuration property objects as * they were initially applied. * This object is used when resetting a property. * @property initialConfig * @private * @type Object */ initialConfig: null, /** * Maintains the local, normalized CustomEvent queue * @property eventQueue * @private * @type Object */ eventQueue: null, /** * Custom Event, notifying subscribers when Config properties are set * (setProperty is called without the silent flag * @event configChangedEvent */ configChangedEvent: null, /** * Initializes the configuration Object and all of its local members. * @method init * @param {Object} owner The owner Object to which this Config * Object belongs */ init: function (owner) { this.owner = owner; this.configChangedEvent = this.createEvent(Config.CONFIG_CHANGED_EVENT); this.configChangedEvent.signature = CustomEvent.LIST; this.queueInProgress = false; this.config = {}; this.initialConfig = {}; this.eventQueue = []; }, /** * Validates that the value passed in is a Boolean. * @method checkBoolean * @param {Object} val The value to validate * @return {Boolean} true, if the value is valid */ checkBoolean: function (val) { return (typeof val == Config.BOOLEAN_TYPE); }, /** * Validates that the value passed in is a number. * @method checkNumber * @param {Object} val The value to validate * @return {Boolean} true, if the value is valid */ checkNumber: function (val) { return (!isNaN(val)); }, /** * Fires a configuration property event using the specified value. * @method fireEvent * @private * @param {String} key The configuration property's name * @param {value} Object The value of the correct type for the property */ fireEvent: function ( key, value ) { YAHOO.log("Firing Config event: " + key + "=" + value, "info", "Config"); var property = this.config[key]; if (property && property.event) { property.event.fire(value); } }, /** * Adds a property to the Config Object's private config hash. * @method addProperty * @param {String} key The configuration property's name * @param {Object} propertyObject The Object containing all of this * property's arguments */ addProperty: function ( key, propertyObject ) { key = key.toLowerCase(); YAHOO.log("Added property: " + key, "info", "Config"); this.config[key] = propertyObject; propertyObject.event = this.createEvent(key, { scope: this.owner }); propertyObject.event.signature = CustomEvent.LIST; propertyObject.key = key; if (propertyObject.handler) { propertyObject.event.subscribe(propertyObject.handler, this.owner); } this.setProperty(key, propertyObject.value, true); if (! propertyObject.suppressEvent) { this.queueProperty(key, propertyObject.value); } }, /** * Returns a key-value configuration map of the values currently set in * the Config Object. * @method getConfig * @return {Object} The current config, represented in a key-value map */ getConfig: function () { var cfg = {}, currCfg = this.config, prop, property; for (prop in currCfg) { if (Lang.hasOwnProperty(currCfg, prop)) { property = currCfg[prop]; if (property && property.event) { cfg[prop] = property.value; } } } return cfg; }, /** * Returns the value of specified property. * @method getProperty * @param {String} key The name of the property * @return {Object} The value of the specified property */ getProperty: function (key) { var property = this.config[key.toLowerCase()]; if (property && property.event) { return property.value; } else { return undefined; } }, /** * Resets the specified property's value to its initial value. * @method resetProperty * @param {String} key The name of the property * @return {Boolean} True is the property was reset, false if not */ resetProperty: function (key) { key = key.toLowerCase(); var property = this.config[key]; if (property && property.event) { if (key in this.initialConfig) { this.setProperty(key, this.initialConfig[key]); return true; } } else { return false; } }, /** * Sets the value of a property. If the silent property is passed as * true, the property's event will not be fired. * @method setProperty * @param {String} key The name of the property * @param {String} value The value to set the property to * @param {Boolean} silent Whether the value should be set silently, * without firing the property event. * @return {Boolean} True, if the set was successful, false if it failed. */ setProperty: function (key, value, silent) { var property; key = key.toLowerCase(); YAHOO.log("setProperty: " + key + "=" + value, "info", "Config"); if (this.queueInProgress && ! silent) { // Currently running through a queue... this.queueProperty(key,value); return true; } else { property = this.config[key]; if (property && property.event) { if (property.validator && !property.validator(value)) { return false; } else { property.value = value; if (! silent) { this.fireEvent(key, value); this.configChangedEvent.fire([key, value]); } return true; } } else { return false; } } }, /** * Sets the value of a property and queues its event to execute. If the * event is already scheduled to execute, it is * moved from its current position to the end of the queue. * @method queueProperty * @param {String} key The name of the property * @param {String} value The value to set the property to * @return {Boolean} true, if the set was successful, false if * it failed. */ queueProperty: function (key, value) { key = key.toLowerCase(); YAHOO.log("queueProperty: " + key + "=" + value, "info", "Config"); var property = this.config[key], foundDuplicate = false, iLen, queueItem, queueItemKey, queueItemValue, sLen, supercedesCheck, qLen, queueItemCheck, queueItemCheckKey, queueItemCheckValue, i, s, q; if (property && property.event) { if (!Lang.isUndefined(value) && property.validator && !property.validator(value)) { // validator return false; } else { if (!Lang.isUndefined(value)) { property.value = value; } else { value = property.value; } foundDuplicate = false; iLen = this.eventQueue.length; for (i = 0; i < iLen; i++) { queueItem = this.eventQueue[i]; if (queueItem) { queueItemKey = queueItem[0]; queueItemValue = queueItem[1]; if (queueItemKey == key) { /* found a dupe... push to end of queue, null current item, and break */ this.eventQueue[i] = null; this.eventQueue.push( [key, (!Lang.isUndefined(value) ? value : queueItemValue)]); foundDuplicate = true; break; } } } // this is a refire, or a new property in the queue if (! foundDuplicate && !Lang.isUndefined(value)) { this.eventQueue.push([key, value]); } } if (property.supercedes) { sLen = property.supercedes.length; for (s = 0; s < sLen; s++) { supercedesCheck = property.supercedes[s]; qLen = this.eventQueue.length; for (q = 0; q < qLen; q++) { queueItemCheck = this.eventQueue[q]; if (queueItemCheck) { queueItemCheckKey = queueItemCheck[0]; queueItemCheckValue = queueItemCheck[1]; if (queueItemCheckKey == supercedesCheck.toLowerCase() ) { this.eventQueue.push([queueItemCheckKey, queueItemCheckValue]); this.eventQueue[q] = null; break; } } } } } YAHOO.log("Config event queue: " + this.outputEventQueue(), "info", "Config"); return true; } else { return false; } }, /** * Fires the event for a property using the property's current value. * @method refireEvent * @param {String} key The name of the property */ refireEvent: function (key) { key = key.toLowerCase(); var property = this.config[key]; if (property && property.event && !Lang.isUndefined(property.value)) { if (this.queueInProgress) { this.queueProperty(key); } else { this.fireEvent(key, property.value); } } }, /** * Applies a key-value Object literal to the configuration, replacing * any existing values, and queueing the property events. * Although the values will be set, fireQueue() must be called for their * associated events to execute. * @method applyConfig * @param {Object} userConfig The configuration Object literal * @param {Boolean} init When set to true, the initialConfig will * be set to the userConfig passed in, so that calling a reset will * reset the properties to the passed values. */ applyConfig: function (userConfig, init) { var sKey, oConfig; if (init) { oConfig = {}; for (sKey in userConfig) { if (Lang.hasOwnProperty(userConfig, sKey)) { oConfig[sKey.toLowerCase()] = userConfig[sKey]; } } this.initialConfig = oConfig; } for (sKey in userConfig) { if (Lang.hasOwnProperty(userConfig, sKey)) { this.queueProperty(sKey, userConfig[sKey]); } } }, /** * Refires the events for all configuration properties using their * current values. * @method refresh */ refresh: function () { var prop; for (prop in this.config) { if (Lang.hasOwnProperty(this.config, prop)) { this.refireEvent(prop); } } }, /** * Fires the normalized list of queued property change events * @method fireQueue */ fireQueue: function () { var i, queueItem, key, value, property; this.queueInProgress = true; for (i = 0;i < this.eventQueue.length; i++) { queueItem = this.eventQueue[i]; if (queueItem) { key = queueItem[0]; value = queueItem[1]; property = this.config[key]; property.value = value; // Clear out queue entry, to avoid it being // re-added to the queue by any queueProperty/supercedes // calls which are invoked during fireEvent this.eventQueue[i] = null; this.fireEvent(key,value); } } this.queueInProgress = false; this.eventQueue = []; }, /** * Subscribes an external handler to the change event for any * given property. * @method subscribeToConfigEvent * @param {String} key The property name * @param {Function} handler The handler function to use subscribe to * the property's event * @param {Object} obj The Object to use for scoping the event handler * (see CustomEvent documentation) * @param {Boolean} overrideContext Optional. If true, will override * "this" within the handler to map to the scope Object passed into the * method. * @return {Boolean} True, if the subscription was successful, * otherwise false. */ subscribeToConfigEvent: function (key, handler, obj, overrideContext) { var property = this.config[key.toLowerCase()]; if (property && property.event) { if (!Config.alreadySubscribed(property.event, handler, obj)) { property.event.subscribe(handler, obj, overrideContext); } return true; } else { return false; } }, /** * Unsubscribes an external handler from the change event for any * given property. * @method unsubscribeFromConfigEvent * @param {String} key The property name * @param {Function} handler The handler function to use subscribe to * the property's event * @param {Object} obj The Object to use for scoping the event * handler (see CustomEvent documentation) * @return {Boolean} True, if the unsubscription was successful, * otherwise false. */ unsubscribeFromConfigEvent: function (key, handler, obj) { var property = this.config[key.toLowerCase()]; if (property && property.event) { return property.event.unsubscribe(handler, obj); } else { return false; } }, /** * Returns a string representation of the Config object * @method toString * @return {String} The Config object in string format. */ toString: function () { var output = "Config"; if (this.owner) { output += " [" + this.owner.toString() + "]"; } return output; }, /** * Returns a string representation of the Config object's current * CustomEvent queue * @method outputEventQueue * @return {String} The string list of CustomEvents currently queued * for execution */ outputEventQueue: function () { var output = "", queueItem, q, nQueue = this.eventQueue.length; for (q = 0; q < nQueue; q++) { queueItem = this.eventQueue[q]; if (queueItem) { output += queueItem[0] + "=" + queueItem[1] + ", "; } } return output; }, /** * Sets all properties to null, unsubscribes all listeners from each * property's change event and all listeners from the configChangedEvent. * @method destroy */ destroy: function () { var oConfig = this.config, sProperty, oProperty; for (sProperty in oConfig) { if (Lang.hasOwnProperty(oConfig, sProperty)) { oProperty = oConfig[sProperty]; oProperty.event.unsubscribeAll(); oProperty.event = null; } } this.configChangedEvent.unsubscribeAll(); this.configChangedEvent = null; this.owner = null; this.config = null; this.initialConfig = null; this.eventQueue = null; } }; /** * Checks to determine if a particular function/Object pair are already * subscribed to the specified CustomEvent * @method YAHOO.util.Config.alreadySubscribed * @static * @param {YAHOO.util.CustomEvent} evt The CustomEvent for which to check * the subscriptions * @param {Function} fn The function to look for in the subscribers list * @param {Object} obj The execution scope Object for the subscription * @return {Boolean} true, if the function/Object pair is already subscribed * to the CustomEvent passed in */ Config.alreadySubscribed = function (evt, fn, obj) { var nSubscribers = evt.subscribers.length, subsc, i; if (nSubscribers > 0) { i = nSubscribers - 1; do { subsc = evt.subscribers[i]; if (subsc && subsc.obj == obj && subsc.fn == fn) { return true; } } while (i--); } return false; }; YAHOO.lang.augmentProto(Config, YAHOO.util.EventProvider); }()); (function () { /** * The Container family of components is designed to enable developers to * create different kinds of content-containing modules on the web. Module * and Overlay are the most basic containers, and they can be used directly * or extended to build custom containers. Also part of the Container family * are four UI controls that extend Module and Overlay: Tooltip, Panel, * Dialog, and SimpleDialog. * @module container * @title Container * @requires yahoo, dom, event * @optional dragdrop, animation, button */ /** * Module is a JavaScript representation of the Standard Module Format. * Standard Module Format is a simple standard for markup containers where * child nodes representing the header, body, and footer of the content are * denoted using the CSS classes "hd", "bd", and "ft" respectively. * Module is the base class for all other classes in the YUI * Container package. * @namespace YAHOO.widget * @class Module * @constructor * @param {String} el The element ID representing the Module OR * @param {HTMLElement} el The element representing the Module * @param {Object} userConfig The configuration Object literal containing * the configuration that should be set for this module. See configuration * documentation for more details. */ YAHOO.widget.Module = function (el, userConfig) { if (el) { this.init(el, userConfig); } else { YAHOO.log("No element or element ID specified" + " for Module instantiation", "error"); } }; var Dom = YAHOO.util.Dom, Config = YAHOO.util.Config, Event = YAHOO.util.Event, CustomEvent = YAHOO.util.CustomEvent, Module = YAHOO.widget.Module, UA = YAHOO.env.ua, m_oModuleTemplate, m_oHeaderTemplate, m_oBodyTemplate, m_oFooterTemplate, /** * Constant representing the name of the Module's events * @property EVENT_TYPES * @private * @final * @type Object */ EVENT_TYPES = { "BEFORE_INIT": "beforeInit", "INIT": "init", "APPEND": "append", "BEFORE_RENDER": "beforeRender", "RENDER": "render", "CHANGE_HEADER": "changeHeader", "CHANGE_BODY": "changeBody", "CHANGE_FOOTER": "changeFooter", "CHANGE_CONTENT": "changeContent", "DESTROY": "destroy", "BEFORE_SHOW": "beforeShow", "SHOW": "show", "BEFORE_HIDE": "beforeHide", "HIDE": "hide" }, /** * Constant representing the Module's configuration properties * @property DEFAULT_CONFIG * @private * @final * @type Object */ DEFAULT_CONFIG = { "VISIBLE": { key: "visible", value: true, validator: YAHOO.lang.isBoolean }, "EFFECT": { key: "effect", suppressEvent: true, supercedes: ["visible"] }, "MONITOR_RESIZE": { key: "monitorresize", value: true }, "APPEND_TO_DOCUMENT_BODY": { key: "appendtodocumentbody", value: false } }; /** * Constant representing the prefix path to use for non-secure images * @property YAHOO.widget.Module.IMG_ROOT * @static * @final * @type String */ Module.IMG_ROOT = null; /** * Constant representing the prefix path to use for securely served images * @property YAHOO.widget.Module.IMG_ROOT_SSL * @static * @final * @type String */ Module.IMG_ROOT_SSL = null; /** * Constant for the default CSS class name that represents a Module * @property YAHOO.widget.Module.CSS_MODULE * @static * @final * @type String */ Module.CSS_MODULE = "yui-module"; /** * CSS classname representing the module header. NOTE: The classname is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source. * @property YAHOO.widget.Module.CSS_HEADER * @static * @final * @type String */ Module.CSS_HEADER = "hd"; /** * CSS classname representing the module body. NOTE: The classname is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source. * @property YAHOO.widget.Module.CSS_BODY * @static * @final * @type String */ Module.CSS_BODY = "bd"; /** * CSS classname representing the module footer. NOTE: The classname is inserted into the DOM as HTML, and should be escaped by the implementor if coming from an external source. * @property YAHOO.widget.Module.CSS_FOOTER * @static * @final * @type String */ Module.CSS_FOOTER = "ft"; /** * Constant representing the url for the "src" attribute of the iframe * used to monitor changes to the browser's base font size * @property YAHOO.widget.Module.RESIZE_MONITOR_SECURE_URL * @static * @final * @type String */ Module.RESIZE_MONITOR_SECURE_URL = "javascript:false;"; /** * Constant representing the buffer amount (in pixels) to use when positioning * the text resize monitor offscreen. The resize monitor is positioned * offscreen by an amount eqaul to its offsetHeight + the buffer value. * * @property YAHOO.widget.Module.RESIZE_MONITOR_BUFFER * @static * @type Number */ // Set to 1, to work around pixel offset in IE8, which increases when zoom is used Module.RESIZE_MONITOR_BUFFER = 1; /** * Singleton CustomEvent fired when the font size is changed in the browser. * Opera's "zoom" functionality currently does not support text * size detection. * @event YAHOO.widget.Module.textResizeEvent */ Module.textResizeEvent = new CustomEvent("textResize"); /** * Helper utility method, which forces a document level * redraw for Opera, which can help remove repaint * irregularities after applying DOM changes. * * @method YAHOO.widget.Module.forceDocumentRedraw * @static */ Module.forceDocumentRedraw = function() { var docEl = document.documentElement; if (docEl) { docEl.className += " "; docEl.className = YAHOO.lang.trim(docEl.className); } }; function createModuleTemplate() { if (!m_oModuleTemplate) { m_oModuleTemplate = document.createElement("div"); m_oModuleTemplate.innerHTML = ("" + ""); m_oHeaderTemplate = m_oModuleTemplate.firstChild; m_oBodyTemplate = m_oHeaderTemplate.nextSibling; m_oFooterTemplate = m_oBodyTemplate.nextSibling; } return m_oModuleTemplate; } function createHeader() { if (!m_oHeaderTemplate) { createModuleTemplate(); } return (m_oHeaderTemplate.cloneNode(false)); } function createBody() { if (!m_oBodyTemplate) { createModuleTemplate(); } return (m_oBodyTemplate.cloneNode(false)); } function createFooter() { if (!m_oFooterTemplate) { createModuleTemplate(); } return (m_oFooterTemplate.cloneNode(false)); } Module.prototype = { /** * The class's constructor function * @property contructor * @type Function */ constructor: Module, /** * The main module element that contains the header, body, and footer * @property element * @type HTMLElement */ element: null, /** * The header element, denoted with CSS class "hd" * @property header * @type HTMLElement */ header: null, /** * The body element, denoted with CSS class "bd" * @property body * @type HTMLElement */ body: null, /** * The footer element, denoted with CSS class "ft" * @property footer * @type HTMLElement */ footer: null, /** * The id of the element * @property id * @type String */ id: null, /** * A string representing the root path for all images created by * a Module instance. * @deprecated It is recommend that any images for a Module be applied * via CSS using the "background-image" property. * @property imageRoot * @type String */ imageRoot: Module.IMG_ROOT, /** * Initializes the custom events for Module which are fired * automatically at appropriate times by the Module class. * @method initEvents */ initEvents: function () { var SIGNATURE = CustomEvent.LIST; /** * CustomEvent fired prior to class initalization. * @event beforeInitEvent * @param {class} classRef class reference of the initializing * class, such as this.beforeInitEvent.fire(Module) */ this.beforeInitEvent = this.createEvent(EVENT_TYPES.BEFORE_INIT); this.beforeInitEvent.signature = SIGNATURE; /** * CustomEvent fired after class initalization. * @event initEvent * @param {class} classRef class reference of the initializing * class, such as this.beforeInitEvent.fire(Module) */ this.initEvent = this.createEvent(EVENT_TYPES.INIT); this.initEvent.signature = SIGNATURE; /** * CustomEvent fired when the Module is appended to the DOM * @event appendEvent */ this.appendEvent = this.createEvent(EVENT_TYPES.APPEND); this.appendEvent.signature = SIGNATURE; /** * CustomEvent fired before the Module is rendered * @event beforeRenderEvent */ this.beforeRenderEvent = this.createEvent(EVENT_TYPES.BEFORE_RENDER); this.beforeRenderEvent.signature = SIGNATURE; /** * CustomEvent fired after the Module is rendered * @event renderEvent */ this.renderEvent = this.createEvent(EVENT_TYPES.RENDER); this.renderEvent.signature = SIGNATURE; /** * CustomEvent fired when the header content of the Module * is modified * @event changeHeaderEvent * @param {String/HTMLElement} content String/element representing * the new header content */ this.changeHeaderEvent = this.createEvent(EVENT_TYPES.CHANGE_HEADER); this.changeHeaderEvent.signature = SIGNATURE; /** * CustomEvent fired when the body content of the Module is modified * @event changeBodyEvent * @param {String/HTMLElement} content String/element representing * the new body content */ this.changeBodyEvent = this.createEvent(EVENT_TYPES.CHANGE_BODY); this.changeBodyEvent.signature = SIGNATURE; /** * CustomEvent fired when the footer content of the Module * is modified * @event changeFooterEvent * @param {String/HTMLElement} content String/element representing * the new footer content */ this.changeFooterEvent = this.createEvent(EVENT_TYPES.CHANGE_FOOTER); this.changeFooterEvent.signature = SIGNATURE; /** * CustomEvent fired when the content of the Module is modified * @event changeContentEvent */ this.changeContentEvent = this.createEvent(EVENT_TYPES.CHANGE_CONTENT); this.changeContentEvent.signature = SIGNATURE; /** * CustomEvent fired when the Module is destroyed * @event destroyEvent */ this.destroyEvent = this.createEvent(EVENT_TYPES.DESTROY); this.destroyEvent.signature = SIGNATURE; /** * CustomEvent fired before the Module is shown * @event beforeShowEvent */ this.beforeShowEvent = this.createEvent(EVENT_TYPES.BEFORE_SHOW); this.beforeShowEvent.signature = SIGNATURE; /** * CustomEvent fired after the Module is shown * @event showEvent */ this.showEvent = this.createEvent(EVENT_TYPES.SHOW); this.showEvent.signature = SIGNATURE; /** * CustomEvent fired before the Module is hidden * @event beforeHideEvent */ this.beforeHideEvent = this.createEvent(EVENT_TYPES.BEFORE_HIDE); this.beforeHideEvent.signature = SIGNATURE; /** * CustomEvent fired after the Module is hidden * @event hideEvent */ this.hideEvent = this.createEvent(EVENT_TYPES.HIDE); this.hideEvent.signature = SIGNATURE; }, /** * String identifying whether the current platform is windows or mac. This property * currently only identifies these 2 platforms, and returns false otherwise. * @property platform * @deprecated Use YAHOO.env.ua * @type {String|Boolean} */ platform: function () { var ua = navigator.userAgent.toLowerCase(); if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) { return "windows"; } else if (ua.indexOf("macintosh") != -1) { return "mac"; } else { return false; } }(), /** * String representing the user-agent of the browser * @deprecated Use YAHOO.env.ua * @property browser * @type {String|Boolean} */ browser: function () { var ua = navigator.userAgent.toLowerCase(); /* Check Opera first in case of spoof and check Safari before Gecko since Safari's user agent string includes "like Gecko" */ if (ua.indexOf('opera') != -1) { return 'opera'; } else if (ua.indexOf('msie 7') != -1) { return 'ie7'; } else if (ua.indexOf('msie') != -1) { return 'ie'; } else if (ua.indexOf('safari') != -1) { return 'safari'; } else if (ua.indexOf('gecko') != -1) { return 'gecko'; } else { return false; } }(), /** * Boolean representing whether or not the current browsing context is * secure (https) * @property isSecure * @type Boolean */ isSecure: function () { if (window.location.href.toLowerCase().indexOf("https") === 0) { return true; } else { return false; } }(), /** * Initializes the custom events for Module which are fired * automatically at appropriate times by the Module class. */ initDefaultConfig: function () { // Add properties // /** * Specifies whether the Module is visible on the page. * @config visible * @type Boolean * @default true */ this.cfg.addProperty(DEFAULT_CONFIG.VISIBLE.key, { handler: this.configVisible, value: DEFAULT_CONFIG.VISIBLE.value, validator: DEFAULT_CONFIG.VISIBLE.validator }); /** ** Object or array of objects representing the ContainerEffect * classes that are active for animating the container. *
** NOTE: Although this configuration * property is introduced at the Module level, an out of the box * implementation is not shipped for the Module class so setting * the proroperty on the Module class has no effect. The Overlay * class is the first class to provide out of the box ContainerEffect * support. *
* @config effect * @type Object * @default null */ this.cfg.addProperty(DEFAULT_CONFIG.EFFECT.key, { handler: this.configEffect, suppressEvent: DEFAULT_CONFIG.EFFECT.suppressEvent, supercedes: DEFAULT_CONFIG.EFFECT.supercedes }); /** * Specifies whether to create a special proxy iframe to monitor * for user font resizing in the document * @config monitorresize * @type Boolean * @default true */ this.cfg.addProperty(DEFAULT_CONFIG.MONITOR_RESIZE.key, { handler: this.configMonitorResize, value: DEFAULT_CONFIG.MONITOR_RESIZE.value }); /** * Specifies if the module should be rendered as the first child * of document.body or appended as the last child when render is called * with document.body as the "appendToNode". ** Appending to the body while the DOM is still being constructed can * lead to Operation Aborted errors in IE hence this flag is set to * false by default. *
* * @config appendtodocumentbody * @type Boolean * @default false */ this.cfg.addProperty(DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.key, { value: DEFAULT_CONFIG.APPEND_TO_DOCUMENT_BODY.value }); }, /** * The Module class's initialization method, which is executed for * Module and all of its subclasses. This method is automatically * called by the constructor, and sets up all DOM references for * pre-existing markup, and creates required markup if it is not * already present. ** If the element passed in does not have an id, one will be generated * for it. *
* @method init * @param {String} el The element ID representing the Module OR * @param {HTMLElement} el The element representing the Module * @param {Object} userConfig The configuration Object literal * containing the configuration that should be set for this module. * See configuration documentation for more details. */ init: function (el, userConfig) { var elId, child; this.initEvents(); this.beforeInitEvent.fire(Module); /** * The Module's Config object used for monitoring * configuration properties. * @property cfg * @type YAHOO.util.Config */ this.cfg = new Config(this); if (this.isSecure) { this.imageRoot = Module.IMG_ROOT_SSL; } if (typeof el == "string") { elId = el; el = document.getElementById(el); if (! el) { el = (createModuleTemplate()).cloneNode(false); el.id = elId; } } this.id = Dom.generateId(el); this.element = el; child = this.element.firstChild; if (child) { var fndHd = false, fndBd = false, fndFt = false; do { // We're looking for elements if (1 == child.nodeType) { if (!fndHd && Dom.hasClass(child, Module.CSS_HEADER)) { this.header = child; fndHd = true; } else if (!fndBd && Dom.hasClass(child, Module.CSS_BODY)) { this.body = child; fndBd = true; } else if (!fndFt && Dom.hasClass(child, Module.CSS_FOOTER)){ this.footer = child; fndFt = true; } } } while ((child = child.nextSibling)); } this.initDefaultConfig(); Dom.addClass(this.element, Module.CSS_MODULE); if (userConfig) { this.cfg.applyConfig(userConfig, true); } /* Subscribe to the fireQueue() method of Config so that any queued configuration changes are excecuted upon render of the Module */ if (!Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) { this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true); } this.initEvent.fire(Module); }, /** * Initialize an empty IFRAME that is placed out of the visible area * that can be used to detect text resize. * @method initResizeMonitor */ initResizeMonitor: function () { var isGeckoWin = (UA.gecko && this.platform == "windows"); if (isGeckoWin) { // Help prevent spinning loading icon which // started with FireFox 2.0.0.8/Win var self = this; setTimeout(function(){self._initResizeMonitor();}, 0); } else { this._initResizeMonitor(); } }, /** * Create and initialize the text resize monitoring iframe. * * @protected * @method _initResizeMonitor */ _initResizeMonitor : function() { var oDoc, oIFrame, sHTML; function fireTextResize() { Module.textResizeEvent.fire(); } if (!UA.opera) { oIFrame = Dom.get("_yuiResizeMonitor"); var supportsCWResize = this._supportsCWResize(); if (!oIFrame) { oIFrame = document.createElement("iframe"); if (this.isSecure && Module.RESIZE_MONITOR_SECURE_URL && UA.ie) { oIFrame.src = Module.RESIZE_MONITOR_SECURE_URL; } if (!supportsCWResize) { // Can't monitor on contentWindow, so fire from inside iframe sHTML = [" to your HTML Add class="sortable" to any table you'd like to make sortable Click on the headers to sort Thanks to many, many people for contributions and suggestions. Licenced as X11: http://www.kryogenix.org/code/browser/licence.html This basically means: do what you want with it. */ var stIsIE = 0; if (navigator.appVersion.indexOf("MSIE") != -1) { stIsIE = 1; } sorttable = { init: function() { // quit if this function has already been called if (arguments.callee.done) { return; } // flag this function so we don't do the same thing twice arguments.callee.done = true; if (!document.createElement || !document.getElementsByTagName) { return; } sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; forEach(document.getElementsByTagName("table"), function(table) { if (table.className.search(/\bsortable\b/) != -1) { var customMethodName = table.getAttribute("custom-sort-method"); if (customMethodName) { sorttable.makeSortable(table, customMethodName); } else { sorttable.makeSortable(table); } } }); }, makeSortable: function(table, customClickHanderName) { if (table.getElementsByTagName("thead").length == 0) { // table doesn't have a tHead. Since it should have, create one and // put the first table row in it. the = document.createElement("thead"); the.appendChild(table.rows[0]); table.insertBefore(the, table.firstChild); } // Safari doesn't support table.tHead, sigh if (table.tHead == null) { table.tHead = table.getElementsByTagName("thead")[0]; } // if creating the table head made an empty tbody element nuke it var tBody = table.getElementsByTagName("tbody"); if (tBody.length > 1) { var is_empty = 1; for (var i = 0; i < tBody[0].childNodes.length; i++) { if (tBody[0].childNodes[i].nodeType != 3) { is_empty = 0; break; } } if (is_empty) { table.removeChild(tBody[0]); } } if (table.tHead.rows.length != 1) { return; } // can't cope with two header rows // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as // "total" rows, for example). This is B&R, since what you're supposed // to do is put them in a tfoot. So, if there are sortbottom rows, // for backwards compatibility, move them to tfoot (creating it if needed). sortbottomrows = []; for (var i = 0; i < table.rows.length; i++) { if (table.rows[i].className.search(/\bsortbottom\b/) != -1) { sortbottomrows[sortbottomrows.length] = table.rows[i]; } } if (sortbottomrows) { if (table.tFoot == null) { // table doesn't have a tfoot. Create one. tfo = document.createElement("tfoot"); table.appendChild(tfo); } for (var i = 0; i < sortbottomrows.length; i++) { tfo.appendChild(sortbottomrows[i]); } delete sortbottomrows; } // work through each column and calculate its type headrow = table.tHead.rows[0].cells; for (var i = 0; i < headrow.length; i++) { // manually override the type with a sorttable_type attribute if (!headrow[i].className.match(/\bsorttable_nosort\b/) && !( headrow[i].getAttribute("nonsortable") != null && headrow[i].getAttribute("nonsortable").length > 0 ) ) { mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/); if (mtch) { override = mtch[1]; } if (mtch && typeof sorttable["sort_" + override] == "function") { headrow[i].sorttable_sortfunction = sorttable["sort_" + override]; } else { headrow[i].sorttable_sortfunction = sorttable.guessType(table, i); } // make it clickable to sort headrow[i].sorttable_columnindex = i; headrow[i].sorttable_tbody = table.tBodies[0]; headrow[i].className += " clickable"; sorttable.initializeHeader(headrow[i]); // Build the sort handler dean_addEvent(headrow[i], "click", function(e) { var customClickHandler = null; if (customClickHanderName) { customClickHandler = window[customClickHanderName]; } if (this.className.search(/\bsorttable_sorted\b/) != -1) { // if we're already sorted by this column, just // reverse the table, which is quicker if (!customClickHanderName) { sorttable.reverse(this.sorttable_tbody); } this.className = this.className.replace("sorttable_sorted", "sorttable_sorted_reverse"); this.removeChild(document.getElementById("sorttable_sortfwdind")); sortrevind = document.createElement("span"); sortrevind.id = "sorttable_sortrevind"; sortrevind.className = "sortable_reverse"; sortrevind.innerHTML = stIsIE ? ' 5' : " ▴"; this.appendChild(sortrevind); if (customClickHandler) { // Normalize the event for ie. if (!e.currentTarget) { e.currentTarget = this; } customClickHandler(e); } return; } if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { // if we're already sorted by this column in reverse, just // re-reverse the table, which is quicker if (!customClickHanderName) { sorttable.reverse(this.sorttable_tbody); } this.className = this.className.replace("sorttable_sorted_reverse", "sorttable_sorted"); this.removeChild(document.getElementById("sorttable_sortrevind")); sortfwdind = document.createElement("span"); sortfwdind.id = "sorttable_sortfwdind"; sortfwdind.className = "sortable_forward"; sortfwdind.innerHTML = stIsIE ? ' 6' : " ▾"; this.appendChild(sortfwdind); if (customClickHandler) { // Normalize the event for ie. if (!e.currentTarget) { e.currentTarget = this; } customClickHandler(e); } return; } // remove sorttable_sorted classes theadrow = this.parentNode; forEach(theadrow.childNodes, function(cell) { if (cell.nodeType == 1) { // an element cell.className = cell.className.replace("sorttable_sorted_reverse", ""); cell.className = cell.className.replace("sorttable_sorted", ""); } }); sortfwdind = document.getElementById("sorttable_sortfwdind"); if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } sortrevind = document.getElementById("sorttable_sortrevind"); if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } // Customize the initial direction for this column. var isDefaultReverse = this.getAttribute("sortable-default-reverse") === "1"; if (!isDefaultReverse) { this.className += " sorttable_sorted"; sortfwdind = document.createElement("span"); sortfwdind.id = "sorttable_sortfwdind"; sortfwdind.innerHTML = stIsIE ? ' 6' : " ▾"; this.appendChild(sortfwdind); } else { this.className += " sorttable_sorted_reverse"; sortrevind = document.createElement("span"); sortrevind.id = "sorttable_sortrevind"; sortrevind.className = "sortable_reverse"; sortrevind.innerHTML = stIsIE ? ' 5' : " ▴"; this.appendChild(sortrevind); } if (customClickHandler) { // Normalize the event for ie. if (!e.currentTarget) { e.currentTarget = this; } // Rely on this method to trigger sorting, client or server customClickHandler(e); } else { // Do the client sorting // build an array to sort. This is a Schwartzian transform thing, // i.e., we "decorate" each row with the actual sort key, // sort based on the sort keys, and then put the rows back in order // which is a lot faster because you only do getInnerText once per row row_array = []; col = this.sorttable_columnindex; rows = this.sorttable_tbody.rows; for (var j = 0; j < rows.length; j++) { row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]]; } row_array.sort(this.sorttable_sortfunction); // sorttable.shaker_sort(row_array, this.sorttable_sortfunction); tb = this.sorttable_tbody; for (var j = 0; j < row_array.length; j++) { var new_class, other_class; if ((j % 2) == 0) { new_class = "info-even"; other_class = "info-odd"; } else { new_class = "info-odd"; other_class = "info-even"; } var row_class = row_array[j][1].className; row_class = row_class.replace(other_class, new_class).replace(/^\s+|\s+$/, "").replace(/\s+/, " "); row_array[j][1].className = row_class; tb.appendChild(row_array[j][1]); } delete row_array; } }); } } }, initializeHeader: function(current) { if (current.className.search(/\bsorttable_sorted\b/) != -1) { sortfwdind = document.createElement("span"); sortfwdind.id = "sorttable_sortfwdind"; sortfwdind.className = "sortable_forward"; sortfwdind.innerHTML = stIsIE ? ' 6' : " ▾"; current.appendChild(sortfwdind); } if (current.className.search(/\bsorttable_sorted_reverse\b/) != -1) { sortrevind = document.createElement("span"); sortrevind.id = "sorttable_sortrevind"; sortrevind.className = "sortable_reverse"; sortrevind.innerHTML = stIsIE ? ' 5' : " ▴"; current.appendChild(sortrevind); } }, guessType: function(table, column) { // guess the type of a column based on its first non-blank row sortfn = sorttable.sort_alpha; if (!table.tBodies[0]) { return sortfn; } for (var i = 0; i < table.tBodies[0].rows.length; i++) { text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]); if (text != "") { if (text.match(/^-?[�$�]?[\d,.]+%?\s(Bytes|KB|MB|GB|TB|PB)$/)) { return sorttable.sort_space; } if (text.match(/^-?[�$�]?[\d,.]+%?$/)) { return sorttable.sort_numeric; } // check for a date: dd/mm/yyyy or dd/mm/yy // can have / or . or - as separator // can be mm/dd as well possdate = text.match(sorttable.DATE_RE); if (possdate) { // looks like a date first = parseInt(possdate[1]); second = parseInt(possdate[2]); if (first > 12) { // definitely dd/mm return sorttable.sort_ddmm; } else if (second > 12) { return sorttable.sort_mmdd; } else { // looks like a date, but we can't tell which, so assume // that it's dd/mm (English imperialism!) and keep looking sortfn = sorttable.sort_ddmm; } } } } return sortfn; }, getInnerText: function(node) { // gets the text we want to use for sorting for a cell. // strips leading and trailing whitespace. // this is *not* a generic getInnerText function; it's special to sorttable. // for example, you can override the cell text with a customkey attribute. // it also gets .value for fields. if (!node) { return ""; } hasInputs = (typeof node.getElementsByTagName == "function") && node.getElementsByTagName("input").length; if (node.nodeType != 3 && node.getAttribute("sorttable_customkey") != null) { return node.getAttribute("sorttable_customkey"); } else if (typeof node.textContent != "undefined" && !hasInputs) { return node.textContent.replace(/^\s+|\s+$/g, ""); } else if (typeof node.innerText != "undefined" && !hasInputs) { return node.innerText.replace(/^\s+|\s+$/g, ""); } else if (typeof node.text != "undefined" && !hasInputs) { return node.text.replace(/^\s+|\s+$/g, ""); } else { switch (node.nodeType) { case 3: if (node.nodeName.toLowerCase() == "input") { return node.value.replace(/^\s+|\s+$/g, ""); } case 4: return node.nodeValue.replace(/^\s+|\s+$/g, ""); break; case 1: case 11: var innerText = ""; for (var i = 0; i < node.childNodes.length; i++) { innerText += sorttable.getInnerText(node.childNodes[i]); } return innerText.replace(/^\s+|\s+$/g, ""); break; default: return ""; } } }, reverse: function(tbody) { // reverse the rows in a tbody newrows = []; for (var i = 0; i < tbody.rows.length; i++) { newrows[newrows.length] = tbody.rows[i]; } for (var i = newrows.length - 1; i >= 0; i--) { tbody.appendChild(newrows[i]); } delete newrows; }, /* sort functions each sort function takes two parameters, a and b you are comparing a[0] and b[0] */ sort_space: function(a, b) { abytesunit = a[0].split(/\s+/); aa = unit_to_bytes(abytesunit[0], abytesunit[1]); if (isNaN(aa)) { aa = 0; } bbytesunit = b[0].split(/\s+/); bb = unit_to_bytes(bbytesunit[0], bbytesunit[1]); if (isNaN(bb)) { bb = 0; } return aa - bb; }, sort_numeric: function(a, b) { aa = parseFloat(a[0].replace(/[^0-9.-]/g, "")); if (isNaN(aa)) { aa = 0; } bb = parseFloat(b[0].replace(/[^0-9.-]/g, "")); if (isNaN(bb)) { bb = 0; } return aa - bb; }, sort_alpha: function(a, b) { if (a[0] == b[0]) { return 0; } if (a[0] < b[0]) { return -1; } return 1; }, sort_ddmm: function(a, b) { mtch = a[0].match(sorttable.DATE_RE); y = mtch[3]; m = mtch[2]; d = mtch[1]; if (m.length == 1) { m = "0" + m; } if (d.length == 1) { d = "0" + d; } dt1 = y + m + d; mtch = b[0].match(sorttable.DATE_RE); y = mtch[3]; m = mtch[2]; d = mtch[1]; if (m.length == 1) { m = "0" + m; } if (d.length == 1) { d = "0" + d; } dt2 = y + m + d; if (dt1 == dt2) { return 0; } if (dt1 < dt2) { return -1; } return 1; }, sort_mmdd: function(a, b) { mtch = a[0].match(sorttable.DATE_RE); y = mtch[3]; d = mtch[2]; m = mtch[1]; if (m.length == 1) { m = "0" + m; } if (d.length == 1) { d = "0" + d; } dt1 = y + m + d; mtch = b[0].match(sorttable.DATE_RE); y = mtch[3]; d = mtch[2]; m = mtch[1]; if (m.length == 1) { m = "0" + m; } if (d.length == 1) { d = "0" + d; } dt2 = y + m + d; if (dt1 == dt2) { return 0; } if (dt1 < dt2) { return -1; } return 1; }, shaker_sort: function(list, comp_func) { // A stable sort function to allow multi-level sorting of data // see: http://en.wikipedia.org/wiki/Cocktail_sort // thanks to Joseph Nahmias var b = 0; var t = list.length - 1; var swap = true; while (swap) { swap = false; for (var i = b; i < t; ++i) { if ( comp_func(list[i], list[i + 1]) > 0 ) { var q = list[i]; list[i] = list[i + 1]; list[i + 1] = q; swap = true; } } // for t--; if (!swap) { break; } for (var i = t; i > b; --i) { if ( comp_func(list[i], list[i - 1]) < 0 ) { var q = list[i]; list[i] = list[i - 1]; list[i - 1] = q; swap = true; } } // for b++; } // while(swap) } }; /* ****************************************************************** Supporting functions: bundled here to avoid depending on a library ****************************************************************** */ YAHOO.util.Event.onDOMReady(sorttable.init); // written by Dean Edwards, 2005 // with input from Tino Zijdel, Matthias Miller, Diego Perini // http://dean.edwards.name/weblog/2005/10/add-event/ function dean_addEvent(element, type, handler) { if (element.addEventListener) { element.addEventListener(type, handler, false); } else { // assign each event handler a unique ID if (!handler.$$guid) { handler.$$guid = dean_addEvent.guid++; } // create a hash table of event types for the element if (!element.events) { element.events = {}; } // create a hash table of event handlers for each element/event pair var handlers = element.events[type]; if (!handlers) { handlers = element.events[type] = {}; // store the existing event handler (if there is one) if (element["on" + type]) { handlers[0] = element["on" + type]; } } // store the event handler in the hash table handlers[handler.$$guid] = handler; // assign a global event handler to do all the work element["on" + type] = handleEvent; } }; // a counter used to create unique IDs dean_addEvent.guid = 1; function removeEvent(element, type, handler) { if (element.removeEventListener) { element.removeEventListener(type, handler, false); } else { // delete the event handler from the hash table if (element.events && element.events[type]) { delete element.events[type][handler.$$guid]; } } }; function handleEvent(event) { var returnValue = true; // grab the event object (IE uses a global event object) event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event); // get a reference to the hash table of event handlers var handlers = this.events[event.type]; // execute each event handler for (var i in handlers) { this.$$handleEvent = handlers[i]; if (this.$$handleEvent(event) === false) { returnValue = false; } } return returnValue; }; function fixEvent(event) { // add W3C standard event methods event.preventDefault = fixEvent.preventDefault; event.stopPropagation = fixEvent.stopPropagation; return event; }; fixEvent.preventDefault = function() { this.returnValue = false; }; fixEvent.stopPropagation = function() { this.cancelBubble = true; }; // Dean's forEach: http://dean.edwards.name/base/forEach.js /* forEach, version 1.0 Copyright 2006, Dean Edwards License: http://www.opensource.org/licenses/mit-license.php */ // array-like enumeration if (!Array.forEach) { // mozilla already supports this Array.forEach = function(array, block, context) { for (var i = 0; i < array.length; i++) { block.call(context, array[i], i, array); } }; } // generic enumeration Function.prototype.forEach = function(object, block, context) { for (var key in object) { if (typeof this.prototype[key] == "undefined") { block.call(context, object[key], key, object); } } }; // character enumeration String.forEach = function(string, block, context) { Array.forEach(string.split(""), function(chr, index) { block.call(context, chr, index, string); }); }; // globally resolve forEach enumeration var forEach = function(object, block, context) { if (object) { var resolve = Object; // default if (object instanceof Function) { // functions have a "length" property resolve = Function; } else if (object.forEach instanceof Function) { // the object implements a custom forEach method so use that object.forEach(block, context); return; } else if (typeof object == "string") { // the object is a string resolve = String; } else if (typeof object.length == "number") { // the object is array-like resolve = Array; } resolve.forEach(object, block, context); } }; function unit_to_bytes(num, bytes) { switch (bytes) { case "KB": return parseFloat(num) * 1024; case "MB": return parseFloat(num) * 1024 * 1024; case "GB": return parseFloat(num) * 1024 * 1024 * 1024; case "TB": return parseFloat(num) * 1024 * 1024 * 1024 * 1024; case "PB": return parseFloat(num) * 1024 * 1024 * 1024 * 1024 * 1024; default: return parseFloat(num); } } /* ***** BEGIN LICENSE BLOCK ***** # cpanel12 - xmlapi.js Copyright(c) 1997-2020 cPanel, L.L.C. # All rights reserved. # copyright@cpanel.net http://cpanel.net # This code is subject to the cPanel license. Unauthorized copying is prohibited * ***** END LICENSE BLOCK ***** * ***** BEGIN APPLICABLE CODE BLOCK ***** */ var use_fast_proto = 1; function cpanel_api1() { var argv = cpanel_api1.arguments; var mycallback = argv[0]; var module = argv[1]; var func = argv[2]; var argc = argv.length; var callback = { success: cpanel_api1_parser, argument: mycallback }; var sFormData; if (use_fast_proto) { sFormData = "cpanel_xmlapi_module=" + encodeURIComponent(module) + "&cpanel_xmlapi_func=" + encodeURIComponent(func) + "&cpanel_xmlapi_apiversion=1"; var argnum = 0; for (var i = 3; i < argc; i++) { sFormData += "&arg-" + argnum + "=" + encodeURIComponent(argv[i]); argnum++; } } else { sFormData = "xmlin=' + alerts[i] + "
"); } document.getElementById("inputs_val").innerHTML = formatted_alerts.join("\n"); validate_data_panel.show(); validateFocusEl.focus(); } return (form_valid ? true : false); } function register_validator(validatemethod, vkey, validateEls, vmsg, required, formId) { if (!vmsg) { alert("register_validator requires 4 arguments: (validatemethod, vkey, validateEls, vmsg, [required func]"); return; } if (self.password_str_handle_validate) { password_str_handle_validate = 0; } if (!formId && validateEls && validateEls.length > 0 && !!validateEls[0]) { formId = validateEls[0].form.id; } if (!formId) { alert("register_validator requires either a list of form elements from which the formId could be derived or the formId parameter."); return; } if (!validators[formId] || validators[formId] == null) { validators[formId] = []; } validators[formId].push({ method: validatemethod, vkey: vkey, Els: validateEls, msg: vmsg, required: required }); } var reset_validators = function() { validators = {}; }; var _deactivate_validator = function(formId, formValidators, validatorId) { // if auto realtime_validate is enabled remove the action if (realtime_validate_inited[formId]) { for (var elId = 0; elId < formValidators[validatorId].Els; elId++) { var thisEl = formValidators[validatorId].Els[elId]; if (thisEl.tagName == "TEXTAREA" || thisEl.type == "text" || thisEl.type == "password" || thisEl.type == "textbox") { YAHOO.util.Event.removeListener(thisEl, "keyup"); } else if (thisEl.tagName == "SELECT" || thisEl.type == "file") { YAHOO.util.Event.removeListener(thisEl, "change"); } } } formValidators.splice(validatorId, 1); // remove the validator }; var remove_validator = function(config) { if (!config.formid && !config.action && !config.elementid) { alert("please pass {formid:'element_id', action:'validator_action', elementid:'elementname'}"); } else { var formValidators = validators[config.formid]; // This is a reference to the array of validators for this form // Search though the array of validators for the one we one and call _deactivate_validator // on it once we find the element in it for (var validatorId = 0; validatorId < formValidators.length; validatorId++) { if (formValidators[validatorId].vkey === config.action) { // check to see if there is more than one element and process each for (var elId = 0; elId < formValidators[validatorId].Els.length; elId++) { if (formValidators[validatorId].Els[elId].id === config.elementid) { _deactivate_validator(config.formid, formValidators, validatorId); break; } } } } } }; function apply_elements_status(elist) { for (var elId in elist) { if (elist[elId]) { setup_accept_image(elId, 1); YAHOO.util.Dom.removeClass(elId, "formverifyfailed"); } else { setup_accept_image(elId, 0); YAHOO.util.Dom.addClass(elId, "formverifyfailed"); } } } function setup_accept_image(parentElId, show) { var imgElIdCon = parentElId + "_status_image_con"; var imgElCon = document.getElementById(imgElIdCon); if (!imgElCon) { var parentEl = document.getElementById(parentElId); var newdiv = document.createElement("div"); newdiv.style.display = "block"; newdiv.style.position = "absolute"; newdiv.style.padding = 0; newdiv.style.margin = 0; newdiv.id = imgElIdCon; newdiv.innerHTML = " "; if (show) { newdiv.className = "accept"; } else { newdiv.className = "reject"; } if (parentEl.nextSibling) { parentEl.parentNode.insertBefore(newdiv, parentEl.nextSibling); } else { parentEl.parentNode.appendChild(newdiv); } imgElCon = newdiv; reposition_validator_img(imgElCon); YAHOO.util.Event.addListener(imgElCon, "click", function() { validate_box(getPreviousInput(this).id); }, imgElCon, true); valImgs.push(imgElCon.id); return; } if (show == 2) { imgElCon.style.display = "none"; } else if (show) { imgElCon.className = "accept"; imgElCon.style.display = ""; } else { imgElCon.className = "reject"; imgElCon.style.display = ""; } } function reposition_all_validator_imgs() { for (var i = 0; i < valImgs.length; i++) { reposition_validator_img(document.getElementById(valImgs[i])); } } function reposition_validator_img(imgElCon) { parentElId = getPreviousInput(imgElCon).id; parentEl = document.getElementById(parentElId); if (!parentEl) { alert("Could not get parent for " + parentElId + " next aw: " + imgElCon.id); return; } var parentReg = YAHOO.util.Region.getRegion(parentEl); // check to see if the input element has a specific validator positioning class var parentElPos; if (YAHOO.util.Dom.hasClass(parentEl, "validator_position_right") == true) { parentElPos = "right"; } if ((parentElPos && parentElPos == "right") || parentEl.tagName == "SELECT" || parentEl.tagName == "TEXTAREA" || parentEl.type == "file") { imgElCon.style.left = (parentReg.left + parentEl.offsetWidth + 3) + "px"; } else { imgElCon.style.left = (parentReg.left + parentEl.offsetWidth - 16 - (offsetQuirk ? 4 : 2)) + "px"; } imgElCon.style.top = (parentReg.top + ((parentEl.offsetHeight - 16) / 2) - (offsetQuirk ? 2 : 0)) + "px"; } function make_elements_valid_status(Els, status, elist) { for (var i = 0; i < Els.length; i++) { if (!Els[i].id) { Els[i].id = "validgen" + validgen++; } if (i > 0) { continue; } /* ignore elements that are not first in the list */ if (status && elist[Els[i].id] != 0) { elist[Els[i].id] = 1; } else { elist[Els[i].id] = 0; } } } function getPreviousInput(El) { while (El.previousSibling && (El.tagName != "INPUT" || El.type == "submit" || El.type == "button") && El.tagName != "SELECT" && El.tagName != "TEXTAREA") { El = El.previousSibling; } return El; } function validate_listmatchers() { var allowed_matchers = []; for (var matcher in match_validators) { allowed_matchers.push(matcher); } return allowed_matchers.join(" "); } function get_url_depth() { if (cached_url_depth) { return cached_url_depth; } var thisurl = window.location.href; var urlpath = thisurl.split("/"); urlpath.shift(); // http urlpath.shift(); // : urlpath.shift(); // HOST urlpath.pop(); // PAGE if (thisurl.match(/\/frontend\//)) { urlpath.shift(); urlpath.shift(); } var dotdot = []; for (i = 0; i < urlpath.length; i++) { dotdot.push(".."); } cached_url_depth = dotdot.join("/"); return cached_url_depth; } function radio_value_is(El, val) { if (isArray(El)) { for (var i = 0; i < El.length; i++) { if (El[i].value == val && El[i].checked) { return true; } } } else { if (El.value == val && El.checked) { return true; } } return false; } function isArray(tobj) { if (tobj.length > 0) { if (tobj[0] && tobj[0].length == 1) { return false; } return true; } return false; } var popupwindows = {}; function popupwindow_init(Elid, pixels, opts) { // Modified 5/1/12 -- can optionally pass opts {} which will override the // default initialization. IE (opts = {fixedcenter=false,modal=true}) will // override fixedcenter's true default and add a modal true value to // the initialization. No other values are touched. PAH var Elid; if (popupwindows[Elid]) { return; } if (!opts) { opts = {}; } if (!pixels) { pixels = "500px"; } var init = { effect: { effect: YAHOO.widget.ContainerEffect.FADE, duration: 0.25 }, width: pixels, buttons: [{ text: "Close", handler: function() { popupwindows[Elid].hide(); }, isDefault: true }], fixedcenter: true, constraintoviewport: true, underlay: "none", close: true, visible: false, draggable: true, modal: false }; for (var opt in opts) { init[opt] = opts[opt]; } document.getElementById(Elid).style.display = ""; popupwindows[Elid] = new YAHOO.widget.Dialog(Elid, init); popupwindows[Elid].render(); popupwindows[Elid].beforeHideEvent.subscribe(handle_hide_popupwindow, Elid, true); } function handle_hide_popupwindow(ev, inc, Elid) { set_popup_display(Elid, "none"); } function set_popup_display(Elid, dstyle) { var Elc = document.getElementById(Elid + "-content"); if (!Elc) { alert("The " + Elid + "'-content' id is missing"); } Elc.style.display = dstyle; var winc = document.getElementById(Elid + "_win"); if (!winc) { return; } winc.style.display = dstyle; } function popupwindow_hide(Elid) { popupwindows[Elid].hide(); } function popupwindow_show(Elid) { set_popup_display(Elid, ""); popupwindows[Elid].render(); popupwindows[Elid].show(); } /* ***** BEGIN LICENSE BLOCK ***** # cpanel12 - interfacereset.js Copyright(c) 1997-2020 cPanel, L.L.C. # All rights reserved. # copyright@cpanel.net http://cpanel.net # This code is subject to the cPanel license. Unauthorized copying is prohibited * ***** END LICENSE BLOCK ***** * ***** BEGIN APPLICABLE CODE BLOCK ***** */ var interfaceConfigs = []; function register_interfacecfg_nvdata(nvname) { interfaceConfigs.push(nvname); } var reset_all_interface_settings = function(securityToken) { var sFormData = "names=" + interfaceConfigs.join("|"); for (var i = 0; i < interfaceConfigs.length; i++) { sFormData += "&" + interfaceConfigs[i] + "="; NVData[interfaceConfigs[i]] = ""; } var successFunction = function() { window.location.reload(); }; var token = securityToken || CPANEL.security_token; var apiUrl = token + "/frontend/" + window.thisTheme + "/nvset.xml"; fetch(apiUrl, { method: "POST", body: sFormData, }) .then(function(res) { successFunction(); }) .catch(function(error) { console.error("Error:", error); }); }; register_interfacecfg_nvdata("ignorecharencoding");