/*! Copyright (c) 2008, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt version: 2.5.2 */ /** * The YAHOO object is the single global object used by YUI Library. It * contains utility function for setting up namespaces, inheritance, and * logging. YAHOO.util, YAHOO.widget, and YAHOO.example are namespaces * created automatically for and used by the library. * @module yahoo * @title YAHOO Global */ /** * YAHOO_config is not included as part of the library. Instead it is an * object that can be defined by the implementer immediately before * including the YUI library. The properties included in this object * will be used to configure global properties needed as soon as the * library begins to load. * @class YAHOO_config * @static */ /** * A reference to a function that will be executed every time a YAHOO module * is loaded. As parameter, this function will receive the version * information for the module. See * YAHOO.env.getVersion for the description of the version data structure. * @property listener * @type Function * @static * @default undefined */ /** * Set to true if the library will be dynamically loaded after window.onload. * Defaults to false * @property injecting * @type boolean * @static * @default undefined */ /** * Instructs the yuiloader component to dynamically load yui components and * their dependencies. See the yuiloader documentation for more information * about dynamic loading * @property load * @static * @default undefined * @see yuiloader */ /** * Forces the use of the supplied locale where applicable in the library * @property locale * @type string * @static * @default undefined */ if (typeof YAHOO == "undefined" || !YAHOO) { /** * The YAHOO global namespace object. If YAHOO is already defined, the * existing YAHOO object will not be overwritten so that defined * namespaces are preserved. * @class YAHOO * @static */ var YAHOO = {}; } /** * Returns the namespace specified and creates it if it doesn't exist *
* YAHOO.namespace("property.package");
* YAHOO.namespace("YAHOO.property.package");
*
* Either of the above would create YAHOO.property, then
* YAHOO.property.package
*
* Be careful when naming packages. Reserved words may work in some browsers
* and not others. For instance, the following will fail in Safari:
*
* YAHOO.namespace("really.long.nested.namespace");
*
* This fails because "long" is a future reserved word in ECMAScript
*
* @method namespace
* @static
* @param {String*} arguments 1-n namespaces to create
* @return {Object} A reference to the last namespace object created
*/
YAHOO.namespace = function() {
var a=arguments, o=null, i, j, d;
for (i=0; i
* Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7
* Firefox 1.5.0.9: 1.8.0.9 <-- Reports 1.8
* Firefox 2.0.0.3: 1.8.1.3 <-- Reports 1.8
* Firefox 3 alpha: 1.9a4 <-- Reports 1.9
*
* @property gecko
* @type float
*/
gecko:0,
/**
* AppleWebKit version. KHTML browsers that are not WebKit browsers
* will evaluate to 1, other browsers 0. Example: 418.9.1
*
* Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
* latest available for Mac OSX 10.3.
* Safari 2.0.2: 416 <-- hasOwnProperty introduced
* Safari 2.0.4: 418 <-- preventDefault fixed
* Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
* different versions of webkit
* Safari 2.0.4 (419.3): 419 <-- Tiger installations that have been
* updated, but not updated
* to the latest patch.
* Webkit 212 nightly: 522+ <-- Safari 3.0 precursor (with native SVG
* and many major issues fixed).
* 3.x yahoo.com, flickr:422 <-- Safari 3.x hacks the user agent
* string when hitting yahoo.com and
* flickr.com.
* Safari 3.0.4 (523.12):523.12 <-- First Tiger release - automatic update
* from 2.x via the 10.4.11 OS patch
* Webkit nightly 1/2008:525+ <-- Supports DOMContentLoaded event.
* yahoo.com user agent hack removed.
*
*
* http://developer.apple.com/internet/safari/uamatrix.html
* @property webkit
* @type float
*/
webkit: 0,
/**
* The mobile property will be set to a string containing any relevant
* user agent information when a modern mobile browser is detected.
* Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
* devices with the WebKit-based browser, and Opera Mini.
* @property mobile
* @type string
*/
mobile: null,
/**
* Adobe AIR version number or 0. Only populated if webkit is detected.
* Example: 1.0
* @property air
* @type float
*/
air: 0
};
var ua=navigator.userAgent, m;
// Modern KHTML browsers should qualify as Safari X-Grade
if ((/KHTML/).test(ua)) {
o.webkit=1;
}
// Modern WebKit browsers are at least X-Grade
m=ua.match(/AppleWebKit\/([^\s]*)/);
if (m&&m[1]) {
o.webkit=parseFloat(m[1]);
// Mobile browser check
if (/ Mobile\//.test(ua)) {
o.mobile = "Apple"; // iPhone or iPod Touch
} else {
m=ua.match(/NokiaN[^\/]*/);
if (m) {
o.mobile = m[0]; // Nokia N-series, ex: NokiaN95
}
}
m=ua.match(/AdobeAIR\/([^\s]*)/);
if (m) {
o.air = m[0]; // Adobe AIR 1.0 or better
}
}
if (!o.webkit) { // not webkit
// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
m=ua.match(/Opera[\s\/]([^\s]*)/);
if (m&&m[1]) {
o.opera=parseFloat(m[1]);
m=ua.match(/Opera Mini[^;]*/);
if (m) {
o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
}
} else { // not opera or webkit
m=ua.match(/MSIE\s([^;]*)/);
if (m&&m[1]) {
o.ie=parseFloat(m[1]);
} else { // not opera, webkit, or ie
m=ua.match(/Gecko\/([^\s]*)/);
if (m) {
o.gecko=1; // Gecko detected, look for revision
m=ua.match(/rv:([^\s\)]*)/);
if (m&&m[1]) {
o.gecko=parseFloat(m[1]);
}
}
}
}
}
return o;
}();
/*
* Initializes the global by creating the default namespaces and applying
* any new configuration information that is detected. This is the setup
* for env.
* @method init
* @static
* @private
*/
(function() {
YAHOO.namespace("util", "widget", "example");
if ("undefined" !== typeof YAHOO_config) {
var l=YAHOO_config.listener,ls=YAHOO.env.listeners,unique=true,i;
if (l) {
// if YAHOO is loaded multiple times we need to check to see if
// this is a new config object. If it is, add the new component
// load listener to the stack
for (i=0;iThe callback is executed with a single parameter: * the custom object parameter, if provided.
* * @method onAvailable * * @param {string||string[]} p_id the id of the element, or an array * of ids to look for. * @param {function} p_fn what to execute when the element is found. * @param {object} p_obj an optional object to be passed back as * a parameter to p_fn. * @param {boolean|object} p_override If set to true, p_fn will execute * in the scope of p_obj, if set to an object it * will execute in the scope of that object * @param checkContent {boolean} check child node readiness (onContentReady) * @static */ onAvailable: function(p_id, p_fn, p_obj, p_override, checkContent) { var a = (YAHOO.lang.isString(p_id)) ? [p_id] : p_id; for (var i=0; iThe callback is a CustomEvent, so the signature is:
*type <string>, args <array>, customobject <object>
*For DOMReady events, there are no fire argments, so the * signature is:
*"DOMReady", [], obj
* * * @method onDOMReady * * @param {function} p_fn what to execute when the element is found. * @param {object} p_obj an optional object to be passed back as * a parameter to p_fn. * @param {boolean|object} p_scope If set to true, p_fn will execute * in the scope of p_obj, if set to an object it * will execute in the scope of that object * * @static */ onDOMReady: function(p_fn, p_obj, p_override) { if (this.DOMReady) { setTimeout(function() { var s = window; if (p_override) { if (p_override === true) { s = p_obj; } else { s = p_override; } } p_fn.call(s, "DOMReady", [], p_obj); }, 0); } else { this.DOMReadyEvent.subscribe(p_fn, p_obj, p_override); } }, /** * Appends an event handler * * @method addListener * * @param {String|HTMLElement|Array|NodeList} el An id, an element * reference, or a collection of ids and/or elements to assign the * listener to. * @param {String} sType The type of event to append * @param {Function} fn The method the event invokes * @param {Object} obj An arbitrary object that will be * passed as a parameter to the handler * @param {Boolean|object} override If true, the obj passed in becomes * the execution scope of the listener. If an * object, this object becomes the execution * scope. * @return {Boolean} True if the action was successful or defered, * false if one or more of the elements * could not have the listener attached, * or if the operation throws an exception. * @static */ addListener: function(el, sType, fn, obj, override) { if (!fn || !fn.call) { return false; } // The el argument can be an array of elements or element ids. if ( this._isValidCollection(el)) { var ok = true; for (var i=0,len=el.length; i
* // assumes yahoo, dom, and event are already on the page
* YAHOO.util.Get.script(
* ["http://yui.yahooapis.com/2.3.1/build/dragdrop/dragdrop-min.js",
* "http://yui.yahooapis.com/2.3.1/build/animation/animation-min.js"], {
* onSuccess: function(o) {
* new YAHOO.util.DDProxy("dd1"); // also new o.reference("dd1"); would work
* this.log("won't cause error because YAHOO is the scope");
* this.log(o.nodes.length === 2) // true
* // o.purge(); // optionally remove the script nodes immediately
* },
* onFailure: function(o) {
* },
* data: "foo",
* scope: YAHOO,
* // win: otherframe // target another window/frame
* autopurge: true // allow the utility to choose when to remove the nodes
* });
*
* @return {tId: string} an object containing info about the transaction
*/
script: function(url, opts) { return _queue("script", url, opts); },
/**
* Fetches and inserts one or more css link nodes into the
* head of the current document or the document in a specified
* window.
* @method css
* @static
* @param url {string} the url or urls to the css file(s)
* @param opts Options:
*
* YAHOO.util.Get.css("http://yui.yahooapis.com/2.3.1/build/menu/assets/skins/sam/menu.css");
*
*
* YAHOO.util.Get.css(["http://yui.yahooapis.com/2.3.1/build/menu/assets/skins/sam/menu.css",
*
* @return {tId: string} an object containing info about the transaction
*/
css: function(url, opts) {
return _queue("css", url, opts);
}
};
}();
YAHOO.register("get", YAHOO.util.Get, {version: "2.5.2", build: "1076"});
/*
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.5.2
*/
YAHOO.namespace('lang');
/**
* Provides methods to parse JSON strings and convert objects to JSON strings.
* @module json
* @requires yahoo
* @class YAHOO.lang.JSON
* @static
*/
YAHOO.lang.JSON = {
/**
* First step in the validation. Regex used to replace all escape
* sequences (i.e. "\\", etc) with '@' characters (a non-JSON character).
* @property _ESCAPES
* @type {RegExp}
* @static
* @private
*/
_ESCAPES : /\\["\\\/bfnrtu]/g,
/**
* Second step in the validation. Regex used to replace all simple
* values with ']' characters.
* @property _VALUES
* @type {RegExp}
* @static
* @private
*/
_VALUES : /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
/**
* Third step in the validation. Regex used to remove all open square
* brackets following a colon, comma, or at the beginning of the string.
* @property _BRACKETS
* @type {RegExp}
* @static
* @private
*/
_BRACKETS : /(?:^|:|,)(?:\s*\[)+/g,
/**
* Final step in the validation. Regex used to test the string left after
* all previous replacements for invalid characters.
* @property _INVALID
* @type {RegExp}
* @static
* @private
*/
_INVALID : /^[\],:{}\s]*$/,
/**
* Regex used to replace special characters in strings for JSON
* stringification.
* @property _SPECIAL_CHARS
* @type {RegExp}
* @static
* @private
*/
_SPECIAL_CHARS : /["\\\x00-\x1f\x7f-\x9f]/g,
/**
* Regex used to reconstitute serialized Dates.
* @property _PARSE_DATE
* @type {RegExp}
* @static
* @private
*/
_PARSE_DATE : /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/,
/**
* Character substitution map for common escapes and special characters.
* @property _CHARS
* @type {Object}
* @static
* @private
*/
_CHARS : {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
/**
* Traverses nested objects, applying a filter or mutation function to
* each value. The value returned from the function will replace the
* original value in the key:value pair. If the value returned is
* undefined, the key will be omitted from the returned object.
* @method _applyFilter
* @param data {MIXED} Any JavaScript data
* @param filter {Function} filter or mutation function
* @return {MIXED} The results of the filtered data
* @static
* @private
*/
_applyFilter : function (data, filter) {
var walk = function (k,v) {
var i, n;
if (v && typeof v === 'object') {
for (i in v) {
if (YAHOO.lang.hasOwnProperty(v,i)) {
n = walk(i, v[i]);
if (n === undefined) {
delete v[i];
} else {
v[i] = n;
}
}
}
}
return filter(k, v);
};
if (YAHOO.lang.isFunction(filter)) {
walk('',data);
}
return data;
},
/**
* Four step determination whether a string is valid JSON. In three steps,
* escape sequences, safe values, and properly placed open square brackets
* are replaced with placeholders or removed. Then in the final step, the
* result of all these replacements is checked for invalid characters.
* @method isValid
* @param str {String} JSON string to be tested
* @return {boolean} is the string safe for eval?
* @static
*/
isValid : function (str) {
if (!YAHOO.lang.isString(str)) {
return false;
}
return this._INVALID.test(str.
replace(this._ESCAPES,'@').
replace(this._VALUES,']').
replace(this._BRACKETS,''));
},
/**
* Serializes a Date instance as a UTC date string. Used internally by
* stringify. Override this method if you need Dates serialized in a
* different format.
* @method dateToString
* @param d {Date} The Date to serialize
* @return {String} stringified Date in UTC format YYYY-MM-DDTHH:mm:SSZ
* @static
*/
dateToString : function (d) {
function _zeroPad(v) {
return v < 10 ? '0' + v : v;
}
return '"' + d.getUTCFullYear() + '-' +
_zeroPad(d.getUTCMonth() + 1) + '-' +
_zeroPad(d.getUTCDate()) + 'T' +
_zeroPad(d.getUTCHours()) + ':' +
_zeroPad(d.getUTCMinutes()) + ':' +
_zeroPad(d.getUTCSeconds()) + 'Z"';
},
/**
* Reconstitute Date instances from the default JSON UTC serialization.
* Reference this from a parse filter function to rebuild Dates during the
* parse operation.
* @method stringToDate
* @param str {String} String serialization of a Date
* @return {Date}
*/
stringToDate : function (str) {
if (this._PARSE_DATE.test(str)) {
var d = new Date();
d.setUTCFullYear(RegExp.$1, (RegExp.$2|0)-1, RegExp.$3);
d.setUTCHours(RegExp.$4, RegExp.$5, RegExp.$6);
return d;
}
},
/**
* Parse a JSON string, returning the native JavaScript representation.
* Only minor modifications from http://www.json.org/json.js.
* @param s {string} JSON string data
* @param filter {function} (optional) function(k,v) passed each key value pair of object literals, allowing pruning or altering values
* @return {MIXED} the native JavaScript representation of the JSON string
* @throws SyntaxError
* @method parse
* @static
* @public
*/
parse : function (s,filter) {
// Ensure valid JSON
if (this.isValid(s)) {
// Eval the text into a JavaScript data structure, apply any
// filter function, and return
return this._applyFilter( eval('(' + s + ')'), filter );
}
// The text is not JSON parsable
throw new SyntaxError('parseJSON');
},
/**
* Converts an arbitrary value to a JSON string representation.
* Cyclical object or array references are replaced with null.
* If a whitelist is provided, only matching object keys will be included.
* If a depth limit is provided, objects and arrays at that depth will
* be stringified as empty.
* @method stringify
* @param o {MIXED} any arbitrary object to convert to JSON string
* @param w {Array} (optional) whitelist of acceptable object keys to include
* @param d {number} (optional) depth limit to recurse objects/arrays (practical minimum 1)
* @return {string} JSON string representation of the input
* @static
* @public
*/
stringify : function (o,w,d) {
var l = YAHOO.lang,
J = l.JSON,
m = J._CHARS,
str_re = this._SPECIAL_CHARS,
pstack = []; // Processing stack used for cyclical ref protection
// escape encode special characters
var _char = function (c) {
if (!m[c]) {
var a = c.charCodeAt();
m[c] = '\\u00' + Math.floor(a / 16).toString(16) +
(a % 16).toString(16);
}
return m[c];
};
// Enclose the escaped string in double quotes
var _string = function (s) {
return '"' + s.replace(str_re, _char) + '"';
};
// Use the configured date conversion
var _date = J.dateToString;
// Worker function. Fork behavior on data type and recurse objects and
// arrays per the configured depth.
var _stringify = function (o,w,d) {
var t = typeof o,
i,len,j, // array iteration
k,v, // object iteration
vt, // typeof v during iteration
a; // composition array for performance over string concat
// String
if (t === 'string') {
return _string(o);
}
// native boolean and Boolean instance
if (t === 'boolean' || o instanceof Boolean) {
return String(o);
}
// native number and Number instance
if (t === 'number' || o instanceof Number) {
return isFinite(o) ? String(o) : 'null';
}
// Date
if (o instanceof Date) {
return _date(o);
}
// Array
if (l.isArray(o)) {
// Check for cyclical references
for (i = pstack.length - 1; i >= 0; --i) {
if (pstack[i] === o) {
return 'null';
}
}
// Add the array to the processing stack
pstack[pstack.length] = o;
a = [];
// Only recurse if we're above depth config
if (d > 0) {
for (i = o.length - 1; i >= 0; --i) {
a[i] = _stringify(o[i],w,d-1) || 'null';
}
}
// remove the array from the stack
pstack.pop();
return '[' + a.join(',') + ']';
}
// Object
if (t === 'object') {
// Test for null reporting as typeof 'object'
if (!o) {
return 'null';
}
// Check for cyclical references
for (i = pstack.length - 1; i >= 0; --i) {
if (pstack[i] === o) {
return 'null';
}
}
// Add the object to the processing stack
pstack[pstack.length] = o;
a = [];
// Only recurse if we're above depth config
if (d > 0) {
// If whitelist provided, take only those keys
if (w) {
for (i = 0, j = 0, len = w.length; i < len; ++i) {
if (typeof w[i] === 'string') {
v = _stringify(o[w[i]],w,d-1);
if (v) {
a[j++] = _string(w[i]) + ':' + v;
}
}
}
// Otherwise, take all valid object properties
// omitting the prototype chain properties
} else {
j = 0;
for (k in o) {
if (typeof k === 'string' && l.hasOwnProperty(o,k)) {
v = _stringify(o[k],w,d-1);
if (v) {
a[j++] = _string(k) + ':' + v;
}
}
}
}
}
// Remove the object from processing stack
pstack.pop();
return '{' + a.join(',') + '}';
}
return undefined; // invalid input
};
// Default depth to POSITIVE_INFINITY
d = d >= 0 ? d : 1/0;
// process the input
return _stringify(o,w,d);
}
};
YAHOO.register("json", YAHOO.lang.JSON, {version: "2.5.2", build: "1076"});
/*
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.5.2
*/
/**
* 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 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 Determines if custom, default headers
* are set for each transaction.
* @property _has_default_header
* @private
* @static
* @type boolean
*/
_default_headers:{},
/**
* @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 Property modified by setForm() to determine if a file(s)
* upload is expected.
* @property _isFileUpload
* @private
* @static
* @type boolean
*/
_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
*/
_formNode:null,
/**
* @description Property modified by setForm() to set the HTML form data
* for each transaction.
* @property _sFormData
* @private
* @static
* @type string
*/
_sFormData:null,
/**
* @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 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
*/
_submitElementValue:null,
/**
* @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
*/
_hasSubmitListener:(function()
{
if(YAHOO.util.Event){
YAHOO.util.Event.addListener(
document,
'click',
function(e){
var obj = YAHOO.util.Event.getTarget(e);
if(obj.nodeName.toLowerCase() == 'input' && (obj.type && obj.type.toLowerCase() == 'submit')){
YAHOO.util.Connect._submitElementValue = encodeURIComponent(obj.name) + "=" + encodeURIComponent(obj.value);
}
});
return true;
}
return false;
})(),
/**
* @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 handleTransactionResponse() determines a
* response in the HTTP 4xx/5xx range.
* @property failureEvent
* @private
* @static
* @type CustomEvent
*/
uploadEvent: new YAHOO.util.CustomEvent('upload'),
/**
* @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);
},
/**
* @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;
}
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;
}
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;
}
},
/**
* @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;
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 };
}
catch(e)
{
for(var i=0; iUsage: 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) { if ( this.patterns.noNegatives.test(attr) ) { val = (val > 0) ? val : 0; } Y.Dom.setStyle(this.getEl(), 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 // 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; } 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); }; var onStart = function() { this.onStart.fire(); this.runtimeAttributes = {}; for (var attr in this.attributes) { 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 */ var onTween = 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) { this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit); } actualFrames += 1; }; var onComplete = 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 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(onStart); this._onTween.subscribe(onTween); this._onComplete.subscribe(onComplete); } }; 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 = 1; /** * 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(); }; /** * 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(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; }; /** * 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; } }; }; /** * 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);