diff --git a/ajax/libs/yui/2.9.0/animation/animation-debug.js b/ajax/libs/yui/2.9.0/animation/animation-debug.js new file mode 100644 index 000000000..ae9e17927 --- /dev/null +++ b/ajax/libs/yui/2.9.0/animation/animation-debug.js @@ -0,0 +1,1429 @@ +/* +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() { + +var Y = YAHOO.util; + +/* +Copyright (c) 2006, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +*/ + +/** + * The animation module provides allows effects to be added to HTMLElements. + * @module animation + * @requires yahoo, event, dom + */ + +/** + * + * Base animation class that provides the interface for building animated effects. + *
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);
0){this.runtimeAttributes[q]=this.runtimeAttributes[q].concat(m);}this.runtimeAttributes[q][this.runtimeAttributes[q].length]=j;}else{f.setRuntimeAttribute.call(this,q);}};var b=function(g,i){var h=e.Dom.getXY(this.getEl());g=[g[0]-h[0]+i[0],g[1]-h[1]+i[1]];return g;};var d=function(g){return(typeof g!=="undefined");};e.Motion=a;})();(function(){var d=function(f,e,g,h){if(f){d.superclass.constructor.call(this,f,e,g,h);}};d.NAME="Scroll";var b=YAHOO.util;YAHOO.extend(d,b.ColorAnim);var c=d.superclass;var a=d.prototype;a.doMethod=function(e,h,f){var g=null;if(e=="scroll"){g=[this.method(this.currentFrame,h[0],f[0]-h[0],this.totalFrames),this.method(this.currentFrame,h[1],f[1]-h[1],this.totalFrames)];}else{g=c.doMethod.call(this,e,h,f);}return g;};a.getAttribute=function(e){var g=null;var f=this.getEl();if(e=="scroll"){g=[f.scrollLeft,f.scrollTop];}else{g=c.getAttribute.call(this,e);}return g;};a.setAttribute=function(e,h,g){var f=this.getEl();if(e=="scroll"){f.scrollLeft=h[0];f.scrollTop=h[1];}else{c.setAttribute.call(this,e,h,g);}};b.Scroll=d;})();YAHOO.register("animation",YAHOO.util.Anim,{version:"2.9.0",build:"2800"}); \ No newline at end of file diff --git a/ajax/libs/yui/2.9.0/animation/animation.js b/ajax/libs/yui/2.9.0/animation/animation.js new file mode 100644 index 000000000..0c4485b23 --- /dev/null +++ b/ajax/libs/yui/2.9.0/animation/animation.js @@ -0,0 +1,1425 @@ +/* +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() { + +var Y = YAHOO.util; + +/* +Copyright (c) 2006, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +*/ + +/** + * The animation module provides allows effects to be added to HTMLElements. + * @module animation + * @requires yahoo, event, dom + */ + +/** + * + * Base animation class that provides the interface for building animated effects. + *
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) { + } + 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 = {}; + + + + /** + * 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);
The Button Control supports the following types:
+*<input>, <button>,
+ * <a>, or <span> element to
+ * be used to create the button.
+ * @param {HTMLInputElement|
+ * HTMLButtonElement|HTMLElement} p_oElement Object reference for the
+ * <input>, <button>,
+ * <a>, or <span> element to be
+ * used to create the button.
+ * @param {Object} p_oElement Object literal specifying a set of
+ * configuration attributes used to create the button.
+ * @param {Object} p_oAttributes Optional. Object literal specifying a set
+ * of configuration attributes used to create the button.
+ * @namespace YAHOO.widget
+ * @class Button
+ * @constructor
+ * @extends YAHOO.util.Element
+ */
+
+
+
+ // Shorthard for utilities
+
+ var Dom = YAHOO.util.Dom,
+ Event = YAHOO.util.Event,
+ Lang = YAHOO.lang,
+ UA = YAHOO.env.ua,
+ Overlay = YAHOO.widget.Overlay,
+ Menu = YAHOO.widget.Menu,
+
+
+ // Private member variables
+
+ m_oButtons = {}, // Collection of all Button instances
+ m_oOverlayManager = null, // YAHOO.widget.OverlayManager instance
+ m_oSubmitTrigger = null, // The button that submitted the form
+ m_oFocusedButton = null; // The button that has focus
+
+
+
+ // Private methods
+
+
+
+ /**
+ * @method createInputElement
+ * @description Creates an <input> element of the
+ * specified type.
+ * @private
+ * @param {String} p_sType String specifying the type of
+ * <input> element to create.
+ * @param {String} p_sName String specifying the name of
+ * <input> element to create.
+ * @param {String} p_sValue String specifying the value of
+ * <input> element to create.
+ * @param {String} p_bChecked Boolean specifying if the
+ * <input> element is to be checked.
+ * @return {HTMLInputElement}
+ */
+ function createInputElement(p_sType, p_sName, p_sValue, p_bChecked) {
+
+ var oInput,
+ sInput;
+
+ if (Lang.isString(p_sType) && Lang.isString(p_sName)) {
+
+ if (UA.ie && (UA.ie < 9)) {
+
+ /*
+ For IE it is necessary to create the element with the
+ "type," "name," "value," and "checked" properties set all
+ at once.
+ */
+
+ sInput = "";
+
+ oInput = document.createElement(sInput);
+
+ oInput.value = p_sValue;
+
+ } else {
+
+ oInput = document.createElement("input");
+ oInput.name = p_sName;
+ oInput.type = p_sType;
+ oInput.value = p_sValue;
+
+ if (p_bChecked) {
+
+ oInput.checked = true;
+
+ }
+
+ }
+
+
+ }
+
+ return oInput;
+
+ }
+
+
+ /**
+ * @method setAttributesFromSrcElement
+ * @description Gets the values for all the attributes of the source element
+ * (either <input> or <a>) that
+ * map to Button configuration attributes and sets them into a collection
+ * that is passed to the Button constructor.
+ * @private
+ * @param {HTMLInputElement|HTMLAnchorElement} p_oElement Object reference to the HTML
+ * element (either <input> or <span>
+ * ) used to create the button.
+ * @param {Object} p_oAttributes Object reference for the collection of
+ * configuration attributes used to create the button.
+ */
+ function setAttributesFromSrcElement(p_oElement, p_oAttributes) {
+
+ var sSrcElementNodeName = p_oElement.nodeName.toUpperCase(),
+ sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME),
+ me = this,
+ oAttribute,
+ oRootNode,
+ sText;
+
+
+ /**
+ * @method setAttributeFromDOMAttribute
+ * @description Gets the value of the specified DOM attribute and sets it
+ * into the collection of configuration attributes used to configure
+ * the button.
+ * @private
+ * @param {String} p_sAttribute String representing the name of the
+ * attribute to retrieve from the DOM element.
+ */
+ function setAttributeFromDOMAttribute(p_sAttribute) {
+
+ if (!(p_sAttribute in p_oAttributes)) {
+
+ /*
+ Need to use "getAttributeNode" instead of "getAttribute"
+ because using "getAttribute," IE will return the innerText
+ of a <button> for the value attribute
+ rather than the value of the "value" attribute.
+ */
+
+ oAttribute = p_oElement.getAttributeNode(p_sAttribute);
+
+
+ if (oAttribute && ("value" in oAttribute)) {
+
+ YAHOO.log("Setting attribute \"" + p_sAttribute +
+ "\" using source element's attribute value of \"" +
+ oAttribute.value + "\"", "info", me.toString());
+
+ p_oAttributes[p_sAttribute] = oAttribute.value;
+
+ }
+
+ }
+
+ }
+
+
+ /**
+ * @method setFormElementProperties
+ * @description Gets the value of the attributes from the form element
+ * and sets them into the collection of configuration attributes used to
+ * configure the button.
+ * @private
+ */
+ function setFormElementProperties() {
+
+ setAttributeFromDOMAttribute("type");
+
+ if (p_oAttributes.type == "button") {
+
+ p_oAttributes.type = "push";
+
+ }
+
+ if (!("disabled" in p_oAttributes)) {
+
+ p_oAttributes.disabled = p_oElement.disabled;
+
+ }
+
+ setAttributeFromDOMAttribute("name");
+ setAttributeFromDOMAttribute("value");
+ setAttributeFromDOMAttribute("title");
+
+ }
+
+
+ switch (sSrcElementNodeName) {
+
+ case "A":
+
+ p_oAttributes.type = "link";
+
+ setAttributeFromDOMAttribute("href");
+ setAttributeFromDOMAttribute("target");
+
+ break;
+
+ case "INPUT":
+
+ setFormElementProperties();
+
+ if (!("checked" in p_oAttributes)) {
+
+ p_oAttributes.checked = p_oElement.checked;
+
+ }
+
+ break;
+
+ case "BUTTON":
+
+ setFormElementProperties();
+
+ oRootNode = p_oElement.parentNode.parentNode;
+
+ if (Dom.hasClass(oRootNode, sClass + "-checked")) {
+
+ p_oAttributes.checked = true;
+
+ }
+
+ if (Dom.hasClass(oRootNode, sClass + "-disabled")) {
+
+ p_oAttributes.disabled = true;
+
+ }
+
+ p_oElement.removeAttribute("value");
+
+ p_oElement.setAttribute("type", "button");
+
+ break;
+
+ }
+
+ p_oElement.removeAttribute("id");
+ p_oElement.removeAttribute("name");
+
+ if (!("tabindex" in p_oAttributes)) {
+
+ p_oAttributes.tabindex = p_oElement.tabIndex;
+
+ }
+
+ if (!("label" in p_oAttributes)) {
+
+ // Set the "label" property
+
+ sText = sSrcElementNodeName == "INPUT" ?
+ p_oElement.value : p_oElement.innerHTML;
+
+
+ if (sText && sText.length > 0) {
+
+ p_oAttributes.label = sText;
+
+ }
+
+ }
+
+ }
+
+
+ /**
+ * @method initConfig
+ * @description Initializes the set of configuration attributes that are
+ * used to instantiate the button.
+ * @private
+ * @param {Object} Object representing the button's set of
+ * configuration attributes.
+ */
+ function initConfig(p_oConfig) {
+
+ var oAttributes = p_oConfig.attributes,
+ oSrcElement = oAttributes.srcelement,
+ sSrcElementNodeName = oSrcElement.nodeName.toUpperCase(),
+ me = this;
+
+
+ if (sSrcElementNodeName == this.NODE_NAME) {
+
+ p_oConfig.element = oSrcElement;
+ p_oConfig.id = oSrcElement.id;
+
+ Dom.getElementsBy(function (p_oElement) {
+
+ switch (p_oElement.nodeName.toUpperCase()) {
+
+ case "BUTTON":
+ case "A":
+ case "INPUT":
+
+ setAttributesFromSrcElement.call(me, p_oElement,
+ oAttributes);
+
+ break;
+
+ }
+
+ }, "*", oSrcElement);
+
+ }
+ else {
+
+ switch (sSrcElementNodeName) {
+
+ case "BUTTON":
+ case "A":
+ case "INPUT":
+
+ setAttributesFromSrcElement.call(this, oSrcElement,
+ oAttributes);
+
+ break;
+
+ }
+
+ }
+
+ }
+
+
+
+ // Constructor
+
+ YAHOO.widget.Button = function (p_oElement, p_oAttributes) {
+
+ if (!Overlay && YAHOO.widget.Overlay) {
+
+ Overlay = YAHOO.widget.Overlay;
+
+ }
+
+
+ if (!Menu && YAHOO.widget.Menu) {
+
+ Menu = YAHOO.widget.Menu;
+
+ }
+
+
+ var fnSuperClass = YAHOO.widget.Button.superclass.constructor,
+ oConfig,
+ oElement;
+
+
+ if (arguments.length == 1 && !Lang.isString(p_oElement) && !p_oElement.nodeName) {
+
+ if (!p_oElement.id) {
+
+ p_oElement.id = Dom.generateId();
+
+ YAHOO.log("No value specified for the button's \"id\" " +
+ "attribute. Setting button id to \"" + p_oElement.id +
+ "\".", "info", this.toString());
+
+ }
+
+ YAHOO.log("No source HTML element. Building the button " +
+ "using the set of configuration attributes.", "info", this.toString());
+
+ fnSuperClass.call(this, (this.createButtonElement(p_oElement.type)), p_oElement);
+
+ }
+ else {
+
+ oConfig = { element: null, attributes: (p_oAttributes || {}) };
+
+
+ if (Lang.isString(p_oElement)) {
+
+ oElement = Dom.get(p_oElement);
+
+ if (oElement) {
+
+ if (!oConfig.attributes.id) {
+
+ oConfig.attributes.id = p_oElement;
+
+ }
+
+ YAHOO.log("Building the button using an existing " +
+ "HTML element as a source element.", "info", this.toString());
+
+
+ oConfig.attributes.srcelement = oElement;
+
+ initConfig.call(this, oConfig);
+
+
+ if (!oConfig.element) {
+
+ YAHOO.log("Source element could not be used " +
+ "as is. Creating a new HTML element for " +
+ "the button.", "info", this.toString());
+
+ oConfig.element = this.createButtonElement(oConfig.attributes.type);
+
+ }
+
+ fnSuperClass.call(this, oConfig.element, oConfig.attributes);
+
+ }
+
+ }
+ else if (p_oElement.nodeName) {
+
+ if (!oConfig.attributes.id) {
+
+ if (p_oElement.id) {
+
+ oConfig.attributes.id = p_oElement.id;
+
+ }
+ else {
+
+ oConfig.attributes.id = Dom.generateId();
+
+ YAHOO.log("No value specified for the button's " +
+ "\"id\" attribute. Setting button id to \"" +
+ oConfig.attributes.id + "\".", "info", this.toString());
+
+ }
+
+ }
+
+ YAHOO.log("Building the button using an existing HTML " +
+ "element as a source element.", "info", this.toString());
+
+
+ oConfig.attributes.srcelement = p_oElement;
+
+ initConfig.call(this, oConfig);
+
+
+ if (!oConfig.element) {
+
+ YAHOO.log("Source element could not be used as is." +
+ " Creating a new HTML element for the button.",
+ "info", this.toString());
+
+ oConfig.element = this.createButtonElement(oConfig.attributes.type);
+
+ }
+
+ fnSuperClass.call(this, oConfig.element, oConfig.attributes);
+
+ }
+
+ }
+
+ };
+
+
+
+ YAHOO.extend(YAHOO.widget.Button, YAHOO.util.Element, {
+
+
+ // Protected properties
+
+
+ /**
+ * @property _button
+ * @description Object reference to the button's internal
+ * <a> or <button> element.
+ * @default null
+ * @protected
+ * @type HTMLAnchorElement|HTMLButtonElement
+ */
+ _button: null,
+
+
+ /**
+ * @property _menu
+ * @description Object reference to the button's menu.
+ * @default null
+ * @protected
+ * @type {YAHOO.widget.Overlay|
+ * YAHOO.widget.Menu}
+ */
+ _menu: null,
+
+
+ /**
+ * @property _hiddenFields
+ * @description Object reference to the <input>
+ * element, or array of HTML form elements used to represent the button
+ * when its parent form is submitted.
+ * @default null
+ * @protected
+ * @type HTMLInputElement|Array
+ */
+ _hiddenFields: null,
+
+
+ /**
+ * @property _onclickAttributeValue
+ * @description Object reference to the button's current value for the
+ * "onclick" configuration attribute.
+ * @default null
+ * @protected
+ * @type Object
+ */
+ _onclickAttributeValue: null,
+
+
+ /**
+ * @property _activationKeyPressed
+ * @description Boolean indicating if the key(s) that toggle the button's
+ * "active" state have been pressed.
+ * @default false
+ * @protected
+ * @type Boolean
+ */
+ _activationKeyPressed: false,
+
+
+ /**
+ * @property _activationButtonPressed
+ * @description Boolean indicating if the mouse button that toggles
+ * the button's "active" state has been pressed.
+ * @default false
+ * @protected
+ * @type Boolean
+ */
+ _activationButtonPressed: false,
+
+
+ /**
+ * @property _hasKeyEventHandlers
+ * @description Boolean indicating if the button's "blur", "keydown" and
+ * "keyup" event handlers are assigned
+ * @default false
+ * @protected
+ * @type Boolean
+ */
+ _hasKeyEventHandlers: false,
+
+
+ /**
+ * @property _hasMouseEventHandlers
+ * @description Boolean indicating if the button's "mouseout,"
+ * "mousedown," and "mouseup" event handlers are assigned
+ * @default false
+ * @protected
+ * @type Boolean
+ */
+ _hasMouseEventHandlers: false,
+
+
+ /**
+ * @property _nOptionRegionX
+ * @description Number representing the X coordinate of the leftmost edge of the Button's
+ * option region. Applies only to Buttons of type "split".
+ * @default 0
+ * @protected
+ * @type Number
+ */
+ _nOptionRegionX: 0,
+
+
+
+ // Constants
+
+ /**
+ * @property CLASS_NAME_PREFIX
+ * @description Prefix used for all class names applied to a Button.
+ * @default "yui-"
+ * @final
+ * @type String
+ */
+ CLASS_NAME_PREFIX: "yui-",
+
+
+ /**
+ * @property NODE_NAME
+ * @description The name of the node to be used for the button's
+ * root element.
+ * @default "SPAN"
+ * @final
+ * @type String
+ */
+ NODE_NAME: "SPAN",
+
+
+ /**
+ * @property CHECK_ACTIVATION_KEYS
+ * @description Array of numbers representing keys that (when pressed)
+ * toggle the button's "checked" attribute.
+ * @default [32]
+ * @final
+ * @type Array
+ */
+ CHECK_ACTIVATION_KEYS: [32],
+
+
+ /**
+ * @property ACTIVATION_KEYS
+ * @description Array of numbers representing keys that (when presed)
+ * toggle the button's "active" state.
+ * @default [13, 32]
+ * @final
+ * @type Array
+ */
+ ACTIVATION_KEYS: [13, 32],
+
+
+ /**
+ * @property OPTION_AREA_WIDTH
+ * @description Width (in pixels) of the area of a split button that
+ * when pressed will display a menu.
+ * @default 20
+ * @final
+ * @type Number
+ */
+ OPTION_AREA_WIDTH: 20,
+
+
+ /**
+ * @property CSS_CLASS_NAME
+ * @description String representing the CSS class(es) to be applied to
+ * the button's root element.
+ * @default "button"
+ * @final
+ * @type String
+ */
+ CSS_CLASS_NAME: "button",
+
+
+
+ // Protected attribute setter methods
+
+
+ /**
+ * @method _setType
+ * @description Sets the value of the button's "type" attribute.
+ * @protected
+ * @param {String} p_sType String indicating the value for the button's
+ * "type" attribute.
+ */
+ _setType: function (p_sType) {
+
+ if (p_sType == "split") {
+
+ this.on("option", this._onOption);
+
+ }
+
+ },
+
+
+ /**
+ * @method _setLabel
+ * @description Sets the value of the button's "label" attribute.
+ * @protected
+ * @param {HTML} p_sLabel String indicating the value for the button's
+ * "label" attribute.
+ */
+ _setLabel: function (p_sLabel) {
+
+ this._button.innerHTML = p_sLabel;
+
+
+ /*
+ Remove and add the default class name from the root element
+ for Gecko to ensure that the button shrinkwraps to the label.
+ Without this the button will not be rendered at the correct
+ width when the label changes. The most likely cause for this
+ bug is button's use of the Gecko-specific CSS display type of
+ "-moz-inline-box" to simulate "inline-block" supported by IE,
+ Safari and Opera.
+ */
+
+ var sClass,
+ nGeckoVersion = UA.gecko;
+
+
+ if (nGeckoVersion && nGeckoVersion < 1.9 && Dom.inDocument(this.get("element"))) {
+
+ sClass = (this.CLASS_NAME_PREFIX + this.CSS_CLASS_NAME);
+
+ this.removeClass(sClass);
+
+ Lang.later(0, this, this.addClass, sClass);
+
+ }
+
+ },
+
+
+ /**
+ * @method _setTabIndex
+ * @description Sets the value of the button's "tabindex" attribute.
+ * @protected
+ * @param {Number} p_nTabIndex Number indicating the value for the
+ * button's "tabindex" attribute.
+ */
+ _setTabIndex: function (p_nTabIndex) {
+
+ this._button.tabIndex = p_nTabIndex;
+
+ },
+
+
+ /**
+ * @method _setTitle
+ * @description Sets the value of the button's "title" attribute.
+ * @protected
+ * @param {String} p_nTabIndex Number indicating the value for
+ * the button's "title" attribute.
+ */
+ _setTitle: function (p_sTitle) {
+
+ if (this.get("type") != "link") {
+
+ this._button.title = p_sTitle;
+
+ }
+
+ },
+
+
+ /**
+ * @method _setDisabled
+ * @description Sets the value of the button's "disabled" attribute.
+ * @protected
+ * @param {Boolean} p_bDisabled Boolean indicating the value for
+ * the button's "disabled" attribute.
+ */
+ _setDisabled: function (p_bDisabled) {
+
+ if (this.get("type") != "link") {
+
+ if (p_bDisabled) {
+
+ if (this._menu) {
+
+ this._menu.hide();
+
+ }
+
+ if (this.hasFocus()) {
+
+ this.blur();
+
+ }
+
+ this._button.setAttribute("disabled", "disabled");
+
+ this.addStateCSSClasses("disabled");
+
+ this.removeStateCSSClasses("hover");
+ this.removeStateCSSClasses("active");
+ this.removeStateCSSClasses("focus");
+
+ }
+ else {
+
+ this._button.removeAttribute("disabled");
+
+ this.removeStateCSSClasses("disabled");
+
+ }
+
+ }
+
+ },
+
+
+ /**
+ * @method _setHref
+ * @description Sets the value of the button's "href" attribute.
+ * @protected
+ * @param {String} p_sHref String indicating the value for the button's
+ * "href" attribute.
+ */
+ _setHref: function (p_sHref) {
+
+ if (this.get("type") == "link") {
+
+ this._button.href = p_sHref;
+
+ }
+
+ },
+
+
+ /**
+ * @method _setTarget
+ * @description Sets the value of the button's "target" attribute.
+ * @protected
+ * @param {String} p_sTarget String indicating the value for the button's
+ * "target" attribute.
+ */
+ _setTarget: function (p_sTarget) {
+
+ if (this.get("type") == "link") {
+
+ this._button.setAttribute("target", p_sTarget);
+
+ }
+
+ },
+
+
+ /**
+ * @method _setChecked
+ * @description Sets the value of the button's "target" attribute.
+ * @protected
+ * @param {Boolean} p_bChecked Boolean indicating the value for
+ * the button's "checked" attribute.
+ */
+ _setChecked: function (p_bChecked) {
+
+ var sType = this.get("type");
+
+ if (sType == "checkbox" || sType == "radio") {
+
+ if (p_bChecked) {
+ this.addStateCSSClasses("checked");
+ }
+ else {
+ this.removeStateCSSClasses("checked");
+ }
+
+ }
+
+ },
+
+
+ /**
+ * @method _setMenu
+ * @description Sets the value of the button's "menu" attribute.
+ * @protected
+ * @param {Object} p_oMenu Object indicating the value for the button's
+ * "menu" attribute.
+ */
+ _setMenu: function (p_oMenu) {
+
+ var bLazyLoad = this.get("lazyloadmenu"),
+ oButtonElement = this.get("element"),
+ sMenuCSSClassName,
+
+ /*
+ Boolean indicating if the value of p_oMenu is an instance
+ of YAHOO.widget.Menu or YAHOO.widget.Overlay.
+ */
+
+ bInstance = false,
+ oMenu,
+ oMenuElement,
+ oSrcElement;
+
+
+ function onAppendTo() {
+
+ oMenu.render(oButtonElement.parentNode);
+
+ this.removeListener("appendTo", onAppendTo);
+
+ }
+
+
+ function setMenuContainer() {
+
+ oMenu.cfg.queueProperty("container", oButtonElement.parentNode);
+
+ this.removeListener("appendTo", setMenuContainer);
+
+ }
+
+
+ function initMenu() {
+
+ var oContainer;
+
+ if (oMenu) {
+
+ Dom.addClass(oMenu.element, this.get("menuclassname"));
+ Dom.addClass(oMenu.element, this.CLASS_NAME_PREFIX + this.get("type") + "-button-menu");
+
+ oMenu.showEvent.subscribe(this._onMenuShow, null, this);
+ oMenu.hideEvent.subscribe(this._onMenuHide, null, this);
+ oMenu.renderEvent.subscribe(this._onMenuRender, null, this);
+
+
+ if (Menu && oMenu instanceof Menu) {
+
+ if (bLazyLoad) {
+
+ oContainer = this.get("container");
+
+ if (oContainer) {
+
+ oMenu.cfg.queueProperty("container", oContainer);
+
+ }
+ else {
+
+ this.on("appendTo", setMenuContainer);
+
+ }
+
+ }
+
+ oMenu.cfg.queueProperty("clicktohide", false);
+
+ oMenu.keyDownEvent.subscribe(this._onMenuKeyDown, this, true);
+ oMenu.subscribe("click", this._onMenuClick, this, true);
+
+ this.on("selectedMenuItemChange", this._onSelectedMenuItemChange);
+
+ oSrcElement = oMenu.srcElement;
+
+ if (oSrcElement && oSrcElement.nodeName.toUpperCase() == "SELECT") {
+
+ oSrcElement.style.display = "none";
+ oSrcElement.parentNode.removeChild(oSrcElement);
+
+ }
+
+ }
+ else if (Overlay && oMenu instanceof Overlay) {
+
+ if (!m_oOverlayManager) {
+
+ m_oOverlayManager = new YAHOO.widget.OverlayManager();
+
+ }
+
+ m_oOverlayManager.register(oMenu);
+
+ }
+
+
+ this._menu = oMenu;
+
+
+ if (!bInstance && !bLazyLoad) {
+
+ if (Dom.inDocument(oButtonElement)) {
+
+ oMenu.render(oButtonElement.parentNode);
+
+ }
+ else {
+
+ this.on("appendTo", onAppendTo);
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+ if (Overlay) {
+
+ if (Menu) {
+
+ sMenuCSSClassName = Menu.prototype.CSS_CLASS_NAME;
+
+ }
+
+ if (p_oMenu && Menu && (p_oMenu instanceof Menu)) {
+
+ oMenu = p_oMenu;
+ bInstance = true;
+
+ initMenu.call(this);
+
+ }
+ else if (Overlay && p_oMenu && (p_oMenu instanceof Overlay)) {
+
+ oMenu = p_oMenu;
+ bInstance = true;
+
+ oMenu.cfg.queueProperty("visible", false);
+
+ initMenu.call(this);
+
+ }
+ else if (Menu && Lang.isArray(p_oMenu)) {
+
+ oMenu = new Menu(Dom.generateId(), { lazyload: bLazyLoad, itemdata: p_oMenu });
+
+ this._menu = oMenu;
+
+ this.on("appendTo", initMenu);
+
+ }
+ else if (Lang.isString(p_oMenu)) {
+
+ oMenuElement = Dom.get(p_oMenu);
+
+ if (oMenuElement) {
+
+ if (Menu && Dom.hasClass(oMenuElement, sMenuCSSClassName) ||
+ oMenuElement.nodeName.toUpperCase() == "SELECT") {
+
+ oMenu = new Menu(p_oMenu, { lazyload: bLazyLoad });
+
+ initMenu.call(this);
+
+ }
+ else if (Overlay) {
+
+ oMenu = new Overlay(p_oMenu, { visible: false });
+
+ initMenu.call(this);
+
+ }
+
+ }
+
+ }
+ else if (p_oMenu && p_oMenu.nodeName) {
+
+ if (Menu && Dom.hasClass(p_oMenu, sMenuCSSClassName) ||
+ p_oMenu.nodeName.toUpperCase() == "SELECT") {
+
+ oMenu = new Menu(p_oMenu, { lazyload: bLazyLoad });
+
+ initMenu.call(this);
+
+ }
+ else if (Overlay) {
+
+ if (!p_oMenu.id) {
+
+ Dom.generateId(p_oMenu);
+
+ }
+
+ oMenu = new Overlay(p_oMenu, { visible: false });
+
+ initMenu.call(this);
+
+ }
+
+ }
+
+ }
+
+ },
+
+
+ /**
+ * @method _setOnClick
+ * @description Sets the value of the button's "onclick" attribute.
+ * @protected
+ * @param {Object} p_oObject Object indicating the value for the button's
+ * "onclick" attribute.
+ */
+ _setOnClick: function (p_oObject) {
+
+ /*
+ Remove any existing listeners if a "click" event handler
+ has already been specified.
+ */
+
+ if (this._onclickAttributeValue &&
+ (this._onclickAttributeValue != p_oObject)) {
+
+ this.removeListener("click", this._onclickAttributeValue.fn);
+
+ this._onclickAttributeValue = null;
+
+ }
+
+
+ if (!this._onclickAttributeValue &&
+ Lang.isObject(p_oObject) &&
+ Lang.isFunction(p_oObject.fn)) {
+
+ this.on("click", p_oObject.fn, p_oObject.obj, p_oObject.scope);
+
+ this._onclickAttributeValue = p_oObject;
+
+ }
+
+ },
+
+
+
+ // Protected methods
+
+
+
+ /**
+ * @method _isActivationKey
+ * @description Determines if the specified keycode is one that toggles
+ * the button's "active" state.
+ * @protected
+ * @param {Number} p_nKeyCode Number representing the keycode to
+ * be evaluated.
+ * @return {Boolean}
+ */
+ _isActivationKey: function (p_nKeyCode) {
+
+ var sType = this.get("type"),
+ aKeyCodes = (sType == "checkbox" || sType == "radio") ?
+ this.CHECK_ACTIVATION_KEYS : this.ACTIVATION_KEYS,
+
+ nKeyCodes = aKeyCodes.length,
+ bReturnVal = false,
+ i;
+
+
+ if (nKeyCodes > 0) {
+
+ i = nKeyCodes - 1;
+
+ do {
+
+ if (p_nKeyCode == aKeyCodes[i]) {
+
+ bReturnVal = true;
+ break;
+
+ }
+
+ }
+ while (i--);
+
+ }
+
+ return bReturnVal;
+
+ },
+
+
+ /**
+ * @method _isSplitButtonOptionKey
+ * @description Determines if the specified keycode is one that toggles
+ * the display of the split button's menu.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ * @return {Boolean}
+ */
+ _isSplitButtonOptionKey: function (p_oEvent) {
+
+ var bShowMenu = (Event.getCharCode(p_oEvent) == 40);
+
+
+ var onKeyPress = function (p_oEvent) {
+
+ Event.preventDefault(p_oEvent);
+
+ this.removeListener("keypress", onKeyPress);
+
+ };
+
+
+ // Prevent the browser from scrolling the window
+ if (bShowMenu) {
+
+ if (UA.opera) {
+
+ this.on("keypress", onKeyPress);
+
+ }
+
+ Event.preventDefault(p_oEvent);
+ }
+
+ return bShowMenu;
+
+ },
+
+
+ /**
+ * @method _addListenersToForm
+ * @description Adds event handlers to the button's form.
+ * @protected
+ */
+ _addListenersToForm: function () {
+
+ var oForm = this.getForm(),
+ onFormKeyPress = YAHOO.widget.Button.onFormKeyPress,
+ bHasKeyPressListener,
+ oSrcElement,
+ aListeners,
+ nListeners,
+ i;
+
+
+ if (oForm) {
+
+ Event.on(oForm, "reset", this._onFormReset, null, this);
+ Event.on(oForm, "submit", this._onFormSubmit, null, this);
+
+ oSrcElement = this.get("srcelement");
+
+
+ if (this.get("type") == "submit" ||
+ (oSrcElement && oSrcElement.type == "submit"))
+ {
+
+ aListeners = Event.getListeners(oForm, "keypress");
+ bHasKeyPressListener = false;
+
+ if (aListeners) {
+
+ nListeners = aListeners.length;
+
+ if (nListeners > 0) {
+
+ i = nListeners - 1;
+
+ do {
+
+ if (aListeners[i].fn == onFormKeyPress) {
+
+ bHasKeyPressListener = true;
+ break;
+
+ }
+
+ }
+ while (i--);
+
+ }
+
+ }
+
+
+ if (!bHasKeyPressListener) {
+
+ Event.on(oForm, "keypress", onFormKeyPress);
+
+ }
+
+ }
+
+ }
+
+ },
+
+
+
+ /**
+ * @method _showMenu
+ * @description Shows the button's menu.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event) that triggered
+ * the display of the menu.
+ */
+ _showMenu: function (p_oEvent) {
+
+ if (YAHOO.widget.MenuManager) {
+ YAHOO.widget.MenuManager.hideVisible();
+ }
+
+
+ if (m_oOverlayManager) {
+ m_oOverlayManager.hideAll();
+ }
+
+
+ var oMenu = this._menu,
+ aMenuAlignment = this.get("menualignment"),
+ bFocusMenu = this.get("focusmenu"),
+ fnFocusMethod;
+
+
+ if (this._renderedMenu) {
+
+ oMenu.cfg.setProperty("context",
+ [this.get("element"), aMenuAlignment[0], aMenuAlignment[1]]);
+
+ oMenu.cfg.setProperty("preventcontextoverlap", true);
+ oMenu.cfg.setProperty("constraintoviewport", true);
+
+ }
+ else {
+
+ oMenu.cfg.queueProperty("context",
+ [this.get("element"), aMenuAlignment[0], aMenuAlignment[1]]);
+
+ oMenu.cfg.queueProperty("preventcontextoverlap", true);
+ oMenu.cfg.queueProperty("constraintoviewport", true);
+
+ }
+
+
+ /*
+ Refocus the Button before showing its Menu in case the call to
+ YAHOO.widget.MenuManager.hideVisible() resulted in another element in the
+ DOM being focused after another Menu was hidden.
+ */
+
+ this.focus();
+
+
+ if (Menu && oMenu && (oMenu instanceof Menu)) {
+
+ // Since Menus automatically focus themselves when made visible, temporarily
+ // replace the Menu focus method so that the value of the Button's "focusmenu"
+ // attribute determines if the Menu should be focus when made visible.
+
+ fnFocusMethod = oMenu.focus;
+
+ oMenu.focus = function () {};
+
+ if (this._renderedMenu) {
+
+ oMenu.cfg.setProperty("minscrollheight", this.get("menuminscrollheight"));
+ oMenu.cfg.setProperty("maxheight", this.get("menumaxheight"));
+
+ }
+ else {
+
+ oMenu.cfg.queueProperty("minscrollheight", this.get("menuminscrollheight"));
+ oMenu.cfg.queueProperty("maxheight", this.get("menumaxheight"));
+
+ }
+
+
+ oMenu.show();
+
+ oMenu.focus = fnFocusMethod;
+
+ oMenu.align();
+
+
+ /*
+ Stop the propagation of the event so that the MenuManager
+ doesn't blur the menu after it gets focus.
+ */
+
+ if (p_oEvent.type == "mousedown") {
+ Event.stopPropagation(p_oEvent);
+ }
+
+
+ if (bFocusMenu) {
+ oMenu.focus();
+ }
+
+ }
+ else if (Overlay && oMenu && (oMenu instanceof Overlay)) {
+
+ if (!this._renderedMenu) {
+ oMenu.render(this.get("element").parentNode);
+ }
+
+ oMenu.show();
+ oMenu.align();
+
+ }
+
+ },
+
+
+ /**
+ * @method _hideMenu
+ * @description Hides the button's menu.
+ * @protected
+ */
+ _hideMenu: function () {
+
+ var oMenu = this._menu;
+
+ if (oMenu) {
+
+ oMenu.hide();
+
+ }
+
+ },
+
+
+
+
+ // Protected event handlers
+
+
+ /**
+ * @method _onMouseOver
+ * @description "mouseover" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onMouseOver: function (p_oEvent) {
+
+ var sType = this.get("type"),
+ oElement,
+ nOptionRegionX;
+
+
+ if (sType === "split") {
+
+ oElement = this.get("element");
+ nOptionRegionX =
+ (Dom.getX(oElement) + (oElement.offsetWidth - this.OPTION_AREA_WIDTH));
+
+ this._nOptionRegionX = nOptionRegionX;
+
+ }
+
+
+ if (!this._hasMouseEventHandlers) {
+
+ if (sType === "split") {
+
+ this.on("mousemove", this._onMouseMove);
+
+ }
+
+ this.on("mouseout", this._onMouseOut);
+
+ this._hasMouseEventHandlers = true;
+
+ }
+
+
+ this.addStateCSSClasses("hover");
+
+
+ if (sType === "split" && (Event.getPageX(p_oEvent) > nOptionRegionX)) {
+
+ this.addStateCSSClasses("hoveroption");
+
+ }
+
+
+ if (this._activationButtonPressed) {
+
+ this.addStateCSSClasses("active");
+
+ }
+
+
+ if (this._bOptionPressed) {
+
+ this.addStateCSSClasses("activeoption");
+
+ }
+
+
+ if (this._activationButtonPressed || this._bOptionPressed) {
+
+ Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
+
+ }
+
+ },
+
+
+ /**
+ * @method _onMouseMove
+ * @description "mousemove" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onMouseMove: function (p_oEvent) {
+
+ var nOptionRegionX = this._nOptionRegionX;
+
+ if (nOptionRegionX) {
+
+ if (Event.getPageX(p_oEvent) > nOptionRegionX) {
+
+ this.addStateCSSClasses("hoveroption");
+
+ }
+ else {
+
+ this.removeStateCSSClasses("hoveroption");
+
+ }
+
+ }
+
+ },
+
+ /**
+ * @method _onMouseOut
+ * @description "mouseout" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onMouseOut: function (p_oEvent) {
+
+ var sType = this.get("type");
+
+ this.removeStateCSSClasses("hover");
+
+
+ if (sType != "menu") {
+
+ this.removeStateCSSClasses("active");
+
+ }
+
+
+ if (this._activationButtonPressed || this._bOptionPressed) {
+
+ Event.on(document, "mouseup", this._onDocumentMouseUp, null, this);
+
+ }
+
+
+ if (sType === "split" && (Event.getPageX(p_oEvent) > this._nOptionRegionX)) {
+
+ this.removeStateCSSClasses("hoveroption");
+
+ }
+
+ },
+
+
+ /**
+ * @method _onDocumentMouseUp
+ * @description "mouseup" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onDocumentMouseUp: function (p_oEvent) {
+
+ this._activationButtonPressed = false;
+ this._bOptionPressed = false;
+
+ var sType = this.get("type"),
+ oTarget,
+ oMenuElement;
+
+ if (sType == "menu" || sType == "split") {
+
+ oTarget = Event.getTarget(p_oEvent);
+ oMenuElement = this._menu.element;
+
+ if (oTarget != oMenuElement &&
+ !Dom.isAncestor(oMenuElement, oTarget)) {
+
+ this.removeStateCSSClasses((sType == "menu" ?
+ "active" : "activeoption"));
+
+ this._hideMenu();
+
+ }
+
+ }
+
+ Event.removeListener(document, "mouseup", this._onDocumentMouseUp);
+
+ },
+
+
+ /**
+ * @method _onMouseDown
+ * @description "mousedown" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onMouseDown: function (p_oEvent) {
+
+ var sType,
+ bReturnVal = true;
+
+
+ function onMouseUp() {
+
+ this._hideMenu();
+ this.removeListener("mouseup", onMouseUp);
+
+ }
+
+
+ if ((p_oEvent.which || p_oEvent.button) == 1) {
+
+
+ if (!this.hasFocus()) {
+ Lang.later(0, this, this.focus);
+ //this.focus();
+ }
+
+
+ sType = this.get("type");
+
+
+ if (sType == "split") {
+
+ if (Event.getPageX(p_oEvent) > this._nOptionRegionX) {
+
+ this.fireEvent("option", p_oEvent);
+ bReturnVal = false;
+
+ }
+ else {
+
+ this.addStateCSSClasses("active");
+
+ this._activationButtonPressed = true;
+
+ }
+
+ }
+ else if (sType == "menu") {
+
+ if (this.isActive()) {
+
+ this._hideMenu();
+
+ this._activationButtonPressed = false;
+
+ }
+ else {
+
+ this._showMenu(p_oEvent);
+
+ this._activationButtonPressed = true;
+
+ }
+
+ }
+ else {
+
+ this.addStateCSSClasses("active");
+
+ this._activationButtonPressed = true;
+
+ }
+
+
+
+ if (sType == "split" || sType == "menu") {
+
+ this._hideMenuTimer = Lang.later(250, this, this.on, ["mouseup", onMouseUp]);
+
+ }
+
+ }
+
+ return bReturnVal;
+
+ },
+
+
+ /**
+ * @method _onMouseUp
+ * @description "mouseup" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onMouseUp: function (p_oEvent) {
+ this.inMouseDown = false;
+
+ var sType = this.get("type"),
+ oHideMenuTimer = this._hideMenuTimer,
+ bReturnVal = true;
+
+
+ if (oHideMenuTimer) {
+
+ oHideMenuTimer.cancel();
+
+ }
+
+
+ if (sType == "checkbox" || sType == "radio") {
+ if ((p_oEvent.which || p_oEvent.button) != 1) {
+ return;
+ }
+
+ this.set("checked", !(this.get("checked")));
+
+ }
+
+
+ this._activationButtonPressed = false;
+
+
+ if (sType != "menu") {
+
+ this.removeStateCSSClasses("active");
+
+ }
+
+
+ if (sType == "split" && Event.getPageX(p_oEvent) > this._nOptionRegionX) {
+
+ bReturnVal = false;
+
+ }
+
+ return bReturnVal;
+
+ },
+
+
+ /**
+ * @method _onFocus
+ * @description "focus" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onFocus: function (p_oEvent) {
+
+ var oElement;
+
+ this.addStateCSSClasses("focus");
+
+ if (this._activationKeyPressed) {
+
+ this.addStateCSSClasses("active");
+
+ }
+
+ m_oFocusedButton = this;
+
+
+ if (!this._hasKeyEventHandlers) {
+
+ oElement = this._button;
+
+ Event.on(oElement, "blur", this._onBlur, null, this);
+ Event.on(oElement, "keydown", this._onKeyDown, null, this);
+ Event.on(oElement, "keyup", this._onKeyUp, null, this);
+
+ this._hasKeyEventHandlers = true;
+
+ }
+
+
+ this.fireEvent("focus", p_oEvent);
+
+ },
+
+
+ /**
+ * @method _onBlur
+ * @description "blur" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onBlur: function (p_oEvent) {
+
+ this.removeStateCSSClasses("focus");
+
+ if (this.get("type") != "menu") {
+
+ this.removeStateCSSClasses("active");
+
+ }
+
+ if (this._activationKeyPressed) {
+
+ Event.on(document, "keyup", this._onDocumentKeyUp, null, this);
+
+ }
+
+
+ m_oFocusedButton = null;
+
+ this.fireEvent("blur", p_oEvent);
+
+ },
+
+
+ /**
+ * @method _onDocumentKeyUp
+ * @description "keyup" event handler for the document.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onDocumentKeyUp: function (p_oEvent) {
+
+ if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
+
+ this._activationKeyPressed = false;
+
+ Event.removeListener(document, "keyup", this._onDocumentKeyUp);
+
+ }
+
+ },
+
+
+ /**
+ * @method _onKeyDown
+ * @description "keydown" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onKeyDown: function (p_oEvent) {
+
+ var oMenu = this._menu;
+
+
+ if (this.get("type") == "split" &&
+ this._isSplitButtonOptionKey(p_oEvent)) {
+
+ this.fireEvent("option", p_oEvent);
+
+ }
+ else if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
+
+ if (this.get("type") == "menu") {
+
+ this._showMenu(p_oEvent);
+
+ }
+ else {
+
+ this._activationKeyPressed = true;
+
+ this.addStateCSSClasses("active");
+
+ }
+
+ }
+
+
+ if (oMenu && oMenu.cfg.getProperty("visible") &&
+ Event.getCharCode(p_oEvent) == 27) {
+
+ oMenu.hide();
+ this.focus();
+
+ }
+
+ },
+
+
+ /**
+ * @method _onKeyUp
+ * @description "keyup" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onKeyUp: function (p_oEvent) {
+
+ var sType;
+
+ if (this._isActivationKey(Event.getCharCode(p_oEvent))) {
+
+ sType = this.get("type");
+
+ if (sType == "checkbox" || sType == "radio") {
+
+ this.set("checked", !(this.get("checked")));
+
+ }
+
+ this._activationKeyPressed = false;
+
+ if (this.get("type") != "menu") {
+
+ this.removeStateCSSClasses("active");
+
+ }
+
+ }
+
+ },
+
+
+ /**
+ * @method _onClick
+ * @description "click" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onClick: function (p_oEvent) {
+
+ var sType = this.get("type"),
+ oForm,
+ oSrcElement,
+ bReturnVal;
+
+
+ switch (sType) {
+
+ case "submit":
+
+ if (p_oEvent.returnValue !== false) {
+
+ this.submitForm();
+
+ }
+
+ break;
+
+ case "reset":
+
+ oForm = this.getForm();
+
+ if (oForm) {
+
+ oForm.reset();
+
+ }
+
+ break;
+
+
+ case "split":
+
+ if (this._nOptionRegionX > 0 &&
+ (Event.getPageX(p_oEvent) > this._nOptionRegionX)) {
+
+ bReturnVal = false;
+
+ }
+ else {
+
+ this._hideMenu();
+
+ oSrcElement = this.get("srcelement");
+
+ if (oSrcElement && oSrcElement.type == "submit" &&
+ p_oEvent.returnValue !== false) {
+
+ this.submitForm();
+
+ }
+
+ }
+
+ break;
+
+ }
+
+ return bReturnVal;
+
+ },
+
+
+ /**
+ * @method _onDblClick
+ * @description "dblclick" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onDblClick: function (p_oEvent) {
+
+ var bReturnVal = true;
+
+ if (this.get("type") == "split" && Event.getPageX(p_oEvent) > this._nOptionRegionX) {
+
+ bReturnVal = false;
+
+ }
+
+ return bReturnVal;
+
+ },
+
+
+ /**
+ * @method _onAppendTo
+ * @description "appendTo" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onAppendTo: function (p_oEvent) {
+
+ /*
+ It is necessary to call "_addListenersToForm" using
+ "setTimeout" to make sure that the button's "form" property
+ returns a node reference. Sometimes, if you try to get the
+ reference immediately after appending the field, it is null.
+ */
+
+ Lang.later(0, this, this._addListenersToForm);
+
+ },
+
+
+ /**
+ * @method _onFormReset
+ * @description "reset" event handler for the button's form.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event
+ * object passed back by the event utility (YAHOO.util.Event).
+ */
+ _onFormReset: function (p_oEvent) {
+
+ var sType = this.get("type"),
+ oMenu = this._menu;
+
+ if (sType == "checkbox" || sType == "radio") {
+
+ this.resetValue("checked");
+
+ }
+
+
+ if (Menu && oMenu && (oMenu instanceof Menu)) {
+
+ this.resetValue("selectedMenuItem");
+
+ }
+
+ },
+
+
+ /**
+ * @method _onFormSubmit
+ * @description "submit" event handler for the button's form.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event
+ * object passed back by the event utility (YAHOO.util.Event).
+ */
+ _onFormSubmit: function (p_oEvent) {
+
+ this.createHiddenFields();
+
+ },
+
+
+ /**
+ * @method _onDocumentMouseDown
+ * @description "mousedown" event handler for the document.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onDocumentMouseDown: function (p_oEvent) {
+
+ var oTarget = Event.getTarget(p_oEvent),
+ oButtonElement = this.get("element"),
+ oMenuElement = this._menu.element;
+
+ function findTargetInSubmenus(aSubmenus) {
+ var i, iMax, oSubmenuElement;
+ if (!aSubmenus) {
+ return true;
+ }
+ for (i = 0, iMax = aSubmenus.length; i < iMax; i++) {
+ oSubmenuElement = aSubmenus[i].element;
+ if (oTarget == oSubmenuElement || Dom.isAncestor(oSubmenuElement, oTarget)) {
+ return true;
+ }
+ if (aSubmenus[i] && aSubmenus[i].getSubmenus) {
+ if (findTargetInSubmenus(aSubmenus[i].getSubmenus())) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ if (oTarget != oButtonElement &&
+ !Dom.isAncestor(oButtonElement, oTarget) &&
+ oTarget != oMenuElement &&
+ !Dom.isAncestor(oMenuElement, oTarget)) {
+
+
+ if (this._menu && this._menu.getSubmenus) {
+ if (!findTargetInSubmenus(this._menu.getSubmenus())) {
+ return;
+ }
+ }
+
+
+ this._hideMenu();
+
+ // In IE when the user mouses down on a focusable element
+ // that element will be focused and become the "activeElement".
+ // (http://msdn.microsoft.com/en-us/library/ms533065(VS.85).aspx)
+ // However, there is a bug in IE where if there is a
+ // positioned element with a focused descendant that is
+ // hidden in response to the mousedown event, the target of
+ // the mousedown event will appear to have focus, but will
+ // not be set as the activeElement. This will result
+ // in the element not firing key events, even though it
+ // appears to have focus. The following call to "setActive"
+ // fixes this bug.
+
+ if (UA.ie && (UA.ie < 9) && oTarget.focus) {
+ oTarget.setActive();
+ }
+
+ Event.removeListener(document, "mousedown",
+ this._onDocumentMouseDown);
+
+ }
+
+ },
+
+
+ /**
+ * @method _onOption
+ * @description "option" event handler for the button.
+ * @protected
+ * @param {Event} p_oEvent Object representing the DOM event object
+ * passed back by the event utility (YAHOO.util.Event).
+ */
+ _onOption: function (p_oEvent) {
+
+ if (this.hasClass(this.CLASS_NAME_PREFIX + "split-button-activeoption")) {
+
+ this._hideMenu();
+
+ this._bOptionPressed = false;
+
+ }
+ else {
+
+ this._showMenu(p_oEvent);
+
+ this._bOptionPressed = true;
+
+ }
+
+ },
+
+
+ /**
+ * @method _onMenuShow
+ * @description "show" event handler for the button's menu.
+ * @private
+ * @param {String} p_sType String representing the name of the event
+ * that was fired.
+ */
+ _onMenuShow: function (p_sType) {
+
+ Event.on(document, "mousedown", this._onDocumentMouseDown,
+ null, this);
+
+ var sState = (this.get("type") == "split") ? "activeoption" : "active";
+
+ this.addStateCSSClasses(sState);
+
+ },
+
+
+ /**
+ * @method _onMenuHide
+ * @description "hide" event handler for the button's menu.
+ * @private
+ * @param {String} p_sType String representing the name of the event
+ * that was fired.
+ */
+ _onMenuHide: function (p_sType) {
+
+ var sState = (this.get("type") == "split") ? "activeoption" : "active";
+
+ this.removeStateCSSClasses(sState);
+
+
+ if (this.get("type") == "split") {
+
+ this._bOptionPressed = false;
+
+ }
+
+ },
+
+
+ /**
+ * @method _onMenuKeyDown
+ * @description "keydown" event handler for the button's menu.
+ * @private
+ * @param {String} p_sType String representing the name of the event
+ * that was fired.
+ * @param {Array} p_aArgs Array of arguments sent when the event
+ * was fired.
+ */
+ _onMenuKeyDown: function (p_sType, p_aArgs) {
+
+ var oEvent = p_aArgs[0];
+
+ if (Event.getCharCode(oEvent) == 27) {
+
+ this.focus();
+
+ if (this.get("type") == "split") {
+
+ this._bOptionPressed = false;
+
+ }
+
+ }
+
+ },
+
+
+ /**
+ * @method _onMenuRender
+ * @description "render" event handler for the button's menu.
+ * @private
+ * @param {String} p_sType String representing the name of the
+ * event thatwas fired.
+ */
+ _onMenuRender: function (p_sType) {
+
+ var oButtonElement = this.get("element"),
+ oButtonParent = oButtonElement.parentNode,
+ oMenu = this._menu,
+ oMenuElement = oMenu.element,
+ oSrcElement = oMenu.srcElement,
+ oItem;
+
+
+ if (oButtonParent != oMenuElement.parentNode) {
+
+ oButtonParent.appendChild(oMenuElement);
+
+ }
+
+ this._renderedMenu = true;
+
+ // If the user has designated an Series
+ * object shouldn't be instantiated directly. Instead, a subclass with a
+ * concrete implementation should be used.
+ *
+ * @namespace YAHOO.widget
+ * @class Series
+ * @constructor
+ */
+YAHOO.widget.Series = function() {};
+
+YAHOO.widget.Series.prototype =
+{
+ /**
+ * The type of series.
+ *
+ * @property type
+ * @type String
+ */
+ type: null,
+
+ /**
+ * The human-readable name of the series.
+ *
+ * @property displayName
+ * @type String
+ */
+ displayName: null
+};
+
+/**
+ * Functionality common to most series appearing in cartesian charts.
+ * Generally, a CartesianSeries object shouldn't be
+ * instantiated directly. Instead, a subclass with a concrete implementation
+ * should be used.
+ *
+ * @namespace YAHOO.widget
+ * @class CartesianSeries
+ * @uses YAHOO.widget.Series
+ * @constructor
+ */
+YAHOO.widget.CartesianSeries = function()
+{
+ YAHOO.widget.CartesianSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.CartesianSeries, YAHOO.widget.Series,
+{
+ /**
+ * The field used to access the x-axis value from the items from the data source.
+ *
+ * @property xField
+ * @type String
+ */
+ xField: null,
+
+ /**
+ * The field used to access the y-axis value from the items from the data source.
+ *
+ * @property yField
+ * @type String
+ */
+ yField: null,
+
+ /**
+ * Indicates which axis the series will bind to
+ *
+ * @property axis
+ * @type String
+ */
+ axis: "primary",
+
+ /**
+ * When a Legend is present, indicates whether the series will show in the legend.
+ *
+ * @property showInLegend
+ * @type Boolean
+ */
+ showInLegend: true
+});
+
+/**
+ * ColumnSeries class for the YUI Charts widget.
+ *
+ * @namespace YAHOO.widget
+ * @class ColumnSeries
+ * @uses YAHOO.widget.CartesianSeries
+ * @constructor
+ */
+YAHOO.widget.ColumnSeries = function()
+{
+ YAHOO.widget.ColumnSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.ColumnSeries, YAHOO.widget.CartesianSeries,
+{
+ type: "column"
+});
+
+/**
+ * LineSeries class for the YUI Charts widget.
+ *
+ * @namespace YAHOO.widget
+ * @class LineSeries
+ * @uses YAHOO.widget.CartesianSeries
+ * @constructor
+ */
+YAHOO.widget.LineSeries = function()
+{
+ YAHOO.widget.LineSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.LineSeries, YAHOO.widget.CartesianSeries,
+{
+ type: "line"
+});
+
+
+/**
+ * BarSeries class for the YUI Charts widget.
+ *
+ * @namespace YAHOO.widget
+ * @class BarSeries
+ * @uses YAHOO.widget.CartesianSeries
+ * @constructor
+ */
+YAHOO.widget.BarSeries = function()
+{
+ YAHOO.widget.BarSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.BarSeries, YAHOO.widget.CartesianSeries,
+{
+ type: "bar"
+});
+
+
+/**
+ * PieSeries class for the YUI Charts widget.
+ *
+ * @namespace YAHOO.widget
+ * @class PieSeries
+ * @uses YAHOO.widget.Series
+ * @constructor
+ */
+YAHOO.widget.PieSeries = function()
+{
+ YAHOO.widget.PieSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.PieSeries, YAHOO.widget.Series,
+{
+ type: "pie",
+
+ /**
+ * The field used to access the data value from the items from the data source.
+ *
+ * @property dataField
+ * @type String
+ */
+ dataField: null,
+
+ /**
+ * The field used to access the category value from the items from the data source.
+ *
+ * @property categoryField
+ * @type String
+ */
+ categoryField: null,
+
+ /**
+ * A string reference to the globally-accessible function that may be called to
+ * determine each of the label values for this series. Also accepts function references.
+ *
+ * @property labelFunction
+ * @type String
+ */
+ labelFunction: null
+});
+
+/**
+ * StackedBarSeries class for the YUI Charts widget.
+ *
+ * @namespace YAHOO.widget
+ * @class StackedBarSeries
+ * @uses YAHOO.widget.CartesianSeries
+ * @constructor
+ */
+YAHOO.widget.StackedBarSeries = function()
+{
+ YAHOO.widget.StackedBarSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.StackedBarSeries, YAHOO.widget.CartesianSeries,
+{
+ type: "stackbar"
+});
+
+/**
+ * StackedColumnSeries class for the YUI Charts widget.
+ *
+ * @namespace YAHOO.widget
+ * @class StackedColumnSeries
+ * @uses YAHOO.widget.CartesianSeries
+ * @constructor
+ */
+YAHOO.widget.StackedColumnSeries = function()
+{
+ YAHOO.widget.StackedColumnSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.StackedColumnSeries, YAHOO.widget.CartesianSeries,
+{
+ type: "stackcolumn"
+});
+YAHOO.register("charts", YAHOO.widget.Chart, {version: "2.9.0", build: "2800"});
diff --git a/ajax/libs/yui/2.9.0/charts/charts-min.js b/ajax/libs/yui/2.9.0/charts/charts-min.js
new file mode 100644
index 000000000..40553ab15
--- /dev/null
+++ b/ajax/libs/yui/2.9.0/charts/charts-min.js
@@ -0,0 +1,9 @@
+/*
+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
+*/
+YAHOO.widget.Chart=function(d,a,j,g){this._type=d;this._dataSource=j;var f={align:"",allowNetworking:"",allowScriptAccess:"",base:"",bgcolor:"",menu:"",name:"",quality:"",salign:"",scale:"",tabindex:"",wmode:""};var b={fixedAttributes:{allowScriptAccess:"always"},flashVars:{allowedDomain:document.location.hostname},backgroundColor:"#ffffff",host:this,version:9.045};for(var c in g){if(f.hasOwnProperty(c)){b.fixedAttributes[c]=g[c];}else{b[c]=g[c];}}this._id=b.id=b.id||YAHOO.util.Dom.generateId(null,"yuigen");this._swfURL=YAHOO.widget.Chart.SWFURL;this._containerID=a;this._attributes=b;this._swfEmbed=new YAHOO.widget.SWF(a,YAHOO.widget.Chart.SWFURL,b);this._swf=this._swfEmbed.swf;this._swfEmbed.subscribe("swfReady",this._eventHandler,this,true);try{this.createEvent("contentReady");}catch(h){}this.createEvent("itemMouseOverEvent");this.createEvent("itemMouseOutEvent");this.createEvent("itemClickEvent");this.createEvent("itemDoubleClickEvent");this.createEvent("itemDragStartEvent");this.createEvent("itemDragEvent");this.createEvent("itemDragEndEvent");};YAHOO.extend(YAHOO.widget.Chart,YAHOO.util.AttributeProvider,{_type:null,_pollingID:null,_pollingInterval:null,_dataTipFunction:null,_legendLabelFunction:null,_seriesFunctions:null,toString:function(){return"Chart "+this._id;},setStyle:function(a,b){b=YAHOO.lang.JSON.stringify(b);this._swf.setStyle(a,b);},setStyles:function(a){a=YAHOO.lang.JSON.stringify(a);this._swf.setStyles(a);},setSeriesStyles:function(b){for(var a=0;aSeries
+ * object shouldn't be instantiated directly. Instead, a subclass with a
+ * concrete implementation should be used.
+ *
+ * @namespace YAHOO.widget
+ * @class Series
+ * @constructor
+ */
+YAHOO.widget.Series = function() {};
+
+YAHOO.widget.Series.prototype =
+{
+ /**
+ * The type of series.
+ *
+ * @property type
+ * @type String
+ */
+ type: null,
+
+ /**
+ * The human-readable name of the series.
+ *
+ * @property displayName
+ * @type String
+ */
+ displayName: null
+};
+
+/**
+ * Functionality common to most series appearing in cartesian charts.
+ * Generally, a CartesianSeries object shouldn't be
+ * instantiated directly. Instead, a subclass with a concrete implementation
+ * should be used.
+ *
+ * @namespace YAHOO.widget
+ * @class CartesianSeries
+ * @uses YAHOO.widget.Series
+ * @constructor
+ */
+YAHOO.widget.CartesianSeries = function()
+{
+ YAHOO.widget.CartesianSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.CartesianSeries, YAHOO.widget.Series,
+{
+ /**
+ * The field used to access the x-axis value from the items from the data source.
+ *
+ * @property xField
+ * @type String
+ */
+ xField: null,
+
+ /**
+ * The field used to access the y-axis value from the items from the data source.
+ *
+ * @property yField
+ * @type String
+ */
+ yField: null,
+
+ /**
+ * Indicates which axis the series will bind to
+ *
+ * @property axis
+ * @type String
+ */
+ axis: "primary",
+
+ /**
+ * When a Legend is present, indicates whether the series will show in the legend.
+ *
+ * @property showInLegend
+ * @type Boolean
+ */
+ showInLegend: true
+});
+
+/**
+ * ColumnSeries class for the YUI Charts widget.
+ *
+ * @namespace YAHOO.widget
+ * @class ColumnSeries
+ * @uses YAHOO.widget.CartesianSeries
+ * @constructor
+ */
+YAHOO.widget.ColumnSeries = function()
+{
+ YAHOO.widget.ColumnSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.ColumnSeries, YAHOO.widget.CartesianSeries,
+{
+ type: "column"
+});
+
+/**
+ * LineSeries class for the YUI Charts widget.
+ *
+ * @namespace YAHOO.widget
+ * @class LineSeries
+ * @uses YAHOO.widget.CartesianSeries
+ * @constructor
+ */
+YAHOO.widget.LineSeries = function()
+{
+ YAHOO.widget.LineSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.LineSeries, YAHOO.widget.CartesianSeries,
+{
+ type: "line"
+});
+
+
+/**
+ * BarSeries class for the YUI Charts widget.
+ *
+ * @namespace YAHOO.widget
+ * @class BarSeries
+ * @uses YAHOO.widget.CartesianSeries
+ * @constructor
+ */
+YAHOO.widget.BarSeries = function()
+{
+ YAHOO.widget.BarSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.BarSeries, YAHOO.widget.CartesianSeries,
+{
+ type: "bar"
+});
+
+
+/**
+ * PieSeries class for the YUI Charts widget.
+ *
+ * @namespace YAHOO.widget
+ * @class PieSeries
+ * @uses YAHOO.widget.Series
+ * @constructor
+ */
+YAHOO.widget.PieSeries = function()
+{
+ YAHOO.widget.PieSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.PieSeries, YAHOO.widget.Series,
+{
+ type: "pie",
+
+ /**
+ * The field used to access the data value from the items from the data source.
+ *
+ * @property dataField
+ * @type String
+ */
+ dataField: null,
+
+ /**
+ * The field used to access the category value from the items from the data source.
+ *
+ * @property categoryField
+ * @type String
+ */
+ categoryField: null,
+
+ /**
+ * A string reference to the globally-accessible function that may be called to
+ * determine each of the label values for this series. Also accepts function references.
+ *
+ * @property labelFunction
+ * @type String
+ */
+ labelFunction: null
+});
+
+/**
+ * StackedBarSeries class for the YUI Charts widget.
+ *
+ * @namespace YAHOO.widget
+ * @class StackedBarSeries
+ * @uses YAHOO.widget.CartesianSeries
+ * @constructor
+ */
+YAHOO.widget.StackedBarSeries = function()
+{
+ YAHOO.widget.StackedBarSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.StackedBarSeries, YAHOO.widget.CartesianSeries,
+{
+ type: "stackbar"
+});
+
+/**
+ * StackedColumnSeries class for the YUI Charts widget.
+ *
+ * @namespace YAHOO.widget
+ * @class StackedColumnSeries
+ * @uses YAHOO.widget.CartesianSeries
+ * @constructor
+ */
+YAHOO.widget.StackedColumnSeries = function()
+{
+ YAHOO.widget.StackedColumnSeries.superclass.constructor.call(this);
+};
+
+YAHOO.lang.extend(YAHOO.widget.StackedColumnSeries, YAHOO.widget.CartesianSeries,
+{
+ type: "stackcolumn"
+});
+YAHOO.register("charts", YAHOO.widget.Chart, {version: "2.9.0", build: "2800"});
diff --git a/ajax/libs/yui/2.9.0/colorpicker/assets/colorpicker-core.css b/ajax/libs/yui/2.9.0/colorpicker/assets/colorpicker-core.css
new file mode 100644
index 000000000..e81c3b2db
--- /dev/null
+++ b/ajax/libs/yui/2.9.0/colorpicker/assets/colorpicker-core.css
@@ -0,0 +1,6 @@
+/*
+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
+*/
diff --git a/ajax/libs/yui/2.9.0/colorpicker/assets/hue_thumb.png b/ajax/libs/yui/2.9.0/colorpicker/assets/hue_thumb.png
new file mode 100644
index 000000000..14d5db486
Binary files /dev/null and b/ajax/libs/yui/2.9.0/colorpicker/assets/hue_thumb.png differ
diff --git a/ajax/libs/yui/2.9.0/colorpicker/assets/picker_mask.png b/ajax/libs/yui/2.9.0/colorpicker/assets/picker_mask.png
new file mode 100644
index 000000000..f8d91932b
Binary files /dev/null and b/ajax/libs/yui/2.9.0/colorpicker/assets/picker_mask.png differ
diff --git a/ajax/libs/yui/2.9.0/colorpicker/assets/picker_thumb.png b/ajax/libs/yui/2.9.0/colorpicker/assets/picker_thumb.png
new file mode 100644
index 000000000..78445a2fe
Binary files /dev/null and b/ajax/libs/yui/2.9.0/colorpicker/assets/picker_thumb.png differ
diff --git a/ajax/libs/yui/2.9.0/colorpicker/assets/skins/sam/colorpicker-skin.css b/ajax/libs/yui/2.9.0/colorpicker/assets/skins/sam/colorpicker-skin.css
new file mode 100644
index 000000000..644243c7e
--- /dev/null
+++ b/ajax/libs/yui/2.9.0/colorpicker/assets/skins/sam/colorpicker-skin.css
@@ -0,0 +1,105 @@
+/*
+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
+*/
+
+.yui-picker-panel {
+ background: #e3e3e3;
+ border-color: #888;
+}
+
+.yui-picker-panel .hd {
+ background-color:#ccc;
+ font-size:100%;
+ line-height:100%;
+ border:1px solid #e3e3e3;
+ font-weight:bold;
+ overflow:hidden;
+ padding: 6px;
+ color: #000;
+}
+
+.yui-picker-panel .bd {
+ background: #e8e8e8;
+ margin: 1px;
+ height: 200px;
+}
+
+.yui-picker-panel .ft {
+ background: #e8e8e8;
+ margin: 1px;
+ padding: 1px;
+ /*
+ text-align: center;
+ */
+}
+
+.yui-picker {
+ position: relative;
+}
+
+.yui-picker-hue-thumb { cursor:default; width:18px; height:18px;
+top: -8px;
+left: -2px;
+ z-index: 9; position:absolute; }
+.yui-picker-hue-bg {-moz-outline: none; outline:0px none;
+ position:absolute; left:200px; height:183px; width:14px;
+ background:url(hue_bg.png) no-repeat;
+ top:4px;
+}
+
+.yui-picker-bg {
+ -moz-outline: none;
+ outline:0px none;
+ position:absolute;
+ top:4px;
+ left:4px;
+ height:182px;
+ width:182px;
+ background-color:#F00;
+ background-image: url(picker_mask.png);
+}
+
+*html .yui-picker-bg {
+ background-image: none;
+ filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='picker_mask.png', sizingMethod='scale');
+}
+
+
+.yui-picker-mask { position:absolute; z-index: 1; top:0px; left:0px; }
+
+.yui-picker-thumb { cursor:default; width:11px; height:11px; z-index: 9; position:absolute;
+ top:-4px; left:-4px; }
+
+.yui-picker-swatch { position:absolute; left:240px; top:4px; height:60px;
+ width:55px; border:1px solid #888; }
+.yui-picker-websafe-swatch { position:absolute; left:304px; top:4px;
+ height:24px; width:24px; border:1px solid #888; }
+
+.yui-picker-controls { position:absolute; top: 72px; left:226px; font:1em monospace;}
+.yui-picker-controls .hd { background: transparent; border-width: 0px !important;}
+.yui-picker-controls .bd { height: 100px; border-width: 0px !important;}
+.yui-picker-controls ul {float:left;padding:0 2px 0 0;margin:0}
+.yui-picker-controls li {padding:2px;list-style:none;margin:0}
+.yui-picker-controls input {
+ font-size: 0.85em;
+ width: 2.4em;
+}
+.yui-picker-hex-controls {
+ clear: both;
+ padding: 2px;
+}
+.yui-picker-hex-controls input {
+ width: 4.6em;
+}
+
+.yui-picker-controls a {
+ font: 1em arial,helvetica,clean,sans-serif;
+ display:block;
+ *display:inline-block; /* IE */
+ padding: 0;
+ color: #000;
+
+}
diff --git a/ajax/libs/yui/2.9.0/colorpicker/assets/skins/sam/colorpicker.css b/ajax/libs/yui/2.9.0/colorpicker/assets/skins/sam/colorpicker.css
new file mode 100644
index 000000000..77ac7c1ea
--- /dev/null
+++ b/ajax/libs/yui/2.9.0/colorpicker/assets/skins/sam/colorpicker.css
@@ -0,0 +1,7 @@
+/*
+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
+*/
+.yui-picker-panel{background:#e3e3e3;border-color:#888}.yui-picker-panel .hd{background-color:#ccc;font-size:100%;line-height:100%;border:1px solid #e3e3e3;font-weight:bold;overflow:hidden;padding:6px;color:#000}.yui-picker-panel .bd{background:#e8e8e8;margin:1px;height:200px}.yui-picker-panel .ft{background:#e8e8e8;margin:1px;padding:1px}.yui-picker{position:relative}.yui-picker-hue-thumb{cursor:default;width:18px;height:18px;top:-8px;left:-2px;z-index:9;position:absolute}.yui-picker-hue-bg{-moz-outline:0;outline:0 none;position:absolute;left:200px;height:183px;width:14px;background:url(hue_bg.png) no-repeat;top:4px}.yui-picker-bg{-moz-outline:0;outline:0 none;position:absolute;top:4px;left:4px;height:182px;width:182px;background-color:#F00;background-image:url(picker_mask.png)}*html .yui-picker-bg{background-image:none;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='picker_mask.png',sizingMethod='scale')}.yui-picker-mask{position:absolute;z-index:1;top:0;left:0}.yui-picker-thumb{cursor:default;width:11px;height:11px;z-index:9;position:absolute;top:-4px;left:-4px}.yui-picker-swatch{position:absolute;left:240px;top:4px;height:60px;width:55px;border:1px solid #888}.yui-picker-websafe-swatch{position:absolute;left:304px;top:4px;height:24px;width:24px;border:1px solid #888}.yui-picker-controls{position:absolute;top:72px;left:226px;font:1em monospace}.yui-picker-controls .hd{background:transparent;border-width:0!important}.yui-picker-controls .bd{height:100px;border-width:0!important}.yui-picker-controls ul{float:left;padding:0 2px 0 0;margin:0}.yui-picker-controls li{padding:2px;list-style:none;margin:0}.yui-picker-controls input{font-size:.85em;width:2.4em}.yui-picker-hex-controls{clear:both;padding:2px}.yui-picker-hex-controls input{width:4.6em}.yui-picker-controls a{font:1em arial,helvetica,clean,sans-serif;display:block;*display:inline-block;padding:0;color:#000}
diff --git a/ajax/libs/yui/2.9.0/colorpicker/assets/skins/sam/hue_bg.png b/ajax/libs/yui/2.9.0/colorpicker/assets/skins/sam/hue_bg.png
new file mode 100644
index 000000000..d9bcdeb5c
Binary files /dev/null and b/ajax/libs/yui/2.9.0/colorpicker/assets/skins/sam/hue_bg.png differ
diff --git a/ajax/libs/yui/2.9.0/colorpicker/assets/skins/sam/picker_mask.png b/ajax/libs/yui/2.9.0/colorpicker/assets/skins/sam/picker_mask.png
new file mode 100644
index 000000000..f8d91932b
Binary files /dev/null and b/ajax/libs/yui/2.9.0/colorpicker/assets/skins/sam/picker_mask.png differ
diff --git a/ajax/libs/yui/2.9.0/colorpicker/colorpicker-debug.js b/ajax/libs/yui/2.9.0/colorpicker/colorpicker-debug.js
new file mode 100644
index 000000000..6db62a060
--- /dev/null
+++ b/ajax/libs/yui/2.9.0/colorpicker/colorpicker-debug.js
@@ -0,0 +1,1784 @@
+/*
+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
+*/
+/**
+ * Provides color conversion and validation utils
+ * @class YAHOO.util.Color
+ * @namespace YAHOO.util
+ */
+YAHOO.util.Color = function() {
+
+ var ZERO = "0",
+ isArray = YAHOO.lang.isArray,
+ isNumber = YAHOO.lang.isNumber;
+
+ return {
+
+ /**
+ * Converts 0-1 to 0-255
+ * @method real2dec
+ * @param n {float} the number to convert
+ * @return {int} a number 0-255
+ */
+ real2dec: function(n) {
+ return Math.min(255, Math.round(n*256));
+ },
+
+ /**
+ * Converts HSV (h[0-360], s[0-1]), v[0-1] to RGB [255,255,255]
+ * @method hsv2rgb
+ * @param h {int|[int, float, float]} the hue, or an
+ * array containing all three parameters
+ * @param s {float} the saturation
+ * @param v {float} the value/brightness
+ * @return {[int, int, int]} the red, green, blue values in
+ * decimal.
+ */
+ hsv2rgb: function(h, s, v) {
+
+ if (isArray(h)) {
+ return this.hsv2rgb.call(this, h[0], h[1], h[2]);
+ }
+
+ var r, g, b,
+ i = Math.floor((h/60)%6),
+ f = (h/60)-i,
+ p = v*(1-s),
+ q = v*(1-f*s),
+ t = v*(1-(1-f)*s),
+ fn;
+
+ switch (i) {
+ case 0: r=v; g=t; b=p; break;
+ case 1: r=q; g=v; b=p; break;
+ case 2: r=p; g=v; b=t; break;
+ case 3: r=p; g=q; b=v; break;
+ case 4: r=t; g=p; b=v; break;
+ case 5: r=v; g=p; b=q; break;
+ }
+
+ fn=this.real2dec;
+
+ return [fn(r), fn(g), fn(b)];
+ },
+
+ /**
+ * Converts to RGB [255,255,255] to HSV (h[0-360], s[0-1]), v[0-1]
+ * @method rgb2hsv
+ * @param r {int|[int, int, int]} the red value, or an
+ * array containing all three parameters
+ * @param g {int} the green value
+ * @param b {int} the blue value
+ * @return {[int, float, float]} the value converted to hsv
+ */
+ rgb2hsv: function(r, g, b) {
+
+ if (isArray(r)) {
+ return this.rgb2hsv.apply(this, r);
+ }
+
+ r /= 255;
+ g /= 255;
+ b /= 255;
+
+ var h,s,
+ min = Math.min(Math.min(r,g),b),
+ max = Math.max(Math.max(r,g),b),
+ delta = max-min,
+ hsv;
+
+ switch (max) {
+ case min: h=0; break;
+ case r: h=60*(g-b)/delta;
+ if (g FFFFFF
+ * @method rgb2hex
+ * @param r {int|[int, int, int]} the red value, or an
+ * array containing all three parameters
+ * @param g {int} the green value
+ * @param b {int} the blue value
+ * @return {string} the hex string
+ */
+ rgb2hex: function(r, g, b) {
+ if (isArray(r)) {
+ return this.rgb2hex.apply(this, r);
+ }
+
+ var f=this.dec2hex;
+ return f(r) + f(g) + f(b);
+ },
+
+ /**
+ * Converts an int 0...255 to hex pair 00...FF
+ * @method dec2hex
+ * @param n {int} the number to convert
+ * @return {string} the hex equivalent
+ */
+ dec2hex: function(n) {
+ n = parseInt(n,10)|0;
+ n = (n > 255 || n < 0) ? 0 : n;
+
+ return (ZERO+n.toString(16)).slice(-2).toUpperCase();
+ },
+
+ /**
+ * Converts a hex pair 00...FF to an int 0...255
+ * @method hex2dec
+ * @param str {string} the hex pair to convert
+ * @return {int} the decimal
+ */
+ hex2dec: function(str) {
+ return parseInt(str,16);
+ },
+
+ /**
+ * Converts a hex string to rgb
+ * @method hex2rgb
+ * @param str {string} the hex string
+ * @return {[int, int, int]} an array containing the rgb values
+ */
+ hex2rgb: function(s) {
+ var f = this.hex2dec;
+ return [f(s.slice(0, 2)), f(s.slice(2, 4)), f(s.slice(4, 6))];
+ },
+
+ /**
+ * Returns the closest websafe color to the supplied rgb value.
+ * @method websafe
+ * @param r {int|[int, int, int]} the red value, or an
+ * array containing all three parameters
+ * @param g {int} the green value
+ * @param b {int} the blue value
+ * @return {[int, int, int]} an array containing the closes
+ * websafe rgb colors.
+ */
+ websafe: function(r, g, b) {
+
+ if (isArray(r)) {
+ return this.websafe.apply(this, r);
+ }
+
+ // returns the closest match [0, 51, 102, 153, 204, 255]
+ var f = function(v) {
+ if (isNumber(v)) {
+ v = Math.min(Math.max(0, v), 255);
+ var i, next;
+ for (i=0; i<256; i=i+51) {
+ next = i+51;
+ if (v >= i && v <= next) {
+ return (v-i > 25) ? next : i;
+ }
+ }
+ YAHOO.log("Error calculating the websafe value for " + v, "warn");
+ }
+
+ return v;
+ };
+
+ return [f(r), f(g), f(b)];
+ }
+ };
+}();
+
+
+/**
+ * The colorpicker module provides a widget for selecting colors
+ * @module colorpicker
+ * @requires yahoo, dom, event, element, slider
+ */
+(function() {
+
+ var _pickercount = 0,
+ util = YAHOO.util,
+ lang = YAHOO.lang,
+ Slider = YAHOO.widget.Slider,
+ Color = util.Color,
+ Dom = util.Dom,
+ Event = util.Event,
+ sub = lang.substitute,
+
+ b = "yui-picker";
+
+
+ /**
+ * A widget to select colors
+ * @namespace YAHOO.widget
+ * @class YAHOO.widget.ColorPicker
+ * @extends YAHOO.util.Element
+ * @constructor
+ * @param {HTMLElement | String | Object} el(optional) The html
+ * element that represents the colorpicker, or the attribute object to use.
+ * An element will be created if none provided.
+ * @param {Object} attr (optional) A key map of the colorpicker's
+ * initial attributes. Ignored if first arg is attributes object.
+ */
+ function ColorPicker(el, attr) {
+ _pickercount = _pickercount + 1;
+ this.logger = new YAHOO.widget.LogWriter("ColorPicker");
+ attr = attr || {};
+ if (arguments.length === 1 && !YAHOO.lang.isString(el) && !el.nodeName) {
+ attr = el; // treat first arg as attr object
+ el = attr.element || null;
+ }
+
+ if (!el && !attr.element) { // create if we dont have one
+ this.logger.log("creating host element");
+ el = this._createHostElement(attr);
+ }
+
+ ColorPicker.superclass.constructor.call(this, el, attr);
+
+ this.initPicker();
+ }
+
+ YAHOO.extend(ColorPicker, YAHOO.util.Element, {
+
+ /**
+ * The element ids used by this control
+ * @property ID
+ * @final
+ */
+ ID : {
+
+ /**
+ * The id for the "red" form field
+ * @property ID.R
+ * @type String
+ * @final
+ * @default yui-picker-r
+ */
+ R: b + "-r",
+
+ /**
+ * The id for the "red" hex pair output
+ * @property ID.R_HEX
+ * @type String
+ * @final
+ * @default yui-picker-rhex
+ */
+ R_HEX: b + "-rhex",
+
+ /**
+ * The id for the "green" form field
+ * @property ID.G
+ * @type String
+ * @final
+ * @default yui-picker-g
+ */
+ G: b + "-g",
+
+ /**
+ * The id for the "green" hex pair output
+ * @property ID.G_HEX
+ * @type String
+ * @final
+ * @default yui-picker-ghex
+ */
+ G_HEX: b + "-ghex",
+
+
+ /**
+ * The id for the "blue" form field
+ * @property ID.B
+ * @type String
+ * @final
+ * @default yui-picker-b
+ */
+ B: b + "-b",
+
+ /**
+ * The id for the "blue" hex pair output
+ * @property ID.B_HEX
+ * @type String
+ * @final
+ * @default yui-picker-bhex
+ */
+ B_HEX: b + "-bhex",
+
+ /**
+ * The id for the "hue" form field
+ * @property ID.H
+ * @type String
+ * @final
+ * @default yui-picker-h
+ */
+ H: b + "-h",
+
+ /**
+ * The id for the "saturation" form field
+ * @property ID.S
+ * @type String
+ * @final
+ * @default yui-picker-s
+ */
+ S: b + "-s",
+
+ /**
+ * The id for the "value" form field
+ * @property ID.V
+ * @type String
+ * @final
+ * @default yui-picker-v
+ */
+ V: b + "-v",
+
+ /**
+ * The id for the picker region slider
+ * @property ID.PICKER_BG
+ * @type String
+ * @final
+ * @default yui-picker-bg
+ */
+ PICKER_BG: b + "-bg",
+
+ /**
+ * The id for the picker region thumb
+ * @property ID.PICKER_THUMB
+ * @type String
+ * @final
+ * @default yui-picker-thumb
+ */
+ PICKER_THUMB: b + "-thumb",
+
+ /**
+ * The id for the hue slider
+ * @property ID.HUE_BG
+ * @type String
+ * @final
+ * @default yui-picker-hue-bg
+ */
+ HUE_BG: b + "-hue-bg",
+
+ /**
+ * The id for the hue thumb
+ * @property ID.HUE_THUMB
+ * @type String
+ * @final
+ * @default yui-picker-hue-thumb
+ */
+ HUE_THUMB: b + "-hue-thumb",
+
+ /**
+ * The id for the hex value form field
+ * @property ID.HEX
+ * @type String
+ * @final
+ * @default yui-picker-hex
+ */
+ HEX: b + "-hex",
+
+ /**
+ * The id for the color swatch
+ * @property ID.SWATCH
+ * @type String
+ * @final
+ * @default yui-picker-swatch
+ */
+ SWATCH: b + "-swatch",
+
+ /**
+ * The id for the websafe color swatch
+ * @property ID.WEBSAFE_SWATCH
+ * @type String
+ * @final
+ * @default yui-picker-websafe-swatch
+ */
+ WEBSAFE_SWATCH: b + "-websafe-swatch",
+
+ /**
+ * The id for the control details
+ * @property ID.CONTROLS
+ * @final
+ * @default yui-picker-controls
+ */
+ CONTROLS: b + "-controls",
+
+ /**
+ * The id for the rgb controls
+ * @property ID.RGB_CONTROLS
+ * @final
+ * @default yui-picker-rgb-controls
+ */
+ RGB_CONTROLS: b + "-rgb-controls",
+
+ /**
+ * The id for the hsv controls
+ * @property ID.HSV_CONTROLS
+ * @final
+ * @default yui-picker-hsv-controls
+ */
+ HSV_CONTROLS: b + "-hsv-controls",
+
+ /**
+ * The id for the hsv controls
+ * @property ID.HEX_CONTROLS
+ * @final
+ * @default yui-picker-hex-controls
+ */
+ HEX_CONTROLS: b + "-hex-controls",
+
+ /**
+ * The id for the hex summary
+ * @property ID.HEX_SUMMARY
+ * @final
+ * @default yui-picker-hex-summary
+ */
+ HEX_SUMMARY: b + "-hex-summary",
+
+ /**
+ * The id for the controls section header
+ * @property ID.CONTROLS_LABEL
+ * @final
+ * @default yui-picker-controls-label
+ */
+ CONTROLS_LABEL: b + "-controls-label"
+ },
+
+ /**
+ * Constants for any script-generated messages. The values here
+ * are the default messages. They can be updated by providing
+ * the complete list to the constructor for the "txt" attribute.
+ * Note: the strings are added to the DOM as HTML.
+ * @property TXT
+ * @final
+ */
+ TXT : {
+ ILLEGAL_HEX: "Illegal hex value entered",
+ SHOW_CONTROLS: "Show color details",
+ HIDE_CONTROLS: "Hide color details",
+ CURRENT_COLOR: "Currently selected color: {rgb}",
+ CLOSEST_WEBSAFE: "Closest websafe color: {rgb}. Click to select.",
+ R: "R",
+ G: "G",
+ B: "B",
+ H: "H",
+ S: "S",
+ V: "V",
+ HEX: "#",
+ DEG: "\u00B0",
+ PERCENT: "%"
+ },
+
+ /**
+ * Constants for the default image locations for img tags that are
+ * generated by the control. They can be modified by passing the
+ * complete list to the contructor for the "images" attribute
+ * @property IMAGE
+ * @final
+ */
+ IMAGE : {
+ PICKER_THUMB: "../../build/colorpicker/assets/picker_thumb.png",
+ HUE_THUMB: "../../build/colorpicker/assets/hue_thumb.png"
+ },
+
+ /**
+ * Constants for the control's default default values
+ * @property DEFAULT
+ * @final
+ */
+ DEFAULT : {
+ PICKER_SIZE: 180
+ },
+
+ /**
+ * Constants for the control's configuration attributes
+ * @property OPT
+ * @final
+ */
+ OPT : {
+ HUE : "hue",
+ SATURATION : "saturation",
+ VALUE : "value",
+ RED : "red",
+ GREEN : "green",
+ BLUE : "blue",
+ HSV : "hsv",
+ RGB : "rgb",
+ WEBSAFE : "websafe",
+ HEX : "hex",
+ PICKER_SIZE : "pickersize",
+ SHOW_CONTROLS : "showcontrols",
+ SHOW_RGB_CONTROLS : "showrgbcontrols",
+ SHOW_HSV_CONTROLS : "showhsvcontrols",
+ SHOW_HEX_CONTROLS : "showhexcontrols",
+ SHOW_HEX_SUMMARY : "showhexsummary",
+ SHOW_WEBSAFE : "showwebsafe",
+ CONTAINER : "container",
+ IDS : "ids",
+ ELEMENTS : "elements",
+ TXT : "txt",
+ IMAGES : "images",
+ ANIMATE : "animate"
+ },
+
+ /**
+ * Flag to allow individual UI updates to forego animation if available.
+ * True during construction for initial thumb placement. Set to false
+ * after that.
+ *
+ * @property skipAnim
+ * @type Boolean
+ * @default true
+ */
+ skipAnim : true,
+
+ /**
+ * Creates the host element if it doesn't exist
+ * @method _createHostElement
+ * @protected
+ */
+ _createHostElement : function () {
+ var el = document.createElement('div');
+
+ if (this.CSS.BASE) {
+ el.className = this.CSS.BASE;
+ }
+
+ return el;
+ },
+
+ /**
+ * Moves the hue slider into the position dictated by the current state
+ * of the control
+ * @method _updateHueSlider
+ * @protected
+ */
+ _updateHueSlider : function() {
+ var size = this.get(this.OPT.PICKER_SIZE),
+ h = this.get(this.OPT.HUE);
+
+ h = size - Math.round(h / 360 * size);
+
+ // 0 is at the top and bottom of the hue slider. Always go to
+ // the top so we don't end up sending the thumb to the bottom
+ // when the value didn't actually change (e.g., a conversion
+ // produced 360 instead of 0 and the value was already 0).
+ if (h === size) {
+ h = 0;
+ }
+ this.logger.log("Hue slider is being set to " + h);
+
+ this.hueSlider.setValue(h, this.skipAnim);
+ },
+
+ /**
+ * Moves the picker slider into the position dictated by the current state
+ * of the control
+ * @method _updatePickerSlider
+ * @protected
+ */
+ _updatePickerSlider : function() {
+ var size = this.get(this.OPT.PICKER_SIZE),
+ s = this.get(this.OPT.SATURATION),
+ v = this.get(this.OPT.VALUE);
+
+ s = Math.round(s * size / 100);
+ v = Math.round(size - (v * size / 100));
+
+ this.logger.log("Setting picker slider to " + [s, v]);
+
+ this.pickerSlider.setRegionValue(s, v, this.skipAnim);
+ },
+
+ /**
+ * Moves the sliders into the position dictated by the current state
+ * of the control
+ * @method _updateSliders
+ * @protected
+ */
+ _updateSliders : function() {
+ this._updateHueSlider();
+ this._updatePickerSlider();
+ },
+
+ /**
+ * Sets the control to the specified rgb value and
+ * moves the sliders to the proper positions
+ * @method setValue
+ * @param rgb {[int, int, int]} the rgb value
+ * @param silent {boolean} whether or not to fire the change event
+ */
+ setValue : function(rgb, silent) {
+ silent = (silent) || false;
+ this.set(this.OPT.RGB, rgb, silent);
+ this._updateSliders();
+ },
+
+ /**
+ * The hue slider
+ * @property hueSlider
+ * @type YAHOO.widget.Slider
+ */
+ hueSlider : null,
+
+ /**
+ * The picker region
+ * @property pickerSlider
+ * @type YAHOO.widget.Slider
+ */
+ pickerSlider : null,
+
+ /**
+ * Translates the slider value into hue, int[0,359]
+ * @method _getH
+ * @protected
+ * @return {int} the hue from 0 to 359
+ */
+ _getH : function() {
+ var size = this.get(this.OPT.PICKER_SIZE),
+ h = (size - this.hueSlider.getValue()) / size;
+ h = Math.round(h*360);
+ return (h === 360) ? 0 : h;
+ },
+
+ /**
+ * Translates the slider value into saturation, int[0,1], left to right
+ * @method _getS
+ * @protected
+ * @return {int} the saturation from 0 to 1
+ */
+ _getS : function() {
+ return this.pickerSlider.getXValue() / this.get(this.OPT.PICKER_SIZE);
+ },
+
+ /**
+ * Translates the slider value into value/brightness, int[0,1], top
+ * to bottom
+ * @method _getV
+ * @protected
+ * @return {int} the value from 0 to 1
+ */
+ _getV : function() {
+ var size = this.get(this.OPT.PICKER_SIZE);
+ return (size - this.pickerSlider.getYValue()) / size;
+ },
+
+ /**
+ * Updates the background of the swatch with the current rbg value.
+ * Also updates the websafe swatch to the closest websafe color
+ * @method _updateSwatch
+ * @protected
+ */
+ _updateSwatch : function() {
+ var rgb = this.get(this.OPT.RGB),
+ websafe = this.get(this.OPT.WEBSAFE),
+ el = this.getElement(this.ID.SWATCH),
+ color = rgb.join(","),
+ txt = this.get(this.OPT.TXT);
+
+ Dom.setStyle(el, "background-color", "rgb(" + color + ")");
+ el.title = sub(txt.CURRENT_COLOR, {
+ "rgb": "#" + this.get(this.OPT.HEX)
+ });
+
+
+ el = this.getElement(this.ID.WEBSAFE_SWATCH);
+ color = websafe.join(",");
+
+ Dom.setStyle(el, "background-color", "rgb(" + color + ")");
+ el.title = sub(txt.CLOSEST_WEBSAFE, {
+ "rgb": "#" + Color.rgb2hex(websafe)
+ });
+
+ },
+
+ /**
+ * Reads the sliders and converts the values to RGB, updating the
+ * internal state for all the individual form fields
+ * @method _getValuesFromSliders
+ * @protected
+ */
+ _getValuesFromSliders : function() {
+ this.logger.log("hsv " + [this._getH(),this._getS(),this._getV()]);
+ this.set(this.OPT.RGB, Color.hsv2rgb(this._getH(), this._getS(), this._getV()));
+ },
+
+ /**
+ * Updates the form field controls with the state data contained
+ * in the control.
+ * @method _updateFormFields
+ * @protected
+ */
+ _updateFormFields : function() {
+ this.getElement(this.ID.H).value = this.get(this.OPT.HUE);
+ this.getElement(this.ID.S).value = this.get(this.OPT.SATURATION);
+ this.getElement(this.ID.V).value = this.get(this.OPT.VALUE);
+ this.getElement(this.ID.R).value = this.get(this.OPT.RED);
+ this.getElement(this.ID.R_HEX).innerHTML = Color.dec2hex(this.get(this.OPT.RED));
+ this.getElement(this.ID.G).value = this.get(this.OPT.GREEN);
+ this.getElement(this.ID.G_HEX).innerHTML = Color.dec2hex(this.get(this.OPT.GREEN));
+ this.getElement(this.ID.B).value = this.get(this.OPT.BLUE);
+ this.getElement(this.ID.B_HEX).innerHTML = Color.dec2hex(this.get(this.OPT.BLUE));
+ this.getElement(this.ID.HEX).value = this.get(this.OPT.HEX);
+ },
+
+ /**
+ * Event handler for the hue slider.
+ * @method _onHueSliderChange
+ * @param newOffset {int} pixels from the start position
+ * @protected
+ */
+ _onHueSliderChange : function(newOffset) {
+ this.logger.log("hue update: " + newOffset , "warn");
+
+ var h = this._getH(),
+ rgb = Color.hsv2rgb(h, 1, 1),
+ styleDef = "rgb(" + rgb.join(",") + ")";
+
+ this.set(this.OPT.HUE, h, true);
+
+ // set picker background to the hue
+ Dom.setStyle(this.getElement(this.ID.PICKER_BG), "background-color", styleDef);
+
+ if (this.hueSlider.valueChangeSource !== Slider.SOURCE_SET_VALUE) {
+ this._getValuesFromSliders();
+ }
+
+ this._updateFormFields();
+ this._updateSwatch();
+ },
+
+ /**
+ * Event handler for the picker slider, which controls the
+ * saturation and value/brightness.
+ * @method _onPickerSliderChange
+ * @param newOffset {{x: int, y: int}} x/y pixels from the start position
+ * @protected
+ */
+ _onPickerSliderChange : function(newOffset) {
+ this.logger.log(sub("picker update [{x}, {y}]", newOffset));
+
+ var s=this._getS(), v=this._getV();
+ this.set(this.OPT.SATURATION, Math.round(s*100), true);
+ this.set(this.OPT.VALUE, Math.round(v*100), true);
+
+ if (this.pickerSlider.valueChangeSource !== Slider.SOURCE_SET_VALUE) {
+ this._getValuesFromSliders();
+ }
+
+ this._updateFormFields();
+ this._updateSwatch();
+ },
+
+
+ /**
+ * Key map to well-known commands for txt field input
+ * @method _getCommand
+ * @param e {Event} the keypress or keydown event
+ * @return {int} a command code
+ * -1){k=l.options[l.selectedIndex];p[y++]=u+encodeURIComponent((k.attributes.value&&k.attributes.value.specified)?k.value:k.text);}break;case"select-multiple":if(l.selectedIndex>-1){for(n=l.selectedIndex,x=l.options.length;n');if(typeof i=="boolean"){k.src="javascript:false";}}else{k=document.createElement("iframe");k.id=j;k.name=j;}k.style.position="absolute";k.style.top="-1000px";k.style.left="-1000px";document.body.appendChild(k);}function f(j){var m=[],k=j.split("&"),l,n;for(l=0;l =8)?true:false,z=this,v=(y&&y.argument)?y.argument:null,x,s,k,r,j,q;j={action:this._formNode.getAttribute("action"),method:this._formNode.getAttribute("method"),target:this._formNode.getAttribute("target")};this._formNode.setAttribute("action",n);this._formNode.setAttribute("method","POST");this._formNode.setAttribute("target",t);if(YAHOO.env.ua.ie&&!p){this._formNode.setAttribute("encoding",u);}else{this._formNode.setAttribute("enctype",u);}if(l){x=this.appendPostData(l);}this._formNode.submit();this.startEvent.fire(m,v);if(m.startEvent){m.startEvent.fire(m,v);}if(y&&y.timeout){this._timeOut[m.tId]=window.setTimeout(function(){z.abort(m,y,true);},y.timeout);}if(x&&x.length>0){for(s=0;s = 200 && httpStatus < 300) || httpStatus === 1223 || xdrS){ + responseObject = o.xdr ? o.r : this.createResponseObject(o, args); + if(callback && callback.success){ + if(!callback.scope){ + callback.success(responseObject); + } + else{ + // If a scope property is defined, the callback will be fired from + // the context of the object. + callback.success.apply(callback.scope, [responseObject]); + } + } + + // Fire global custom event -- successEvent + this.successEvent.fire(responseObject); + + if(o.successEvent){ + // Fire transaction custom event -- successEvent + o.successEvent.fire(responseObject); + } + } + else{ + switch(httpStatus){ + // The following cases are wininet.dll error codes that may be encountered. + case 12002: // Server timeout + case 12029: // 12029 to 12031 correspond to dropped connections. + case 12030: + case 12031: + case 12152: // Connection closed by server. + case 13030: // See above comments for variable status. + // XDR transactions will not resolve to this case, since the + // response object is already built in the xdr response. + responseObject = this.createExceptionObject(o.tId, args, (isAbort?isAbort:false)); + if(callback && callback.failure){ + if(!callback.scope){ + callback.failure(responseObject); + } + else{ + callback.failure.apply(callback.scope, [responseObject]); + } + } + + break; + default: + responseObject = (o.xdr) ? o.response : this.createResponseObject(o, args); + if(callback && callback.failure){ + if(!callback.scope){ + callback.failure(responseObject); + } + else{ + callback.failure.apply(callback.scope, [responseObject]); + } + } + } + + // Fire global custom event -- failureEvent + this.failureEvent.fire(responseObject); + + if(o.failureEvent){ + // Fire transaction custom event -- failureEvent + o.failureEvent.fire(responseObject); + } + + } + + this.releaseObject(o); + responseObject = null; + }, + + /** + * @description This method evaluates the server response, creates and returns the results via + * its properties. Success and failure cases will differ in the response + * object's property values. + * @method createResponseObject + * @private + * @static + * @param {object} o The connection object + * @param {callbackArg} callbackArg The user-defined argument or arguments to be passed to the callback + * @return {object} + */ + createResponseObject:function(o, callbackArg) + { + var obj = {}, headerObj = {}, + i, headerStr, header, delimitPos; + + try + { + headerStr = o.conn.getAllResponseHeaders(); + header = headerStr.split('\n'); + for(i=0; i ' + + '' + + '' + + '', + c = document.createElement('div'); + + document.body.appendChild(c); + c.innerHTML = o; + } + + /** + * @description This method calls the public method on the + * Flash transport to start the XDR transaction. It is analogous + * to Connection Manager's asyncRequest method. + * @method xdr + * @private + * @static + * @param {object} The transaction object. + * @param {string} HTTP request method. + * @param {string} URI for the transaction. + * @param {object} The transaction's callback object. + * @param {object} The JSON object used as HTTP POST data. + * @return {void} + */ + function _xdr(o, m, u, c, d) { + _fn[parseInt(o.tId)] = { 'o':o, 'c':c }; + if (d) { + c.method = m; + c.data = d; + } + + o.conn.send(u, c, o.tId); + } + + /** + * @description This method instantiates the Flash transport and + * establishes a static reference to it, used for all XDR requests. + * @method transport + * @public + * @static + * @param {string} URI to connection.swf. + * @return {void} + */ + function _init(uri) { + _swf(uri); + YCM._transport = document.getElementById('YUIConnectionSwf'); + } + + function _xdrReady() { + YCM.xdrReadyEvent.fire(); + } + + /** + * @description This method fires the global and transaction start + * events. + * @method _xdrStart + * @private + * @static + * @param {object} The transaction object. + * @param {string} The transaction's callback object. + * @return {void} + */ + function _xdrStart(o, cb) { + if (o) { + // Fire global custom event -- startEvent + YCM.startEvent.fire(o, cb.argument); + + if(o.startEvent){ + // Fire transaction custom event -- startEvent + o.startEvent.fire(o, cb.argument); + } + } + } + + /** + * @description This method is the initial response handler + * for XDR transactions. The Flash transport calls this + * function and sends the response payload. + * @method handleXdrResponse + * @private + * @static + * @param {object} The response object sent from the Flash transport. + * @return {void} + */ + function _handleXdrResponse(r) { + var o = _fn[r.tId].o, + cb = _fn[r.tId].c; + + if (r.statusText === 'xdr:start') { + _xdrStart(o, cb); + return; + } + + r.responseText = decodeURI(r.responseText); + o.r = r; + if (cb.argument) { + o.r.argument = cb.argument; + } + + this.handleTransactionResponse(o, cb, r.statusText === 'xdr:abort' ? true : false); + delete _fn[r.tId]; + } + + // Bind the functions to Connection Manager as static fields. + YCM.xdr = _xdr; + YCM.swf = _swf; + YCM.transport = _init; + YCM.xdrReadyEvent = new YAHOO.util.CustomEvent('xdrReady'); + YCM.xdrReady = _xdrReady; + YCM.handleXdrResponse = _handleXdrResponse; +})(); + +/** + * @for YAHOO.util.Connect + */ +(function(){ + var YCM = YAHOO.util.Connect, + YE = YAHOO.util.Event, + dM = document.documentMode ? document.documentMode : false; + + /** + * @description Property modified by setForm() to determine if a file(s) + * upload is expected. + * @property _isFileUpload + * @private + * @static + * @type boolean + */ + YCM._isFileUpload = false; + + /** + * @description Property modified by setForm() to set a reference to the HTML + * form node if the desired action is file upload. + * @property _formNode + * @private + * @static + * @type object + */ + YCM._formNode = null; + + /** + * @description Property modified by setForm() to set the HTML form data + * for each transaction. + * @property _sFormData + * @private + * @static + * @type string + */ + YCM._sFormData = null; + + /** + * @description Tracks the name-value pair of the "clicked" submit button if multiple submit + * buttons are present in an HTML form; and, if YAHOO.util.Event is available. + * @property _submitElementValue + * @private + * @static + * @type string + */ + YCM._submitElementValue = null; + + /** + * @description Custom event that fires when handleTransactionResponse() determines a + * response in the HTTP 4xx/5xx range. + * @property failureEvent + * @private + * @static + * @type CustomEvent + */ + YCM.uploadEvent = new YAHOO.util.CustomEvent('upload'); + + /** + * @description Determines whether YAHOO.util.Event is available and returns true or false. + * If true, an event listener is bound at the document level to trap click events that + * resolve to a target type of "Submit". This listener will enable setForm() to determine + * the clicked "Submit" value in a multi-Submit button, HTML form. + * @property _hasSubmitListener + * @private + * @static + */ + YCM._hasSubmitListener = function() { + if(YE){ + YE.addListener( + document, + 'click', + function(e){ + var obj = YE.getTarget(e), + name = obj.nodeName.toLowerCase(); + + if((name === 'input' || name === 'button') && (obj.type && obj.type.toLowerCase() == 'submit')){ + YCM._submitElementValue = encodeURIComponent(obj.name) + "=" + encodeURIComponent(obj.value); + } + }); + return true; + } + return false; + }(); + + /** + * @description This method assembles the form label and value pairs and + * constructs an encoded string. + * asyncRequest() will automatically initialize the transaction with a + * a HTTP header Content-Type of application/x-www-form-urlencoded. + * @method setForm + * @public + * @static + * @param {string || object} form id or name attribute, or form object. + * @param {boolean} optional enable file upload. + * @param {boolean} optional enable file upload over SSL in IE only. + * @return {string} string of the HTML form field name and value pairs.. + */ + function _setForm(formId, isUpload, secureUri) + { + var oForm, oElement, oName, oValue, oDisabled, + hasSubmit = false, + data = [], item = 0, + i,len,j,jlen,opt; + + this.resetFormState(); + + if(typeof formId == 'string'){ + // Determine if the argument is a form id or a form name. + // Note form name usage is deprecated by supported + // here for legacy reasons. + oForm = (document.getElementById(formId) || document.forms[formId]); + } + else if(typeof formId == 'object'){ + // Treat argument as an HTML form object. + oForm = formId; + } + else{ + return; + } + + // If the isUpload argument is true, setForm will call createFrame to initialize + // an iframe as the form target. + // + // The argument secureURI is also required by IE in SSL environments + // where the secureURI string is a fully qualified HTTP path, used to set the source + // of the iframe, to a stub resource in the same domain. + if(isUpload){ + + // Create iframe in preparation for file upload. + this.createFrame(secureUri?secureUri:null); + + // Set form reference and file upload properties to true. + this._isFormSubmit = true; + this._isFileUpload = true; + this._formNode = oForm; + + return; + } + + // Iterate over the form elements collection to construct the + // label-value pairs. + for (i=0,len=oForm.elements.length; i -1) { + opt = oElement.options[oElement.selectedIndex]; + data[item++] = oName + encodeURIComponent( + (opt.attributes.value && opt.attributes.value.specified) ? opt.value : opt.text); + } + break; + case 'select-multiple': + if (oElement.selectedIndex > -1) { + for(j=oElement.selectedIndex, jlen=oElement.options.length; j '); + + // IE will throw a security exception in an SSL environment if the + // iframe source is undefined. + if(typeof secureUri == 'boolean'){ + io.src = 'javascript:false'; + } + } + else{ + io = document.createElement('iframe'); + io.id = frameId; + io.name = frameId; + } + + io.style.position = 'absolute'; + io.style.top = '-1000px'; + io.style.left = '-1000px'; + + document.body.appendChild(io); + } + + /** + * @description Parses the POST data and creates hidden form elements + * for each key-value, and appends them to the HTML form object. + * @method appendPostData + * @private + * @static + * @param {string} postData The HTTP POST data + * @return {array} formElements Collection of hidden fields. + */ + function _appendPostData(postData){ + var formElements = [], + postMessage = postData.split('&'), + i, delimitPos; + + for(i=0; i < postMessage.length; i++){ + delimitPos = postMessage[i].indexOf('='); + if(delimitPos != -1){ + formElements[i] = document.createElement('input'); + formElements[i].type = 'hidden'; + formElements[i].name = decodeURIComponent(postMessage[i].substring(0,delimitPos)); + formElements[i].value = decodeURIComponent(postMessage[i].substring(delimitPos+1)); + this._formNode.appendChild(formElements[i]); + } + } + + return formElements; + } + + /** + * @description Uploads HTML form, inclusive of files/attachments, using the + * iframe created in createFrame to facilitate the transaction. + * @method uploadFile + * @private + * @static + * @param {int} id The transaction id. + * @param {object} callback User-defined callback object. + * @param {string} uri Fully qualified path of resource. + * @param {string} postData POST data to be submitted in addition to HTML form. + * @return {void} + */ + function _uploadFile(o, callback, uri, postData){ + // Each iframe has an id prefix of "yuiIO" followed + // by the unique transaction id. + var frameId = 'yuiIO' + o.tId, + uploadEncoding = 'multipart/form-data', + io = document.getElementById(frameId), + ie8 = (dM >= 8) ? true : false, + oConn = this, + args = (callback && callback.argument)?callback.argument:null, + oElements,i,prop,obj, rawFormAttributes, uploadCallback; + + // Track original HTML form attribute values. + rawFormAttributes = { + action:this._formNode.getAttribute('action'), + method:this._formNode.getAttribute('method'), + target:this._formNode.getAttribute('target') + }; + + // Initialize the HTML form properties in case they are + // not defined in the HTML form. + this._formNode.setAttribute('action', uri); + this._formNode.setAttribute('method', 'POST'); + this._formNode.setAttribute('target', frameId); + + if(YAHOO.env.ua.ie && !ie8){ + // IE does not respect property enctype for HTML forms. + // Instead it uses the property - "encoding". + this._formNode.setAttribute('encoding', uploadEncoding); + } + else{ + this._formNode.setAttribute('enctype', uploadEncoding); + } + + if(postData){ + oElements = this.appendPostData(postData); + } + + // Start file upload. + this._formNode.submit(); + + // Fire global custom event -- startEvent + this.startEvent.fire(o, args); + + if(o.startEvent){ + // Fire transaction custom event -- startEvent + o.startEvent.fire(o, args); + } + + // Start polling if a callback is present and the timeout + // property has been defined. + if(callback && callback.timeout){ + this._timeOut[o.tId] = window.setTimeout(function(){ oConn.abort(o, callback, true); }, callback.timeout); + } + + // Remove HTML elements created by appendPostData + if(oElements && oElements.length > 0){ + for(i=0; i < oElements.length; i++){ + this._formNode.removeChild(oElements[i]); + } + } + + // Restore HTML form attributes to their original + // values prior to file upload. + for(prop in rawFormAttributes){ + if(YAHOO.lang.hasOwnProperty(rawFormAttributes, prop)){ + if(rawFormAttributes[prop]){ + this._formNode.setAttribute(prop, rawFormAttributes[prop]); + } + else{ + this._formNode.removeAttribute(prop); + } + } + } + + // Reset HTML form state properties. + this.resetFormState(); + + // Create the upload callback handler that fires when the iframe + // receives the load event. Subsequently, the event handler is detached + // and the iframe removed from the document. + uploadCallback = function() { + var body, pre, text; + + if(callback && callback.timeout){ + window.clearTimeout(oConn._timeOut[o.tId]); + delete oConn._timeOut[o.tId]; + } + + // Fire global custom event -- completeEvent + oConn.completeEvent.fire(o, args); + + if(o.completeEvent){ + // Fire transaction custom event -- completeEvent + o.completeEvent.fire(o, args); + } + + obj = { + tId : o.tId, + argument : args + }; + + try + { + body = io.contentWindow.document.getElementsByTagName('body')[0]; + pre = io.contentWindow.document.getElementsByTagName('pre')[0]; + + if (body) { + if (pre) { + text = pre.textContent?pre.textContent:pre.innerText; + } + else { + text = body.textContent?body.textContent:body.innerText; + } + } + obj.responseText = text; + // responseText and responseXML will be populated with the same data from the iframe. + // Since the HTTP headers cannot be read from the iframe + obj.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document; + } + catch(e){} + + if(callback && callback.upload){ + if(!callback.scope){ + callback.upload(obj); + } + else{ + callback.upload.apply(callback.scope, [obj]); + } + } + + // Fire global custom event -- uploadEvent + oConn.uploadEvent.fire(obj); + + if(o.uploadEvent){ + // Fire transaction custom event -- uploadEvent + o.uploadEvent.fire(obj); + } + + YE.removeListener(io, "load", uploadCallback); + + setTimeout( + function(){ + document.body.removeChild(io); + oConn.releaseObject(o); + }, 100); + }; + + // Bind the onload handler to the iframe to detect the file upload response. + YE.addListener(io, "load", uploadCallback); + } + + YCM.setForm = _setForm; + YCM.resetFormState = _resetFormState; + YCM.createFrame = _createFrame; + YCM.appendPostData = _appendPostData; + YCM.uploadFile = _uploadFile; +})(); + +YAHOO.register("connection", YAHOO.util.Connect, {version: "2.9.0", build: "2800"}); diff --git a/ajax/libs/yui/2.9.0/connection/connection.swf b/ajax/libs/yui/2.9.0/connection/connection.swf new file mode 100644 index 000000000..c33a7fe27 Binary files /dev/null and b/ajax/libs/yui/2.9.0/connection/connection.swf differ diff --git a/ajax/libs/yui/2.9.0/connection/connection_core-debug.js b/ajax/libs/yui/2.9.0/connection/connection_core-debug.js new file mode 100644 index 000000000..880b2c21d --- /dev/null +++ b/ajax/libs/yui/2.9.0/connection/connection_core-debug.js @@ -0,0 +1,994 @@ +/* +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 Connection Manager provides a simplified interface to the XMLHttpRequest + * object. It handles cross-browser instantiantion of XMLHttpRequest, negotiates the + * interactive states and server response, returning the results to a pre-defined + * callback you create. + * + * @namespace YAHOO.util + * @module connection + * @requires yahoo + * @requires event + */ + +/** + * The Connection Manager singleton provides methods for creating and managing + * asynchronous transactions. + * + * @class YAHOO.util.Connect + */ + +YAHOO.util.Connect = +{ + /** + * @description Array of MSFT ActiveX ids for XMLHttpRequest. + * @property _msxml_progid + * @private + * @static + * @type array + */ + _msxml_progid:[ + 'Microsoft.XMLHTTP', + 'MSXML2.XMLHTTP.3.0', + 'MSXML2.XMLHTTP' + ], + + /** + * @description Object literal of HTTP header(s) + * @property _http_header + * @private + * @static + * @type object + */ + _http_headers:{}, + + /** + * @description Determines if HTTP headers are set. + * @property _has_http_headers + * @private + * @static + * @type boolean + */ + _has_http_headers:false, + + /** + * @description Determines if a default header of + * Content-Type of 'application/x-www-form-urlencoded' + * will be added to any client HTTP headers sent for POST + * transactions. + * @property _use_default_post_header + * @private + * @static + * @type boolean + */ + _use_default_post_header:true, + + /** + * @description The default header used for POST transactions. + * @property _default_post_header + * @private + * @static + * @type boolean + */ + _default_post_header:'application/x-www-form-urlencoded; charset=UTF-8', + + /** + * @description The default header used for transactions involving the + * use of HTML forms. + * @property _default_form_header + * @private + * @static + * @type boolean + */ + _default_form_header:'application/x-www-form-urlencoded', + + /** + * @description Determines if a default header of + * 'X-Requested-With: XMLHttpRequest' + * will be added to each transaction. + * @property _use_default_xhr_header + * @private + * @static + * @type boolean + */ + _use_default_xhr_header:true, + + /** + * @description The default header value for the label + * "X-Requested-With". This is sent with each + * transaction, by default, to identify the + * request as being made by YUI Connection Manager. + * @property _default_xhr_header + * @private + * @static + * @type boolean + */ + _default_xhr_header:'XMLHttpRequest', + + /** + * @description Determines if custom, default headers + * are set for each transaction. + * @property _has_default_header + * @private + * @static + * @type boolean + */ + _has_default_headers:true, + + /** + * @description Property modified by setForm() to determine if the data + * should be submitted as an HTML form. + * @property _isFormSubmit + * @private + * @static + * @type boolean + */ + _isFormSubmit:false, + + /** + * @description Determines if custom, default headers + * are set for each transaction. + * @property _has_default_header + * @private + * @static + * @type boolean + */ + _default_headers:{}, + + /** + * @description Collection of polling references to the polling mechanism in handleReadyState. + * @property _poll + * @private + * @static + * @type object + */ + _poll:{}, + + /** + * @description Queue of timeout values for each transaction callback with a defined timeout value. + * @property _timeOut + * @private + * @static + * @type object + */ + _timeOut:{}, + + /** + * @description The polling frequency, in milliseconds, for HandleReadyState. + * when attempting to determine a transaction's XHR readyState. + * The default is 50 milliseconds. + * @property _polling_interval + * @private + * @static + * @type int + */ + _polling_interval:50, + + /** + * @description A transaction counter that increments the transaction id for each transaction. + * @property _transaction_id + * @private + * @static + * @type int + */ + _transaction_id:0, + + /** + * @description Custom event that fires at the start of a transaction + * @property startEvent + * @private + * @static + * @type CustomEvent + */ + startEvent: new YAHOO.util.CustomEvent('start'), + + /** + * @description Custom event that fires when a transaction response has completed. + * @property completeEvent + * @private + * @static + * @type CustomEvent + */ + completeEvent: new YAHOO.util.CustomEvent('complete'), + + /** + * @description Custom event that fires when handleTransactionResponse() determines a + * response in the HTTP 2xx range. + * @property successEvent + * @private + * @static + * @type CustomEvent + */ + successEvent: new YAHOO.util.CustomEvent('success'), + + /** + * @description Custom event that fires when handleTransactionResponse() determines a + * response in the HTTP 4xx/5xx range. + * @property failureEvent + * @private + * @static + * @type CustomEvent + */ + failureEvent: new YAHOO.util.CustomEvent('failure'), + + /** + * @description Custom event that fires when a transaction is successfully aborted. + * @property abortEvent + * @private + * @static + * @type CustomEvent + */ + abortEvent: new YAHOO.util.CustomEvent('abort'), + + /** + * @description A reference table that maps callback custom events members to its specific + * event name. + * @property _customEvents + * @private + * @static + * @type object + */ + _customEvents: + { + onStart:['startEvent', 'start'], + onComplete:['completeEvent', 'complete'], + onSuccess:['successEvent', 'success'], + onFailure:['failureEvent', 'failure'], + onUpload:['uploadEvent', 'upload'], + onAbort:['abortEvent', 'abort'] + }, + + /** + * @description Member to add an ActiveX id to the existing xml_progid array. + * In the event(unlikely) a new ActiveX id is introduced, it can be added + * without internal code modifications. + * @method setProgId + * @public + * @static + * @param {string} id The ActiveX id to be added to initialize the XHR object. + * @return void + */ + setProgId:function(id) + { + this._msxml_progid.unshift(id); + YAHOO.log('ActiveX Program Id ' + id + ' added to _msxml_progid.', 'info', 'Connection'); + }, + + /** + * @description Member to override the default POST header. + * @method setDefaultPostHeader + * @public + * @static + * @param {boolean} b Set and use default header - true or false . + * @return void + */ + setDefaultPostHeader:function(b) + { + if(typeof b == 'string'){ + this._default_post_header = b; + this._use_default_post_header = true; + + YAHOO.log('Default POST header set to ' + b, 'info', 'Connection'); + } + else if(typeof b == 'boolean'){ + this._use_default_post_header = b; + } + }, + + /** + * @description Member to override the default transaction header.. + * @method setDefaultXhrHeader + * @public + * @static + * @param {boolean} b Set and use default header - true or false . + * @return void + */ + setDefaultXhrHeader:function(b) + { + if(typeof b == 'string'){ + this._default_xhr_header = b; + YAHOO.log('Default XHR header set to ' + b, 'info', 'Connection'); + } + else{ + this._use_default_xhr_header = b; + } + }, + + /** + * @description Member to modify the default polling interval. + * @method setPollingInterval + * @public + * @static + * @param {int} i The polling interval in milliseconds. + * @return void + */ + setPollingInterval:function(i) + { + if(typeof i == 'number' && isFinite(i)){ + this._polling_interval = i; + YAHOO.log('Default polling interval set to ' + i +'ms', 'info', 'Connection'); + } + }, + + /** + * @description Instantiates a XMLHttpRequest object and returns an object with two properties: + * the XMLHttpRequest instance and the transaction id. + * @method createXhrObject + * @private + * @static + * @param {int} transactionId Property containing the transaction id for this transaction. + * @return object + */ + createXhrObject:function(transactionId) + { + var obj,http,i; + try + { + // Instantiates XMLHttpRequest in non-IE browsers and assigns to http. + http = new XMLHttpRequest(); + // Object literal with http and tId properties + obj = { conn:http, tId:transactionId, xhr: true }; + YAHOO.log('XHR object created for transaction ' + transactionId, 'info', 'Connection'); + } + catch(e) + { + for(i=0; i = 200 && httpStatus < 300) || httpStatus === 1223 || xdrS){ + responseObject = o.xdr ? o.r : this.createResponseObject(o, args); + if(callback && callback.success){ + if(!callback.scope){ + callback.success(responseObject); + YAHOO.log('Success callback. HTTP code is ' + httpStatus, 'info', 'Connection'); + } + else{ + // If a scope property is defined, the callback will be fired from + // the context of the object. + callback.success.apply(callback.scope, [responseObject]); + YAHOO.log('Success callback with scope. HTTP code is ' + httpStatus, 'info', 'Connection'); + } + } + + // Fire global custom event -- successEvent + this.successEvent.fire(responseObject); + + if(o.successEvent){ + // Fire transaction custom event -- successEvent + o.successEvent.fire(responseObject); + } + } + else{ + switch(httpStatus){ + // The following cases are wininet.dll error codes that may be encountered. + case 12002: // Server timeout + case 12029: // 12029 to 12031 correspond to dropped connections. + case 12030: + case 12031: + case 12152: // Connection closed by server. + case 13030: // See above comments for variable status. + // XDR transactions will not resolve to this case, since the + // response object is already built in the xdr response. + responseObject = this.createExceptionObject(o.tId, args, (isAbort?isAbort:false)); + if(callback && callback.failure){ + if(!callback.scope){ + callback.failure(responseObject); + YAHOO.log('Failure callback. Exception detected. Status code is ' + httpStatus, 'warn', 'Connection'); + } + else{ + callback.failure.apply(callback.scope, [responseObject]); + YAHOO.log('Failure callback with scope. Exception detected. Status code is ' + httpStatus, 'warn', 'Connection'); + } + } + + break; + default: + responseObject = (o.xdr) ? o.response : this.createResponseObject(o, args); + if(callback && callback.failure){ + if(!callback.scope){ + callback.failure(responseObject); + YAHOO.log('Failure callback. HTTP status code is ' + httpStatus, 'warn', 'Connection'); + } + else{ + callback.failure.apply(callback.scope, [responseObject]); + YAHOO.log('Failure callback with scope. HTTP status code is ' + httpStatus, 'warn', 'Connection'); + } + } + } + + // Fire global custom event -- failureEvent + this.failureEvent.fire(responseObject); + + if(o.failureEvent){ + // Fire transaction custom event -- failureEvent + o.failureEvent.fire(responseObject); + } + + } + + this.releaseObject(o); + responseObject = null; + }, + + /** + * @description This method evaluates the server response, creates and returns the results via + * its properties. Success and failure cases will differ in the response + * object's property values. + * @method createResponseObject + * @private + * @static + * @param {object} o The connection object + * @param {callbackArg} callbackArg The user-defined argument or arguments to be passed to the callback + * @return {object} + */ + createResponseObject:function(o, callbackArg) + { + var obj = {}, headerObj = {}, + i, headerStr, header, delimitPos; + + try + { + headerStr = o.conn.getAllResponseHeaders(); + header = headerStr.split('\n'); + for(i=0; i =200&&E<300)||E===1223||C){A=B.xdr?B.r:this.createResponseObject(B,G);if(I&&I.success){if(!I.scope){I.success(A);}else{I.success.apply(I.scope,[A]);}}this.successEvent.fire(A);if(B.successEvent){B.successEvent.fire(A);}}else{switch(E){case 12002:case 12029:case 12030:case 12031:case 12152:case 13030:A=this.createExceptionObject(B.tId,G,(D?D:false));if(I&&I.failure){if(!I.scope){I.failure(A);}else{I.failure.apply(I.scope,[A]);}}break;default:A=(B.xdr)?B.response:this.createResponseObject(B,G);if(I&&I.failure){if(!I.scope){I.failure(A);}else{I.failure.apply(I.scope,[A]);}}}this.failureEvent.fire(A);if(B.failureEvent){B.failureEvent.fire(A);}}this.releaseObject(B);A=null;},createResponseObject:function(A,G){var D={},I={},E,C,F,B;try{C=A.conn.getAllResponseHeaders();F=C.split("\n");for(E=0;E = 200 && httpStatus < 300) || httpStatus === 1223 || xdrS){ + responseObject = o.xdr ? o.r : this.createResponseObject(o, args); + if(callback && callback.success){ + if(!callback.scope){ + callback.success(responseObject); + } + else{ + // If a scope property is defined, the callback will be fired from + // the context of the object. + callback.success.apply(callback.scope, [responseObject]); + } + } + + // Fire global custom event -- successEvent + this.successEvent.fire(responseObject); + + if(o.successEvent){ + // Fire transaction custom event -- successEvent + o.successEvent.fire(responseObject); + } + } + else{ + switch(httpStatus){ + // The following cases are wininet.dll error codes that may be encountered. + case 12002: // Server timeout + case 12029: // 12029 to 12031 correspond to dropped connections. + case 12030: + case 12031: + case 12152: // Connection closed by server. + case 13030: // See above comments for variable status. + // XDR transactions will not resolve to this case, since the + // response object is already built in the xdr response. + responseObject = this.createExceptionObject(o.tId, args, (isAbort?isAbort:false)); + if(callback && callback.failure){ + if(!callback.scope){ + callback.failure(responseObject); + } + else{ + callback.failure.apply(callback.scope, [responseObject]); + } + } + + break; + default: + responseObject = (o.xdr) ? o.response : this.createResponseObject(o, args); + if(callback && callback.failure){ + if(!callback.scope){ + callback.failure(responseObject); + } + else{ + callback.failure.apply(callback.scope, [responseObject]); + } + } + } + + // Fire global custom event -- failureEvent + this.failureEvent.fire(responseObject); + + if(o.failureEvent){ + // Fire transaction custom event -- failureEvent + o.failureEvent.fire(responseObject); + } + + } + + this.releaseObject(o); + responseObject = null; + }, + + /** + * @description This method evaluates the server response, creates and returns the results via + * its properties. Success and failure cases will differ in the response + * object's property values. + * @method createResponseObject + * @private + * @static + * @param {object} o The connection object + * @param {callbackArg} callbackArg The user-defined argument or arguments to be passed to the callback + * @return {object} + */ + createResponseObject:function(o, callbackArg) + { + var obj = {}, headerObj = {}, + i, headerStr, header, delimitPos; + + try + { + headerStr = o.conn.getAllResponseHeaders(); + header = headerStr.split('\n'); + for(i=0; i elements bleeding through + the modality mask in IE 6. + + 2) ".drag select" is used to hide