
var xmlHttp;
xmlHttp=getHTTPObject(); // We create the HTTP Object 
prePath = "http://www.kokaly.com/"; //"http://www.kokaly.com/";


/*
function getGame(gameURL) {
				url = prePath + gameURL ;
				xmlHttp.onreadystatechange=stateChangedForGame ;
				xmlHttp.open("GET",url,true);
				xmlHttp.send(null);
} 
 
function stateChangedForGame() 
				{ 
				if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
					{ 
						document.getElementById("gameDiv").innerHTML=xmlHttp.responseText; 
						xmlHttp=getHTTPObject();
					} 
				}


function getSection(sectionURL, ourTitle) {
				document.getElementById("ourTitle").innerHTML= ourTitle; 
				url = prePath + sectionURL ;
				xmlHttp.onreadystatechange=stateChanged ;
				xmlHttp.open("GET",url,true);
				xmlHttp.send(null);
} 
 
function stateChanged() 
				{ 
				if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
					{ 
						document.getElementById("theContent3").innerHTML=xmlHttp.responseText; 
						xmlHttp=getHTTPObject();
					} 
				}

*/

function getHTTPObject() {
			  var xmlhttp;
			  /*@cc_on

			  @if (@_jscript_version >= 5)

				try {

				  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");

				} catch (e) {

				  try {

					xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

				  } catch (E) {

					xmlhttp = false;

				  }

				}

			  @else

			  xmlhttp = false;

			  @end @*/

			  if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {

				try {

				  xmlhttp = new XMLHttpRequest();

				} catch (e) {

				  xmlhttp = false;

				}

			  }

			  return xmlhttp;

}


// Slide Show


				var slideshow2_noFading = false;
				var slideshow2_timeBetweenSlides = 3000;	// Amount of time between each image(1000 = 1 second)
				var slideshow2_fadingSpeed = 10;	// Speed of fading	(Lower value = faster)
				
				var slideshow2_galleryContainer;	// Reference to the gallery div
				var slideshow2_galleryWidth;	// Width of gallery
				var slideshow2_galleryHeight;	// Height of galery
				var slideshow2_slideIndex = -1;	// Index of current image shown
				var slideshow2_slideIndexNext = false;	// Index of next image shown
				var slideshow2_imageDivs = new Array();	// Array of image divs(Created dynamically)
				var slideshow2_currentOpacity = 100;	// Initial opacity
				var slideshow2_imagesInGallery = false;	// Number of images in gallery
				var Opera = navigator.userAgent.indexOf('Opera')>=0?true:false;
				function createParentDivs(imageIndex)
				{
					if(imageIndex==slideshow2_imagesInGallery){			
						showGallery();
					}else{
						var imgObj = document.getElementById('galleryImage' + imageIndex);	
						if(Opera)imgObj.style.position = 'static';
						slideshow2_imageDivs[slideshow2_imageDivs.length] =  imgObj;
						imgObj.style.visibility = 'hidden';	
						imageIndex++;
						createParentDivs(imageIndex);	
					}		
				}
				
				function showGallery()
				{
					if(slideshow2_slideIndex==-1)slideshow2_slideIndex=0; else slideshow2_slideIndex++;	// Index of next image to show
					if(slideshow2_slideIndex==slideshow2_imageDivs.length)slideshow2_slideIndex=0;
					slideshow2_slideIndexNext = slideshow2_slideIndex+1;	// Index of the next next image
					if(slideshow2_slideIndexNext==slideshow2_imageDivs.length)slideshow2_slideIndexNext = 0;
					
					slideshow2_currentOpacity=100;	// Reset current opacity

					// Displaying image divs
					slideshow2_imageDivs[slideshow2_slideIndex].style.visibility = 'visible';
					if(Opera)slideshow2_imageDivs[slideshow2_slideIndex].style.display = 'inline';
					if(navigator.userAgent.indexOf('Opera')<0){
						slideshow2_imageDivs[slideshow2_slideIndexNext].style.visibility = 'visible';
					}
					
					if(document.all){	// IE rules
						slideshow2_imageDivs[slideshow2_slideIndex].style.filter = 'alpha(opacity=100)';
						slideshow2_imageDivs[slideshow2_slideIndexNext].style.filter = 'alpha(opacity=1)';
					}else{
						slideshow2_imageDivs[slideshow2_slideIndex].style.opacity = 0.99;	// Can't use 1 and 0 because of screen flickering in FF
						slideshow2_imageDivs[slideshow2_slideIndexNext].style.opacity = 0.01;
					}		
					

					setTimeout('revealImage()',slideshow2_timeBetweenSlides);		
				}
				
				
				
				
				function revealImage()
				{
					if(slideshow2_noFading){
						slideshow2_imageDivs[slideshow2_slideIndex].style.visibility = 'hidden';
						if(Opera)slideshow2_imageDivs[slideshow2_slideIndex].style.display = 'none';
						showGallery();
						return;
					}
					slideshow2_currentOpacity--;
					if(document.all){
						slideshow2_imageDivs[slideshow2_slideIndex].style.filter = 'alpha(opacity='+slideshow2_currentOpacity+')';
						slideshow2_imageDivs[slideshow2_slideIndexNext].style.filter = 'alpha(opacity='+(100-slideshow2_currentOpacity)+')';
					}else{
						slideshow2_imageDivs[slideshow2_slideIndex].style.opacity = Math.max(0.01,slideshow2_currentOpacity/100);	// Can't use 1 and 0 because of screen flickering in FF
						slideshow2_imageDivs[slideshow2_slideIndexNext].style.opacity = Math.min(0.99,(1 - (slideshow2_currentOpacity/100)));
					}
					if(slideshow2_currentOpacity>0){
						setTimeout('revealImage()',slideshow2_fadingSpeed);
					}else{
						slideshow2_imageDivs[slideshow2_slideIndex].style.visibility = 'hidden';	
						if(Opera)slideshow2_imageDivs[slideshow2_slideIndex].style.display = 'none';		
						showGallery();
					}
				}
				
				function initImageGallery()
				{
					slideshow2_galleryContainer = document.getElementById('imageSlideshowHolder');
					slideshow2_galleryWidth = slideshow2_galleryContainer.clientWidth;
					slideshow2_galleryHeight = slideshow2_galleryContainer.clientHeight;
					galleryImgArray = slideshow2_galleryContainer.getElementsByTagName('IMG');
					for(var no=0;no<galleryImgArray.length;no++){
						galleryImgArray[no].id = 'galleryImage' + no;
					}
					slideshow2_imagesInGallery = galleryImgArray.length;
					createParentDivs(0);		
					
				}

				
// Automatic fill

function fillUserName() {
					var emailAdd = document.getElementById("emailAdd");
					var length = emailAdd.value.length;
					
					if (emailAdd.value.substring( length - 11, length ) == "@kokaly.com") {
						// Do Nothing
					}
					else if (length > 0){ 
						var currentString = emailAdd.value;
						emailAdd.value = currentString + "@kokaly.com";
					}
				}

				/*                                                                                                                                                      
Copyright (c) 2006, Yahoo! Inc. All rights reserved.                                                                                                    
Code licensed under the BSD License:                                                                                                                    
http://developer.yahoo.net/yui/license.txt                                                                                                              
version: 0.10.0                                                                                                                                         
*/ 

/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */

/**
			 * The Yahoo global namespace
			 * @constructor
			 */
var YAHOO = window.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
			 *
			 * @param  {String} sNameSpace String representation of the desired 
			 *                             namespace
			 * @return {Object}            A reference to the namespace object
			 */
YAHOO.namespace = function( sNameSpace ) {

				if (!sNameSpace || !sNameSpace.length) {
					return null;
				}

				var levels = sNameSpace.split(".");

				var currentNS = YAHOO;

				// YAHOO is implied, so it is ignored if it is included
				for (var i=(levels[0] == "YAHOO") ? 1 : 0; i<levels.length; ++i) {
					currentNS[levels[i]] = currentNS[levels[i]] || {};
					currentNS = currentNS[levels[i]];
				}

				return currentNS;
};

/**
			 * Global log method.
			 */
YAHOO.log = function(sMsg,sCategory) {
				if(YAHOO.widget.Logger) {
					YAHOO.widget.Logger.log(null, sMsg, sCategory);
				} else {
					return false;
				}
};

YAHOO.namespace("util");
YAHOO.namespace("widget");
YAHOO.namespace("example");

/*                                                                                                                                                      
Copyright (c) 2006, Yahoo! Inc. All rights reserved.                                                                                                    
Code licensed under the BSD License:                                                                                                                    
http://developer.yahoo.net/yui/license.txt                                                                                                              
version: 0.10.0                                                                                                                                         
*/ 

/**
			 * The CustomEvent class lets you define events for your application
			 * that can be subscribed to by one or more independent component.
			 *
			 * @param {String} type The type of event, which is passed to the callback
			 *                 when the event fires
			 * @param {Object} oScope The context the event will fire from.  "this" will
			 *                 refer to this object in the callback.  Default value: 
			 *                 the window object.  The listener can override this.
			 * @constructor
			 */
YAHOO.util.CustomEvent = function(type, oScope) {
				/**
				 * The type of event, returned to subscribers when the event fires
				 * @type string
				 */
				this.type = type;

				/**
				 * The scope the the event will fire from by default.  Defaults to the window 
				 * obj
				 * @type object
				 */
				this.scope = oScope || window;

				/**
				 * The subscribers to this event
				 * @type Subscriber[]
				 */
				this.subscribers = [];

				// Register with the event utility for automatic cleanup.  Made optional
				// so that CustomEvent can be used independently of pe.event
				if (YAHOO.util.Event) { 
					YAHOO.util.Event.regCE(this);
				}
};

YAHOO.util.CustomEvent.prototype = {
				/**
				 * Subscribes the caller to this event
				 * @param {Function} fn       The function to execute
				 * @param {Object}   obj      An object to be passed along when the event fires
				 * @param {boolean}  bOverride If true, the obj passed in becomes the execution
				 *                            scope of the listener
				 */
				subscribe: function(fn, obj, bOverride) {
					this.subscribers.push( new YAHOO.util.Subscriber(fn, obj, bOverride) );
				},

				/**
				 * Unsubscribes the caller from this event
				 * @param {Function} fn  The function to execute
				 * @param {Object}   obj An object to be passed along when the event fires
				 * @return {boolean} True if the subscriber was found and detached.
				 */
				unsubscribe: function(fn, obj) {
					var found = false;
					for (var i=0, len=this.subscribers.length; i<len; ++i) {
						var s = this.subscribers[i];
						if (s && s.contains(fn, obj)) {
							this._delete(i);
							found = true;
						}
					}

					return found;
				},

				/**
				 * Notifies the subscribers.  The callback functions will be executed
				 * from the scope specified when the event was created, and with the following
				 * parameters:
				 *   <pre>
				 *   - The type of event
				 *   - All of the arguments fire() was executed with as an array
				 *   - The custom object (if any) that was passed into the subscribe() method
				 *   </pre>
				 *   
				 * @param {Array} an arbitrary set of parameters to pass to the handler
				 */
				fire: function() {
					for (var i=0, len=this.subscribers.length; i<len; ++i) {
						var s = this.subscribers[i];
						if (s) {
							var scope = (s.override) ? s.obj : this.scope;
							s.fn.call(scope, this.type, arguments, s.obj);
						}
					}
				},

				/**
				 * Removes all listeners
				 */
				unsubscribeAll: function() {
					for (var i=0, len=this.subscribers.length; i<len; ++i) {
						this._delete(i);
					}
				},

				/**
				 * @private
				 */
				_delete: function(index) {
					var s = this.subscribers[index];
					if (s) {
						delete s.fn;
						delete s.obj;
					}

					delete this.subscribers[index];
				}
};

/////////////////////////////////////////////////////////////////////

/**
			 * @class Stores the subscriber information to be used when the event fires.
			 * @param {Function} fn       The function to execute
			 * @param {Object}   obj      An object to be passed along when the event fires
			 * @param {boolean}  bOverride If true, the obj passed in becomes the execution
			 *                            scope of the listener
			 * @constructor
			 */
YAHOO.util.Subscriber = function(fn, obj, bOverride) {
				/**
				 * The callback that will be execute when the event fires
				 * @type function
				 */
				this.fn = fn;

				/**
				 * An optional custom object that will passed to the callback when
				 * the event fires
				 * @type object
				 */
				this.obj = obj || null;

				/**
				 * The default execution scope for the event listener is defined when the
				 * event is created (usually the object which contains the event).
				 * By setting override to true, the execution scope becomes the custom
				 * object passed in by the subscriber
				 * @type boolean
				 */
				this.override = (bOverride);
};

/**
			 * Returns true if the fn and obj match this objects properties.
			 * Used by the unsubscribe method to match the right subscriber.
			 *
			 * @param {Function} fn the function to execute
			 * @param {Object} obj an object to be passed along when the event fires
			 * @return {boolean} true if the supplied arguments match this 
			 *                   subscriber's signature.
			 */
YAHOO.util.Subscriber.prototype.contains = function(fn, obj) {
				return (this.fn == fn && this.obj == obj);
};

/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */

// Only load this library once.  If it is loaded a second time, existing
// events cannot be detached.
if (!YAHOO.util.Event) {

/**
			 * @class
			 * The event utility provides functions to add and remove event listeners,
			 * event cleansing.  It also tries to automatically remove listeners it
			 * registers during the unload event.
			 * @constructor
			 */
				YAHOO.util.Event = function() {

					/**
					 * True after the onload event has fired
					 * @type boolean
					 * @private
					 */
					var loadComplete =  false;

					/**
					 * Cache of wrapped listeners
					 * @type array
					 * @private
					 */
					var listeners = [];

					/**
					 * Listeners that will be attached during the onload event
					 * @type array
					 * @private
					 */
					var delayedListeners = [];

					/**
					 * User-defined unload function that will be fired before all events
					 * are detached
					 * @type array
					 * @private
					 */
					var unloadListeners = [];

					/**
					 * Cache of the custom events that have been defined.  Used for
					 * automatic cleanup
					 * @type array
					 * @private
					 */
					var customEvents = [];

					/**
					 * Cache of DOM0 event handlers to work around issues with DOM2 events
					 * in Safari
					 * @private
					 */
					var legacyEvents = [];

					/**
					 * Listener stack for DOM0 events
					 * @private
					 */
					var legacyHandlers = [];

					/**
					 * The number of times to poll after window.onload.  This number is
					 * increased if additional late-bound handlers are requested after
					 * the page load.
					 * @private
					 */
					var retryCount = 0;

					/**
					 * onAvailable listeners
					 * @private
					 */
					var onAvailStack = [];

					/**
					 * Lookup table for legacy events
					 * @private
					 */
					var legacyMap = [];

					/**
					 * Counter for auto id generation
					 * @private
					 */
					var counter = 0;

					return { // PREPROCESS

						/**
						 * The number of times we should look for elements that are not
						 * in the DOM at the time the event is requested after the document
						 * has been loaded.  The default is 200@50 ms, so it will poll
						 * for 10 seconds or until all outstanding handlers are bound
						 * (whichever comes first).
						 * @type int
						 */
						POLL_RETRYS: 200,

						/**
						 * The poll interval in milliseconds
						 * @type int
						 */
						POLL_INTERVAL: 50,

						/**
						 * Element to bind, int constant
						 * @type int
						 */
						EL: 0,

						/**
						 * Type of event, int constant
						 * @type int
						 */
						TYPE: 1,

						/**
						 * Function to execute, int constant
						 * @type int
						 */
						FN: 2,

						/**
						 * Function wrapped for scope correction and cleanup, int constant
						 * @type int
						 */
						WFN: 3,

						/**
						 * Object passed in by the user that will be returned as a 
						 * parameter to the callback, int constant
						 * @type int
						 */
						SCOPE: 3,

						/**
						 * Adjusted scope, either the element we are registering the event
						 * on or the custom object passed in by the listener, int constant
						 * @type int
						 */
						ADJ_SCOPE: 4,

						/**
						 * Safari detection is necessary to work around the preventDefault
						 * bug that makes it so you can't cancel a href click from the 
						 * handler.  There is not a capabilities check we can use here.
						 * @private
						 */
						isSafari: (/Safari|Konqueror|KHTML/gi).test(navigator.userAgent),

						/**
						 * IE detection needed to properly calculate pageX and pageY.  
						 * capabilities checking didn't seem to work because another 
						 * browser that does not provide the properties have the values 
						 * calculated in a different manner than IE.
						 * @private
						 */
						isIE: (!this.isSafari && !navigator.userAgent.match(/opera/gi) && 
								navigator.userAgent.match(/msie/gi)),

						/**
						 * @private
						 */
						addDelayedListener: function(el, sType, fn, oScope, bOverride) {
							delayedListeners[delayedListeners.length] =
								[el, sType, fn, oScope, bOverride];

							// If this happens after the inital page load, we need to
							// reset the poll counter so that we continue to search for
							// the element for a fixed period of time.
							if (loadComplete) {
								retryCount = this.POLL_RETRYS;
								this.startTimeout(0);
								// this._tryPreloadAttach();
							}
						},

						/**
						 * @private
						 */
						startTimeout: function(interval) {
							var i = (interval || interval === 0) ? interval : this.POLL_INTERVAL;
							var self = this;
							var callback = function() { self._tryPreloadAttach(); };
							this.timeout = setTimeout(callback, i);
						},

						/**
						 * Executes the supplied callback when the item with the supplied
						 * id is found.  This is meant to be used to execute behavior as
						 * soon as possible as the page loads.  If you use this after the
						 * initial page load it will poll for a fixed time for the element.
						 * The number of times it will poll and the frequency are
						 * configurable.  By default it will poll for 10 seconds.
						 * @param {string} p_id the id of the element 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} p_override If set to true, p_fn will execute
						 * in the scope of p_obj
						 *
						 */
						onAvailable: function(p_id, p_fn, p_obj, p_override) {
							onAvailStack.push( { id:       p_id, 
												 fn:       p_fn, 
												 obj:      p_obj, 
												 override: p_override } );

							retryCount = this.POLL_RETRYS;
							this.startTimeout(0);
							// this._tryPreloadAttach();
						},

						/**
						 * Appends an event handler
						 *
						 * @param {Object}   el        The html element to assign the 
						 *                             event to
						 * @param {String}   sType     The type of event to append
						 * @param {Function} fn        The method the event invokes
						 * @param {Object}   oScope    An arbitrary object that will be 
						 *                             passed as a parameter to the handler
						 * @param {boolean}  bOverride If true, the obj passed in becomes
						 *                             the execution scope of the listener
						 * @return {boolean} True if the action was successful or defered,
						 *                        false if one or more of the elements 
						 *                        could not have the event bound to it.
						 */
						addListener: function(el, sType, fn, oScope, bOverride) {

							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<len; ++i) {
									ok = ( this.on(el[i], 
												   sType, 
												   fn, 
												   oScope, 
												   bOverride) && ok );
								}
								return ok;

							} else if (typeof el == "string") {
								var oEl = this.getEl(el);
								// If the el argument is a string, we assume it is 
								// actually the id of the element.  If the page is loaded
								// we convert el to the actual element, otherwise we 
								// defer attaching the event until onload event fires

								// check to see if we need to delay hooking up the event 
								// until after the page loads.
								if (loadComplete && oEl) {
									el = oEl;
								} else {
									// defer adding the event until onload fires
									this.addDelayedListener(el, 
															sType, 
															fn, 
															oScope, 
															bOverride);

									return true;
								}
							}

							// Element should be an html element or an array if we get 
							// here.
							if (!el) {
								return false;
							}

							// we need to make sure we fire registered unload events 
							// prior to automatically unhooking them.  So we hang on to 
							// these instead of attaching them to the window and fire the
							// handles explicitly during our one unload event.
							if ("unload" == sType && oScope !== this) {
								unloadListeners[unloadListeners.length] =
										[el, sType, fn, oScope, bOverride];
								return true;
							}


							// if the user chooses to override the scope, we use the custom
							// object passed in, otherwise the executing scope will be the
							// HTML element that the event is registered on
							var scope = (bOverride) ? oScope : el;

							// wrap the function so we can return the oScope object when
							// the event fires;
							var wrappedFn = function(e) {
									return fn.call(scope, YAHOO.util.Event.getEvent(e), 
											oScope);
								};

							var li = [el, sType, fn, wrappedFn, scope];
							var index = listeners.length;
							// cache the listener so we can try to automatically unload
							listeners[index] = li;

							if (this.useLegacyEvent(el, sType)) {
								var legacyIndex = this.getLegacyIndex(el, sType);
								if (legacyIndex == -1) {

									legacyIndex = legacyEvents.length;
									legacyMap[el.id + sType] = legacyIndex;

									// cache the signature for the DOM0 event, and 
									// include the existing handler for the event, if any
									legacyEvents[legacyIndex] = 
										[el, sType, el["on" + sType]];
									legacyHandlers[legacyIndex] = [];

									el["on" + sType] = 
										function(e) {
											YAHOO.util.Event.fireLegacyEvent(
												YAHOO.util.Event.getEvent(e), legacyIndex);
										};
								}

								// add a reference to the wrapped listener to our custom
								// stack of events
								legacyHandlers[legacyIndex].push(index);

							// DOM2 Event model
							} else if (el.addEventListener) {
								el.addEventListener(sType, wrappedFn, false);
							// Internet Explorer abstraction
							} else if (el.attachEvent) {
								el.attachEvent("on" + sType, wrappedFn);
							}

							return true;
							
						},

						/**
						 * Shorthand for YAHOO.util.Event.addListener
						 * @type function
						 */
						// on: this.addListener,

						/**
						 * When using legacy events, the handler is routed to this object
						 * so we can fire our custom listener stack.
						 * @private
						 */
						fireLegacyEvent: function(e, legacyIndex) {
							var ok = true;

							var le = legacyHandlers[legacyIndex];
							for (var i=0,len=le.length; i<len; ++i) {
								var index = le[i];
								if (index) {
									var li = listeners[index];
									if ( li && li[this.WFN] ) {
										var scope = li[this.ADJ_SCOPE];
										var ret = li[this.WFN].call(scope, e);
										ok = (ok && ret);
									} else {
										// This listener was removed, so delete it from
										// the array
										delete le[i];
									}
								}
							}

							return ok;
						},

						/**
						 * Returns the legacy event index that matches the supplied 
						 * signature
						 * @private
						 */
						getLegacyIndex: function(el, sType) {
							/*
							for (var i=0,len=legacyEvents.length; i<len; ++i) {
								var le = legacyEvents[i];
								if (le && le[0] === el && le[1] === sType) {
									return i;
								}
							}
							return -1;
							*/

							var key = this.generateId(el) + sType;
							if (typeof legacyMap[key] == "undefined") { 
								return -1;
							} else {
								return legacyMap[key];
							}

						},

						/**
						 * Logic that determines when we should automatically use legacy
						 * events instead of DOM2 events.
						 * @private
						 */
						useLegacyEvent: function(el, sType) {

							if (!el.addEventListener && !el.attachEvent) {
								return true;
							} else if (this.isSafari) {
								if ("click" == sType || "dblclick" == sType) {
									return true;
								}
							}

							return false;
						},
								
						/**
						 * Removes an event handler
						 *
						 * @param {Object} el the html element or the id of the element to 
						 * assign the event to.
						 * @param {String} sType the type of event to remove
						 * @param {Function} fn the method the event invokes
						 * @return {boolean} true if the unbind was successful, false 
						 * otherwise
						 */
						removeListener: function(el, sType, fn, index) {

							if (!fn || !fn.call) {
								return false;
							}

							// The el argument can be a string
							if (typeof el == "string") {
								el = this.getEl(el);
							// The el argument can be an array of elements or element ids.
							} else if ( this._isValidCollection(el)) {
								var ok = true;
								for (var i=0,len=el.length; i<len; ++i) {
									ok = ( this.removeListener(el[i], sType, fn) && ok );
								}
								return ok;
							}

							if ("unload" == sType) {

								for (i=0, len=unloadListeners.length; i<len; i++) {
									var li = unloadListeners[i];
									if (li && 
										li[0] == el && 
										li[1] == sType && 
										li[2] == fn) {
											delete unloadListeners[i];
											return true;
									}
								}

								return false;
							}

							var cacheItem = null;
			  
							if ("undefined" == typeof index) {
								index = this._getCacheIndex(el, sType, fn);
							}

							if (index >= 0) {
								cacheItem = listeners[index];
							}

							if (!el || !cacheItem) {
								return false;
							}


							if (el.removeEventListener) {
								el.removeEventListener(sType, cacheItem[this.WFN], false);
							} else if (el.detachEvent) {
								el.detachEvent("on" + sType, cacheItem[this.WFN]);
							}

							// removed the wrapped handler
							delete listeners[index][this.WFN];
							delete listeners[index][this.FN];
							delete listeners[index];

							return true;

						},

						/**
						 * Returns the event's target element
						 * @param {Event} ev the event
						 * @param {boolean} resolveTextNode when set to true the target's
						 *                  parent will be returned if the target is a 
						 *                  text node
						 * @return {HTMLElement} the event's target
						 */
						getTarget: function(ev, resolveTextNode) {
							var t = ev.target || ev.srcElement;

							if (resolveTextNode && t && "#text" == t.nodeName) {
								return t.parentNode;
							} else {
								return t;
							}
						},

						/**
						 * Returns the event's pageX
						 * @param {Event} ev the event
						 * @return {int} the event's pageX
						 */
						getPageX: function(ev) {
							var x = ev.pageX;
							if (!x && 0 !== x) {
								x = ev.clientX || 0;

								if ( this.isIE ) {
									x += this._getScrollLeft();
								}
							}

							return x;
						},

						/**
						 * Returns the event's pageY
						 * @param {Event} ev the event
						 * @return {int} the event's pageY
						 */
						getPageY: function(ev) {
							var y = ev.pageY;
							if (!y && 0 !== y) {
								y = ev.clientY || 0;

								if ( this.isIE ) {
									y += this._getScrollTop();
								}
							}

							return y;
						},

						/**
						 * Returns the pageX and pageY properties as an indexed array.
						 * @type int[]
						 */
						getXY: function(ev) {
							return [this.getPageX(ev), this.getPageY(ev)];
						},

						/**
						 * Returns the event's related target 
						 * @param {Event} ev the event
						 * @return {HTMLElement} the event's relatedTarget
						 */
						getRelatedTarget: function(ev) {
							var t = ev.relatedTarget;
							if (!t) {
								if (ev.type == "mouseout") {
									t = ev.toElement;
								} else if (ev.type == "mouseover") {
									t = ev.fromElement;
								}
							}

							return t;
						},

						/**
						 * Returns the time of the event.  If the time is not included, the
						 * event is modified using the current time.
						 * @param {Event} ev the event
						 * @return {Date} the time of the event
						 */
						getTime: function(ev) {
							if (!ev.time) {
								var t = new Date().getTime();
								try {
									ev.time = t;
								} catch(e) { 
									// can't set the time property  
									return t;
								}
							}

							return ev.time;
						},

						/**
						 * Convenience method for stopPropagation + preventDefault
						 * @param {Event} ev the event
						 */
						stopEvent: function(ev) {
							this.stopPropagation(ev);
							this.preventDefault(ev);
						},

						/**
						 * Stops event propagation
						 * @param {Event} ev the event
						 */
						stopPropagation: function(ev) {
							if (ev.stopPropagation) {
								ev.stopPropagation();
							} else {
								ev.cancelBubble = true;
							}
						},

						/**
						 * Prevents the default behavior of the event
						 * @param {Event} ev the event
						 */
						preventDefault: function(ev) {
							if (ev.preventDefault) {
								ev.preventDefault();
							} else {
								ev.returnValue = false;
							}
						},
						 
						/**
						 * Finds the event in the window object, the caller's arguments, or
						 * in the arguments of another method in the callstack.  This is
						 * executed automatically for events registered through the event
						 * manager, so the implementer should not normally need to execute
						 * this function at all.
						 * @param {Event} the event parameter from the handler
						 * @return {Event} the event 
						 */
						getEvent: function(e) {
							var ev = e || window.event;

							if (!ev) {
								var c = this.getEvent.caller;
								while (c) {
									ev = c.arguments[0];
									if (ev && Event == ev.constructor) {
										break;
									}
									c = c.caller;
								}
							}

							return ev;
						},

						/**
						 * Returns the charcode for an event
						 * @param {Event} ev the event
						 * @return {int} the event's charCode
						 */
						getCharCode: function(ev) {
							return ev.charCode || ((ev.type == "keypress") ? ev.keyCode : 0);
						},

						/**
						 * @private
						 * Locating the saved event handler data by function ref
						 */
						_getCacheIndex: function(el, sType, fn) {
							for (var i=0,len=listeners.length; i<len; ++i) {
								var li = listeners[i];
								if ( li                 && 
									 li[this.FN] == fn  && 
									 li[this.EL] == el  && 
									 li[this.TYPE] == sType ) {
									return i;
								}
							}

							return -1;
						},

						/**
						 * Generates an unique ID for the element if it does not already 
						 * have one.
						 * @param el the element
						 * @return {string} the id of the element
						 */
						generateId: function(el) {
							var id = el.id;

							if (!id) {
								id = "yuievtautoid-" + (counter++);
								el.id = id;
							}

							return id;
						},

						/**
						 * We want to be able to use getElementsByTagName as a collection
						 * to attach a group of events to.  Unfortunately, different 
						 * browsers return different types of collections.  This function
						 * tests to determine if the object is array-like.  It will also 
						 * fail if the object is an array, but is empty.
						 * @param o the object to test
						 * @return {boolean} true if the object is array-like and populated
						 * @private
						 */
						_isValidCollection: function(o) {

							return ( o                    && // o is something
									 o.length             && // o is indexed
									 typeof o != "string" && // o is not a string
									 !o.tagName           && // o is not an HTML element
									 !o.alert             && // o is not a window
									 typeof o[0] != "undefined" );

						},

						/**
						 * @private
						 * DOM element cache
						 */
						elCache: {},

						/**
						 * We cache elements bound by id because when the unload event 
						 * fires, we can no longer use document.getElementById
						 * @private
						 */
						getEl: function(id) {
							return document.getElementById(id);
						},

						/**
						 * Clears the element cache
						 * @deprecated
						 * @private
						 */
						clearCache: function() { },

						/**
						 * Called by CustomEvent instances to provide a handle to the 
						 * event * that can be removed later on.  Should be package 
						 * protected.
						 * @private
						 */
						regCE: function(ce) {
							customEvents.push(ce);
						},

						/**
						 * @private
						 * hook up any deferred listeners
						 */
						_load: function(e) {
							loadComplete = true;
						},

						/**
						 * Polling function that runs before the onload event fires, 
						 * attempting * to attach to DOM Nodes as soon as they are 
						 * available
						 * @private
						 */
						_tryPreloadAttach: function() {

							if (this.locked) {
								return false;
							}

							this.locked = true;


							// keep trying until after the page is loaded.  We need to 
							// check the page load state prior to trying to bind the 
							// elements so that we can be certain all elements have been 
							// tested appropriately
							var tryAgain = !loadComplete;
							if (!tryAgain) {
								tryAgain = (retryCount > 0);
							}

							// Delayed listeners
							var stillDelayed = [];

							for (var i=0,len=delayedListeners.length; i<len; ++i) {
								var d = delayedListeners[i];
								// There may be a race condition here, so we need to 
								// verify the array element is usable.
								if (d) {

									// el will be null if document.getElementById did not
									// work
									var el = this.getEl(d[this.EL]);

									if (el) {
										this.on(el, d[this.TYPE], d[this.FN], 
												d[this.SCOPE], d[this.ADJ_SCOPE]);
										delete delayedListeners[i];
									} else {
										stillDelayed.push(d);
									}
								}
							}

							delayedListeners = stillDelayed;

							// onAvailable
							notAvail = [];
							for (i=0,len=onAvailStack.length; i<len ; ++i) {
								var item = onAvailStack[i];
								if (item) {
									el = this.getEl(item.id);

									if (el) {
										var scope = (item.override) ? item.obj : el;
										item.fn.call(scope, item.obj);
										delete onAvailStack[i];
									} else {
										notAvail.push(item);
									}
								}
							}

							retryCount = (stillDelayed.length === 0 && 
												notAvail.length === 0) ? 0 : retryCount - 1;

							if (tryAgain) {
								this.startTimeout();
							}

							this.locked = false;

						},

						/**
						 * Removes all listeners registered by pe.event.  Called 
						 * automatically during the unload event.
						 * @private
						 */
						_unload: function(e, me) {
							for (var i=0,len=unloadListeners.length; i<len; ++i) {
								var l = unloadListeners[i];
								if (l) {
									var scope = (l[this.ADJ_SCOPE]) ? l[this.SCOPE]: window;
									l[this.FN].call(scope, this.getEvent(e), l[this.SCOPE] );
								}
							}

							if (listeners && listeners.length > 0) {
								for (i=0,len=listeners.length; i<len ; ++i) {
									l = listeners[i];
									if (l) {
										this.removeListener(l[this.EL], l[this.TYPE], 
												l[this.FN], i);
									}
								}

								this.clearCache();
							}

							for (i=0,len=customEvents.length; i<len; ++i) {
								customEvents[i].unsubscribeAll();
								delete customEvents[i];
							}

							for (i=0,len=legacyEvents.length; i<len; ++i) {
								// dereference the element
								delete legacyEvents[i][0];
								// delete the array item
								delete legacyEvents[i];
							}
						},

						/**
						 * Returns scrollLeft
						 * @private
						 */
						_getScrollLeft: function() {
							return this._getScroll()[1];
						},

						/**
						 * Returns scrollTop
						 * @private
						 */
						_getScrollTop: function() {
							return this._getScroll()[0];
						},

						/**
						 * Returns the scrollTop and scrollLeft.  Used to calculate the 
						 * pageX and pageY in Internet Explorer
						 * @private
						 */
						_getScroll: function() {
							var dd = document.documentElement; db = document.body;
							if (dd && dd.scrollTop) {
								return [dd.scrollTop, dd.scrollLeft];
							} else if (db) {
								return [db.scrollTop, db.scrollLeft];
							} else {
								return [0, 0];
							}
						}
					};
				} ();

				/**
				 * @private
				 */
				YAHOO.util.Event.on = YAHOO.util.Event.addListener;

				if (document && document.body) {
					YAHOO.util.Event._load();
				} else {
					YAHOO.util.Event.on(window, "load", YAHOO.util.Event._load, 
							YAHOO.util.Event, true);
				}

				YAHOO.util.Event.on(window, "unload", YAHOO.util.Event._unload, 
							YAHOO.util.Event, true);

				YAHOO.util.Event._tryPreloadAttach();

}

/*
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
*/

/**
			 * @class Provides helper methods for DOM elements.
			 */
YAHOO.util.Dom = function() {
			   var ua = navigator.userAgent.toLowerCase();
			   var isOpera = (ua.indexOf('opera') != -1);
			   var isIE = (ua.indexOf('msie') != -1 && !isOpera); // not opera spoof
			   var id_counter = 0;
			   
			   return {
				  /**
				   * Returns an HTMLElement reference
				   * @param {String/HTMLElement/Array} el Accepts a string to use as an ID for getting a DOM reference, an actual DOM reference, or an Array of IDs and/or HTMLElements.
				   * @return {HTMLElement/Array} A DOM reference to an HTML element or an array of HTMLElements.
				   */
				  get: function(el) {
					 if (typeof el != 'string' && !(el instanceof Array) )
					 { // assuming HTMLElement or HTMLCollection, so pass back as is
						return el;
					 }
					 
					 if (typeof el == 'string') 
					 { // ID
						return document.getElementById(el);
					 }
					 else
					 { // array of ID's and/or elements
						var collection = [];
						for (var i = 0, len = el.length; i < len; ++i)
						{
						   collection[collection.length] = this.get(el[i]);
						}
						
						return collection;
					 }

					 return null; // safety, should never happen
				  },
			   
				  /**
				   * Normalizes currentStyle and ComputedStyle.
				   * @param {String/HTMLElement/Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements.
				   * @param {String} property The style property whose value is returned.
				   * @return {String/Array} The current value of the style property for the element(s).
				   */
				  getStyle: function(el, property) {
					 var f = function(el) {
						var value = null;
						var dv = document.defaultView;
						
						if (property == 'opacity' && el.filters) 
						{// IE opacity
						   value = 1;
						   try {
							  value = el.filters.item('DXImageTransform.Microsoft.Alpha').opacity / 100;
						   } catch(e) {
							  try {
								 value = el.filters.item('alpha').opacity / 100;
							  } catch(e) {}
						   }
						}
						else if (el.style[property]) 
						{
						   value = el.style[property];
						}
						else if (el.currentStyle && el.currentStyle[property]) {
						   value = el.currentStyle[property];
						}
						else if ( dv && dv.getComputedStyle )
						{  // convert camelCase to hyphen-case
						   
						   var converted = '';
						   for(var i = 0, len = property.length;i < len; ++i) {
							  if (property.charAt(i) == property.charAt(i).toUpperCase()) 
							  {
								 converted = converted + '-' + property.charAt(i).toLowerCase();
							  } else {
								 converted = converted + property.charAt(i);
							  }
						   }
						   
						   if (dv.getComputedStyle(el, '') && dv.getComputedStyle(el, '').getPropertyValue(converted)) {
							  value = dv.getComputedStyle(el, '').getPropertyValue(converted);
						   }
						}
				  
						return value;
					 };
					 
					 return this.batch(el, f, this, true);
				  },
			   
				  /**
				   * Wrapper for setting style properties of HTMLElements.  Normalizes "opacity" across modern browsers.
				   * @param {String/HTMLElement/Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements.
				   * @param {String} property The style property to be set.
				   * @param {String} val The value to apply to the given property.
				   */
				  setStyle: function(el, property, val) {
					 var f = function(el) {
						switch(property) {
						   case 'opacity' :
							  if (isIE && typeof el.style.filter == 'string') { // in case not appended
								 el.style.filter = 'alpha(opacity=' + val * 100 + ')';
								 
								 if (!el.currentStyle || !el.currentStyle.hasLayout) {
									el.style.zoom = 1; // when no layout or cant tell
								 }
							  } else {
								 el.style.opacity = val;
								 el.style['-moz-opacity'] = val;
								 el.style['-khtml-opacity'] = val;
							  }

							  break;
						   default :
							  el.style[property] = val;
						}
						
					 };
					 
					 this.batch(el, f, this, true);
				  },
				  
				  /**
				   * Gets the current position of an element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
				   * @param {String/HTMLElement/Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements
				   @ return {Array} The XY position of the element(s)
				   */
				  getXY: function(el) {
					 var f = function(el) {
			   
					 // has to be part of document to have pageXY
						if (el.parentNode === null || this.getStyle(el, 'display') == 'none') {
						   return false;
						}
						
						var parent = null;
						var pos = [];
						var box;
						
						if (el.getBoundingClientRect) { // IE
						   box = el.getBoundingClientRect();
						   var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
						   var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
						   
						   return [box.left + scrollLeft, box.top + scrollTop];
						}
						else if (document.getBoxObjectFor) { // gecko
						   box = document.getBoxObjectFor(el);
						   
						   var borderLeft = parseInt(this.getStyle(el, 'borderLeftWidth'));
						   var borderTop = parseInt(this.getStyle(el, 'borderTopWidth'));
						   
						   pos = [box.x - borderLeft, box.y - borderTop];
						}
						else { // safari & opera
						   pos = [el.offsetLeft, el.offsetTop];
						   parent = el.offsetParent;
						   if (parent != el) {
							  while (parent) {
								 pos[0] += parent.offsetLeft;
								 pos[1] += parent.offsetTop;
								 parent = parent.offsetParent;
							  }
						   }
						   if (
							  ua.indexOf('opera') != -1 
							  || ( ua.indexOf('safari') != -1 && this.getStyle(el, 'position') == 'absolute' ) 
						   ) {
							  pos[0] -= document.body.offsetLeft;
							  pos[1] -= document.body.offsetTop;
						   } 
						}
						
						if (el.parentNode) { parent = el.parentNode; }
						else { parent = null; }
				  
						while (parent && parent.tagName != 'BODY' && parent.tagName != 'HTML') 
						{ // account for any scrolled ancestors
						   pos[0] -= parent.scrollLeft;
						   pos[1] -= parent.scrollTop;
				  
						   if (parent.parentNode) { parent = parent.parentNode; } 
						   else { parent = null; }
						}
				  
						return pos;
					 };
					 
					 return this.batch(el, f, this, true);
				  },
				  
				  /**
				   * Gets the current X position of an element based on page coordinates.  The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
				   * @param {String/HTMLElement/Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements
				   * @return {String/Array} The X position of the element(s)
				   */
				  getX: function(el) {
					 return this.getXY(el)[0];
				  },
				  
				  /**
				   * Gets the current Y position of an element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
				   * @param {String/HTMLElement/Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements
				   * @return {String/Array} The Y position of the element(s)
				   */
				  getY: function(el) {
					 return this.getXY(el)[1];
				  },
				  
				  /**
				   * Set the position of an html element in page coordinates, regardless of how the element is positioned.
				   * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
				   * @param {String/HTMLElement/Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements
				   * @param {Array} pos Contains X & Y values for new position (coordinates are page-based)
				   * @param {Boolean} noRetry By default we try and set the position a second time if the first fails
				   */
				  setXY: function(el, pos, noRetry) {
					 var f = function(el) {
			   
						var style_pos = this.getStyle(el, 'position');
						if (style_pos == 'static') { // default to relative
						   this.setStyle(el, 'position', 'relative');
						   style_pos = 'relative';
						}
						
						var pageXY = YAHOO.util.Dom.getXY(el);
						if (pageXY === false) { return false; } // has to be part of doc to have pageXY
						
						var delta = [
						   parseInt( YAHOO.util.Dom.getStyle(el, 'left'), 10 ),
						   parseInt( YAHOO.util.Dom.getStyle(el, 'top'), 10 )
						];
					 
						if ( isNaN(delta[0]) ) // defaults to 'auto'
						{ 
						   delta[0] = (style_pos == 'relative') ? 0 : el.offsetLeft;
						} 
						if ( isNaN(delta[1]) ) // defaults to 'auto'
						{ 
						   delta[1] = (style_pos == 'relative') ? 0 : el.offsetTop;
						} 
				  
						if (pos[0] !== null) { el.style.left = pos[0] - pageXY[0] + delta[0] + 'px'; }
						if (pos[1] !== null) { el.style.top = pos[1] - pageXY[1] + delta[1] + 'px'; }
				  
						var newXY = this.getXY(el);
				  
						// if retry is true, try one more time if we miss
						if (!noRetry && (newXY[0] != pos[0] || newXY[1] != pos[1]) ) {
						   var retry = function() { YAHOO.util.Dom.setXY(el, pos, true); };
						   setTimeout(retry, 0); // "delay" for IE resize timing issue
						}
					 };
					 
					 this.batch(el, f, this, true);
				  },
				  
				  /**
				   * Set the X position of an html element in page coordinates, regardless of how the element is positioned.
				   * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
				   * @param {String/HTMLElement/Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements.
				   * @param {Int} x to use as the X coordinate for the element(s).
				   */
				  setX: function(el, x) {
					 this.setXY(el, [x, null]);
				  },
				  
				  /**
				   * Set the Y position of an html element in page coordinates, regardless of how the element is positioned.
				   * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
				   * @param {String/HTMLElement/Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements.
				   * @param {Int} x to use as the Y coordinate for the element(s).
				   */
				  setY: function(el, y) {
					 this.setXY(el, [null, y]);
				  },
				  
				  /**
				   * Returns the region position of the given element.
				   * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
				   * @param {String/HTMLElement/Array} el Accepts a string to use as an ID, an actual DOM reference, or an Array of IDs and/or HTMLElements.
				   * @return {Region/Array} A Region or array of Region instances containing "top, left, bottom, right" member data.
				   */
				  getRegion: function(el) {
					 var f = function(el) {
						return new YAHOO.util.Region.getRegion(el);
					 };
					 
					 return this.batch(el, f, this, true);
				  },
				  
				  /**
				   * Returns the width of the client (viewport).
				   * Now using getViewportWidth.  This interface left intact for back compat.
				   * @return {Int} The width of the viewable area of the page.
				   */
				  getClientWidth: function() {
					 return this.getViewportWidth();
				  },
				  
				  /**
				   * Returns the height of the client (viewport).
				   * Now using getViewportHeight.  This interface left intact for back compat.
				   * @return {Int} The height of the viewable area of the page.
				   */
				  getClientHeight: function() {
					 return this.getViewportHeight();
				  },

				  /**
				   * Returns a array of HTMLElements with the given class
				   * For optimized performance, include a tag and/or root node if possible
				   * @param {String} className The class name to match against
				   * @param {String} tag (optional) The tag name of the elements being collected
				   * @param {String/HTMLElement} root (optional) The HTMLElement or an ID to use as the starting point 
				   * @return {Array} An array of elements that have the given class name
				   */
				  getElementsByClassName: function(className, tag, root) {
					 var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
					 
					 var method = function(el) { return re.test(el['className']); };
					 
					 return this.getElementsBy(method, tag, root);
				  },

				  /**
				   * Determines whether an HTMLElement has the given className
				   * @param {String/HTMLElement/Array} el The element or collection to test
				   * @param {String} className the class name to search for
				   * @return {Boolean/Array} A boolean value or array of boolean values
				   */
				  hasClass: function(el, className) {
					 var f = function(el) {
						var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
						return re.test(el['className']);
					 };
					 
					 return this.batch(el, f, this, true);
				  },
			   
				  /**
				   * Adds a class name to a given element or collection of elements
				   * @param {String/HTMLElement/Array} el The element or collection to add the class to
				   * @param {String} className the class name to add to the class attribute
				   */
				  addClass: function(el, className) {
					 var f = function(el) {
						if (this.hasClass(el, className)) { return; } // already present
						
						el['className'] = [el['className'], className].join(' ');
					 };
					 
					 this.batch(el, f, this, true);
				  },
			   
				  /**
				   * Removes a class name from a given element or collection of elements
				   * @param {String/HTMLElement/Array} el The element or collection to remove the class from
				   * @param {String} className the class name to remove from the class attribute
				   */
				  removeClass: function(el, className) {
					 var f = function(el) {
						if (!this.hasClass(el, className)) { return; } // not present
						
						var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', 'g');
						var c = el['className'];
						
						el['className'] = c.replace( re, ' ');
					 };
					 
					 this.batch(el, f, this, true);
				  },
				  
				  /**
				   * Replace a class with another class for a given element or collection of elements.
				   * If no oldClassName is present, the newClassName is simply added.
				   * @param {String/HTMLElement/Array} el The element or collection to remove the class from
				   * @param {String} oldClassName the class name to be replaced
				   * @param {String} newClassName the class name that will be replacing the old class name
				   */
				  replaceClass: function(el, oldClassName, newClassName) {
					 var f = function(el) {
						this.removeClass(el, oldClassName);
						this.addClass(el, newClassName);
					 };
					 
					 this.batch(el, f, this, true);
				  },
				  
				  /**
				   * Generates a unique ID
				   * @param {String/HTMLElement/Array} el (optional) An optional element array of elements to add an ID to (no ID is added if one is already present)
				   * @param {String} prefix (optional) an optional prefix to use (defaults to "yui-gen")
				   * @return {String/Array} The generated ID, or array of generated IDs (or original ID if already present on an element)
				   */
				  generateId: function(el, prefix) {
					 prefix = prefix || 'yui-gen';
					 
					 var f = function(el) {
						el = el || {}; // just generating ID in this case
						
						if (!el.id) { el.id = prefix + id_counter++; } // dont override existing
						
						return el.id;
					 };
					 
					 return this.batch(el, f, this, true);
				  },
				  
				  /**
				   * Determines whether an HTMLElement is an ancestor of another HTML element in the DOM hierarchy
				   * @param {String/HTMLElement} haystack The possible ancestor
				   * @param {String/HTMLElement} needle The possible descendent
				   * @return {Boolean} Whether or not the haystack is an ancestor of needle
				   */
				  isAncestor: function(haystack, needle) {
					 haystack = this.get(haystack);
					 if (!haystack || !needle) { return false; }
					 
					 var f = function(needle) {
						if (haystack.contains && ua.indexOf('safari') < 0) 
						{ // safari "contains" is broken
						   return haystack.contains(needle);
						}
						else if ( haystack.compareDocumentPosition ) 
						{
						   return !!(haystack.compareDocumentPosition(needle) & 16);
						}
						else 
						{ // loop up and test each parent
						   var parent = needle.parentNode;
						   
						   while (parent) {
							  if (parent == haystack) {
								 return true;
							  }
							  else if (parent.tagName == 'HTML') {
								 return false;
							  }
							  
							  parent = parent.parentNode;
						   }
						   
						   return false;
						}    
					 };
					 
					 return this.batch(needle, f, this, true);     
				  },
				  
				  /**
				   * Determines whether an HTMLElement is present in the current document
				   * @param {String/HTMLElement} el The element to search for
				   * @return {Boolean} Whether or not the element is present in the current document
				   */
				  inDocument: function(el) {
					 var f = function(el) {
						return this.isAncestor(document.documentElement, el);
					 };
					 
					 return this.batch(el, f, this, true);
				  },
				  
				  /**
				   * Returns a array of HTMLElements that pass the test applied by supplied boolean method
				   * For optimized performance, include a tag and/or root node if possible
				   * @param {Function} method A boolean method to test elements with
				   * @param {String} tag (optional) The tag name of the elements being collected
				   * @param {String/HTMLElement} root (optional) The HTMLElement or an ID to use as the starting point 
				   */
				  getElementsBy: function(method, tag, root) {
					 tag = tag || '*';
					 root = this.get(root) || document;
					 
					 var nodes = [];
					 var elements = root.getElementsByTagName(tag);
					 
					 if ( !elements.length && (tag == '*' && root.all) ) {
						elements = root.all; // IE < 6
					 }
					 
					 for (var i = 0, len = elements.length; i < len; ++i) 
					 {
						if ( method(elements[i]) ) { nodes[nodes.length] = elements[i]; }
					 }

					 return nodes;
				  },
				  
				  /**
				   * Returns an array of elements that have had the supplied method applied.
				   * The method is called with the element(s) as the first arg, and the optional param as the second ( method(el, o) )
				   * @param {String/HTMLElement/Array} el (optional) An element or array of elements to apply the method to
				   * @param {Function} method The method to apply to the element(s)
				   * @param {Generic} (optional) o An optional arg that is passed to the supplied method
				   * @param {Boolean} (optional) override Whether or not to override the scope of "method" with "o"
				   * @return {HTMLElement/Array} The element(s) with the method applied
				   */
				  batch: function(el, method, o, override) {
					 el = this.get(el);
					 var scope = (override) ? o : window;
					 
					 if (!el || el.tagName || !el.length) 
					 { // is null or not a collection (tagName for SELECT and others that can be both an element and a collection)
						return method.call(scope, el, o);
					 } 
					 
					 var collection = [];
					 
					 for (var i = 0, len = el.length; i < len; ++i)
					 {
						collection[collection.length] = method.call(scope, el[i], o);
					 }
					 
					 return collection;
				  },
				  
				  /**
				   * Returns the height of the document.
				   * @return {Int} The height of the actual document (which includes the body and its margin).
				   */
				  getDocumentHeight: function() {
					 var scrollHeight=-1,windowHeight=-1,bodyHeight=-1;
					 var marginTop = parseInt(this.getStyle(document.body, 'marginTop'), 10);
					 var marginBottom = parseInt(this.getStyle(document.body, 'marginBottom'), 10);
					 
					 var mode = document.compatMode;
					 
					 if ( (mode || isIE) && !isOpera ) { // (IE, Gecko)
						switch (mode) {
						   case 'CSS1Compat': // Standards mode
							  scrollHeight = ((window.innerHeight && window.scrollMaxY) ?  window.innerHeight+window.scrollMaxY : -1);
							  windowHeight = [document.documentElement.clientHeight,self.innerHeight||-1].sort(function(a, b){return(a-b);})[1];
							  bodyHeight = document.body.offsetHeight + marginTop + marginBottom;
							  break;
						   
						   default: // Quirks
							  scrollHeight = document.body.scrollHeight;
							  bodyHeight = document.body.clientHeight;
						}
					 } else { // Safari & Opera
						scrollHeight = document.documentElement.scrollHeight;
						windowHeight = self.innerHeight;
						bodyHeight = document.documentElement.clientHeight;
					 }
				  
					 var h = [scrollHeight,windowHeight,bodyHeight].sort(function(a, b){return(a-b);});
					 return h[2];
				  },
				  
				  /**
				   * Returns the width of the document.
				   * @return {Int} The width of the actual document (which includes the body and its margin).
				   */
				  getDocumentWidth: function() {
					 var docWidth=-1,bodyWidth=-1,winWidth=-1;
					 var marginRight = parseInt(this.getStyle(document.body, 'marginRight'), 10);
					 var marginLeft = parseInt(this.getStyle(document.body, 'marginLeft'), 10);
					 
					 var mode = document.compatMode;
					 
					 if (mode || isIE) { // (IE, Gecko, Opera)
						switch (mode) {
						   case 'CSS1Compat': // Standards mode
							  docWidth = document.documentElement.clientWidth;
							  bodyWidth = document.body.offsetWidth + marginLeft + marginRight;
							  winWidth = self.innerWidth || -1;
							  break;
							  
						   default: // Quirks
							  bodyWidth = document.body.clientWidth;
							  winWidth = document.body.scrollWidth;
							  break;
						}
					 } else { // Safari
						docWidth = document.documentElement.clientWidth;
						bodyWidth = document.body.offsetWidth + marginLeft + marginRight;
						winWidth = self.innerWidth;
					 }
				  
					 var w = [docWidth,bodyWidth,winWidth].sort(function(a, b){return(a-b);});
					 return w[2];
				  },

				  /**
				   * Returns the current height of the viewport.
				   * @return {Int} The height of the viewable area of the page (excludes scrollbars).
				   */
				  getViewportHeight: function() {
					 var height = -1;
					 var mode = document.compatMode;
				  
					 if ( (mode || isIE) && !isOpera ) {
						switch (mode) { // (IE, Gecko)
						   case 'CSS1Compat': // Standards mode
							  height = document.documentElement.clientHeight;
							  break;
				  
						   default: // Quirks
							  height = document.body.clientHeight;
						}
					 } else { // Safari, Opera
						height = self.innerHeight;
					 }
				  
					 return height;
				  },
				  
				  /**
				   * Returns the current width of the viewport.
				   * @return {Int} The width of the viewable area of the page (excludes scrollbars).
				   */
				  
				  getViewportWidth: function() {
					 var width = -1;
					 var mode = document.compatMode;
					 
					 if (mode || isIE) { // (IE, Gecko, Opera)
						switch (mode) {
						case 'CSS1Compat': // Standards mode 
						   width = document.documentElement.clientWidth;
						   break;
						   
						default: // Quirks
						   width = document.body.clientWidth;
						}
					 } else { // Safari
						width = self.innerWidth;
					 }
					 
					 return width;
				  }
			   };
}();

/*
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
*/

/**
			 * @class A region is a representation of an object on a grid.  It is defined
			 * by the top, right, bottom, left extents, so is rectangular by default.  If 
			 * other shapes are required, this class could be extended to support it.
			 *
			 * @param {int} t the top extent
			 * @param {int} r the right extent
			 * @param {int} b the bottom extent
			 * @param {int} l the left extent
			 * @constructor
			 */
YAHOO.util.Region = function(t, r, b, l) {

				/**
				 * The region's top extent
				 * @type int
				 */
				this.top = t;
				
				/**
				 * The region's top extent as index, for symmetry with set/getXY
				 * @type int
				 */
				this[1] = t;

				/**
				 * The region's right extent
				 * @type int
				 */
				this.right = r;

				/**
				 * The region's bottom extent
				 * @type int
				 */
				this.bottom = b;

				/**
				 * The region's left extent
				 * @type int
				 */
				this.left = l;
				
				/**
				 * The region's left extent as index, for symmetry with set/getXY
				 * @type int
				 */
				this[0] = l;
};

/**
			 * Returns true if this region contains the region passed in
			 *
			 * @param  {Region}  region The region to evaluate
			 * @return {boolean}        True if the region is contained with this region, 
			 *                          else false
			 */
YAHOO.util.Region.prototype.contains = function(region) {
				return ( region.left   >= this.left   && 
						 region.right  <= this.right  && 
						 region.top    >= this.top    && 
						 region.bottom <= this.bottom    );

				// this.logger.debug("does " + this + " contain " + region + " ... " + ret);
};

/**
			 * Returns the area of the region
			 *
			 * @return {int} the region's area
			 */
YAHOO.util.Region.prototype.getArea = function() {
				return ( (this.bottom - this.top) * (this.right - this.left) );
};

/**
			 * Returns the region where the passed in region overlaps with this one
			 *
			 * @param  {Region} region The region that intersects
			 * @return {Region}        The overlap region, or null if there is no overlap
			 */
YAHOO.util.Region.prototype.intersect = function(region) {
				var t = Math.max( this.top,    region.top    );
				var r = Math.min( this.right,  region.right  );
				var b = Math.min( this.bottom, region.bottom );
				var l = Math.max( this.left,   region.left   );
				
				if (b >= t && r >= l) {
					return new YAHOO.util.Region(t, r, b, l);
				} else {
					return null;
				}
};

/**
			 * Returns the region representing the smallest region that can contain both
			 * the passed in region and this region.
			 *
			 * @param  {Region} region The region that to create the union with
			 * @return {Region}        The union region
			 */
YAHOO.util.Region.prototype.union = function(region) {
				var t = Math.min( this.top,    region.top    );
				var r = Math.max( this.right,  region.right  );
				var b = Math.max( this.bottom, region.bottom );
				var l = Math.min( this.left,   region.left   );

				return new YAHOO.util.Region(t, r, b, l);
};

/**
			 * toString
			 * @return string the region properties
			 */
YAHOO.util.Region.prototype.toString = function() {
				return ( "Region {" +
						 "t: "    + this.top    + 
						 ", r: "    + this.right  + 
						 ", b: "    + this.bottom + 
						 ", l: "    + this.left   + 
						 "}" );
};

/**
			 * Returns a region that is occupied by the DOM element
			 *
			 * @param  {HTMLElement} el The element
			 * @return {Region}         The region that the element occupies
			 * @static
			 */
YAHOO.util.Region.getRegion = function(el) {
				var p = YAHOO.util.Dom.getXY(el);

				var t = p[1];
				var r = p[0] + el.offsetWidth;
				var b = p[1] + el.offsetHeight;
				var l = p[0];

				return new YAHOO.util.Region(t, r, b, l);
};

/////////////////////////////////////////////////////////////////////////////


/**
			 * @class
			 *
			 * A point is a region that is special in that it represents a single point on 
			 * the grid.
			 *
			 * @param {int} x The X position of the point
			 * @param {int} y The Y position of the point
			 * @constructor
			 * @extends Region
			 */
YAHOO.util.Point = function(x, y) {
				/**
				 * The X position of the point
				 * @type int
				 */
				this.x      = x;

				/**
				 * The Y position of the point
				 * @type int
				 */
				this.y      = y;
				this.top    = y;
				this[1] = y;
				
				this.right  = x;
				this.bottom = y;
				this.left   = x;
				this[0] = x;
};

YAHOO.util.Point.prototype = new YAHOO.util.Region();

/*
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 0.10.0
*/
/**
* @class 
* Config is a utility used within an object to allow the implementer to maintain a list of local configuration properties and listen for changes to those properties dynamically using CustomEvent. The initial values are also maintained so that the configuration can be reset at any given point to its initial state.
* @param {object}	owner	The owner object to which this Config object belongs
* @constructor
*/
YAHOO.util.Config = function(owner) {
				if (owner) {
					this.init(owner);
				}
}

YAHOO.util.Config.prototype = {
				
				/**
				* Object reference to the owner of this Config object
				* @type object
				*/
				owner : null,

				/**
				* Object reference to the owner of this Config object
				* args: key, value
				* @type YAHOO.util.CustomEvent
				*/
				configChangedEvent : null,

				/**
				* Boolean flag that specifies whether a queue is currently being executed
				* @type boolean
				*/
				queueInProgress : false,

				/**
				* Adds a property to the Config object's private config hash. 
				* @param {string}	key	The configuration property's name
				* @param {object}	propertyObject	The object containing all of this property's arguments
				*/
				addProperty : function(key, propertyObject){},

				/**
				* Returns a key-value configuration map of the values currently set in the Config object.
				* @return {object} The current config, represented in a key-value map
				*/
				getConfig : function(){},

				/**
				* Returns the value of specified property.
				* @param {key}		The name of the property
				* @return {object}	The value of the specified property
				*/
				getProperty : function(key){},

				/**
				* Resets the specified property's value to its initial value.
				* @param {key}		The name of the property
				*/
				resetProperty : function(key){},

				/**
				* Sets the value of a property. If the silent property is passed as true, the property's event will not be fired.
				* @param {key}		The name of the property
				* @param {value}	The value to set the property to
				* @param {boolean}	Whether the value should be set silently, without firing the property event.
				* @return {boolean}	true, if the set was successful, false if it failed.
				*/
				setProperty : function(key,value,silent){},

				/**
				* Sets the value of a property and queues its event to execute. If the event is already scheduled to execute, it is
				* moved from its current position to the end of the queue.
				* @param {key}		The name of the property
				* @param {value}	The value to set the property to
				* @return {boolean}	true, if the set was successful, false if it failed.
				*/	
				queueProperty : function(key,value){},

				/**
				* Fires the event for a property using the property's current value.
				* @param {key}		The name of the property
				*/
				refireEvent : function(key){},

				/**
				* Applies a key-value object literal to the configuration, replacing any existing values, and queueing the property events.
				* Although the values will be set, fireQueue() must be called for their associated events to execute.
				* @param {object}	userConfig	The configuration object literal
				* @param {boolean}	init		When set to true, the initialConfig will be set to the userConfig passed in, so that calling a reset will reset the properties to the passed values.
				*/
				applyConfig : function(userConfig,init){},

				/**
				* Refires the events for all configuration properties using their current values.
				*/
				refresh : function(){},

				/**
				* Fires the normalized list of queued property change events
				*/
				fireQueue : function(){},

				/**
				* Subscribes an external handler to the change event for any given property. 
				* @param {string}	key			The property name
				* @param {Function}	handler		The handler function to use subscribe to the property's event
				* @param {object}	obj			The object to use for scoping the event handler (see CustomEvent documentation)
				* @param {boolean}	override	Optional. If true, will override "this" within the handler to map to the scope object passed into the method.
				*/	
				subscribeToConfigEvent : function(key,handler,obj,override){},

				/**
				* Unsubscribes an external handler from the change event for any given property. 
				* @param {string}	key			The property name
				* @param {Function}	handler		The handler function to use subscribe to the property's event
				* @param {object}	obj			The object to use for scoping the event handler (see CustomEvent documentation)
				*/
				unsubscribeFromConfigEvent: function(key,handler,obj){},

				/**
				* Validates that the value passed in is a boolean.
				* @param	{object}	val	The value to validate
				* @return	{boolean}	true, if the value is valid
				*/	
				checkBoolean: function(val) {
					if (typeof val == 'boolean') {
						return true;
					} else {
						return false;
					}
				},

				/**
				* Validates that the value passed in is a number.
				* @param	{object}	val	The value to validate
				* @return	{boolean}	true, if the value is valid
				*/
				checkNumber: function(val) {
					if (isNaN(val)) {
						return false;
					} else {
						return true;
					}
				}
}


/**
* Initializes the configuration object and all of its local members.
* @param {object}	owner	The owner object to which this Config object belongs
*/
YAHOO.util.Config.prototype.init = function(owner) {

				this.owner = owner;
				this.configChangedEvent = new YAHOO.util.CustomEvent("configChanged");
				this.queueInProgress = false;

				/* Private Members */

				var config = {};
				var initialConfig = {};
				var eventQueue = [];

				/**
				* @private
				* Fires a configuration property event using the specified value. 
				* @param {string}	key			The configuration property's name
				* @param {value}	object		The value of the correct type for the property
				*/ 
				var fireEvent = function( key, value ) {
					key = key.toLowerCase();

					var property = config[key];

					if (typeof property != 'undefined' && property.event) {
						property.event.fire(value);
					}	
				}
				/* End Private Members */

				this.addProperty = function( key, propertyObject ) {
					key = key.toLowerCase();

					config[key] = propertyObject;

					propertyObject.event = new YAHOO.util.CustomEvent(key);
					propertyObject.key = key;

					if (propertyObject.handler) {
						propertyObject.event.subscribe(propertyObject.handler, this.owner, true);
					}

					this.setProperty(key, propertyObject.value, true);
					
					if (! propertyObject.suppressEvent) {
						this.queueProperty(key, propertyObject.value);
					}
				}

				this.getConfig = function() {
					var cfg = {};
						
					for (var prop in config) {
						var property = config[prop]
						if (typeof property != 'undefined' && property.event) {
							cfg[prop] = property.value;
						}
					}
					
					return cfg;
				}

				this.getProperty = function(key) {
					key = key.toLowerCase();

					var property = config[key];
					if (typeof property != 'undefined' && property.event) {
						return property.value;
					} else {
						return undefined;
					}
				}


				this.resetProperty = function(key) {
					key = key.toLowerCase();

					var property = config[key];
					if (typeof property != 'undefined' && property.event) {
						this.setProperty(key, initialConfig[key].value);
					} else {
						return undefined;
					}
				}


				this.setProperty = function(key, value, silent) {
					key = key.toLowerCase();

					if (this.queueInProgress && ! silent) {
						this.queueProperty(key,value); // Currently running through a queue... 
						return true;
					} else {
						var property = config[key];
						if (typeof property != 'undefined' && property.event) {
							if (property.validator && ! property.validator(value)) { // validator
								return false;
							} else {
								property.value = value;
								if (! silent) {
									fireEvent(key, value);
									this.configChangedEvent.fire([key, value]);
								}
								return true;
							}
						} else {
							return false;
						}
					}
				}

				this.queueProperty = function(key, value) {
					key = key.toLowerCase();

					var property = config[key];
										
					if (typeof property != 'undefined' && property.event) {
						if (typeof value != 'undefined' && property.validator && ! property.validator(value)) { // validator
							return false;
						} else {

							if (typeof value != 'undefined') {
								property.value = value;
							} else {
								value = property.value;
							}

							var foundDuplicate = false;

							for (var i=0;i<eventQueue.length;i++) {
								var queueItem = eventQueue[i];

								if (queueItem) {
									var queueItemKey = queueItem[0];
									var queueItemValue = queueItem[1];
									
									if (queueItemKey.toLowerCase() == key) {
										// found a dupe... push to end of queue, null current item, and break
										eventQueue[i] = null;
										eventQueue.push([key, (typeof value != 'undefined' ? value : queueItemValue)]);
										foundDuplicate = true;
										break;
									}
								}
							}
							
							if (! foundDuplicate && typeof value != 'undefined') { // this is a refire, or a new property in the queue
								eventQueue.push([key, value]);
							}
						}

						if (property.supercedes) {
							for (var s=0;s<property.supercedes.length;s++) {
								var supercedesCheck = property.supercedes[s];

								for (var q=0;q<eventQueue.length;q++) {
									var queueItemCheck = eventQueue[q];

									if (queueItemCheck) {
										var queueItemCheckKey = queueItemCheck[0];
										var queueItemCheckValue = queueItemCheck[1];
										
										if ( queueItemCheckKey.toLowerCase() == supercedesCheck.toLowerCase() ) {
											eventQueue.push([queueItemCheckKey, queueItemCheckValue]);
											eventQueue[q] = null;
											break;
										}
									}
								}
							}
						}

						return true;
					} else {
						return false;
					}
				}

				this.refireEvent = function(key) {
					key = key.toLowerCase();

					var property = config[key];
					if (typeof property != 'undefined' && property.event && typeof property.value != 'undefined') {
						if (this.queueInProgress) {
							this.queueProperty(key);
						} else {
							fireEvent(key, property.value);
						}
					}
				}

				this.applyConfig = function(userConfig, init) {
					if (init) {
						initialConfig = userConfig;
					}
					for (var prop in userConfig) {
						this.queueProperty(prop, userConfig[prop]);
					}
				}

				this.refresh = function() {
					for (var prop in config) {
						this.refireEvent(prop);
					}
				}

				this.fireQueue = function() {
					this.queueInProgress = true;
					for (var i=0;i<eventQueue.length;i++) {
						var queueItem = eventQueue[i];
						if (queueItem) {
							var key = queueItem[0];
							var value = queueItem[1];
							
							var property = config[key];
							property.value = value;

							fireEvent(key,value);
						}
					}
					
					this.queueInProgress = false;
					eventQueue = new Array();
				}

				this.subscribeToConfigEvent = function(key, handler, obj, override) {
					key = key.toLowerCase();

					var property = config[key];
					if (typeof property != 'undefined' && property.event) {
						if (! YAHOO.util.Config.alreadySubscribed(property.event, handler, obj)) {
							property.event.subscribe(handler, obj, override);
						}
						return true;
					} else {
						return false;
					}
				}


				this.unsubscribeFromConfigEvent = function(key, handler, obj) {
					key = key.toLowerCase();

					var property = config[key];
					if (typeof property != 'undefined' && property.event) {
						return property.event.unsubscribe(handler, obj);
					} else {
						return false;
					}
				}

				// TODO: REMOVE
				this.outputEventQueue = function() {
					var output = "";
					for (var q=0;q<eventQueue.length;q++) {
						var queueItem = eventQueue[q];
						if (queueItem) {
							output += queueItem[0] + "=" + queueItem[1] + ", ";
						}
					}
					return output;
				}
}

/**
* Checks to determine if a particular function/object pair are already subscribed to the specified CustomEvent
* @param {YAHOO.util.CustomEvent} evt	The CustomEvent for which to check the subscriptions
* @param {Function}	fn	The function to look for in the subscribers list
* @param {object}	obj	The execution scope object for the subscription
* @return {boolean}	true, if the function/object pair is already subscribed to the CustomEvent passed in
*/
YAHOO.util.Config.alreadySubscribed = function(evt, fn, obj) {
				for (var e=0;e<evt.subscribers.length;e++) {
					var subsc = evt.subscribers[e];
					if (subsc && subsc.obj == obj && subsc.fn == fn) {
						return true;
						break;
					}
				}
				return false;
}/**
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
* @class 
* Module is a JavaScript representation of the Standard Module Format. Standard Module Format is a simple standard for markup containers where child nodes representing the header, body, and footer of the content are denoted using the CSS classes "hd", "bd", and "ft" respectively. Module is the base class for all other classes in the YUI Container package.
* @param {string}	el	The element ID representing the Module <em>OR</em>
* @param {Element}	el	The element representing the Module
* @param {object}	userConfig	The configuration object literal containing the configuration that should be set for this module. See configuration documentation for more details.
* @constructor
*/
YAHOO.widget.Module = function(el, userConfig) {
				if (el) { 
					this.init(el, userConfig); 
				}
}

/**
* Constant representing the prefix path to use for non-secure images
* @type string
*/
YAHOO.widget.Module.IMG_ROOT = "http://us.i1.yimg.com/us.yimg.com/i/";

/**
* Constant representing the prefix path to use for securely served images
* @type string
*/
YAHOO.widget.Module.IMG_ROOT_SSL = "https://a248.e.akamai.net/sec.yimg.com/i/";

/**
* Constant for the default CSS class name that represents a Module
* @type string
* @final
*/
YAHOO.widget.Module.CSS_MODULE = "module";

/**
* Constant representing the module header
* @type string
* @final
*/
YAHOO.widget.Module.CSS_HEADER = "hd";

/**
* Constant representing the module body
* @type string
* @final
*/
YAHOO.widget.Module.CSS_BODY   = "bd";

/**
* Constant representing the module footer
* @type string
* @final
*/
YAHOO.widget.Module.CSS_FOOTER = "ft";

YAHOO.widget.Module.prototype = {

				/**
				* The class's constructor function
				* @type function
				*/
				constructor : YAHOO.widget.Module,

				/**
				* The main module element that contains the header, body, and footer
				* @type Element
				*/
				element : null, 

				/**
				* The header element, denoted with CSS class "hd"
				* @type Element
				*/
				header : null,

				/**
				* The body element, denoted with CSS class "bd"
				* @type Element
				*/
				body : null,

				/**
				* The footer element, denoted with CSS class "ft"
				* @type Element
				*/
				footer : null,

				/**
				* The id of the element
				* @type string
				*/
				id : null,

				/**
				* Array of elements
				* @type Element[]
				*/
				childNodesInDOM : null,

				/**
				* The string representing the image root
				* @type string
				*/
				imageRoot : YAHOO.widget.Module.IMG_ROOT,

				/**
				* CustomEvent fired prior to class initalization.
				* args: class reference of the initializing class, such as this.beforeInitEvent.fire(YAHOO.widget.Module)
				* @type YAHOO.util.CustomEvent
				*/
				beforeInitEvent : null,

				/**
				* CustomEvent fired after class initalization.
				* args: class reference of the initializing class, such as this.initEvent.fire(YAHOO.widget.Module)
				* @type YAHOO.util.CustomEvent
				*/
				initEvent : null,

				/**
				* CustomEvent fired when the Module is appended to the DOM
				* args: none
				* @type YAHOO.util.CustomEvent
				*/
				appendEvent : null,

				/**
				* CustomEvent fired before the Module is rendered
				* args: none
				* @type YAHOO.util.CustomEvent
				*/
				beforeRenderEvent : null,

				/**
				* CustomEvent fired after the Module is rendered
				* args: none
				* @type YAHOO.util.CustomEvent
				*/
				renderEvent : null,

				/**
				* CustomEvent fired when the header content of the Module is modified
				* args: string/element representing the new header content
				* @type YAHOO.util.CustomEvent
				*/
				changeHeaderEvent : null,

				/**
				* CustomEvent fired when the body content of the Module is modified
				* args: string/element representing the new body content
				* @type YAHOO.util.CustomEvent
				*/
				changeBodyEvent : null,

				/**
				* CustomEvent fired when the footer content of the Module is modified
				* args: string/element representing the new footer content
				* @type YAHOO.util.CustomEvent
				*/
				changeFooterEvent : null,

				/**
				* CustomEvent fired when the content of the Module is modified
				* args: none
				* @type YAHOO.util.CustomEvent
				*/
				changeContentEvent : null,

				/**
				* CustomEvent fired when the Module is destroyed
				* args: none
				* @type YAHOO.util.CustomEvent
				*/
				destroyEvent : null,

				/**
				* CustomEvent fired before the Module is shown
				* args: none
				* @type YAHOO.util.CustomEvent
				*/
				beforeShowEvent : null,

				/**
				* CustomEvent fired after the Module is shown
				* args: none
				* @type YAHOO.util.CustomEvent
				*/
				showEvent : null,

				/**
				* CustomEvent fired before the Module is hidden
				* args: none
				* @type YAHOO.util.CustomEvent
				*/
				beforeHideEvent : null,
				
				/**
				* CustomEvent fired after the Module is hidden
				* args: none
				* @type YAHOO.util.CustomEvent
				*/
				hideEvent : null,
					
				/**
				* Initializes the custom events for Module which are fired automatically at appropriate times by the Module class.
				*/
				initEvents : function() {

					this.beforeInitEvent		= new YAHOO.util.CustomEvent("beforeInit");
					this.initEvent				= new YAHOO.util.CustomEvent("init");

					this.appendEvent			= new YAHOO.util.CustomEvent("append");

					this.beforeRenderEvent		= new YAHOO.util.CustomEvent("beforeRender");
					this.renderEvent			= new YAHOO.util.CustomEvent("render");

					this.changeHeaderEvent		= new YAHOO.util.CustomEvent("changeHeader");
					this.changeBodyEvent		= new YAHOO.util.CustomEvent("changeBody");
					this.changeFooterEvent		= new YAHOO.util.CustomEvent("changeFooter");

					this.changeContentEvent		= new YAHOO.util.CustomEvent("changeContent");

					this.destroyEvent			= new YAHOO.util.CustomEvent("destroy");
					this.beforeShowEvent		= new YAHOO.util.CustomEvent("beforeShow");
					this.showEvent				= new YAHOO.util.CustomEvent("show");
					this.beforeHideEvent		= new YAHOO.util.CustomEvent("beforeHide");
					this.hideEvent				= new YAHOO.util.CustomEvent("hide");
				}, 

				/**
				* String representing the current user-agent platform
				* @type string
				*/
				platform : function() {
								var ua = navigator.userAgent.toLowerCase();
								if (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1) {
									return "windows";
								} else if (ua.indexOf("macintosh") != -1) {
									return "mac";
								} else {
									return false;
								}
							}(),

				/**
				* String representing the current user-agent browser
				* @type string
				*/
				browser : function() {
						var ua = navigator.userAgent.toLowerCase();
							  if (ua.indexOf('opera')!=-1) { // Opera (check first in case of spoof)
								 return 'opera';
							  } else if (ua.indexOf('msie 7')!=-1) { // IE7
								 return 'ie7';
							  } else if (ua.indexOf('msie') !=-1) { // IE
								 return 'ie';
							  } else if (ua.indexOf('safari')!=-1) { // Safari (check before Gecko because it includes "like Gecko")
								 return 'safari';
							  } else if (ua.indexOf('gecko') != -1) { // Gecko
								 return 'gecko';
							  } else {
								 return false;
							  }
						}(),

				/**
				* Boolean representing whether or not the current browsing context is secure (https)
				* @type boolean
				*/
				isSecure : function() {
					if (window.location.href.toLowerCase().indexOf("https") == 0) {
						this.imageRoot = YAHOO.widget.Module.IMG_ROOT_SSL;
						return true;
					} else {
						return false;
					}
				}(),

				/**
				* Initializes the custom events for Module which are fired automatically at appropriate times by the Module class.
				*/
				initDefaultConfig : function() {
					// Add properties //

					this.cfg.addProperty("visible", { value:true, handler:this.configVisible, validator:this.cfg.checkBoolean } );
					this.cfg.addProperty("effect", { suppressEvent:true, supercedes:["visible"] } );
					this.cfg.addProperty("monitorresize", { value:true, handler:this.configMonitorResize } );
				},

				/**
				* The Module class's initialization method, which is executed for Module and all of its subclasses. This method is automatically called by the constructor, and  sets up all DOM references for pre-existing markup, and creates required markup if it is not already present.
				* @param {string}	el	The element ID representing the Module <em>OR</em>
				* @param {Element}	el	The element representing the Module
				* @param {object}	userConfig	The configuration object literal containing the configuration that should be set for this module. See configuration documentation for more details.
				*/
				init : function(el, userConfig) {

					this.initEvents();

					this.beforeInitEvent.fire(YAHOO.widget.Module);

					this.cfg = new YAHOO.util.Config(this);
					
					if (typeof el == "string") {
						var elId = el;

						el = document.getElementById(el);
						if (! el) {
							el = document.createElement("DIV");
							el.id = elId;
						}
					}

					this.element = el;
					
					if (el.id) {
						this.id = el.id;
					} 

					var childNodes = this.element.childNodes;

					if (childNodes) {
						for (var i=0;i<childNodes.length;i++) {
							var child = childNodes[i];
							switch (child.className) {
								case YAHOO.widget.Module.CSS_HEADER:
									this.header = child;
									break;
								case YAHOO.widget.Module.CSS_BODY:
									this.body = child;
									break;
								case YAHOO.widget.Module.CSS_FOOTER:
									this.footer = child;
									break;
							}
						}
					}

					this.initDefaultConfig();

					YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Module.CSS_MODULE);

					if (userConfig) {
						this.cfg.applyConfig(userConfig, true);
					}

					// Subscribe to the fireQueue() method of Config so that any queued configuration changes are
					// excecuted upon render of the Module
					if (! YAHOO.util.Config.alreadySubscribed(this.renderEvent, this.cfg.fireQueue, this.cfg)) {
						this.renderEvent.subscribe(this.cfg.fireQueue, this.cfg, true);
					}

					this.initEvent.fire(YAHOO.widget.Module);
				},

				/**
				* Initialized an empty DOM element that is placed out of the visible area that can be used to detect text resize.
				*/
				initResizeMonitor : function() {
					var resizeMonitor = document.getElementById("_yuiResizeMonitor");
					if (! resizeMonitor) {
						resizeMonitor = document.createElement("DIV");
						resizeMonitor.style.position = "absolute";
						resizeMonitor.id = "_yuiResizeMonitor";
						resizeMonitor.style.width = "1em";
						resizeMonitor.style.height = "1em";
						resizeMonitor.style.top = "-1000px";
						resizeMonitor.style.left = "-1000px";
						resizeMonitor.innerHTML = "&nbsp;";
						document.body.appendChild(resizeMonitor);
					}
					this.resizeMonitor = resizeMonitor;
					YAHOO.util.Event.addListener(this.resizeMonitor, "resize", this.onDomResize, this, true);
				},

				/**
				* Event handler fired when the resize monitor element is resized.
				*/
				onDomResize : function(e, obj) { },

				/**
				* Sets the Module's header content to the HTML specified, or appends the passed element to the header. If no header is present, one will be automatically created.
				* @param {string}	headerContent	The HTML used to set the header <em>OR</em>
				* @param {Element}	headerContent	The Element to append to the header
				*/	
				setHeader : function(headerContent) {
					if (! this.header) {
						this.header = document.createElement("DIV");
						this.header.className = YAHOO.widget.Module.CSS_HEADER;
					}
					
					if (typeof headerContent == "string") {
						this.header.innerHTML = headerContent;
					} else {
						this.header.innerHTML = "";
						this.header.appendChild(headerContent);
					}

					this.changeHeaderEvent.fire(headerContent);
					this.changeContentEvent.fire();
				},

				/**
				* Appends the passed element to the header. If no header is present, one will be automatically created.
				* @param {Element}	element	The element to append to the header
				*/	
				appendToHeader : function(element) {
					if (! this.header) {
						this.header = document.createElement("DIV");
						this.header.className = YAHOO.widget.Module.CSS_HEADER;
					}
					
					this.header.appendChild(element);
					this.changeHeaderEvent.fire(element);
					this.changeContentEvent.fire();
				},

				/**
				* Sets the Module's body content to the HTML specified, or appends the passed element to the body. If no body is present, one will be automatically created.
				* @param {string}	bodyContent	The HTML used to set the body <em>OR</em>
				* @param {Element}	bodyContent	The Element to append to the body
				*/		
				setBody : function(bodyContent) {
					if (! this.body) {
						this.body = document.createElement("DIV");
						this.body.className = YAHOO.widget.Module.CSS_BODY;
					}

					if (typeof bodyContent == "string")
					{
						this.body.innerHTML = bodyContent;
					} else {
						this.body.innerHTML = "";
						this.body.appendChild(bodyContent);
					}

					this.changeBodyEvent.fire(bodyContent);
					this.changeContentEvent.fire();
				},

				/**
				* Appends the passed element to the body. If no body is present, one will be automatically created.
				* @param {Element}	element	The element to append to the body
				*/
				appendToBody : function(element) {
					if (! this.body) {
						this.body = document.createElement("DIV");
						this.body.className = YAHOO.widget.Module.CSS_BODY;
					}

					this.body.appendChild(element);
					this.changeBodyEvent.fire(element);
					this.changeContentEvent.fire();
				},

				/**
				* Sets the Module's footer content to the HTML specified, or appends the passed element to the footer. If no footer is present, one will be automatically created.
				* @param {string}	footerContent	The HTML used to set the footer <em>OR</em>
				* @param {Element}	footerContent	The Element to append to the footer
				*/	
				setFooter : function(footerContent) {
					if (! this.footer) {
						this.footer = document.createElement("DIV");
						this.footer.className = YAHOO.widget.Module.CSS_FOOTER;
					}

					if (typeof footerContent == "string") {
						this.footer.innerHTML = footerContent;
					} else {
						this.footer.innerHTML = "";
						this.footer.appendChild(footerContent);
					}

					this.changeFooterEvent.fire(footerContent);
					this.changeContentEvent.fire();
				},

				/**
				* Appends the passed element to the footer. If no footer is present, one will be automatically created.
				* @param {Element}	element	The element to append to the footer
				*/
				appendToFooter : function(element) {
					if (! this.footer) {
						this.footer = document.createElement("DIV");
						this.footer.className = YAHOO.widget.Module.CSS_FOOTER;
					}

					this.footer.appendChild(element);
					this.changeFooterEvent.fire(element);
					this.changeContentEvent.fire();
				},

				/**
				* Renders the Module by inserting the elements that are not already in the main Module into their correct places. Optionally appends the Module to the specified node prior to the render's execution. NOTE: For Modules without existing markup, the appendToNode argument is REQUIRED. If this argument is ommitted and the current element is not present in the document, the function will return false, indicating that the render was a failure.
				* @param {string}	appendToNode	The element id to which the Module should be appended to prior to rendering <em>OR</em>
				* @param {Element}	appendToNode	The element to which the Module should be appended to prior to rendering	
				* @param {Element}	moduleElement	OPTIONAL. The element that represents the actual Standard Module container. 
				* @return {boolean} Success or failure of the render
				*/
				render : function(appendToNode, moduleElement) {
					this.beforeRenderEvent.fire();

					if (! moduleElement) {
						moduleElement = this.element;
					}

					var me = this;
					var appendTo = function(element) {
						if (typeof element == "string") {
							element = document.getElementById(element);
						}
						
						if (element) {
							element.appendChild(me.element);
							me.appendEvent.fire();
						}
					}

					if (appendToNode) {
						appendTo(appendToNode);
					} else { // No node was passed in. If the element is not pre-marked up, this fails
						if (! YAHOO.util.Dom.inDocument(this.element)) {
							return false;
						}
					}

					// Need to get everything into the DOM if it isn't already
					
					if (this.header && ! YAHOO.util.Dom.inDocument(this.header)) {
						// There is a header, but it's not in the DOM yet... need to add it
						var firstChild = moduleElement.firstChild;
						if (firstChild) { // Insert before first child if exists
							moduleElement.insertBefore(this.header, firstChild);
						} else { // Append to empty body because there are no children
							moduleElement.appendChild(this.header);
						}
					}

					if (this.body && ! YAHOO.util.Dom.inDocument(this.body)) {
						// There is a body, but it's not in the DOM yet... need to add it
						if (this.footer && YAHOO.util.Dom.isAncestor(this.moduleElement, this.footer)) { // Insert before footer if exists in DOM
							moduleElement.insertBefore(this.body, this.footer);
						} else { // Append to element because there is no footer
							moduleElement.appendChild(this.body);
						}
					}

					if (this.footer && ! YAHOO.util.Dom.inDocument(this.footer)) {
						// There is a footer, but it's not in the DOM yet... need to add it
						moduleElement.appendChild(this.footer);
					}

					this.renderEvent.fire();
					return true;
				},

				/**
				* Removes the Module element from the DOM and sets all child elements to null.
				*/
				destroy : function() {
					if (this.element) {
						var parent = this.element.parentNode;
					}
					if (parent) {
						parent.removeChild(this.element);
					}

					this.element = null;
					this.header = null;
					this.body = null;
					this.footer = null;

					this.destroyEvent.fire();
				},

				/**
				* Shows the Module element by setting the visible configuration property to true. Also fires two events: beforeShowEvent prior to the visibility change, and showEvent after.
				*/
				show : function() {
					this.cfg.setProperty("visible", true);
				},

				/**
				* Hides the Module element by setting the visible configuration property to false. Also fires two events: beforeHideEvent prior to the visibility change, and hideEvent after.
				*/
				hide : function() {
					this.cfg.setProperty("visible", false);
				},

				// BUILT-IN EVENT HANDLERS FOR MODULE //

				/**
				* Default event handler for changing the visibility property of a Module. By default, this is achieved by switching the "display" style between "block" and "none".
				* This method is responsible for firing showEvent and hideEvent.
				*/
				configVisible : function(type, args, obj) {
					var visible = args[0];
					if (visible) {
						this.beforeShowEvent.fire();
						YAHOO.util.Dom.setStyle(this.element, "display", "block");
						this.showEvent.fire();
					} else {
						this.beforeHideEvent.fire();
						YAHOO.util.Dom.setStyle(this.element, "display", "none");
						this.hideEvent.fire();
					}
				},

				/**
				* Default event handler for the "monitorresize" configuration property
				*/
				configMonitorResize : function(type, args, obj) {
					var monitor = args[0];
					if (monitor) {
						this.initResizeMonitor();
					} else {
						YAHOO.util.Event.removeListener(this.resizeMonitor, "resize", this.onDomResize);
						this.resizeMonitor = null;
					}
				}
}
/**
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
* @class Overlay is a Module that is absolutely positioned above the page flow. It has convenience methods for positioning and sizing, as well as options for controlling zIndex and constraining the Overlay's position to the current visible viewport. Overlay also contains a dynamicly generated IFRAME which is placed beneath it for Internet Explorer 6 and 5.x so that it will be properly rendered above SELECT elements.
* @param {string}	el	The element ID representing the Overlay <em>OR</em>
* @param {Element}	el	The element representing the Overlay
* @param {object}	userConfig	The configuration object literal containing the configuration that should be set for this Overlay. See configuration documentation for more details.
* @constructor
*/
YAHOO.widget.Overlay = function(el, userConfig) {
				if (arguments.length > 0) {
					YAHOO.widget.Overlay.superclass.constructor.call(this, el, userConfig);
				}
}

YAHOO.widget.Overlay.prototype = new YAHOO.widget.Module();
YAHOO.widget.Overlay.prototype.constructor = YAHOO.widget.Overlay;

/**
* Reference to the Overlay's superclass, Module
* @type class
* @final
*/
YAHOO.widget.Overlay.superclass = YAHOO.widget.Module.prototype;

/**
* The URL of the blank image that will be placed in the iframe
* @type string
* @final
*/
YAHOO.widget.Overlay.IFRAME_SRC = "promo/m/irs/blank.gif";

/**
* Constant representing the top left corner of an element, used for configuring the context element alignment
* @type string
* @final
*/
YAHOO.widget.Overlay.TOP_LEFT = "tl";

/**
* Constant representing the top right corner of an element, used for configuring the context element alignment
* @type string
* @final
*/
YAHOO.widget.Overlay.TOP_RIGHT = "tr";

/**
* Constant representing the top bottom left corner of an element, used for configuring the context element alignment
* @type string
* @final
*/
YAHOO.widget.Overlay.BOTTOM_LEFT = "bl";

/**
* Constant representing the bottom right corner of an element, used for configuring the context element alignment
* @type string
* @final
*/
YAHOO.widget.Overlay.BOTTOM_RIGHT = "br";

/**
* Constant representing the default CSS class used for an Overlay
* @type string
* @final
*/
YAHOO.widget.Overlay.CSS_OVERLAY = "overlay";

/**
* CustomEvent fired before the Overlay is moved.
* args: x,y that the Overlay will be moved to
* @type YAHOO.util.CustomEvent
*/
YAHOO.widget.Overlay.prototype.beforeMoveEvent = null;

/**
* CustomEvent fired after the Overlay is moved.
* args: x,y that the Overlay was moved to
* @type YAHOO.util.CustomEvent
*/
YAHOO.widget.Overlay.prototype.moveEvent = null;

/*
* The Overlay initialization method, which is executed for Overlay and all of its subclasses. This method is automatically called by the constructor, and  sets up all DOM references for pre-existing markup, and creates required markup if it is not already present.
* @param {string}	el	The element ID representing the Overlay <em>OR</em>
* @param {Element}	el	The element representing the Overlay
* @param {object}	userConfig	The configuration object literal containing the configuration that should be set for this Overlay. See configuration documentation for more details.
*/
YAHOO.widget.Overlay.prototype.init = function(el, userConfig) {
				YAHOO.widget.Overlay.superclass.init.call(this, el/*, userConfig*/);  // Note that we don't pass the user config in here yet because we only want it executed once, at the lowest subclass level
				
				this.beforeInitEvent.fire(YAHOO.widget.Overlay);

				YAHOO.util.Dom.addClass(this.element, YAHOO.widget.Overlay.CSS_OVERLAY);

				if (userConfig) {
					this.cfg.applyConfig(userConfig, true);
				}

				if (this.platform == "mac" && this.browser == "gecko") {
					if (! YAHOO.util.Config.alreadySubscribed(this.showEvent,this.showMacGeckoScrollbars,this)) {
						this.showEvent.subscribe(this.showMacGeckoScrollbars,this,true);
					}
					if (! YAHOO.util.Config.alreadySubscribed(this.hideEvent,this.hideMacGeckoScrollbars,this)) {
						this.hideEvent.subscribe(this.hideMacGeckoScrollbars,this,true);
					}
				}

				this.initEvent.fire(YAHOO.widget.Overlay);

}

/**
* Initializes the custom events for Overlay which are fired automatically at appropriate times by the Overlay class.
*/
YAHOO.widget.Overlay.prototype.initEvents = function() {
				YAHOO.widget.Overlay.superclass.initEvents.call(this);

				this.beforeMoveEvent = new YAHOO.util.CustomEvent("beforeMove", this);
				this.moveEvent = new YAHOO.util.CustomEvent("move", this);
}

/**
* Initializes the class's configurable properties which can be changed using the Overlay's Config object (cfg).
*/
YAHOO.widget.Overlay.prototype.initDefaultConfig = function() {
				YAHOO.widget.Overlay.superclass.initDefaultConfig.call(this);

				// Add overlay config properties //
				this.cfg.addProperty("x", { handler:this.configX, validator:this.cfg.checkNumber, suppressEvent:true, supercedes:["iframe"] } );
				this.cfg.addProperty("y", { handler:this.configY, validator:this.cfg.checkNumber, suppressEvent:true, supercedes:["iframe"] } );
				this.cfg.addProperty("xy",{ handler:this.configXY, suppressEvent:true, supercedes:["iframe"] } );

				this.cfg.addProperty("context",	{ handler:this.configContext, suppressEvent:true, supercedes:["iframe"] } );
				this.cfg.addProperty("fixedcenter", { value:false, handler:this.configFixedCenter, validator:this.cfg.checkBoolean, supercedes:["iframe","visible"] } );

				this.cfg.addProperty("width", { handler:this.configWidth, suppressEvent:true, supercedes:["iframe"] } );
				this.cfg.addProperty("height", { handler:this.configHeight, suppressEvent:true, supercedes:["iframe"] } );

				this.cfg.addProperty("zIndex", { value:null, handler:this.configzIndex } );

				this.cfg.addProperty("constraintoviewport", { value:false, handler:this.configConstrainToViewport, validator:this.cfg.checkBoolean, supercedes:["iframe","x","y","xy"] } );
				this.cfg.addProperty("iframe", { value:(this.browser == "ie" ? true : false), handler:this.configIframe, validator:this.cfg.checkBoolean, supercedes:["zIndex"] } );
}

/**
* Moves the Overlay to the specified position. This function is identical to calling this.cfg.setProperty("xy", [x,y]);
* @param {int}	x	The Overlay's new x position
* @param {int}	y	The Overlay's new y position
*/
YAHOO.widget.Overlay.prototype.moveTo = function(x, y) {
				this.cfg.setProperty("xy",[x,y]);
}

/**
* Adds a special CSS class to the Overlay when Mac/Gecko is in use, to work around a Gecko bug where
* scrollbars cannot be hidden. See https://bugzilla.mozilla.org/show_bug.cgi?id=187435
*/
YAHOO.widget.Overlay.prototype.hideMacGeckoScrollbars = function() {
				YAHOO.util.Dom.removeClass(this.element, "show-scrollbars");
				YAHOO.util.Dom.addClass(this.element, "hide-scrollbars");
}

/**
* Removes a special CSS class from the Overlay when Mac/Gecko is in use, to work around a Gecko bug where
* scrollbars cannot be hidden. See https://bugzilla.mozilla.org/show_bug.cgi?id=187435
*/
YAHOO.widget.Overlay.prototype.showMacGeckoScrollbars = function() {
				YAHOO.util.Dom.removeClass(this.element, "hide-scrollbars");
				YAHOO.util.Dom.addClass(this.element, "show-scrollbars");
}

// BEGIN BUILT-IN PROPERTY EVENT HANDLERS //

/**
* The default event handler fired when the "visible" property is changed. This method is responsible for firing showEvent and hideEvent.
*/
YAHOO.widget.Overlay.prototype.configVisible = function(type, args, obj) {
				var visible = args[0];
				var currentVis = YAHOO.util.Dom.getStyle(this.element, "visibility");

				var effect = this.cfg.getProperty("effect");

				var effectInstances = new Array();
				if (effect) {
					if (effect instanceof Array) {
						for (var i=0;i<effect.length;i++) {
							var eff = effect[i];
							effectInstances[effectInstances.length] = eff.effect(this, eff.duration);
						}
					} else {
						effectInstances[effectInstances.length] = effect.effect(this, effect.duration);
					}
				}

				var isMacGecko = (this.platform == "mac" && this.browser == "gecko");

				if (visible) { // Show
					if (isMacGecko) {
						this.showMacGeckoScrollbars();
					}	

					if (effect) { // Animate in
						if (visible) { // Animate in if not showing
							if (currentVis != "visible") {
								this.beforeShowEvent.fire();
								for (var i=0;i<effectInstances.length;i++) {
									var e = effectInstances[i];
									if (i == 0 && ! YAHOO.util.Config.alreadySubscribed(e.animateInCompleteEvent,this.showEvent.fire,this.showEvent)) {
										e.animateInCompleteEvent.subscribe(this.showEvent.fire,this.showEvent,true); // Delegate showEvent until end of animateInComplete
									}
									e.animateIn();
								}
							}
						}
					} else { // Show
						if (currentVis != "visible") {
							this.beforeShowEvent.fire();
							YAHOO.util.Dom.setStyle(this.element, "visibility", "visible");
							this.cfg.refireEvent("iframe");
							this.showEvent.fire();
						}
					}

				} else { // Hide
					if (isMacGecko) {
						this.hideMacGeckoScrollbars();
					}	

					if (effect) { // Animate out if showing
						if (currentVis != "hidden") {
							this.beforeHideEvent.fire();
							for (var i=0;i<effectInstances.length;i++) {
								var e = effectInstances[i];
								if (i == 0 && ! YAHOO.util.Config.alreadySubscribed(e.animateOutCompleteEvent,this.hideEvent.fire,this.hideEvent)) {				
									e.animateOutCompleteEvent.subscribe(this.hideEvent.fire,this.hideEvent,true); // Delegate hideEvent until end of animateOutComplete
								}
								e.animateOut();
							}
						}
					} else { // Simple hide
						if (currentVis != "hidden") {
							this.beforeHideEvent.fire();
							YAHOO.util.Dom.setStyle(this.element, "visibility", "hidden");
							this.cfg.refireEvent("iframe");
							this.hideEvent.fire();
						}
					}	
				}
}

/**
* Center event handler used for centering on scroll/resize, but only if the Overlay is visible
*/
YAHOO.widget.Overlay.prototype.doCenterOnDOMEvent = function() {
				if (this.cfg.getProperty("visible")) {
					this.center();
				}
}

/**
* The default event handler fired when the "fixedcenter" property is changed.
*/
YAHOO.widget.Overlay.prototype.configFixedCenter = function(type, args, obj) {
				var val = args[0];

				if (val) {
					this.center();
						
					if (! YAHOO.util.Config.alreadySubscribed(this.beforeShowEvent, this.center, this)) {
						this.beforeShowEvent.subscribe(this.center, this, true);
					}
					
					if (! YAHOO.util.Config.alreadySubscribed(YAHOO.widget.Overlay.windowResizeEvent, this.doCenterOnDOMEvent, this)) {
						YAHOO.widget.Overlay.windowResizeEvent.subscribe(this.doCenterOnDOMEvent, this, true);
					}

					if (! YAHOO.util.Config.alreadySubscribed(YAHOO.widget.Overlay.windowScrollEvent, this.doCenterOnDOMEvent, this)) {
						YAHOO.widget.Overlay.windowScrollEvent.subscribe( this.doCenterOnDOMEvent, this, true);
					}
				} else {
					YAHOO.widget.Overlay.windowResizeEvent.unsubscribe(this.doCenterOnDOMEvent, this);
					YAHOO.widget.Overlay.windowScrollEvent.unsubscribe(this.doCenterOnDOMEvent, this);
				}
}

/**
* The default event handler fired when the "height" property is changed.
*/
YAHOO.widget.Overlay.prototype.configHeight = function(type, args, obj) {
				var height = args[0];
				var el = this.element;
				YAHOO.util.Dom.setStyle(el, "height", height);
				this.cfg.refireEvent("iframe");
}

/**
* The default event handler fired when the "width" property is changed.
*/
YAHOO.widget.Overlay.prototype.configWidth = function(type, args, obj) {
				var width = args[0];
				var el = this.element;
				YAHOO.util.Dom.setStyle(el, "width", width);
				this.cfg.refireEvent("iframe");
}

/**
* The default event handler fired when the "zIndex" property is changed.
*/
YAHOO.widget.Overlay.prototype.configzIndex = function(type, args, obj) {
				var zIndex = args[0];

				var el = this.element;

				if (! zIndex) {
					zIndex = YAHOO.util.Dom.getStyle(el, "zIndex");
					if (! zIndex || isNaN(zIndex)) {
						zIndex = 0;
					}
				}

				if (this.iframe) {
					if (zIndex <= 0) {
						zIndex = 1;
					}
					YAHOO.util.Dom.setStyle(this.iframe, "zIndex", (zIndex-1));
				}

				YAHOO.util.Dom.setStyle(el, "zIndex", zIndex);
				this.cfg.setProperty("zIndex", zIndex, true);
}

/**
* The default event handler fired when the "xy" property is changed.
*/
YAHOO.widget.Overlay.prototype.configXY = function(type, args, obj) {
				var pos = args[0];
				var x = pos[0];
				var y = pos[1];

				this.cfg.setProperty("x", x);
				this.cfg.setProperty("y", y);

				this.beforeMoveEvent.fire([x,y]);

				x = this.cfg.getProperty("x");
				y = this.cfg.getProperty("y");

				this.cfg.refireEvent("iframe");
				this.moveEvent.fire([x,y]);
}

/**
* The default event handler fired when the "x" property is changed.
*/
YAHOO.widget.Overlay.prototype.configX = function(type, args, obj) {
				var x = args[0];
				var y = this.cfg.getProperty("y");

				this.cfg.setProperty("x", x, true);
				this.cfg.setProperty("y", y, true);

				this.beforeMoveEvent.fire([x,y]);

				x = this.cfg.getProperty("x");
				y = this.cfg.getProperty("y");

				YAHOO.util.Dom.setX(this.element, x, true);
				
				this.cfg.setProperty("xy", [x, y], true);

				this.cfg.refireEvent("iframe");
				this.moveEvent.fire([x, y]);
}

/**
* The default event handler fired when the "y" property is changed.
*/
YAHOO.widget.Overlay.prototype.configY = function(type, args, obj) {
				var x = this.cfg.getProperty("x");
				var y = args[0];

				this.cfg.setProperty("x", x, true);
				this.cfg.setProperty("y", y, true);

				this.beforeMoveEvent.fire([x,y]);

				x = this.cfg.getProperty("x");
				y = this.cfg.getProperty("y");

				YAHOO.util.Dom.setY(this.element, y, true);

				this.cfg.setProperty("xy", [x, y], true);

				this.cfg.refireEvent("iframe");
				this.moveEvent.fire([x, y]);
}

/**
* The default event handler fired when the "iframe" property is changed.
*/
YAHOO.widget.Overlay.prototype.configIframe = function(type, args, obj) {
				var val = args[0];

				var el = this.element;

				if (val) {
					var x = this.cfg.getProperty("x");
					var y = this.cfg.getProperty("y");

					if (! x || ! y) {
						this.syncPosition();
						x = this.cfg.getProperty("x");
						y = this.cfg.getProperty("y");
					}

					if (! isNaN(x) && ! isNaN(y)) {
						if (! this.iframe) {
							this.iframe = document.createElement("iframe");
							
							var parent = el.parentNode;
							if (parent) {
								parent.appendChild(this.iframe);
							} else {
								document.body.appendChild(this.iframe);
							}

							this.iframe.src = this.imageRoot + YAHOO.widget.Overlay.IFRAME_SRC;
							YAHOO.util.Dom.setStyle(this.iframe, "position", "absolute");
							YAHOO.util.Dom.setStyle(this.iframe, "border", "none");
							YAHOO.util.Dom.setStyle(this.iframe, "margin", "0");
							YAHOO.util.Dom.setStyle(this.iframe, "padding", "0");
							YAHOO.util.Dom.setStyle(this.iframe, "opacity", "0");
						}

						YAHOO.util.Dom.setStyle(this.iframe, "left", x-2 + "px");
						YAHOO.util.Dom.setStyle(this.iframe, "top", y-2 + "px");

						var width = el.clientWidth;
						var height = el.clientHeight;

						YAHOO.util.Dom.setStyle(this.iframe, "width", (width+2) + "px");
						YAHOO.util.Dom.setStyle(this.iframe, "height", (height+2) + "px");

						if (! this.cfg.getProperty("visible")) {
							this.iframe.style.display = "none";
						} else {
							this.iframe.style.display = "block";
						}
					}
				} else {
					if (this.iframe) {
						this.iframe.style.display = "none";
					}
				}
}

/**
* The default event handler fired when the "constraintoviewport" property is changed.
*/
YAHOO.widget.Overlay.prototype.configConstrainToViewport = function(type, args, obj) {
				var val = args[0];
				if (val) {
					if (! YAHOO.util.Config.alreadySubscribed(this.beforeMoveEvent, this.enforceConstraints, this)) {
						this.beforeMoveEvent.subscribe(this.enforceConstraints, this, true);
					}
				} else {
					this.beforeMoveEvent.unsubscribe(this.enforceConstraints, this);
				}
}

/**
* The default event handler fired when the "context" property is changed.
*/
YAHOO.widget.Overlay.prototype.configContext = function(type, args, obj) {
				var contextArgs = args[0];

				if (contextArgs) {
					var contextEl = contextArgs[0];
					var elementMagnetCorner = contextArgs[1];
					var contextMagnetCorner = contextArgs[2];

					if (contextEl) {
						if (typeof contextEl == "string") {
							this.cfg.setProperty("context", [document.getElementById(contextEl),elementMagnetCorner,contextMagnetCorner], true);
						}
						
						if (elementMagnetCorner && contextMagnetCorner) {
							this.align(elementMagnetCorner, contextMagnetCorner);
						}
					}	
				}
}


// END BUILT-IN PROPERTY EVENT HANDLERS //

/**
* Aligns the Overlay to its context element using the specified corner points (represented by the constants TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, and BOTTOM_RIGHT.
* @param {string} elementAlign		The string representing the corner of the Overlay that should be aligned to the context element
* @param {string} contextAlign		The corner of the context element that the elementAlign corner should stick to.
*/
YAHOO.widget.Overlay.prototype.align = function(elementAlign, contextAlign) {
				var contextArgs = this.cfg.getProperty("context");
				if (contextArgs) {
					var context = contextArgs[0];
					
					var element = this.element;
					var me = this;

					if (! elementAlign) {
						elementAlign = contextArgs[1];
					}

					if (! contextAlign) {
						contextAlign = contextArgs[2];
					}

					if (element && context) {
						var elementRegion = YAHOO.util.Dom.getRegion(element);
						var contextRegion = YAHOO.util.Dom.getRegion(context);

						var doAlign = function(v,h) {
							switch (elementAlign) {
								case YAHOO.widget.Overlay.TOP_LEFT:
									me.moveTo(h,v);
									break;
								case YAHOO.widget.Overlay.TOP_RIGHT:
									me.moveTo(h-element.offsetWidth,v);
									break;
								case YAHOO.widget.Overlay.BOTTOM_LEFT:
									me.moveTo(h,v-element.offsetHeight);
									break;
								case YAHOO.widget.Overlay.BOTTOM_RIGHT:
									me.moveTo(h-element.offsetWidth,v-element.offsetHeight);
									break;
							}
						}

						switch (contextAlign) {
							case YAHOO.widget.Overlay.TOP_LEFT:
								doAlign(contextRegion.top, contextRegion.left);
								break;
							case YAHOO.widget.Overlay.TOP_RIGHT:
								doAlign(contextRegion.top, contextRegion.right);
								break;		
							case YAHOO.widget.Overlay.BOTTOM_LEFT:
								doAlign(contextRegion.bottom, contextRegion.left);
								break;
							case YAHOO.widget.Overlay.BOTTOM_RIGHT:
								doAlign(contextRegion.bottom, contextRegion.right);
								break;
						}
					}
				}
}

/**
* The default event handler executed when the moveEvent is fired, if the "constraintoviewport" is set to true.
*/
YAHOO.widget.Overlay.prototype.enforceConstraints = function(type, args, obj) {
				var pos = args[0];

				var x = pos[0];
				var y = pos[1];

				var width = parseInt(this.cfg.getProperty("width"));

				if (isNaN(width)) {
					width = 0;
				}

				var offsetHeight = this.element.offsetHeight;
				var offsetWidth = (width>0?width:this.element.offsetWidth); //this.element.offsetWidth;

				var viewPortWidth = YAHOO.util.Dom.getViewportWidth();
				var viewPortHeight = YAHOO.util.Dom.getViewportHeight();

				var scrollX = window.scrollX || document.documentElement.scrollLeft;
				var scrollY = window.scrollY || document.documentElement.scrollTop;

				var topConstraint = scrollY + 10;
				var leftConstraint = scrollX + 10;
				var bottomConstraint = scrollY + viewPortHeight - offsetHeight - 10;
				var rightConstraint = scrollX + viewPortWidth - offsetWidth - 10;
				
				if (x < leftConstraint) {
					x = leftConstraint;
				} else if (x > rightConstraint) {
					x = rightConstraint;
				}

				if (y < topConstraint) {
					y = topConstraint;
				} else if (y > bottomConstraint) {
					y = bottomConstraint;
				}

				this.cfg.setProperty("x", x, true);
				this.cfg.setProperty("y", y, true);
				this.cfg.setProperty("xy", [x,y], true);
}

/**
* Centers the container in the viewport.
*/
YAHOO.widget.Overlay.prototype.center = function() {
				var scrollX = window.scrollX || document.documentElement.scrollLeft;
				var scrollY = window.scrollY || document.documentElement.scrollTop;

				var viewPortWidth = YAHOO.util.Dom.getClientWidth();
				var viewPortHeight = YAHOO.util.Dom.getClientHeight();

				var elementWidth = this.element.offsetWidth;
				var elementHeight = this.element.offsetHeight;

				var x = (viewPortWidth / 2) - (elementWidth / 2) + scrollX;
				var y = (viewPortHeight / 2) - (elementHeight / 2) + scrollY;
				
				this.element.style.left = parseInt(x) + "px";
				this.element.style.top = parseInt(y) + "px";
				this.syncPosition();

				this.cfg.refireEvent("iframe");
}

/**
* Synchronizes the Panel's "xy", "x", and "y" properties with the Panel's position in the DOM. This is primarily used to update position information during drag & drop.
*/
YAHOO.widget.Overlay.prototype.syncPosition = function() {
				var pos = YAHOO.util.Dom.getXY(this.element);
				this.cfg.setProperty("x", pos[0], true);
				this.cfg.setProperty("y", pos[1], true);
				this.cfg.setProperty("xy", pos, true);
}

/**
* Event handler fired when the resize monitor element is resized.
*/
YAHOO.widget.Overlay.prototype.onDomResize = function(e, obj) {
				YAHOO.widget.Overlay.superclass.onDomResize.call(this, e, obj);
				this.cfg.refireEvent("iframe");
}

/**
* A singleton CustomEvent used for reacting to the DOM event for window scroll
* @type YAHOO.util.CustomEvent
*/
YAHOO.widget.Overlay.windowScrollEvent = new YAHOO.util.CustomEvent("windowScroll");

/**
* A singleton CustomEvent used for reacting to the DOM event for window resize
* @type YAHOO.util.CustomEvent
*/
YAHOO.widget.Overlay.windowResizeEvent = new YAHOO.util.CustomEvent("windowResize");

/**
* The DOM event handler used to fire the CustomEvent for window scroll
* @type Function
*/
YAHOO.widget.Overlay.windowScrollHandler = function(e) {
				YAHOO.widget.Overlay.windowScrollEvent.fire();
}

/**
* The DOM event handler used to fire the CustomEvent for window resize
* @type Function
*/
YAHOO.widget.Overlay.windowResizeHandler = function(e) {
				YAHOO.widget.Overlay.windowResizeEvent.fire();
}


if (YAHOO.widget.Overlay._initialized == undefined) {
				YAHOO.util.Event.addListener(window, "scroll", YAHOO.widget.Overlay.windowScrollHandler);
				YAHOO.util.Event.addListener(window, "resize", YAHOO.widget.Overlay.windowResizeHandler);
				/**
				* @private
				*/
				YAHOO.widget.Overlay._initialized = true;
}
/**
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
* @class
* OverlayManager is used for maintaining the focus status of multiple Overlays.
* @param {Array}	overlays	Optional. A collection of Overlays to register with the manager.
* @param {object}	userConfig		The object literal representing the user configuration of the OverlayManager
* @constructor
*/
YAHOO.widget.OverlayManager = function(userConfig) {
				this.init(userConfig);
}

/**
* The CSS class representing a focused Overlay
* @type string
*/
YAHOO.widget.OverlayManager.CSS_FOCUSED = "focused";

YAHOO.widget.OverlayManager.prototype = {

				constructor : YAHOO.widget.OverlayManager,

				/**
				* The array of Overlays that are currently registered
				* @type Array
				*/
				overlays : new Array(),

				/**
				* Initializes the default configuration of the OverlayManager
				*/	
				initDefaultConfig : function() {
					this.cfg.addProperty("overlays", { suppressEvent:true } );
					this.cfg.addProperty("focusevent", { value:"mousedown" } );
				}, 

				/**
				* Returns the currently focused Overlay
				* @return {Overlay}	The currently focused Overlay
				*/
				getActive : function() {},

				/**
				* Focuses the specified Overlay
				* @param {Overlay}	The Overlay to focus
				* @param {string}	The id of the Overlay to focus
				*/
				focus : function(overlay) {},

				/**
				* Removes the specified Overlay from the manager
				* @param {Overlay}	The Overlay to remove
				* @param {string}	The id of the Overlay to remove
				*/
				remove: function(overlay) {},

				/**
				* Removes focus from all registered Overlays in the manager
				*/
				blurAll : function() {},

				/**
				* Initializes the OverlayManager
				* @param {Array}	overlays	Optional. A collection of Overlays to register with the manager.
				* @param {object}	userConfig		The object literal representing the user configuration of the OverlayManager
				*/
				init : function(userConfig) {
					this.cfg = new YAHOO.util.Config(this);

					this.initDefaultConfig();

					if (userConfig) {
						this.cfg.applyConfig(userConfig, true);
					}
					this.cfg.fireQueue();

					var activeOverlay = null;

					this.getActive = function() {
						return activeOverlay;
					}

					this.focus = function(overlay) {
						var o = this.find(overlay);
						if (o) {
							this.blurAll();
							activeOverlay = o;
							YAHOO.util.Dom.addClass(activeOverlay.element, YAHOO.widget.OverlayManager.CSS_FOCUSED);
							this.overlays.sort(this.compareZIndexDesc);
							var topZIndex = YAHOO.util.Dom.getStyle(this.overlays[0].element, "zIndex");
							if (! isNaN(topZIndex) && this.overlays[0] != overlay) {
								activeOverlay.cfg.setProperty("zIndex", (parseInt(topZIndex) + 1));
							}
							this.overlays.sort(this.compareZIndexDesc);
						}
					}

					this.remove = function(overlay) {
						var o = this.find(overlay);
						if (o) {
							var originalZ = YAHOO.util.Dom.getStyle(o.element, "zIndex");
							o.cfg.setProperty("zIndex", -1000, true);
							this.overlays.sort(this.compareZIndexDesc);
							this.overlays = this.overlays.slice(0, this.overlays.length-1);
							o.cfg.setProperty("zIndex", originalZ, true);

							o.cfg.setProperty("manager", null);
							o.focusEvent = null
							o.blurEvent = null;
							o.focus = null;
							o.blur = null;
						}
					}

					this.blurAll = function() {
						activeOverlay = null;
						for (var o=0;o<this.overlays.length;o++) {
							YAHOO.util.Dom.removeClass(this.overlays[o].element, YAHOO.widget.OverlayManager.CSS_FOCUSED);
						}		
					}

					var overlays = this.cfg.getProperty("overlays");

					if (overlays) {
						this.register(overlays);
						this.overlays.sort(this.compareZIndexDesc);
					}
				},

				/**
				* Registers an Overlay or an array of Overlays with the manager. Upon registration, the Overlay receives functions for focus and blur, along with CustomEvents for each.
				* @param {Overlay}	overlay		An Overlay to register with the manager.
				* @param {Overlay[]}	overlay		An array of Overlays to register with the manager.
				* @return	{boolean}	True if any Overlays are registered.
				*/
				register : function(overlay) {
					if (overlay instanceof YAHOO.widget.Overlay) {
						overlay.cfg.addProperty("manager", { value:this } );

						overlay.focusEvent = new YAHOO.util.CustomEvent("focus");
						overlay.blurEvent = new YAHOO.util.CustomEvent("blur");
						
						var mgr=this;

						overlay.focus = function() {
							mgr.focus(this);
							this.focusEvent.fire();
						} 

						overlay.blur = function() {
							mgr.blurAll();
							this.blurEvent.fire();
						}

						var focusOnDomEvent = function(e,obj) {
							mgr.focus(overlay);
						}
						
						var focusevent = this.cfg.getProperty("focusevent");
						YAHOO.util.Event.addListener(overlay.element,focusevent,focusOnDomEvent,this,true);

						var zIndex = YAHOO.util.Dom.getStyle(overlay.element, "zIndex");
						if (! isNaN(zIndex)) {
							overlay.cfg.setProperty("zIndex", parseInt(zIndex));
						} else {
							overlay.cfg.setProperty("zIndex", 0);
						}
						
						this.overlays.push(overlay);
						return true;
					} else if (overlay instanceof Array) {
						var regcount = 0;
						for (var i=0;i<overlay.length;i++) {
							if (this.register(overlay[i])) {
								regcount++;
							}
						}
						if (regcount > 0) {
							return true;
						}
					} else {
						return false;
					}
				},

				/**
				* Attempts to locate an Overlay by instance or ID.
				* @param {Overlay}	overlay		An Overlay to locate within the manager
				* @param {string}	overlay		An Overlay id to locate within the manager
				* @return	{Overlay}	The requested Overlay, if found, or null if it cannot be located.
				*/
				find : function(overlay) {
					if (overlay instanceof YAHOO.widget.Overlay) {
						for (var o=0;o<this.overlays.length;o++) {
							if (this.overlays[o] == overlay) {
								return this.overlays[o];
							}
						}
					} else if (typeof overlay == "string") {
						for (var o=0;o<this.overlays.length;o++) {
							if (this.overlays[o].id == overlay) {
								return this.overlays[o];
							}
						}			
					}
					return null;
				},

				/**
				* Used for sorting the manager's Overlays by z-index.
				* @private
				*/
				compareZIndexDesc : function(o1, o2) {
					var zIndex1 = o1.cfg.getProperty("zIndex");
					var zIndex2 = o2.cfg.getProperty("zIndex");

					if (zIndex1 > zIndex2) {
						return -1;
					} else if (zIndex1 < zIndex2) {
						return 1;
					} else {
						return 0;
					}
				},

				/**
				* Shows all Overlays in the manager.
				*/
				showAll : function() {
					for (var o=0;o<this.overlays.length;o++) {
						this.overlays[o].show();
					}
				},

				/**
				* Hides all Overlays in the manager.
				*/
				hideAll : function() {
					for (var o=0;o<this.overlays.length;o++) {
						this.overlays[o].hide();
					}
				}

}/**
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
* @class 
* KeyListener is a utility that provides an easy interface for listening for keydown/keyup events fired against DOM elements.
* @param {Element}	attachTo	The element or element ID to which the key event should be attached
* @param {string}	attachTo	The element or element ID to which the key event should be attached
* @param (object}	keyData		The object literal representing the key(s) to detect. Possible attributes are shift(boolean), alt(boolean), ctrl(boolean) and keys(either an int or an array of ints representing keycodes).
* @param {function}	handler		The CustomEvent handler to fire when the key event is detected
* @param {object}	handler		An object literal representing the handler. 
* @param {string}	event		Optional. The event (keydown or keyup) to listen for. Defaults automatically to keydown.
* @constructor
*/
YAHOO.util.KeyListener = function(attachTo, keyData, handler, event) {
				if (! event) {
					event = YAHOO.util.KeyListener.KEYDOWN;
				}

				var keyEvent = new YAHOO.util.CustomEvent("keyPressed");
				
				this.enabledEvent = new YAHOO.util.CustomEvent("enabled");
				this.disabledEvent = new YAHOO.util.CustomEvent("disabled");

				if (typeof attachTo == 'string') {
					attachTo = document.getElementById(attachTo);
				}

				if (typeof handler == 'function') {
					keyEvent.subscribe(handler);
				} else {
					keyEvent.subscribe(handler.fn, handler.scope, handler.correctScope);
				}

				/**
				* Handles the key event when a key is pressed.
				* @private
				*/
				var handleKeyPress = function(e, obj) {
					var keyPressed = e.charCode || e.keyCode;
					
					if (! keyData.shift)	keyData.shift = false;
					if (! keyData.alt)		keyData.alt = false;
					if (! keyData.ctrl)		keyData.ctrl = false;

					// check held down modifying keys first
					if (e.shiftKey == keyData.shift && 
						e.altKey   == keyData.alt &&
						e.ctrlKey  == keyData.ctrl) { // if we pass this, all modifiers match

						if (keyData.keys instanceof Array) {
							for (var i=0;i<keyData.keys.length;i++) {
								if (keyPressed == keyData.keys[i]) {
									keyEvent.fire(keyPressed, e);
									break;
								}
							}
						} else {
							if (keyPressed == keyData.keys) {
								keyEvent.fire(keyPressed, e);
							}
						}
					}
				}

				this.enable = function() {
					if (! this.enabled) {
						YAHOO.util.Event.addListener(attachTo, event, handleKeyPress);
						this.enabledEvent.fire(keyData);
					}
					this.enabled = true;
				}

				this.disable = function() {
					if (this.enabled) {
						YAHOO.util.Event.removeListener(attachTo, event, handleKeyPress);
						this.disabledEvent.fire(keyData);
					}
					this.enabled = false;
				}

}

/**
* Constant representing the DOM "keydown" event.
* @final
*/
YAHOO.util.KeyListener.KEYDOWN = "keydown";

/**
* Constant representing the DOM "keyup" event.
* @final
*/
YAHOO.util.KeyListener.KEYUP = "keyup";

/**
* Enables the KeyListener, by dynamically attaching the key event to the appropriate DOM element.
*/
YAHOO.util.KeyListener.prototype.enable = function() {};

/**
* Disables the KeyListener, by dynamically removing the key event from the appropriate DOM element.
*/
YAHOO.util.KeyListener.prototype.disable = function() {};

/**
* CustomEvent fired when the KeyListener is enabled
* args: keyData
* @type YAHOO.util.CustomEvent
*/
YAHOO.util.KeyListener.prototype.enabledEvent = null;

/**
* CustomEvent fired when the KeyListener is disabled
* args: keyData
* @type YAHOO.util.CustomEvent
*/
YAHOO.util.KeyListener.prototype.disabledEvent = null;

/*
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
*/

/**
* @class The superclass of all menu containers.
* @constructor
* @extends YAHOO.widget.Overlay
* @base YAHOO.widget.Overlay
* @param {String or HTMLElement} p_oElement String id or HTMLElement 
* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node.
* @param {Object} p_oUserConfig Optional. The configuration object literal 
* containing the configuration for a MenuModule instance. See 
* configuration class documentation for more details.
*/
YAHOO.widget.MenuModule = function(p_oElement, p_oUserConfig) {

				if (arguments.length > 0) {

					YAHOO.widget.MenuModule.superclass.constructor.call(
						this, 
						p_oElement, 
						p_oUserConfig
					);

				}

};

YAHOO.widget.MenuModule.prototype = new YAHOO.widget.Overlay();
YAHOO.widget.MenuModule.prototype.constructor = YAHOO.widget.MenuModule;
YAHOO.widget.MenuModule.superclass = YAHOO.widget.Overlay.prototype;


// Constants

/**
* Constant representing the CSS class(es) to be applied to the root 
* HTMLDivElement of the MenuModule instance.
* @final
* @type String
*/
YAHOO.widget.MenuModule.prototype.CSS_CLASS_NAME = "yuimenu";


/**
* Constant representing the type of item to instantiate and add when parsing 
* the child nodes (either HTMLLIElement, HTMLOptGroupElement or 
* HTMLOptionElement) of a menu's DOM.  The default 
* is YAHOO.widget.MenuModuleItem.
* @final
* @type YAHOO.widget.MenuModuleItem
*/
YAHOO.widget.MenuModule.prototype.ITEM_TYPE = null;


/**
* Constant representing the tagname of the HTMLElement used to title 
* a group of items.
* @final
* @type String
*/
YAHOO.widget.MenuModule.prototype.GROUP_TITLE_TAG_NAME = "H6";


// Private properties

/**
* Array of HTMLElements used to title groups of items.
* @private
* @type {Array}
*/
YAHOO.widget.MenuModule.prototype._aGroupTitleElements = null;


/**
* Multi-dimensional array of items.
* @private
* @type {Array}
*/
YAHOO.widget.MenuModule.prototype._aItemGroups = null;


/**
* An array of HTMLUListElements, each of which is the parent node of each 
* items's HTMLLIElement node.
* @private
* @type {Array}
*/
YAHOO.widget.MenuModule.prototype._aListElements = null;


/**
* Reference to the Event utility singleton.
* @private
* @type {YAHOO.util.Event}
*/
YAHOO.widget.MenuModule.prototype._oEventUtil = YAHOO.util.Event;


/**
* Reference to the Dom utility singleton.
* @private
* @type {YAHOO.util.Dom}
*/
YAHOO.widget.MenuModule.prototype._oDom = YAHOO.util.Dom;


/**
* Reference to the item the mouse is currently over.
* @private
* @type {YAHOO.widget.MenuModuleItem}
*/
YAHOO.widget.MenuModule.prototype._oCurrentItem = null;


/** 
* The current state of a MenuModule instance's "mouseover" event
* @private
* @type {Boolean}
*/
YAHOO.widget.MenuModule.prototype._bFiredMouseOverEvent = false;


/** 
* The current state of a MenuModule instance's "mouseout" event
* @private
* @type {Boolean}
*/
YAHOO.widget.MenuModule.prototype._bFiredMouseOutEvent = false;


// Public properties

/**
* Reference to the item that has focus.
* @private
* @type {YAHOO.widget.MenuModuleItem}
*/
YAHOO.widget.MenuModule.prototype.activeItem = null;


/**
* Returns a MenuModule instance's parent object.
* @type {YAHOO.widget.MenuModuleItem}
*/
YAHOO.widget.MenuModule.prototype.parent = null;


/**
* Returns the HTMLElement (either HTMLSelectElement or HTMLDivElement)
* used create the MenuModule instance.
* @type {HTMLSelectElement/HTMLDivElement}
*/
YAHOO.widget.MenuModule.prototype.srcElement = null;


// Events

/**
* Fires when the mouse has entered a MenuModule instance.  Passes back the 
* DOM Event object as an argument.
* @type {YAHOO.util.CustomEvent}
* @see YAHOO.util.CustomEvent
*/
YAHOO.widget.MenuModule.prototype.mouseOverEvent = null;


/**
* Fires when the mouse has left a MenuModule instance.  Passes back the DOM 
* Event object as an argument.
* @type {YAHOO.util.CustomEvent}
* @see YAHOO.util.CustomEvent
*/
YAHOO.widget.MenuModule.prototype.mouseOutEvent = null;


/**
* Fires when the user mouses down on a MenuModule instance.  Passes back the 
* DOM Event object as an argument.
* @type {YAHOO.util.CustomEvent}
* @see YAHOO.util.CustomEvent
*/
YAHOO.widget.MenuModule.prototype.mouseDownEvent = null;


/**
* Fires when the user releases a mouse button while the mouse is over 
* a MenuModule instance.  Passes back the DOM Event object as an argument.
* @type {YAHOO.util.CustomEvent}
* @see YAHOO.util.CustomEvent
*/
YAHOO.widget.MenuModule.prototype.mouseUpEvent = null;


/**
* Fires when the user clicks the on a MenuModule instance.  Passes back the 
* DOM Event object as an argument.
* @type {YAHOO.util.CustomEvent}
* @see YAHOO.util.CustomEvent
*/
YAHOO.widget.MenuModule.prototype.clickEvent = null;


/**
* Fires when the user presses an alphanumeric key.  Passes back the 
* DOM Event object as an argument.
* @type {YAHOO.util.CustomEvent}
* @see YAHOO.util.CustomEvent
*/
YAHOO.widget.MenuModule.prototype.keyPressEvent = null;


/**
* Fires when the user presses a key.  Passes back the DOM Event 
* object as an argument.
* @type {YAHOO.util.CustomEvent}
* @see YAHOO.util.CustomEvent
*/
YAHOO.widget.MenuModule.prototype.keyDownEvent = null;


/**
* Fires when the user releases a key.  Passes back the DOM Event 
* object as an argument.
* @type {YAHOO.util.CustomEvent}
* @see YAHOO.util.CustomEvent
*/
YAHOO.widget.MenuModule.prototype.keyUpEvent = null;


/**
* The MenuModule class's initialization method. This method is automatically 
* called  by the constructor, and sets up all DOM references for 
* pre-existing markup, and creates required markup if it is not already present.
* @param {String or HTMLElement} p_oElement String id or HTMLElement 
* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node.
* @param {Object} p_oUserConfig Optional. The configuration object literal 
* containing the configuration for a MenuModule instance. See 
* configuration class documentation for more details.
*/
YAHOO.widget.MenuModule.prototype.init = function(p_oElement, p_oUserConfig) {

				if(!this.ITEM_TYPE) {

					this.ITEM_TYPE = YAHOO.widget.MenuModuleItem;

				}


				this._aItemGroups = [];
				this._aListElements = [];
				this._aGroupTitleElements = [];


				var oElement;

				if(typeof p_oElement == "string") {

					oElement = document.getElementById(p_oElement);

				}
				else if(p_oElement.tagName) {

					oElement = p_oElement;

				}


				if(oElement) {

					switch(oElement.tagName) {
				
						case "DIV":

							this.srcElement = oElement;

							/* 
								Note: we don't pass the user config in here yet 
								because we only want it executed once, at the lowest 
								subclass level.
							*/ 
						
							YAHOO.widget.MenuModule.superclass.init.call(this, oElement);

							this.beforeInitEvent.fire(YAHOO.widget.MenuModule);


							/*
								Populate the collection of item groups and item
								group titles
							*/

							var oNode = this.body.firstChild, 
								i = 0;

							do {

								switch(oNode.tagName) {

									case this.GROUP_TITLE_TAG_NAME:
									
										this._aGroupTitleElements[i] = oNode;

									break;

									case "UL":

										this._aListElements[i] = oNode;
										this._aItemGroups[i] = [];
										i++;

									break;

								}

							}
							while((oNode = oNode.nextSibling));


							/*
								Apply the "first" class to the first UL to mimic 
								the "first-child" psuedo class.
							*/

							if(this._aListElements[0]) {

								this._oDom.addClass(this._aListElements[0], "first");

							}

				
						break;
				
						case "SELECT":
				
							this.srcElement = oElement;
				
				
							/*
								The source element is not something that we can use 
								outright, so we need to create a new Overlay
							*/
				
							var sId = this._oDom.generateId();

							/* 
								Note: we don't pass the user config in here yet 
								because we only want it executed once, at the lowest 
								subclass level.
							*/ 
						
							YAHOO.widget.MenuModule.superclass.init.call(this, sId); 

							this.beforeInitEvent.fire(YAHOO.widget.MenuModule);

						break;
				
					}

				}
				else {

					/* 
						Note: we don't pass the user config in here yet 
						because we only want it executed once, at the lowest 
						subclass level.
					*/ 
				
					YAHOO.widget.MenuModule.superclass.init.call(this, p_oElement);

					this.beforeInitEvent.fire(YAHOO.widget.MenuModule);

				}


				if(this.element) {

					this._oDom.addClass(this.element, this.CSS_CLASS_NAME);


					// Assign DOM event handlers

					this._oEventUtil.addListener(
						this.element, 
						"mouseover", 
						this._onElementMouseOver, 
						this,
						true
					);

					this._oEventUtil.addListener(
						this.element, 
						"mouseout", 
						this._onElementMouseOut, 
						this,
						true
					);

					this._oEventUtil.addListener(
						this.element, 
						"mousedown", 
						this._onDOMEvent, 
						this,
						true
					);

					this._oEventUtil.addListener(
						this.element, 
						"mouseup", 
						this._onDOMEvent, 
						this,
						true
					);

					this._oEventUtil.addListener(
						this.element, 
						"click", 
						this._onElementClick, 
						this,
						true
					);

					this._oEventUtil.addListener(
						this.element, 
						"keydown", 
						this._onDOMEvent, 
						this,
						true
					);

					this._oEventUtil.addListener(
						this.element, 
						"keyup", 
						this._onDOMEvent, 
						this,
						true
					);

					this._oEventUtil.addListener(
						this.element, 
						"keypress", 
						this._onDOMEvent, 
						this,
						true
					);


					// Create custom events

					var CustomEvent = YAHOO.util.CustomEvent;

					this.mouseOverEvent = new CustomEvent("mouseOverEvent", this);
					this.mouseOutEvent = new CustomEvent("mouseOutEvent", this);
					this.mouseDownEvent = new CustomEvent("mouseDownEvent", this);
					this.mouseUpEvent = new CustomEvent("mouseUpEvent", this);
					this.clickEvent = new CustomEvent("clickEvent", this);
					this.keyPressEvent = new CustomEvent("keyPressEvent", this);
					this.keyDownEvent = new CustomEvent("keyDownEvent", this);
					this.keyUpEvent = new CustomEvent("keyUpEvent", this);


					// Subscribe to Custom Events

					this.beforeRenderEvent.subscribe(this._onBeforeRender, this, true);
					this.renderEvent.subscribe(this._onRender, this, true);
					this.showEvent.subscribe(this._onShow, this, true);
					this.hideEvent.subscribe(this._onHide, this, true);


					if(p_oUserConfig) {
				
						this.cfg.applyConfig(p_oUserConfig, true);
				
					}


					this.cfg.queueProperty("visible", false);


					if(this.srcElement) {

						this._initSubTree();

					}

				}


				this.initEvent.fire(YAHOO.widget.MenuModule);

};


// Private methods


/**
* Returns the first enabled item in a menu instance.
* @return Returns a MenuModuleItem instance.
* @type YAHOO.widget.MenuModuleItem
* @private
*/
YAHOO.widget.MenuModule.prototype._getFirstEnabledItem = function() {

				var nGroups = this._aItemGroups.length,
					oItem,
					aItemGroup;

				for(var i=0; i<nGroups; i++) {

					aItemGroup = this._aItemGroups[i];
					
					if(aItemGroup) {

						var nItems = aItemGroup.length;
						
						for(var n=0; n<nItems; n++) {
						
							oItem = aItemGroup[n];
							
							if(!oItem.cfg.getProperty("disabled")) {
							
								return oItem;
							
							}
				
							oItem = null;
				
						}
					
					}
				
				}
				
};


/**
* Determines if the value is one of the supported positions.
* @private
* @param {Object} p_sPosition The object to be evaluated.
* @return Returns true if the position is supported.
* @type Boolean
*/
YAHOO.widget.MenuModule.prototype._checkPosition = function(p_sPosition) {

				if(typeof p_sPosition == "string") {

					var sPosition = p_sPosition.toLowerCase();

					return ("dynamic,static".indexOf(sPosition) != -1);

				}

};


/**
* Adds an item to a group.
* @private
* @param {Number} p_nGroupIndex Number indicating the group to which
* the item belongs.
* @param {YAHOO.widget.MenuModuleItem} p_oItem The item to be added.
* @param {Number} p_nItemIndex Optional. Index at which the item 
* should be added.
* @return The item that was added.
* @type YAHOO.widget.MenuModuleItem
*/
YAHOO.widget.MenuModule.prototype._addItemToGroup = 

				function(p_nGroupIndex, p_oItem, p_nItemIndex) {

					if(typeof p_nItemIndex == "number") {

						var nGroupIndex = typeof p_nGroupIndex == "number" ? 
								p_nGroupIndex : 0,
								aGroup = this._getItemGroup(nGroupIndex);

				
						if(!aGroup) {
				
							aGroup = this._createItemGroup(nGroupIndex);
				
						}


						var bAppend = (p_nItemIndex >= aGroup.length);            


						if(aGroup[p_nItemIndex]) {
				
							aGroup.splice(p_nItemIndex, 0, p_oItem);
				
						}
						else {
				
							aGroup[p_nItemIndex] = p_oItem;
				
						}


						var oItem = aGroup[p_nItemIndex];

						if(oItem) {

							if(bAppend && !oItem.element.parentNode) {
					
								this._aListElements[nGroupIndex].appendChild(oItem.element);
				
							}
							else {
			  
				
								/**
								* Returns the next sibling of an item in an array 
								* @param {p_aArray} An array
								* @param {p_nStartIndex} The index to start searching the array 
								* @ignore
								* @return Returns an item in an array
								* @type Object 
								*/
								function getNextItemSibling(p_aArray, p_nStartIndex) {
						
									return (
											p_aArray[p_nStartIndex] || 
											getNextItemSibling(p_aArray, (p_nStartIndex+1))
										);
						
								}
				
				
								var oNextItemSibling = 
										getNextItemSibling(aGroup, (p_nItemIndex+1));
				
								if(oNextItemSibling && !oItem.element.parentNode) {
						
									this._aListElements[nGroupIndex].insertBefore(
											oItem.element, 
											oNextItemSibling.element
										);
					
								}
				
							}
				

							oItem.parent = this;
					
							this._subscribeToItemEvents(oItem);
				
							this._configureItemSubmenuModule(oItem);
							
							this._updateItemProperties(nGroupIndex);
					
							return oItem;
				
						}

					}
					else {
				
						var nGroupIndex = typeof p_nGroupIndex == "number" ? p_nGroupIndex : 0,
							aGroup = this._getItemGroup(nGroupIndex);
				
						if(!aGroup) {
				
							aGroup = this._createItemGroup(nGroupIndex);
				
						}
				
						var nItemIndex = aGroup.length;
				
						aGroup[nItemIndex] = p_oItem;
				
				
						var oItem = aGroup[nItemIndex];
				
						if(oItem) {
				
							if(
								!this._oDom.isAncestor(
									this._aListElements[nGroupIndex], 
									oItem.element
								)
							) {
				
								this._aListElements[nGroupIndex].appendChild(oItem.element);
				
							}
				
							oItem.element.setAttribute("groupindex", nGroupIndex);
							oItem.element.setAttribute("index", nItemIndex);
					
							oItem.parent = this;
				
							oItem.index = nItemIndex;
							oItem.groupIndex = nGroupIndex;
					
							this._subscribeToItemEvents(oItem);
				
							this._configureItemSubmenuModule(oItem);
				
							if(nItemIndex === 0) {
					
								this._oDom.addClass(oItem.element, "first");
					
							}
					
							return oItem;
				
						}
				
					}
				
				};


/**
* Removes an item from a group by index.
* @private
* @param {Number} p_nGroupIndex Number indicating the group to which
* the item belongs.
* @param {Number} p_nItemIndex Number indicating the index of the item to  
* be removed.
* @return The item that was removed.
* @type YAHOO.widget.MenuModuleItem
*/    
YAHOO.widget.MenuModule.prototype._removeItemFromGroupByIndex = 

				function(p_nGroupIndex, p_nItemIndex) {

					var nGroupIndex = typeof p_nGroupIndex == "number" ? p_nGroupIndex : 0,
						aGroup = this._getItemGroup(nGroupIndex);
				
					if(aGroup) {
				
						var aArray = aGroup.splice(p_nItemIndex, 1),
							oItem = aArray[0];
					
						if(oItem) {
					
							// Update the index and className properties of each member        
							
							this._updateItemProperties(nGroupIndex);
					
							if(aGroup.length === 0) {
					
								// Remove the UL
					
								var oUL = this._aListElements[nGroupIndex];
					
								if(this.body && oUL) {
					
									this.body.removeChild(oUL);
					
								}
					
								// Remove the group from the array of items
					
								this._aItemGroups.splice(nGroupIndex, 1);
					
					
								// Remove the UL from the array of ULs
					
								this._aListElements.splice(nGroupIndex, 1);
					
					
								/*
									 Assign the "first" class to the new first UL in 
									 the collection
								*/
					
								oUL = this._aListElements[0];
					
								if(oUL) {
					
									this._oDom.addClass(oUL, "first");
					
								}            
					
							}
					
					
							// Return a reference to the item that was removed
						
							return oItem;
					
						}
				
					}
				
				};


/**
* Removes a item from a group by reference.
* @private
* @param {Number} p_nGroupIndex Number indicating the group to which
* the item belongs.
* @param {YAHOO.widget.MenuModuleItem} p_oItem The item to be removed.
* @return The item that was removed.
* @type YAHOO.widget.MenuModuleItem
*/    
YAHOO.widget.MenuModule.prototype._removeItemFromGroupByValue =

				function(p_nGroupIndex, p_oItem) {

					var aGroup = this._getItemGroup(p_nGroupIndex);

					if(aGroup) {

						var nItems = aGroup.length,
							nItemIndex = -1;
					
						if(nItems > 0) {
					
							var i = nItems-1;
						
							do {
						
								if(aGroup[i] == p_oItem) {
						
									nItemIndex = i;
									break;    
						
								}
						
							}
							while(i--);
						
							if(nItemIndex > -1) {
						
								return this._removeItemFromGroupByIndex(
											p_nGroupIndex, 
											nItemIndex
										);
						
							}
					
						}
					
					}
				
				};


/**
* Updates the index, groupindex, and className properties of the items
* in the specified group. 
* @private
* @param {Number} p_nGroupIndex Number indicating the group of items to update.
*/
YAHOO.widget.MenuModule.prototype._updateItemProperties = 

				function(p_nGroupIndex) {

					var aGroup = this._getItemGroup(p_nGroupIndex),
						nItems = aGroup.length;
				
					if(nItems > 0) {
				
						var i = nItems - 1,
							oItem,
							oLI;
				
						// Update the index and className properties of each member        
					
						do {
				
							oItem = aGroup[i];
				
							if(oItem) {
					
								oLI = oItem.element;
				
								oItem.index = i;
								oItem.groupIndex = p_nGroupIndex;
				
								oLI.setAttribute("groupindex", p_nGroupIndex);
								oLI.setAttribute("index", i);
				
								this._oDom.removeClass(oLI, "first");
				
							}
					
						}
						while(i--);
				
				
						if(oLI) {
				
							this._oDom.addClass(oLI, "first");
				
						}
				
					}
				
				};


/**
* Creates a new item group (array) and it's associated HTMLUlElement node 
* @private
* @param {Number} p_nIndex Number indicating the group to create.
* @return An item group.
* @type Array
*/
YAHOO.widget.MenuModule.prototype._createItemGroup = function(p_nIndex) {

				if(!this._aItemGroups[p_nIndex]) {

					this._aItemGroups[p_nIndex] = [];

					var oUL = document.createElement("ul");

					this._aListElements[p_nIndex] = oUL;

					return this._aItemGroups[p_nIndex];

				}

};


/**
* Returns the item group at the specified index.
* @private
* @param {Number} p_nIndex Number indicating the index of the item group to
* be retrieved.
* @return An array of items.
* @type Array
*/
YAHOO.widget.MenuModule.prototype._getItemGroup = function(p_nIndex) {

				var nIndex = ((typeof p_nIndex == "number") ? p_nIndex : 0);

				return this._aItemGroups[nIndex];

};


/**
* Subscribe's a MenuModule instance to it's parent MenuModule instance's events.
* @private
* @param {YAHOO.widget.MenuModuleItem} p_oItem The item to listen
* for events on.
*/
YAHOO.widget.MenuModule.prototype._configureItemSubmenuModule = 

				function(p_oItem) {

					var oSubmenu = p_oItem.cfg.getProperty("submenu");
				
					if(oSubmenu) {
				
						/*
							Listen for configuration changes to the parent MenuModule 
							instance so they they can be applied to the submenu.
						*/
				
						this.cfg.configChangedEvent.subscribe(
							this._onParentMenuModuleConfigChange, 
							oSubmenu, 
							true
						);
						
						this.renderEvent.subscribe(
							this._onParentMenuModuleRender,
							oSubmenu, 
							true
						);
				
						oSubmenu.beforeShowEvent.subscribe(
							this._onSubmenuBeforeShow, 
							oSubmenu, 
							true
						);
				
						oSubmenu.showEvent.subscribe(this._onSubmenuShow, oSubmenu, true);
				
						oSubmenu.hideEvent.subscribe(this._onSubmenuHide, oSubmenu, true);
				
					}

};


/**
* Subscribes a MenuModule instance to the specified item's Custom Events.
* @private
* @param {YAHOO.widget.MenuModuleItem} p_oItem The item to listen for events on.
*/
YAHOO.widget.MenuModule.prototype._subscribeToItemEvents = function(p_oItem) {

				var aArguments = [this, p_oItem];

				p_oItem.focusEvent.subscribe(this._onItemFocus, aArguments);

				p_oItem.blurEvent.subscribe(this._onItemBlur, aArguments);

				p_oItem.cfg.configChangedEvent.subscribe(
					this._onItemConfigChange,
					aArguments
				);

};


/**
* Returns the offset width of a MenuModule instance.
* @private
*/
YAHOO.widget.MenuModule.prototype._getOffsetWidth = function() {

				var oClone = this.element.cloneNode(true);

				this._oDom.setStyle(oClone, "width", "");

				document.body.appendChild(oClone);

				var sWidth = oClone.offsetWidth;

				document.body.removeChild(oClone);

				return sWidth;

};


/**
* Determines if a DOM event was fired on an item and (if so) fires the item's
* associated Custom Event
* @private
* @param {HTMLElement} p_oElement The original target of the event.
* @param {String} p_sEventType The type/name of the Custom Event to fire.
* @param {Event} p_oDOMEvent The DOM event to pass back when firing the 
* Custom Event.
* @return An item.
* @type YAHOO.widget.MenuModuleItem
*/
YAHOO.widget.MenuModule.prototype._fireItemEvent = 

				function(p_oElement, p_sEventType, p_oDOMEvent) {

					var me = this;
				
					/**
					* Returns the specified element's parent HTMLLIElement (&#60;LI&#60;)
					* @param {p_oElement} An HTMLElement node
					* @ignore
					* @return Returns an HTMLElement node
					* @type HTMLElement 
					*/
					function getItemElement(p_oElement) {
					
						if(p_oElement == me.element) {
				
							return;
						
						}
						else if(p_oElement.tagName == "LI") {
					
							return p_oElement;
					
						}
						else if(p_oElement.parentNode) {
				
							return getItemElement(p_oElement.parentNode);
					
						}
					
					}
				
				
					var oElement = getItemElement(p_oElement);
				
					if(oElement) {
				
						/*
							Retrieve the item that corresponds to the 
							HTMLLIElement (&#60;LI&#60;) and fire the Custom Event        
						*/
				
						var nGroupIndex = parseInt(oElement.getAttribute("groupindex"), 10),
							nIndex = parseInt(oElement.getAttribute("index"), 10),
							oItem = this._aItemGroups[nGroupIndex][nIndex];
				
						if(!oItem.cfg.getProperty("disabled")) {
				
							oItem[p_sEventType].fire(p_oDOMEvent);
				
							return oItem;
				
						}
				
					}

				};


// Private DOM event handlers

/**
* Generic event handler for the MenuModule's root HTMLDivElement node.  Used to
* handle "mousedown," "mouseup," "keydown," "keyup," and "keypress" events.
* @private
* @param {Event} p_oEvent Event object passed back by the event 
* utility (YAHOO.util.Event).
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance 
* corresponding to the HTMLDivElement that fired the event.
*/
YAHOO.widget.MenuModule.prototype._onDOMEvent = 

				function(p_oEvent, p_oMenuModule) {

					// Map of DOM event types to Custom Event types
					
					var oEventTypes =  {
							"mousedown": "mouseDownEvent",
							"mouseup": "mouseUpEvent",
							"keydown": "keyDownEvent",
							"keyup": "keyUpEvent",
							"keypress": "keyPressEvent"
						},
				
						sCustomEventType = oEventTypes[p_oEvent.type],
					
						oTarget = this._oEventUtil.getTarget(p_oEvent, true);
				
					/*
						Check if the target was an element that is a part of a 
						an item and (if so), fire the associated custom event.
					*/
				
					this._fireItemEvent(oTarget, sCustomEventType, p_oEvent);
				
				
					// Fire the associated custom event for the MenuModule
				
					this[sCustomEventType].fire(p_oEvent);
				
				
					/*
						Stop the propagation of the event at each MenuModule instance
						since menus can be embedded in eachother.
					*/
						
					this._oEventUtil.stopPropagation(p_oEvent);

				};


/**
* "mouseover" event handler for the MenuModule's root HTMLDivElement node.
* @private
* @param {Event} p_oEvent Event object passed back by the event
* utility (YAHOO.util.Event).
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance 
* corresponding to the HTMLDivElement that fired the event.
*/
YAHOO.widget.MenuModule.prototype._onElementMouseOver = 

				function(p_oEvent, p_oMenuModule) {

					var oTarget = this._oEventUtil.getTarget(p_oEvent, true);
				
					if(
						(
							oTarget == this.element || 
							this._oDom.isAncestor(this.element, oTarget)
						)  && 
						!this._bFiredMouseOverEvent
					) {
				
						// Fire the "mouseover" Custom Event for the MenuModule instance
				
						this.mouseOverEvent.fire(p_oEvent);
				
						this._bFiredMouseOverEvent = true;
						this._bFiredMouseOutEvent = false;
				
					}
				
				
					/*
						Check if the target was an element that is a part of an item
						and (if so), fire the "mouseover" Custom Event.
					*/
				
					if(!this._oCurrentItem) {
				
						this._oCurrentItem = 
							this._fireItemEvent(oTarget, "mouseOverEvent", p_oEvent);
				
					}
				
				
					/*
						Stop the propagation of the event at each MenuModule instance
						since menus can be embedded in eachother.
					*/
				
					this._oEventUtil.stopPropagation(p_oEvent);

				};


/**
* "mouseout" event handler for the MenuModule's root HTMLDivElement node.
* @private
* @param {Event} p_oEvent Event object passed back by the event
* utility (YAHOO.util.Event).
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance 
* corresponding to the HTMLDivElement that fired the event.
*/
YAHOO.widget.MenuModule.prototype._onElementMouseOut = 

				function(p_oEvent, p_oMenuModule) {

					var oRelatedTarget = this._oEventUtil.getRelatedTarget(p_oEvent),
						bLIMouseOut = true,
						bMovingToSubmenu = false;
				
				
					// Determine where the mouse is going
				
					if(this._oCurrentItem && oRelatedTarget) {
				
						if(
							oRelatedTarget == this._oCurrentItem.element || 

							this._oDom.isAncestor(
									this._oCurrentItem.element, 
									oRelatedTarget
								)
						) {
				
							bLIMouseOut = false;
				
						}
				
				
						var oSubmenu = this._oCurrentItem.cfg.getProperty("submenu");
				
						if(
							oSubmenu && 
							(
								oRelatedTarget == oSubmenu.element ||
								this._oDom.isAncestor(oSubmenu.element, oRelatedTarget)
							)
						) {
				
							bMovingToSubmenu = true;
				
						}
				
					}
				
				
					if(this._oCurrentItem && (bLIMouseOut || bMovingToSubmenu)) {
				
						// Fire the "mouseout" Custom Event for the item
				
						this._oCurrentItem.mouseOutEvent.fire(p_oEvent);
				
						this._oCurrentItem = null;
				
					}
				
				
					if(
						!this._bFiredMouseOutEvent && 
						(
							!this._oDom.isAncestor(this.element, oRelatedTarget) ||
							bMovingToSubmenu
						)
					) {
				
						// Fire the "mouseout" Custom Event for the MenuModule instance
				
						this.mouseOutEvent.fire(p_oEvent);
				
						this._bFiredMouseOutEvent = true;
						this._bFiredMouseOverEvent = false;
				
					}
				
				
					/*
						Stop the propagation of the event at each MenuModule instance
						since menus can be embedded in eachother.
					*/
				
					this._oEventUtil.stopPropagation(p_oEvent);

				};


/**
* "click" event handler for the MenuModule's root HTMLDivElement node.
* @private
* @param {Event} p_oEvent Event object passed back by the 
* event utility (YAHOO.util.Event).
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance 
* corresponding to the HTMLDivElement that fired the event.
*/         
YAHOO.widget.MenuModule.prototype._onElementClick = 

				function(p_oEvent, p_oMenuModule) {

					var oTarget = this._oEventUtil.getTarget(p_oEvent, true),
				
						/*
							Check if the target was a DOM element that is a part of an
							item and (if so), fire the associated "click" 
							Custom Event.
						*/
					
						oItem = this._fireItemEvent(oTarget, "clickEvent", p_oEvent),
				
						bCurrentPageURL; // Indicates if the URL points to the current page
				
				
					if(oItem) {
				
						var sURL = oItem.cfg.getProperty("url"),
							oSubmenu = oItem.cfg.getProperty("submenu");
						
						bCurrentPageURL = (sURL.substr((sURL.length-1),1) == "#");
				
						/*
							ACCESSIBILITY FEATURE FOR SCREEN READERS: Expand/collapse the
							submenu when the user clicks on the submenu indicator image.
						*/        
				
						if(oTarget == oItem.subMenuIndicator && oSubmenu) {

							if(oSubmenu.cfg.getProperty("visible")) {
					
								oSubmenu.hide();
					
							}
							else {

								var oActiveItem = this.activeItem;
						   

								// Hide any other submenus that might be visible
							
								if(oActiveItem && oActiveItem != this) {
							
									this.clearActiveItem();
							
								}

								this.activeItem = oItem;
					
								oItem.cfg.setProperty("selected", true);

								oSubmenu.show();
					
							}                
					
						}
						else if(!bCurrentPageURL) {
							
							/*
								Follow the URL of the item regardless of whether or 
								not the user clicked specifically on the
								HTMLAnchorElement (&#60;A&#60;) node.
							*/
				
							document.location = sURL;
					
						}
					
					}
						
				
					switch(oTarget.tagName) {
					
						case "A":
						
							if(bCurrentPageURL) {
				
								// Don't follow URLs that are equal to "#"
				
								this._oEventUtil.preventDefault(p_oEvent);
							
							}
							else {
				
								/*
									Break if the anchor's URL is something other than "#" 
									to prevent the call to "stopPropagation" from be 
									executed.  This is required for Safari to be able to 
									follow the URL.
								*/
							
								break;
							
							}
						
						default:
				
							/*
								Stop the propagation of the event at each MenuModule 
								instance since Menus can be embedded in eachother.
							*/
				
							this._oEventUtil.stopPropagation(p_oEvent);
						
						break;
					
					}
				
				
					// Fire the associated "click" Custom Event for the MenuModule instance
				
					this.clickEvent.fire(p_oEvent);

				};


// Private Custom Event handlers

/**
* Iterates the source element's childNodes collection and uses the child 
* nodes to instantiate MenuModule and MenuModuleItem instances.
* @private
*/
YAHOO.widget.MenuModule.prototype._initSubTree = function() {

				var oNode;

				switch(this.srcElement.tagName) {

					case "DIV":

						if(this._aListElements.length > 0) {

							var i = this._aListElements.length - 1;

							do {
					
								oNode = this._aListElements[i].firstChild;
				
								do {
				
									switch(oNode.tagName) {
					
										case "LI":
					
											this.addItem(new this.ITEM_TYPE(oNode), i);
					
										break;
					
									}
						
								}
								while((oNode = oNode.nextSibling));
						
							}
							while(i--);

						}

					break;

					case "SELECT":

						oNode = this.srcElement.firstChild;

						do {

							switch(oNode.tagName) {

								case "OPTGROUP":
								case "OPTION":

									this.addItem(new this.ITEM_TYPE(oNode));

								break;

							}

						}
						while((oNode = oNode.nextSibling));

					break;

				}

};


/**
* "beforerender" Custom Event handler for a MenuModule instance.  Appends all 
* of the HTMLUListElement (&#60;UL&#60;s) nodes (and their child 
* HTMLLIElement (&#60;LI&#60;)) nodes and their accompanying title nodes to  
* the body of the MenuModule instance.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance that 
* fired the event.
*/
YAHOO.widget.MenuModule.prototype._onBeforeRender = 

				function(p_sType, p_aArguments, p_oMenuModule) {

					if(this.cfg.getProperty("position") == "static") {
				
						this.cfg.queueProperty("iframe", false);
						this.cfg.queueProperty("visible", true);
						
					}
				
					var nListElements = this._aListElements.length;
				
					if(nListElements > 0) {
				
						var i = 0, 
							bFirstList = true,
							oUL,
							oGroupTitle;
				
				
						do {
				
							oUL = this._aListElements[i];
				
							if(oUL) {
				
								if(bFirstList) {
						
									this._oDom.addClass(oUL, "first");
									bFirstList = false;
						
								}
				
				
								if(!this._oDom.isAncestor(this.element, oUL)) {
				
									this.appendToBody(oUL);
				
								}
				
				
								oGroupTitle = this._aGroupTitleElements[i];
				
								if(oGroupTitle) {
				
									if(!this._oDom.isAncestor(this.element, oGroupTitle)) {
				
										oUL.parentNode.insertBefore(oGroupTitle, oUL);
				
									}
				
				
									this._oDom.addClass(oUL, "hastitle");
				
								}
				
							}
				
							i++;
				
						}
						while(i < nListElements);
				
					}

				};


/**
* "render" Custom Event handler for a MenuModule instance.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance that 
* fired the event.
*/
YAHOO.widget.MenuModule.prototype._onRender = 

				function(p_sType, p_aArguments, p_oMenuModule) {

					if(this.cfg.getProperty("position") == "dynamic") {
				
						var sWidth = this.element.parentNode.tagName == "BODY" ? 
								this.element.offsetWidth : this._getOffsetWidth();
					
						this.cfg.setProperty("width", (sWidth + "px"));
				
					}

				};


/**
* "show" Custom Event handler for a MenuModule instance.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance that 
* fired the event.
*/
YAHOO.widget.MenuModule.prototype._onShow = 

				function(p_sType, p_aArguments, p_oMenuModule) {
				
					/*
						Setting focus to an item in the newly visible submenu alerts the 
						contents of the submenu to the screen reader.
					*/

					this.setInitialFocus();
				
				};


/**
* "hide" Custom Event handler for a MenuModule instance.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance that 
* fired the event.
*/
YAHOO.widget.MenuModule.prototype._onHide = 

				function(p_sType, p_aArguments, p_oMenuModule) {

					if(this.activeItem) {
				
						if(this.activeItem.cfg.getProperty("selected")) {
				
							this.activeItem.cfg.setProperty("selected", false);
							this.activeItem.blur();
				
						}
				
						var oSubmenu = this.activeItem.cfg.getProperty("submenu");
				
						if(oSubmenu && oSubmenu.cfg.getProperty("visible")) {
				
							oSubmenu.hide();
				
						}
				
					}

				};


/**
* "configchange" Custom Event handler for a submenu.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oSubmenu The submenu that subscribed
* to the event.
*/
YAHOO.widget.MenuModule.prototype._onParentMenuModuleConfigChange = 

				function(p_sType, p_aArguments, p_oSubmenu) {
				
					var sPropertyName = p_aArguments[0][0],
						oPropertyValue = p_aArguments[0][1];
				
					switch(sPropertyName) {
				
						case "iframe":
						case "constraintoviewport":
						case "submenualignment":
				
							p_oSubmenu.cfg.setProperty(sPropertyName, oPropertyValue);
								
						break;        
						
					}
				
				};


/**
* "render" Custom Event handler for a MenuModule instance.  Renders a submenu in 
* response to the firing of it's parent's "render" event.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oSubmenu The submenu that subscribed
* to the event.
*/
YAHOO.widget.MenuModule.prototype._onParentMenuModuleRender = 

				function(p_sType, p_aArguments, p_oSubmenu) {

					/*
						Set the "iframe" and "constraintoviewport" configuration 
						properties to match the parent MenuModule
					*/ 
				
					var oParentMenu = p_oSubmenu.parent.parent;
				
					p_oSubmenu.cfg.applyConfig(
					
						{
							constraintoviewport: 
								oParentMenu.cfg.getProperty("constraintoviewport"),
				
							xy: [0,0],
				
							iframe: oParentMenu.cfg.getProperty("iframe")
				
						}
					
					);
				
				
					if(this._oDom.inDocument(this.element)) {
				
						this.render();
				
					}
					else {
				
						this.render(this.parent.element);
				
					}
				
				};


/**
* "beforeshow" Custom Event handler for a submenu.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oSubmenu The submenu that fired
* the event.
*/
YAHOO.widget.MenuModule.prototype._onSubmenuBeforeShow = 

				function(p_sType, p_aArguments, p_oSubmenu) {
				
					var aAlignment = this.parent.parent.cfg.getProperty("submenualignment");

					this.cfg.setProperty(
						"submenualignment", 
						[ aAlignment[0], aAlignment[1] ]
					);

					this.cfg.setProperty(
						"context", 
						[
							this.parent.element, 
							aAlignment[0], 
							aAlignment[1]
						]
					);

					this.parent.subMenuIndicator.alt = 
						this.parent.EXPANDED_SUBMENU_INDICATOR_ALT_TEXT;
				
				};


/**
* "show" Custom Event handler for a submenu.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oSubmenu The submenu that fired
* the event.
*/
YAHOO.widget.MenuModule.prototype._onSubmenuShow = 

				function(p_sType, p_aArguments, p_oSubmenu) {
				
					this.parent.subMenuIndicator.alt = 
						this.parent.EXPANDED_SUBMENU_INDICATOR_ALT_TEXT;
				
				};


/**
* "hide" Custom Event handler for a submenu.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oSubmenu The submenu that fired
* the event.
*/
YAHOO.widget.MenuModule.prototype._onSubmenuHide = 

				function(p_sType, p_aArguments, p_oSubmenu) {
				
					if(this.parent.parent.cfg.getProperty("visible")) {

						this.parent.cfg.setProperty("selected", false);
				
						this.parent.focus();
					
					}

					this.parent.subMenuIndicator.alt = 
						this.parent.COLLAPSED_SUBMENU_INDICATOR_ALT_TEXT;
				
				};


/**
* "focus" YAHOO.util.CustomEvent handler for a MenuModule instance's items.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {Array} p_aObjects Array containing the current MenuModule instance 
* and the item that fired the event.
*/
YAHOO.widget.MenuModule.prototype._onItemFocus = 

				function(p_sType, p_aArguments, p_aObjects) {
				
					var me = p_aObjects[0],
						oItem = p_aObjects[1];
				
					me.activeItem = oItem;
				
				};


/**
* "blur" YAHOO.util.CustomEvent handler for a MenuModule instance's items.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {Array} p_aObjects Array containing the current MenuModule instance 
* and the item that fired the event.
*/
YAHOO.widget.MenuModule.prototype._onItemBlur = 

				function(p_sType, p_aArguments, p_aObjects) {
				
					var me = p_aObjects[0],
						oItem = p_aObjects[1],
						oSubmenu = oItem.cfg.getProperty("submenu");
				
					if(!oSubmenu || (oSubmenu && !oSubmenu.cfg.getProperty("visible"))) {
				
						me.activeItem = null;
				
					}
				
				};


/**
* "configchange" YAHOO.util.CustomEvent handler for the MenuModule 
* instance's items.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the 
* event was fired.
* @param {Array} p_aObjects Array containing the current MenuModule instance 
* and the item that fired the event.
*/
YAHOO.widget.MenuModule.prototype._onItemConfigChange = 

				function(p_sType, p_aArguments, p_aObjects) {
				
					var sProperty = p_aArguments[0][0],
						me = p_aObjects[0],
						oItem = p_aObjects[1];
				
					switch(sProperty) {
				
						case "submenu":
				
							var oSubmenu = p_aArguments[0][1];
				
							if(oSubmenu) {
				
								me._configureItemSubmenuModule(oItem);
				
							}
				
						break;
				
						case "text":
						case "helptext":
				
							/*
								A change to an item's "text" or "helptext"
								configuration properties requires the width of the parent
								MenuModule instance to be recalculated.
							*/
				
							if(me.element.style.width) {
					
								var sWidth = me._getOffsetWidth() + "px";
				
								me._oDom.setStyle(me.element, "width", sWidth);
				
							}
				
						break;
				
					}
				
				};


/**
* The default event handler executed when the moveEvent is fired, if the 
* "constraintoviewport" configuration property is set to true.
*/
YAHOO.widget.MenuModule.prototype.enforceConstraints = 

				function(type, args, obj) {
				
					var pos = args[0],
				
						x = pos[0],
						y = pos[1],
				
						bod = document.getElementsByTagName('body')[0],
						htm = document.getElementsByTagName('html')[0],
					
						bodyOverflow = YAHOO.util.Dom.getStyle(bod, "overflow"),
						htmOverflow = YAHOO.util.Dom.getStyle(htm, "overflow"),
				
						offsetHeight = this.element.offsetHeight,
						offsetWidth = this.element.offsetWidth,
					
						viewPortWidth = YAHOO.util.Dom.getClientWidth(),
						viewPortHeight = YAHOO.util.Dom.getClientHeight(),
					
						scrollX = window.scrollX || document.body.scrollLeft,
						scrollY = window.scrollY || document.body.scrollTop,
					
						topConstraint = scrollY + 10,
						leftConstraint = scrollX + 10,
						bottomConstraint = scrollY + viewPortHeight - offsetHeight - 10,
						rightConstraint = scrollX + viewPortWidth - offsetWidth - 10,
					
						aContext = this.cfg.getProperty("context"),
						oContextElement = aContext ? aContext[0] : null;
				
				
					if (x < 10) {
				
						x = leftConstraint;
				
					} else if ((x + offsetWidth) > viewPortWidth) {
				
						if(
							oContextElement && 
							((x - oContextElement.offsetWidth) > offsetWidth)
						) {
				
							x = (x - (oContextElement.offsetWidth + offsetWidth));
				
						}
						else {
				
							x = rightConstraint;
				
						}
				
					}
				
					if (y < 10) {
				
						y = topConstraint;
				
					} else if (y > bottomConstraint) {
				
						if(oContextElement && (y > offsetHeight)) {
				
							y = ((y + oContextElement.offsetHeight) - offsetHeight);
				
						}
						else {
				
							y = bottomConstraint;
				
						}
				
					}
				
					this.cfg.setProperty("x", x, true);
					this.cfg.setProperty("y", y, true);
				
				};


// Event handlers for configuration properties

/**
* Event handler for when the "position" configuration property of a
* MenuModule changes.
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance fired
* the event.
* @see YAHOO.widget.Overlay#configIframe
*/
YAHOO.widget.MenuModule.prototype.configPosition = 

				function(p_sType, p_aArguments, p_oMenuModule) {

					var sCSSPosition = 'relative'; // p_aArguments[0] == "static" ? "static" : "absolute"; // Edit (Ryan)
				
					this._oDom.setStyle(this.element, "position", sCSSPosition);
				
				};


// Public methods

/**
* Sets the title of a group of items.
* @param {String} p_sGroupTitle The title of the group.
* @param {Number} p_nGroupIndex Optional. Number indicating the group to which
* the title belongs.
*/
YAHOO.widget.MenuModule.prototype.setItemGroupTitle = 

				function(p_sGroupTitle, p_nGroupIndex) {
					
					if(typeof p_sGroupTitle == "string" && p_sGroupTitle.length > 0) {
				
						var nGroupIndex = 
								typeof p_nGroupIndex == "number" ? p_nGroupIndex : 0,
				
							oTitle = this._aGroupTitleElements[nGroupIndex];
				
				
						if(oTitle) {
				
							oTitle.innerHTML = p_sGroupTitle;
							
						}
						else {
				
							oTitle = document.createElement(this.GROUP_TITLE_TAG_NAME);
									
							oTitle.innerHTML = p_sGroupTitle;
				
							this._aGroupTitleElements[nGroupIndex] = oTitle;
				
						}
				
				
						var i = this._aGroupTitleElements.length - 1,
							nFirstIndex;
				
						do {
				
							if(this._aGroupTitleElements[i]) {
				
								this._oDom.removeClass(
									this._aGroupTitleElements[i],
									"first"
								);

								nFirstIndex = i;
				
							}
				
						}
						while(i--);
				
				
						if(nFirstIndex !== null) {
				
							this._oDom.addClass(
								this._aGroupTitleElements[nFirstIndex], 
								"first"
							);
				
						}
				
					}
				
				};


/**
* Appends the specified item to a MenuModule instance.
* @param {YAHOO.widget.MenuModuleItem} p_oItem The item to be added.
* @param {Number} p_nGroupIndex Optional. Number indicating the group to which
* the item belongs.
* @return The item that was added to the MenuModule.
* @type YAHOO.widget.MenuModuleItem
*/
YAHOO.widget.MenuModule.prototype.addItem = function(p_oItem, p_nGroupIndex) {

				if(p_oItem && p_oItem instanceof YAHOO.widget.MenuModuleItem) {

					return this._addItemToGroup(p_nGroupIndex, p_oItem);

				}

};


/**
* Inserts an item into a MenuModule instance at the specified index.
* @param {YAHOO.widget.MenuModuleItem} p_oItem The item to be inserted.
* @param {Number} p_nItemIndex Number indicating the ordinal position 
* at which the item should be added.
* @param {Number} p_nGroupIndex Optional. Number indicating the group to which
* the item belongs.
* @return The item that was inserted into the MenuModule.
* @type YAHOO.widget.MenuModuleItem
*/
YAHOO.widget.MenuModule.prototype.insertItem = 

				function(p_oItem, p_nItemIndex, p_nGroupIndex) {
				
					if(p_oItem && p_oItem instanceof YAHOO.widget.MenuModuleItem) {
				
						return this._addItemToGroup(p_nGroupIndex, p_oItem, p_nItemIndex);
				
					}
				
				};


/**
* Removes the specified item from a MenuModule instance.
* @param {YAHOO.widget.MenuModuleItem/Number} p_oObject The item or index of the
* item to be removed.
* @param {Number} p_nGroupIndex Optional. Number indicating the group to which
* the item belongs.
* @return The item that was removed from the MenuModule.
* @type YAHOO.widget.MenuModuleItem
*/
YAHOO.widget.MenuModule.prototype.removeItem =

				function(p_oObject, p_nGroupIndex) {
				
					if(typeof p_oObject != "undefined") {
				
						var oItem;
				
						if(p_oObject instanceof YAHOO.widget.MenuModuleItem) {
				
							oItem = 
								this._removeItemFromGroupByValue(p_nGroupIndex, p_oObject);           
				
						}
						else if(typeof p_oObject == "number") {
				
							oItem = 
								this._removeItemFromGroupByIndex(p_nGroupIndex, p_oObject);
				
						}
				
						if(oItem) {
				
							oItem.destroy();
				
							return oItem;
				
						}
				
					}
				
				};


/**
* Returns a multi-dimensional array of all of a MenuModule's items.
* @return An array of items.
* @type Array
*/        
YAHOO.widget.MenuModule.prototype.getItemGroups = function() {

				return this._aItemGroups;

};


/**
* Returns the item at the specified index.
* @param {Number} p_nItemIndex Number indicating the ordinal position of the 
* item to be retrieved.
* @param {Number} p_nGroupIndex Optional. Number indicating the group to which
* the item belongs.
* @return An item.
* @type YAHOO.widget.MenuModuleItem
*/
YAHOO.widget.MenuModule.prototype.getItem = 

				function(p_nItemIndex, p_nGroupIndex) {
				
					if(typeof p_nItemIndex == "number") {
				
						var aGroup = this._getItemGroup(p_nGroupIndex);
				
						if(aGroup) {
				
							return aGroup[p_nItemIndex];
						
						}
				
					}
				
				};


/**
* Removes the MenuModule instance's element from the DOM and sets all child 
* elements to null.
*/
YAHOO.widget.MenuModule.prototype.destroy = function() {

				// Remove DOM event handlers

				this._oEventUtil.removeListener(
					this.element, 
					"mouseover", 
					this._onElementMouseOver
				);

				this._oEventUtil.removeListener(
					this.element, 
					"mouseout", 
					this._onElementMouseOut
				);

				this._oEventUtil.removeListener(
					this.element, 
					"click", 
					this._onElementClick
				);

				this._oEventUtil.removeListener(
					this.element, 
					"mousedown", 
					this._onDOMEvent
					);

				this._oEventUtil.removeListener(this.element, "mouseup", this._onDOMEvent);

				this._oEventUtil.removeListener(this.element, "keydown", this._onDOMEvent);

				this._oEventUtil.removeListener(this.element, "keyup", this._onDOMEvent);

				this._oEventUtil.removeListener(this.element, "keypress", this._onDOMEvent);


				// Remove Custom Event listeners

				this.mouseOverEvent.unsubscribeAll();
				this.mouseOutEvent.unsubscribeAll();
				this.mouseDownEvent.unsubscribeAll();
				this.mouseUpEvent.unsubscribeAll();
				this.clickEvent.unsubscribeAll();
				this.keyPressEvent.unsubscribeAll();
				this.keyDownEvent.unsubscribeAll();
				this.keyUpEvent.unsubscribeAll();
				this.beforeMoveEvent.unsubscribeAll();


				var nItemGroups = this._aItemGroups.length,
					nItems,
					i,
					n;


				// Remove all items

				if(nItemGroups > 0) {

					i = nItemGroups - 1;

					do {

						if(this._aItemGroups[i]) {

							nItems = this._aItemGroups[i].length;
				
							if(nItems > 0) {
				
								n = nItems - 1;
					
								do {

									if(this._aItemGroups[i][n]) {
					
										this._aItemGroups[i][n].destroy();
									}
					
								}
								while(n--);
				
							}

						}

					}
					while(i--);

				}        


				// Continue with the superclass implementation of this method

				YAHOO.widget.MenuModule.superclass.destroy.call(this);

};




/**
* Sets focus to a MenuModule instance's first enabled item.
*/
YAHOO.widget.MenuModule.prototype.setInitialFocus = function() {

				var oItem = this._getFirstEnabledItem();
				
				if(oItem) {
				
					oItem.focus();
				}
				
};


/**
* Sets the "selected" configuration property of a MenuModule instance's first
* enabled item to "true."
*/
YAHOO.widget.MenuModule.prototype.setInitialSelection = function() {

				var oItem = this._getFirstEnabledItem();
				
				if(oItem) {
				
					oItem.cfg.setProperty("selected", true);
				}        

};


/**
* Sets the "selected" configuration property of a MenuModule instance's active 
* item to "false," blurs the item and hide's the item's submenu.
*/
YAHOO.widget.MenuModule.prototype.clearActiveItem = function () {

				var oActiveItem = this.activeItem;

				if(oActiveItem) {

					oActiveItem.cfg.setProperty("selected", false);

					var oSubmenu = oActiveItem.cfg.getProperty("submenu");

					if(oSubmenu) {

						oSubmenu.hide();

					}

				}

};


/**
* Initializes the class's configurable properties which can be changed using 
* the MenuModule's Config object (cfg).
*/
YAHOO.widget.MenuModule.prototype.initDefaultConfig = function() {

				YAHOO.widget.MenuModule.superclass.initDefaultConfig.call(this);

				// Add configuration properties

				this.cfg.addProperty(
					"position", 
					{
						value: "dynamic", 
						handler: this.configPosition, 
						validator: this._checkPosition 
					} 
				);

				this.cfg.refireEvent("position");

				this.cfg.addProperty("submenualignment", { value: ["tl","tr"] } );

};


/**
* @class The MenuModuleItem class allows you to create and modify an item for a
* MenuModule instance.
* @constructor
* @param {String or HTMLElement} p_oObject String or HTMLElement 
* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the 
* source HTMLElement node.
* @param {Object} p_oUserConfig The configuration object literal containing 
* the configuration for a MenuModuleItem instance. See the configuration 
* class documentation for more details.
*/
YAHOO.widget.MenuModuleItem = function(p_oObject, p_oUserConfig) {

				if(p_oObject) {

					this.init(p_oObject, p_oUserConfig);

				}

};

YAHOO.widget.MenuModuleItem.prototype = {

				// Constants

				/**
				* Constant representing the path to the image to be used for the submenu
				* arrow indicator.
				* @final
				* @type String
				*/
				SUBMENU_INDICATOR_IMAGE_PATH: "nt/ic/ut/alt1/menuarorght9_nrm_1.gif",


				/**
				* Constant representing the path to the image to be used for the submenu
				* arrow indicator when a MenuModuleItem instance has focus.
				* @final
				* @type String
				*/
				SELECTED_SUBMENU_INDICATOR_IMAGE_PATH: 
					"nt/ic/ut/alt1/menuarorght9_hov_1.gif",


				/**
				* Constant representing the path to the image to be used for the submenu
				* arrow indicator when a MenuModuleItem instance is disabled.
				* @final
				* @type String
				*/
				DISABLED_SUBMENU_INDICATOR_IMAGE_PATH: 
					"nt/ic/ut/alt1/menuarorght9_dim_1.gif",


				/**
				* Constant representing the alt text for the image to be used for the 
				* submenu arrow indicator.
				* @final
				* @type String
				*/
				COLLAPSED_SUBMENU_INDICATOR_ALT_TEXT: "Collapsed.  Click to expand.",


				/**
				* Constant representing the alt text for the image to be used for the 
				* submenu arrow indicator when the submenu is visible.
				* @final
				* @type String
				*/
				EXPANDED_SUBMENU_INDICATOR_ALT_TEXT: "Expanded.  Click to collapse.",


				/**
				* Constant representing the alt text for the image to be used for the 
				* submenu arrow indicator when a MenuModuleItem instance is disabled.
				* @final
				* @type String
				*/
				DISABLED_SUBMENU_INDICATOR_ALT_TEXT: "Disabled.",


				/**
				* Constant representing the CSS class(es) to be applied to the root 
				* HTMLLIElement of the MenuModuleItem.
				* @final
				* @type String
				*/
				CSS_CLASS_NAME: "yuimenuitem",


				/**
				* Constant representing the type of menu to instantiate when creating 
				* submenu instances from parsing the child nodes (either HTMLSelectElement 
				* or HTMLDivElement) of the item's DOM.  The default 
				* is YAHOO.widget.MenuModule.
				* @final
				* @type YAHOO.widget.MenuModule
				*/
				SUBMENU_TYPE: null,


				/**
				* Constant representing the type of item to instantiate when 
				* creating item instances from parsing the child nodes (either 
				* HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the 
				* submenu's DOM.  
				* The default is YAHOO.widget.MenuModuleItem.
				* @final
				* @type YAHOO.widget.MenuModuleItem
				*/
				SUBMENU_ITEM_TYPE: null,


				// Private member variables
				
				/**
				* Reference to the HTMLAnchorElement of the MenuModuleItem's core internal
				* DOM structure.
				* @private
				* @type {HTMLAnchorElement}
				*/
				_oAnchor: null,
				

				/**
				* Reference to the text node of the MenuModuleItem's core internal
				* DOM structure.
				* @private
				* @type {Text}
				*/
				_oText: null,
				
				
				/**
				* Reference to the HTMLElement (&#60;EM&#60;) used to create the optional
				* help text for a MenuModuleItem instance.
				* @private
				* @type {HTMLElement}
				*/
				_oHelpTextEM: null,
				
				
				/**
				* Reference to the submenu for a MenuModuleItem instance.
				* @private
				* @type {YAHOO.widget.MenuModule}
				*/
				_oSubmenu: null,
				
				
				/**
				* Reference to the Dom utility singleton.
				* @private
				* @type {YAHOO.util.Dom}
				*/
				_oDom: YAHOO.util.Dom,


				/**
				* Reference to the browser's user agent string.
				* @private
				* @type {String}
				*/
				_sUserAgent: window.navigator.userAgent.toLowerCase(),


				// Public properties

				/**
				* The class's constructor function
				* @type YAHOO.widget.MenuModuleItem
				*/
				constructor: YAHOO.widget.MenuModuleItem,


				/**
				* The string representing the image root
				* @type string
				*/
				imageRoot: YAHOO.widget.Module.IMG_ROOT,


				/**
				* Boolean representing whether or not the current browsing context 
				* is secure (https)
				* @type boolean
				*/
				isSecure: function() {

					if(window.location.href.toLowerCase().indexOf("https") === 0) {

						this.imageRoot = YAHOO.widget.Module.IMG_ROOT_SSL;

						return true;

					} else {

						return false;

					}

				}(),


				/**
				* Returns the ordinal position of a MenuModuleItem instance in a group.
				* @type Number
				*/
				index: null,


				/**
				* Returns the index of the group to which a MenuModuleItem instance belongs.
				* @type Number
				*/
				groupIndex: null,


				/**
				* Returns the parent object for a MenuModuleItem instance.
				* @type {YAHOO.widget.MenuModule}
				*/
				parent: null,


				/**
				* Returns the HTMLLIElement for a MenuModuleItem instance.
				* @type {HTMLLIElement}
				*/
				element: null,


				/**
				* Returns the HTMLElement (either HTMLLIElement, HTMLOptGroupElement or
				* HTMLOptionElement) used create the MenuModuleItem instance.
				* @type {HTMLLIElement/HTMLOptGroupElement/HTMLOptionElement}
				*/
				srcElement: null,


				/**
				* Specifies an arbitrary value for a MenuModuleItem instance.
				* @type {Object}
				*/
				value: null,


				/**
				* Reference to the HTMLImageElement used to create the submenu
				* indicator for a MenuModuleItem instance.
				* @type {HTMLImageElement}
				*/
				subMenuIndicator: null,


				/**
				* String representing the browser
				* @type string
				*/
				browser: function() {

					var sUserAgent = navigator.userAgent.toLowerCase();

					// Opera (check first in case of spoof)
				
					if(sUserAgent.indexOf("opera")!=-1) { 
					
						return "opera";
					
					// IE7

					} else if(sUserAgent.indexOf("msie 7")!=-1) {
					
						return "ie7";
					
					// IE

					} else if(sUserAgent.indexOf("msie") !=-1) {
					
						return "ie";
					
					// Safari (check before Gecko because it includes "like Gecko")

					} else if(sUserAgent.indexOf("safari")!=-1) {
					
						return "safari";
					
					// Gecko

					} else if(sUserAgent.indexOf("gecko") != -1) {
					
						return "gecko";
					
					} else {
					
						return false;
					
					}

				}(),


				// Events

				/**
				* Fires when a MenuModuleItem instances's HTMLLIElement is removed from
				* it's parent HTMLUListElement node.
				* @type {YAHOO.util.CustomEvent}
				* @see YAHOO.util.CustomEvent
				*/
				destroyEvent: null,


				/**
				* Fires when the mouse has entered a MenuModuleItem instance.  Passes
				* back the DOM Event object as an argument.
				* @type {YAHOO.util.CustomEvent}
				* @see YAHOO.util.CustomEvent
				*/
				mouseOverEvent: null,


				/**
				* Fires when the mouse has left a MenuModuleItem instance.  Passes back  
				* the DOM Event object as an argument.
				* @type {YAHOO.util.CustomEvent}
				* @see YAHOO.util.CustomEvent
				*/
				mouseOutEvent: null,


				/**
				* Fires when the user mouses down on a MenuModuleItem instance.  Passes 
				* back the DOM Event object as an argument.
				* @type {YAHOO.util.CustomEvent}
				* @see YAHOO.util.CustomEvent
				*/
				mouseDownEvent: null,


				/**
				* Fires when the user releases a mouse button while the mouse is 
				* over a MenuModuleItem instance.  Passes back the DOM Event object as
				* an argument.
				* @type {YAHOO.util.CustomEvent}
				* @see YAHOO.util.CustomEvent
				*/
				mouseUpEvent: null,


				/**
				* Fires when the user clicks the on a MenuModuleItem instance.  Passes 
				* back the DOM Event object as an argument.
				* @type {YAHOO.util.CustomEvent}
				* @see YAHOO.util.CustomEvent
				*/
				clickEvent: null,


				/**
				* Fires when the user presses an alphanumeric key.  Passes back the 
				* DOM Event object as an argument.
				* @type {YAHOO.util.CustomEvent}
				* @see YAHOO.util.CustomEvent
				*/
				keyPressEvent: null,


				/**
				* Fires when the user presses a key.  Passes back the DOM Event 
				* object as an argument.
				* @type {YAHOO.util.CustomEvent}
				* @see YAHOO.util.CustomEvent
				*/
				keyDownEvent: null,


				/**
				* Fires when the user releases a key.  Passes back the DOM Event 
				* object as an argument.
				* @type {YAHOO.util.CustomEvent}
				* @see YAHOO.util.CustomEvent
				*/
				keyUpEvent: null,


				/**
				* Fires when a MenuModuleItem instance receives focus.
				* @type {YAHOO.util.CustomEvent}
				* @see YAHOO.util.CustomEvent
				*/
				focusEvent: null,


				/**
				* Fires when a MenuModuleItem instance loses the input focus.
				* @type {YAHOO.util.CustomEvent}
				* @see YAHOO.util.CustomEvent
				*/
				blurEvent: null,


				/**
				* The MenuModuleItem class's initialization method. This method is 
				* automatically called by the constructor, and sets up all DOM references 
				* for pre-existing markup, and creates required markup if it is not
				* already present.
				* @param {String or HTMLElement} p_oObject String or HTMLElement 
				* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the 
				* source HTMLElement node.
				* @param {Object} p_oUserConfig The configuration object literal containing 
				* the configuration for a MenuModuleItem instance. See the configuration 
				* class documentation for more details.
				*/
				init: function(p_oObject, p_oUserConfig) {

					if(!this.SUBMENU_TYPE) {
				
						this.SUBMENU_TYPE = YAHOO.widget.MenuModule;
				
					}

					if(!this.SUBMENU_ITEM_TYPE) {
				
						this.SUBMENU_ITEM_TYPE = YAHOO.widget.MenuModuleItem;
				
					}


					// Create the config object

					this.cfg = new YAHOO.util.Config(this);


					// Define the config properties


					this.cfg.addProperty(
						"text", 
						{ 
							value:"", 
							handler: this.configText, 
							validator: this._checkString, 
							suppressEvent: true 
						}
					);
					
					this.cfg.addProperty("helptext", { handler: this.configHelpText });
					
					this.cfg.addProperty(
						"url", 
						{ value: "#", handler: this.configURL, suppressEvent: true }
					);
					
					this.cfg.addProperty(
						"emphasis", 
						{ 
							value: false, 
							handler: this.configEmphasis, 
							validator: this.cfg.checkBoolean, 
							suppressEvent: true 
						}
					);
					
					this.cfg.addProperty(
						"strongemphasis", 
						{
							value: false, 
							handler: this.configStrongEmphasis, 
							validator: this.cfg.checkBoolean, 
							suppressEvent: true 
						}
					);
					
					this.cfg.addProperty(
						"disabled", 
						{
							value: false, 
							handler: this.configDisabled, 
							validator: this.cfg.checkBoolean, 
							suppressEvent: true 
						}
					);
					
					this.cfg.addProperty(
						"selected", 
						{
							value: false, 
							handler: this.configSelected, 
							validator: this.cfg.checkBoolean, 
							suppressEvent: true 
						}
					);
					
					this.cfg.addProperty("submenu", { handler: this.configSubmenu });


					if(this._checkString(p_oObject)) {

						this._createRootNodeStructure();

						this.cfg.setProperty("text", p_oObject);

					}
					else if(this._checkDOMNode(p_oObject)) {

						switch(p_oObject.tagName) {

							case "OPTION":

								this._createRootNodeStructure();

								this.cfg.setProperty("text", p_oObject.text);

								this.srcElement = p_oObject;

							break;

							case "OPTGROUP":

								this._createRootNodeStructure();

								this.cfg.setProperty("text", p_oObject.label);

								this.srcElement = p_oObject;

								this._initSubTree();

							break;

							case "LI":

								// Get the anchor node (if it exists)

								var oAnchor = this._getFirstElement(p_oObject, "A"),
									sURL = null,
									sText = null;


								// Capture the "text" and/or the "URL"

								if(oAnchor) {

									sURL = oAnchor.getAttribute("href");

									if(oAnchor.innerText) {
							
										sText = oAnchor.innerText;
							
									}
									else {
							
										var oRange = oAnchor.ownerDocument.createRange();
							
										oRange.selectNodeContents(oAnchor);
							
										sText = oRange.toString();             
							
									}

								}
								else {

									var oText = p_oObject.firstChild;

									sText = oText.nodeValue;

									oAnchor = document.createElement("a");

									p_oObject.replaceChild(oAnchor, oText);
									
									oAnchor.appendChild(oText);

								}


								this.srcElement = p_oObject;
								this.element = p_oObject;
								this._oAnchor = oAnchor;
				

								// Check if emphasis has been applied to the MenuModuleItem

								var oEmphasisNode = this._getFirstElement(oAnchor),
									bEmphasis = false,
									bStrongEmphasis = false;

								if(oEmphasisNode) {

									// Set a reference to the text node 

									this._oText = oEmphasisNode.firstChild;

									switch(oEmphasisNode.tagName) {

										case "EM":

											bEmphasis = true;

										break;

										case "STRONG":

											bStrongEmphasis = true;

										break;

									}

								}
								else {

									// Set a reference to the text node 

									this._oText = oAnchor.firstChild;

								}


								/*
									Set these properties silently to sync up the 
									configuration object without making changes to the 
									element's DOM
								*/ 

								this.cfg.setProperty("text", sText, true);
								this.cfg.setProperty("url", sURL, true);
								this.cfg.setProperty("emphasis", bEmphasis, true);
								this.cfg.setProperty(
									"strongemphasis", 
									bStrongEmphasis, 
									true
								);

								this._initSubTree();

							break;

						}            

					}


					if(this.element) {


						this._oDom.addClass(this.element, this.CSS_CLASS_NAME);


						// Create custom events
				
						var CustomEvent = YAHOO.util.CustomEvent;
				
						this.destroyEvent = new CustomEvent("destroyEvent", this);
						this.mouseOverEvent = new CustomEvent("mouseOverEvent", this);
						this.mouseOutEvent = new CustomEvent("mouseOutEvent", this);
						this.mouseDownEvent = new CustomEvent("mouseDownEvent", this);
						this.mouseUpEvent = new CustomEvent("mouseUpEvent", this);
						this.clickEvent = new CustomEvent("clickEvent", this);
						this.keyPressEvent = new CustomEvent("keyPressEvent", this);
						this.keyDownEvent = new CustomEvent("keyDownEvent", this);
						this.keyUpEvent = new CustomEvent("keyUpEvent", this);
						this.focusEvent = new CustomEvent("focusEvent", this);
						this.blurEvent = new CustomEvent("blurEvent", this);


						if(p_oUserConfig) {
				
							this.cfg.applyConfig(p_oUserConfig);
				
						}        

						this.cfg.fireQueue();

					}

				},


				// Private methods

				/**
				* Returns an HTMLElement's first HTMLElement node
				* @private
				* @param {HTMLElement} p_oElement The element to be evaluated.
				* @param {String} p_sTagName Optional. The tagname of the element.
				* @return Returns an HTMLElement node.
				* @type Boolean
				*/
				_getFirstElement: function(p_oElement, p_sTagName) {

					var oElement;

					if(p_oElement.firstChild && p_oElement.firstChild.nodeType == 1) {

						oElement = p_oElement.firstChild;

					}
					else if(
						p_oElement.firstChild && 
						p_oElement.firstChild.nextSibling && 
						p_oElement.firstChild.nextSibling.nodeType == 1
					) {

						oElement = p_oElement.firstChild.nextSibling;

					}


					if(p_sTagName) {

						return (oElement && oElement.tagName == p_sTagName) ? 
							oElement : false;

					}

					return oElement;

				},


				/**
				* Determines if an object is a string
				* @private
				* @param {Object} p_oObject The object to be evaluated.
				* @return Returns true if the object is a string.
				* @type Boolean
				*/
				_checkString: function(p_oObject) {

					return (typeof p_oObject == "string");

				},


				/**
				* Determines if an object is an HTMLElement.
				* @private
				* @param {Object} p_oObject The object to be evaluated.
				* @return Returns true if the object is an HTMLElement.
				* @type Boolean
				*/
				_checkDOMNode: function(p_oObject) {

					return (p_oObject && p_oObject.tagName);

				},


				/**
				* Creates the core DOM structure for a MenuModuleItem instance.
				* @private
				*/
				_createRootNodeStructure: function () {

					this.element = document.createElement("li");

					this._oText = document.createTextNode("");

					this._oAnchor = document.createElement("a");
					this._oAnchor.appendChild(this._oText);
					
					this.cfg.refireEvent("url");

					this.element.appendChild(this._oAnchor);            

				},


				/**
				* Iterates the source element's childNodes collection and uses the  
				* child nodes to instantiate other menus.
				* @private
				*/
				_initSubTree: function() {

					var Menu = this.SUBMENU_TYPE,
						MenuModuleItem = this.SUBMENU_ITEM_TYPE;


					if(this.srcElement.childNodes.length > 0) {

						var oNode = this.srcElement.firstChild,
							aOptions = [];

						do {

							switch(oNode.tagName) {
					
								case "DIV":
					
									this.cfg.setProperty("submenu", (new Menu(oNode)));
					
								break;
			 
								case "OPTION":

									aOptions[aOptions.length] = oNode;

								break;
				   
							}
						
						}        
						while((oNode = oNode.nextSibling));


						var nOptions = aOptions.length;

						if(nOptions > 0) {
				
							this.cfg.setProperty(
								"submenu", 
								(new Menu(this._oDom.generateId()))
							);
				
							for(var n=0; n<nOptions; n++) {
				
								this._oSubmenu.addItem((new MenuModuleItem(aOptions[n])));
				
							}
				
						}

					}

				},


				// Event handlers for configuration properties

				/**
				* Event handler for when the "text" configuration property of
				* a MenuModuleItem instance changes. 
				* @param {String} p_sType The name of the event that was fired.
				* @param {Array} p_aArguments Collection of arguments sent when the 
				* event was fired.
				* @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance 
				* that fired the event.
				*/
				configText: function(p_sType, p_aArguments, p_oItem) {

					var sText = p_aArguments[0];


					if(this._oText) {

						this._oText.nodeValue = sText;

					}

				},


				/**
				* Event handler for when the "helptext" configuration property of
				* a MenuModuleItem instance changes. 
				* @param {String} p_sType The name of the event that was fired.
				* @param {Array} p_aArguments Collection of arguments sent when the 
				* event was fired.
				* @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance 
				* that fired the event.
				*/    
				configHelpText: function(p_sType, p_aArguments, p_oItem) {

					var oHelpText = p_aArguments[0],
						aNodes = [this.element, this._oAnchor],
						me = this;


					/**
					* Adds the "hashelptext" class to the necessary nodes and refires the 
					* "selected" and "disabled" configuration events
					* @ignore
					*/
					function initHelpText() {

						me._oDom.addClass(aNodes, "hashelptext");

						if(me.cfg.getProperty("disabled")) {

							me.cfg.refireEvent("disabled");

						}

						if(me.cfg.getProperty("selected")) {

							me.cfg.refireEvent("selected");

						}                

					}


					/**
					* Removes the "hashelptext" class and corresponding DOM element (EM)
					* @ignore
					*/
					function removeHelpText() {

						me._oDom.removeClass(aNodes, "hashelptext");

						me.element.removeChild(me._oHelpTextEM);
						me._oHelpTextEM = null;

					}


					if(this._checkDOMNode(oHelpText)) {

						if(this._oHelpTextEM) {

							var oParentNode = this._oHelpTextEM.parentNode;
							oParentNode.replaceChild(oHelpText, this._oHelpTextEM);

						}
						else {

							this._oHelpTextEM = oHelpText;

							this.element.insertBefore(
								this._oHelpTextEM, 
								this.subMenuIndicator
							);

						}

						initHelpText();

					}
					else if(this._checkString(oHelpText)) {

						if(oHelpText.length === 0) {

							removeHelpText();

						}
						else {

							if(!this._oHelpTextEM) {

								this._oHelpTextEM = document.createElement("em");

								this.element.insertBefore(
									this._oHelpTextEM, 
									this.subMenuIndicator
								);

							}

							this._oHelpTextEM.innerHTML = oHelpText;

							initHelpText();

						}

					}
					else if(!oHelpText && this._oHelpTextEM) {

						removeHelpText();

					}

				},


				/**
				* Event handler for when the "url" configuration property of
				* a MenuModuleItem instance changes.  
				* @param {String} p_sType The name of the event that was fired.
				* @param {Array} p_aArguments Collection of arguments sent when the 
				* event was fired.
				* @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance 
				* that fired the event.
				*/    
				configURL: function(p_sType, p_aArguments, p_oItem) {

					var sURL = p_aArguments[0];

					if(!sURL) {

						sURL = "#";

					}

					this._oAnchor.setAttribute("href", sURL);

				},


				/**
				* Event handler for when the "emphasis" configuration property of
				* a MenuModuleItem instance changes.  
				* @param {String} p_sType The name of the event that was fired.
				* @param {Array} p_aArguments Collection of arguments sent when the 
				* event was fired.
				* @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance 
				* that fired the event.
				*/    
				configEmphasis: function(p_sType, p_aArguments, p_oItem) {

					var bEmphasis = p_aArguments[0];


					if(bEmphasis && this.cfg.getProperty("strongemphasis")) {

						this.cfg.setProperty("strongemphasis", false);

					}


					if(this._oAnchor) {

						var oEM;

						if(bEmphasis) {

							oEM = document.createElement("em");
							oEM.appendChild(this._oText);

							this._oAnchor.appendChild(oEM);

						}
						else {

							oEM = this._getFirstElement(this._oAnchor, "EM");

							this._oAnchor.removeChild(oEM);
							this._oAnchor.appendChild(this._oText);

						}

					}

				},


				/**
				* Event handler for when the "strongemphasis" configuration property of
				* a MenuModuleItem instance changes. 
				* @param {String} p_sType The name of the event that was fired.
				* @param {Array} p_aArguments Collection of arguments sent when the 
				* event was fired.
				* @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance 
				* that fired the event.
				*/    
				configStrongEmphasis: function(p_sType, p_aArguments, p_oItem) {

					var bStrongEmphasis = p_aArguments[0];


					if(bStrongEmphasis && this.cfg.getProperty("emphasis")) {

						this.cfg.setProperty("emphasis", false);

					}

					if(this._oAnchor) {

						var oStrong;

						if(bStrongEmphasis) {

							oStrong = document.createElement("strong");
							oStrong.appendChild(this._oText);

							this._oAnchor.appendChild(oStrong);

						}
						else {

							oStrong = this._getFirstElement(this._oAnchor, "STRONG");

							this._oAnchor.removeChild(oStrong);
							this._oAnchor.appendChild(this._oText);

						}

					}

				},


				/**
				* Event handler for when the "disabled" configuration property of
				* a MenuModuleItem instance changes. 
				* @param {String} p_sType The name of the event that was fired.
				* @param {Array} p_aArguments Collection of arguments sent when the 
				* event was fired.
				* @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance 
				* that fired the event.
				*/    
				configDisabled: function(p_sType, p_aArguments, p_oItem) {

					var bDisabled = p_aArguments[0],
						aNodes = [this.element, this._oAnchor],
						sImageId,
						sImageAlt;

					if(this._oHelpTextEM) {

						aNodes[2] = this._oHelpTextEM;  

					}

					if(bDisabled) {

						if(this.cfg.getProperty("selected")) {

							this.cfg.setProperty("selected", false);

						}

						this._oAnchor.removeAttribute("href");

						this._oDom.addClass(aNodes, "disabled");

						sImageId = "yuidisabledsubmenuindicator";
						sImageAlt = this.DISABLED_SUBMENU_INDICATOR_ALT_TEXT;

					}
					else {

						this._oAnchor.setAttribute("href", this.cfg.getProperty("url"));

						this._oDom.removeClass(aNodes, "disabled");

						sImageId = "yuisubmenuindicator";
						sImageAlt = this.COLLAPSED_SUBMENU_INDICATOR_ALT_TEXT;

					}


					if(this.subMenuIndicator) {

						this.subMenuIndicator.src = document.getElementById(sImageId).src;
						this.subMenuIndicator.alt = sImageAlt;

					}

				},


				/**
				* Event handler for when the "selected" configuration property of
				* a MenuModuleItem instance changes. 
				* @param {String} p_sType The name of the event that was fired.
				* @param {Array} p_aArguments Collection of arguments sent when the 
				* event was fired.
				* @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance 
				* that fired the event.
				*/    
				configSelected: function(p_sType, p_aArguments, p_oItem) {

					var bSelected = p_aArguments[0],
						aNodes = [this.element, this._oAnchor],
						sImageId;

					if(this._oHelpTextEM) {

						aNodes[2] = this._oHelpTextEM;  

					}

					if(bSelected) {

						this._oDom.addClass(aNodes, "selected");

						sImageId = "yuiselectedsubmenuindicator";

					}
					else {

						this._oDom.removeClass(aNodes, "selected");

						sImageId = "yuisubmenuindicator";

					}

					if(this.subMenuIndicator) {

						this.subMenuIndicator.src = document.getElementById(sImageId).src;

					}

				},


				/**
				* Event handler for when the "submenu" configuration property of
				* a MenuModuleItem instance changes. 
				* @param {String} p_sType The name of the event that was fired.
				* @param {Array} p_aArguments Collection of arguments sent when the 
				* event was fired.
				* @param {YAHOO.widget.MenuModuleItem} p_oItem The MenuModuleItem instance 
				* that fired the event.
				*/
				configSubmenu: function(p_sType, p_aArguments, p_oItem) {

					var oSubmenu = p_aArguments[0],
						aNodes = [this.element, this._oAnchor];

					if(oSubmenu) {

						// Set the submenu's parent to this MenuModuleItem instance

						oSubmenu.parent = this;

						this._oSubmenu = oSubmenu;


						if(!this.subMenuIndicator) { 

							var oSubMenuIndicator = 
									document.getElementById("yuisubmenuindicator");

							if(!oSubMenuIndicator) {

								oSubMenuIndicator = document.createElement("img");

								oSubMenuIndicator.src = 
									(this.imageRoot + this.SUBMENU_INDICATOR_IMAGE_PATH);
					
								oSubMenuIndicator.alt = 
									this.COLLAPSED_SUBMENU_INDICATOR_ALT_TEXT;

								oSubMenuIndicator.id = "yuisubmenuindicator";


								var oSelectedSubMenuIndicator = 
										document.createElement("img");

									oSelectedSubMenuIndicator.src = 
										(
											this.imageRoot + 
											this.SELECTED_SUBMENU_INDICATOR_IMAGE_PATH
										);

									oSelectedSubMenuIndicator.id = 
										"yuiselectedsubmenuindicator";
								

								var oDisabledSubMenuIndicator = 
										document.createElement("img");

									oDisabledSubMenuIndicator.src = 
										(
											this.imageRoot + 
											this.DISABLED_SUBMENU_INDICATOR_IMAGE_PATH
										);

									oDisabledSubMenuIndicator.id = 
										"yuidisabledsubmenuindicator";

								var oDIV = document.createElement("div");

								oDIV.style.position = "absolute";
								oDIV.style.left = "-1000px";

								oDIV.appendChild(oSubMenuIndicator);
								oDIV.appendChild(oSelectedSubMenuIndicator);
								oDIV.appendChild(oDisabledSubMenuIndicator);

								document.body.appendChild(oDIV);

							}              


							var oClone = oSubMenuIndicator.cloneNode(false);
							oClone.removeAttribute("id");

							this.subMenuIndicator = oClone;
								
							this.element.appendChild(this.subMenuIndicator);

							this._oDom.addClass(aNodes, "hassubmenu");


							if(this.cfg.getProperty("disabled")) {

								this.cfg.refireEvent("disabled");

							}

							if(this.cfg.getProperty("selected")) {

								this.cfg.refireEvent("selected");

							}                

						}

					}
					else {

						this._oDom.removeClass(aNodes, "hassubmenu");

						if(this.subMenuIndicator) {

							this.element.removeChild(this.subMenuIndicator);

						}

						if(this._oSubmenu) {

							this._oSubmenu.destroy();

						}

					}

				},


				// Public methods

				/**
				* Finds the next enabled MenuModuleItem instance in a MenuModule instance 
				* @return Returns a MenuModuleItem instance.
				* @type YAHOO.widget.MenuModuleItem
				*/
				getNextEnabledSibling: function() {

					if(this.parent instanceof YAHOO.widget.MenuModule) {


						/**
						* Returns the next item in an array 
						* @param {p_aArray} An array
						* @param {p_nStartIndex} The index to start searching the array 
						* @ignore
						* @return Returns an item in an array
						* @type Object 
						*/
						function getNextArrayItem(p_aArray, p_nStartIndex) {
				
							return p_aArray[p_nStartIndex] || 
								getNextArrayItem(p_aArray, (p_nStartIndex+1));
				
						}
				
				
						var aItemGroups = this.parent.getItemGroups(),
							oNextItem;
				
				
						if(this.index < (aItemGroups[this.groupIndex].length - 1)) {
				
							oNextItem = getNextArrayItem(
									aItemGroups[this.groupIndex], 
									(this.index+1)
								);
				
						}
						else {
				
							var nNextGroupIndex;
				
							if(this.groupIndex < (aItemGroups.length - 1)) {
				
								nNextGroupIndex = this.groupIndex + 1;
				
							}
							else {
				
								nNextGroupIndex = 0;
				
							}
				
							var aNextGroup = getNextArrayItem(aItemGroups, nNextGroupIndex);
				
							// Retrieve the first MenuModuleItem instance in the next group
				
							oNextItem = getNextArrayItem(aNextGroup, 0);
				
						}
				
						return oNextItem.cfg.getProperty("disabled") ? 
									oNextItem.getNextEnabledSibling() : oNextItem;

					}

				},


				/**
				* Finds the previous enabled MenuModuleItem instance in a 
				* MenuModule instance 
				* @return Returns a MenuModuleItem instance.
				* @type YAHOO.widget.MenuModuleItem
				*/
				getPreviousEnabledSibling: function() {

					if(this.parent instanceof YAHOO.widget.MenuModule) {

						/**
						* Returns the previous item in an array 
						* @param {p_aArray} An array
						* @param {p_nStartIndex} The index to start searching the array 
						* @ignore
						* @return Returns an item in an array
						* @type Object 
						*/
						function getPreviousArrayItem(p_aArray, p_nStartIndex) {
				
							return p_aArray[p_nStartIndex] || 
								getPreviousArrayItem(p_aArray, (p_nStartIndex-1));
				
						}


						/**
						* Get the index of the first item in an array 
						* @param {p_aArray} An array
						* @param {p_nStartIndex} The index to start searching the array 
						* @ignore
						* @return Returns an item in an array
						* @type Object 
						*/    
						function getFirstItemIndex(p_aArray, p_nStartIndex) {
				
							return p_aArray[p_nStartIndex] ? 
								p_nStartIndex : 
								getFirstItemIndex(p_aArray, (p_nStartIndex+1));
				
						}
				
						var aItemGroups = this.parent.getItemGroups(),
							oPreviousItem;
				
						if(
							this.index > getFirstItemIndex(aItemGroups[this.groupIndex], 0)
						) {
				
							oPreviousItem = 
								getPreviousArrayItem(
									aItemGroups[this.groupIndex], 
									(this.index-1)
								);
				
						}
						else {
				
							var nPreviousGroupIndex;
				
							if(this.groupIndex > getFirstItemIndex(aItemGroups, 0)) {
				
								nPreviousGroupIndex = this.groupIndex - 1;
				
							}
							else {
				
								nPreviousGroupIndex = aItemGroups.length - 1;
				
							}
				
							var aPreviousGroup = 
									getPreviousArrayItem(aItemGroups, nPreviousGroupIndex);
				
							oPreviousItem = 
								getPreviousArrayItem(
									aPreviousGroup, 
									(aPreviousGroup.length - 1)
								);
				
						}
				
						return oPreviousItem.cfg.getProperty("disabled") ? 
								oPreviousItem.getPreviousEnabledSibling() : oPreviousItem;

					}

				},


				/**
				* Causes a MenuModuleItem instance to receive the focus and fires the
				* focus event.
				*/
				focus: function() {

					if(
						!this.cfg.getProperty("disabled") && 
						this.parent && 
						this.parent.cfg.getProperty("visible")
					) {

						var oActiveItem = this.parent.activeItem;

						if(oActiveItem) {

							oActiveItem.blur();

						}

						this._oAnchor.focus();

						/*
							Opera 8.5 doesn't always focus the anchor if a MenuModuleItem
							instance has a submenu, this is fixed by calling "focus"
							twice.
						*/
						if(
							this.parent && 
							this.parent.browser == "opera" && 
							this._oSubmenu
						) {

							this._oAnchor.focus();

						}

						this.focusEvent.fire();

					}

				},


				/**
				* Causes a MenuModuleItem instance to lose focus and fires the onblur event.
				*/    
				blur: function() {

					if(
						!this.cfg.getProperty("disabled") && 
						this.parent && 
						this.parent.cfg.getProperty("visible")
					) {

						this._oAnchor.blur();

						this.blurEvent.fire();

					}

				},


				/**
				* Removes a MenuModuleItem instance's HTMLLIElement from it's parent
				* HTMLUListElement node.
				*/
				destroy: function() {

					if(this.element) {

						// Remove CustomEvent listeners
				
						this.mouseOverEvent.unsubscribeAll();
						this.mouseOutEvent.unsubscribeAll();
						this.mouseDownEvent.unsubscribeAll();
						this.mouseUpEvent.unsubscribeAll();
						this.clickEvent.unsubscribeAll();
						this.keyPressEvent.unsubscribeAll();
						this.keyDownEvent.unsubscribeAll();
						this.keyUpEvent.unsubscribeAll();
						this.focusEvent.unsubscribeAll();
						this.blurEvent.unsubscribeAll();
						this.cfg.configChangedEvent.unsubscribeAll();


						// Remove the element from the parent node

						var oParentNode = this.element.parentNode;

						if(oParentNode) {

							oParentNode.removeChild(this.element);

							this.destroyEvent.fire();

						}

						this.destroyEvent.unsubscribeAll();

					}

				}

};


/**
* @class Extends YAHOO.widget.MenuModule to provide a set of default mouse and 
* key event behaviors.
* @constructor
* @extends YAHOO.widget.MenuModule
* @base YAHOO.widget.MenuModule
* @param {String or HTMLElement} p_oElement String id or HTMLElement 
* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node.
* @param {Object} p_oUserConfig Optional. The configuration object literal 
* containing the configuration for a Menu instance. See 
* configuration class documentation for more details.
*/
YAHOO.widget.Menu = function(p_oElement, p_oUserConfig) {

				if(arguments.length > 0) {

					YAHOO.widget.Menu.superclass.constructor.call(
							this, 
							p_oElement,
							p_oUserConfig
						);

				}

};

YAHOO.widget.Menu.prototype = new YAHOO.widget.MenuModule();
YAHOO.widget.Menu.prototype.constructor = YAHOO.widget.Menu;
YAHOO.widget.Menu.superclass = YAHOO.widget.MenuModule.prototype;


/**
* The Menu class's initialization method. This method is automatically 
* called by the constructor, and sets up all DOM references for pre-existing 
* markup, and creates required markup if it is not already present.
* @param {String or HTMLElement} p_oElement String id or HTMLElement 
* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node.
* @param {Object} p_oUserConfig Optional. The configuration object literal 
* containing the configuration for a Menu instance. See 
* configuration class documentation for more details.
*/
YAHOO.widget.Menu.prototype.init = function(p_oElement, p_oUserConfig) {

				if(!this.ITEM_TYPE) {

					this.ITEM_TYPE = YAHOO.widget.MenuItem;

				}


				// Call the init of the superclass (YAHOO.widget.Menu)

				YAHOO.widget.Menu.superclass.init.call(this, p_oElement);


				this.beforeInitEvent.fire(YAHOO.widget.Menu);


				// Add event handlers

				this.mouseOverEvent.subscribe(this._onMouseOver, this, true);
				this.keyDownEvent.subscribe(this._onKeyDown, this, true);


				if(p_oUserConfig) {

					this.cfg.applyConfig(p_oUserConfig, true);

				}
				
				this.initEvent.fire(YAHOO.widget.Menu);

};


// Private event handlers

/**
* "mouseover" Custom Event handler for a Menu instance.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance that fired the event.
*/
YAHOO.widget.Menu.prototype._onMouseOver = 

				function(p_sType, p_aArguments, p_oMenu) {
				
					/*
						If the menu is a submenu, then select the menu's parent
						MenuItem instance
					*/
				
					if(this.parent) {
				
						this.parent.cfg.setProperty("selected", true);
				
					}
				
				};


/**
* "mouseover" Custom Event handler for a Menu instance.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.Menu} p_oMenu The Menu instance that fired the event.
*/
YAHOO.widget.Menu.prototype._onKeyDown = 

				function(p_sType, p_aArguments, p_oMenu) {
				
					if(this.cfg.getProperty("position") == "dynamic") {
				
						var oEvent = p_aArguments[0];
					
						if(oEvent.keyCode == 27) { // Esc key
					
							this.hide();
					
							// Set focus to the parent MenuItem if one exists
					
							if(this.parent) {
					
								this.parent.focus();

								if(this.parent.parent instanceof YAHOO.widget.Menu) {

									this.parent.cfg.setProperty("selected", true);
					
								}
					
							}
						
						}
					
					}
				
				};
				

/**
* @class The MenuItem class allows you to create and modify an item for a
* Menu instance.  MenuItem extends YAHOO.widget.MenuModuleItem to provide a 
* set of default mouse and key event behaviors.
* @constructor
* @extends YAHOO.widget.MenuModuleItem
* @base YAHOO.widget.MenuModuleItem
* @param {String or HTMLElement} p_oObject String or HTMLElement 
* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the 
* source HTMLElement node.
* @param {Object} p_oUserConfig The configuration object literal containing 
* the configuration for a MenuItem instance. See the configuration 
* class documentation for more details.
*/
YAHOO.widget.MenuItem = function(p_oObject, p_oUserConfig) {

				if(p_oObject) {

					YAHOO.widget.MenuItem.superclass.constructor.call(
						this, 
						p_oObject, 
						p_oUserConfig
					);

				}

};

YAHOO.widget.MenuItem.prototype = new YAHOO.widget.MenuModuleItem();
YAHOO.widget.MenuItem.prototype.constructor = YAHOO.widget.MenuItem;
YAHOO.widget.MenuItem.superclass = YAHOO.widget.MenuModuleItem.prototype;


/**
* The MenuItem class's initialization method. This method is automatically
* called by the constructor, and sets up all DOM references for
* pre-existing markup, and creates required markup if it is not
* already present.
* @param {String or HTMLElement} p_oObject String or HTMLElement 
* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the 
* source HTMLElement node.
* @param {Object} p_oUserConfig The configuration object literal containing 
* the configuration for a MenuItem instance. See the configuration 
* class documentation for more details.
*/
YAHOO.widget.MenuItem.prototype.init = function(p_oObject, p_oUserConfig) {

				if(!this.SUBMENU_TYPE) {

					this.SUBMENU_TYPE = YAHOO.widget.Menu;

				}

				if(!this.SUBMENU_ITEM_TYPE) {

					this.SUBMENU_ITEM_TYPE = YAHOO.widget.MenuItem;

				}


				/* 
					Call the init of the superclass (YAHOO.widget.MenuModuleItem)
					Note: We don't pass the user config in here yet 
					because we only want it executed once, at the lowest 
					subclass level.
				*/ 

				YAHOO.widget.MenuItem.superclass.init.call(this, p_oObject);  


				// Add event handlers to each "MenuItem" instance

				this.keyDownEvent.subscribe(this._onKeyDown, this, true);
				this.mouseOverEvent.subscribe(this._onMouseOver, this, true);
				this.mouseOutEvent.subscribe(this._onMouseOut, this, true);


				if(p_oUserConfig) {

					this.cfg.applyConfig(p_oUserConfig, true);

				}

				this.cfg.fireQueue();

};


// Private event handlers


/**
* "keydown" Custom Event handler for a MenuItem instance.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance that 
* fired the event.
*/
YAHOO.widget.MenuItem.prototype._onKeyDown = 

				function(p_sType, p_aArguments, p_oMenuItem) {
				
					var oEvent = p_aArguments[0];
				
					switch(oEvent.keyCode) {
				
						case 38:    // Up arrow
						case 40:    // Down arrow
				
							var oActiveItem = this.parent.activeItem;
				
							if(this == oActiveItem && !this.cfg.getProperty("selected")) {
				
								this.cfg.setProperty("selected", true);
				
							}
							else {
				
								var oNextItem = (oEvent.keyCode == 38) ? 
										this.getPreviousEnabledSibling() : 
										this.getNextEnabledSibling();
						
								if(oNextItem) {

									this.parent.clearActiveItem();

									oNextItem.cfg.setProperty("selected", true);
						
									oNextItem.focus();
				
								}
				
							}
				
							YAHOO.util.Event.preventDefault(oEvent);

						break;
						
				
						case 39:    // Right arrow

							this.parent.clearActiveItem();

							this.cfg.setProperty("selected", true);
							
							this.focus();


							var oSubmenu = this.cfg.getProperty("submenu");
				
							if(oSubmenu) {

								oSubmenu.show();
								oSubmenu.setInitialSelection();                    
				
							}
							else if(
								YAHOO.widget.MenuBarItem && 
								this.parent.parent && 
								this.parent.parent instanceof YAHOO.widget.MenuBarItem
							) {

								this.parent.hide();
				
								// Set focus to the parent MenuItem if one exists
				
								var oMenuItem = this.parent.parent;
				
								if(oMenuItem) {
				
									oMenuItem.focus();
									oMenuItem.cfg.setProperty("selected", true);
				
								}                    
							
							}
				
							YAHOO.util.Event.preventDefault(oEvent);

						break;
				
				
						case 37:    // Left arrow
				
							// Only hide if this this is a MenuItem of a submenu
				
							if(this.parent.parent) {
				
								this.parent.hide();
				
								// Set focus to the parent MenuItem if one exists
				
								var oMenuItem = this.parent.parent;
				
								if(oMenuItem) {
				
									oMenuItem.focus();
									oMenuItem.cfg.setProperty("selected", true);
				
								}
				
							}

							YAHOO.util.Event.preventDefault(oEvent);
				
						break;        
				
					}
				
				};


/**
* "mouseover" Custom Event handler for a MenuItem instance.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance that 
* fired the event.
*/
YAHOO.widget.MenuItem.prototype._onMouseOver = 

				function(p_sType, p_aArguments, p_oMenuItem) {
				
					var oActiveItem = this.parent.activeItem;
				
				
					// Hide any other submenus that might be visible
				
					if(oActiveItem && oActiveItem != this) {
				
						this.parent.clearActiveItem();
				
					}
				
				
					// Select and focus the current MenuItem instance
				
					this.cfg.setProperty("selected", true);
					this.focus();
				
				
					// Show the submenu for this instance
				
					var oSubmenu = this.cfg.getProperty("submenu");
				
					if(oSubmenu) {
				
						oSubmenu.show();
				
					}
				
				};


/**
* "mouseout" Custom Event handler for a MenuItem instance.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance that 
* fired the event.
*/
YAHOO.widget.MenuItem.prototype._onMouseOut = 

				function(p_sType, p_aArguments, p_oMenuItem) {
				
					this.cfg.setProperty("selected", false);
				
				
					var oSubmenu = this.cfg.getProperty("submenu");
				
					if(oSubmenu) {
				
						var oEvent = p_aArguments[0],
							oRelatedTarget = YAHOO.util.Event.getRelatedTarget(oEvent);
				
						if(
							!(
								oRelatedTarget == oSubmenu.element || 
								this._oDom.isAncestor(oSubmenu.element, oRelatedTarget)
							)
						) {
				
							oSubmenu.hide();
				
						}
				
					}
				
				};
				
				
/**
* @class Creates a list of options which vary depending on the context in 
* which the menu is invoked.
* @constructor
* @extends YAHOO.widget.Menu
* @base YAHOO.widget.Menu
* @param {String or HTMLElement} p_oElement String id or HTMLElement 
* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node.
* @param {Object} p_oUserConfig Optional. The configuration object literal 
* containing the configuration for a ContextMenu instance. See 
* configuration class documentation for more details.
*/
YAHOO.widget.ContextMenu = function(p_oElement, p_oUserConfig) {

				if(arguments.length > 0) {

					YAHOO.widget.ContextMenu.superclass.constructor.call(
							this, 
							p_oElement,
							p_oUserConfig
						);

				}

};

YAHOO.widget.ContextMenu.prototype = new YAHOO.widget.Menu();
YAHOO.widget.ContextMenu.prototype.constructor = YAHOO.widget.ContextMenu;
YAHOO.widget.ContextMenu.superclass = YAHOO.widget.Menu.prototype;


/**
* The ContextMenu class's initialization method. This method is automatically  
* called by the constructor, and sets up all DOM references for pre-existing 
* markup, and creates required markup if it is not already present.
* @param {String or HTMLElement} p_oElement String id or HTMLElement 
* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node.
* @param {Object} p_oUserConfig Optional. The configuration object literal 
* containing the configuration for a ContextMenu instance. See 
* configuration class documentation for more details.
*/
YAHOO.widget.ContextMenu.prototype.init = function(p_oElement, p_oUserConfig) {

				if(!this.ITEM_TYPE) {

					this.ITEM_TYPE = YAHOO.widget.ContextMenuItem;

				}


				// Call the init of the superclass (YAHOO.widget.Menu)

				YAHOO.widget.ContextMenu.superclass.init.call(this, p_oElement);


				this.beforeInitEvent.fire(YAHOO.widget.ContextMenu);


				if(p_oUserConfig) {

					this.cfg.applyConfig(p_oUserConfig, true);

				}
				
				
				this.initEvent.fire(YAHOO.widget.ContextMenu);


};


// Private event handlers

/**
* "mousedown" event handler for the document object.
* @private
* @param {Event} p_oEvent Event object passed back by the 
* event utility (YAHOO.util.Event).
* @param {YAHOO.widget.ContextMenu} p_oMenu The ContextMenu instance 
* handling the event.
*/
YAHOO.widget.ContextMenu.prototype._onDocumentMouseDown = 

				function(p_oEvent, p_oMenu) {
				
					var oTarget = this._oEventUtil.getTarget(p_oEvent, true);
				
					if(
						oTarget != this._oTargetElement || 
						!this._oDom.isAncestor(this._oTargetElement, oTarget)
					) {
				
						this.hide();    
					
					}
				
				};


/**
* "click" event handler for the HTMLElement node that triggered the event. 
* Used to cancel default behaviors in Opera.
* @private
* @param {Event} p_oEvent Event object passed back by the 
* event utility (YAHOO.util.Event).
* @param {YAHOO.widget.ContextMenu} p_oMenu The ContextMenu instance 
* handling the event.
*/
YAHOO.widget.ContextMenu.prototype._onTriggerClick = 

				function(p_oEvent, p_oMenu) {

					if(p_oEvent.ctrlKey) {
					
						this._oEventUtil.stopEvent(p_oEvent);
				
					}
					
				};


/**
* "contextmenu" event handler ("mousedown" for Opera) for the HTMLElement 
* node that triggered the event.
* @private
* @param {Event} p_oEvent Event object passed back by the 
* event utility (YAHOO.util.Event).
* @param {YAHOO.widget.ContextMenu} p_oMenu The ContextMenu instance 
* handling the event.
*/
YAHOO.widget.ContextMenu.prototype._onTriggerContextMenu = 

				function(p_oEvent, p_oMenu) {
				
					if(p_oEvent.type == "mousedown") {
					
						if(!p_oEvent.ctrlKey) {
				
							return;
						
						}
					
						this._oEventUtil.stopEvent(p_oEvent);
				
					}
				
				
					this.contextEventTarget = this._oEventUtil.getTarget(p_oEvent, true);
				
				
					// Position and display the context menu
				
					var nX = this._oEventUtil.getPageX(p_oEvent),
						nY = this._oEventUtil.getPageY(p_oEvent);
				
				
					this.cfg.applyConfig( { x:nX, y:nY, visible:true } );
					this.cfg.fireQueue();
				
				
					// Prevent the browser's default context menu from appearing
				
					this._oEventUtil.preventDefault(p_oEvent);
				
				};


// Public properties

/**
* Returns the HTMLElement node that was the target of the "contextmenu" 
* DOM event.
* @type HTMLElement
*/
YAHOO.widget.ContextMenu.prototype.contextEventTarget = null;


// Public methods

/**
* Initializes the class's configurable properties which can be changed using 
* a ContextMenu instance's Config object (cfg).
*/
YAHOO.widget.ContextMenu.prototype.initDefaultConfig = function() {

				YAHOO.widget.ContextMenu.superclass.initDefaultConfig.call(this);


				// Add a configuration property

				this.cfg.addProperty("trigger", { handler: this.configTrigger });

};


// Event handlers for configuration properties

/**
* Event handler for when the "trigger" configuration property of
* a MenuItem instance. 
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the 
* event was fired.
* @param {YAHOO.widget.ContextMenu} p_oMenu The ContextMenu that instance fired
* the event.
*/
YAHOO.widget.ContextMenu.prototype.configTrigger = 

				function(p_sType, p_aArguments, p_oMenu) {
				
					var oTrigger = p_aArguments[0];
				
					if(oTrigger) {
				
						/*
							Listen for the "mousedown" event in Opera b/c it does not 
							support the "contextmenu" event
						*/ 
				  
						var bOpera = (this.browser == "opera");
				
						var sContextEvent = bOpera ? "mousedown" : "contextmenu";
				
						this._oEventUtil.addListener(
							oTrigger, 
							sContextEvent, 
							this._onTriggerContextMenu,
							this,
							true
						);
				
				
						/*
							Assign a "click" event handler to the trigger element(s) for
							Opera to prevent default browser behaviors.
						*/
				
						if(bOpera) {
						
							this._oEventUtil.addListener(
								oTrigger, 
								"click", 
								this._onTriggerClick,
								this,
								true
							);
				
						}
				
				
						// Assign a "mousedown" event handler to the document
					
						this._oEventUtil.addListener(
							document, 
							"mousedown", 
							this._onDocumentMouseDown,
							this,
							true
						);        
				
					}
					
				};


/**
* @class Creates an item for a context menu instance.
* @constructor
* @extends YAHOO.widget.MenuItem
* @base YAHOO.widget.MenuItem
* @param {String or HTMLElement} p_oObject String or HTMLElement 
* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the 
* source HTMLElement node.
* @param {Object} p_oUserConfig The configuration object literal containing 
* the configuration for a ContextMenuItem instance. See the configuration 
* class documentation for more details.
*/
YAHOO.widget.ContextMenuItem = function(p_oObject, p_oUserConfig) {

				if(p_oObject) {

					YAHOO.widget.ContextMenuItem.superclass.constructor.call(
						this, 
						p_oObject, 
						p_oUserConfig
					);

				}

};

YAHOO.widget.ContextMenuItem.prototype = new YAHOO.widget.MenuItem();

YAHOO.widget.ContextMenuItem.prototype.constructor = 

				YAHOO.widget.ContextMenuItem;

YAHOO.widget.ContextMenuItem.superclass = YAHOO.widget.MenuItem.prototype;


/**
* The ContextMenuItem class's initialization method. This method is
* automatically called by the constructor, and sets up all DOM references for
* pre-existing markup, and creates required markup if it is not
* already present.
* @param {String or HTMLElement} p_oObject String or HTMLElement 
* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the 
* source HTMLElement node.
* @param {Object} p_oUserConfig The configuration object literal containing 
* the configuration for a ContextMenuItem instance. See the configuration 
* class documentation for more details.
*/
YAHOO.widget.ContextMenuItem.prototype.init = 

				function(p_oObject, p_oUserConfig) {
				
					if(!this.SUBMENU_TYPE) {
				
						this.SUBMENU_TYPE = YAHOO.widget.ContextMenu;
				
					}
				
					if(!this.SUBMENU_ITEM_TYPE) {
				
						this.SUBMENU_ITEM_TYPE = YAHOO.widget.ContextMenuItem;
				
					}
				
				
					/* 
						Call the init of the superclass (YAHOO.widget.MenuItem)
						Note: We don't pass the user config in here yet 
						because we only want it executed once, at the lowest 
						subclass level.
					*/ 
				
					YAHOO.widget.ContextMenuItem.superclass.init.call(this, p_oObject);
				
				
					if(p_oUserConfig) {
				
						this.cfg.applyConfig(p_oUserConfig, true);
				
					}
				
				
					this.cfg.fireQueue();
				
				};
				

/**
* @class Horizontal collection of items, each of which can contain a submenu.
* Extends YAHOO.widget.MenuModule to provide a set of default mouse and 
* key event behaviors.
* @constructor
* @extends YAHOO.widget.MenuModule
* @base YAHOO.widget.MenuModule
* @param {String or HTMLElement} p_oElement String id or HTMLElement 
* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node.
* @param {Object} p_oUserConfig Optional. The configuration object literal 
* containing the configuration for a MenuBar instance. See 
* configuration class documentation for more details.
*/
YAHOO.widget.MenuBar = function(p_oElement, p_oUserConfig) {

				if(arguments.length > 0) {

					YAHOO.widget.MenuBar.superclass.constructor.call(
							this, 
							p_oElement,
							p_oUserConfig
						);

				}

};

YAHOO.widget.MenuBar.prototype = new YAHOO.widget.MenuModule();
YAHOO.widget.MenuBar.prototype.constructor = YAHOO.widget.MenuBar;
YAHOO.widget.MenuBar.superclass = YAHOO.widget.MenuModule.prototype;


/**
* The MenuBar class's initialization method. This method is automatically 
* called by the constructor, and sets up all DOM references for pre-existing 
* markup, and creates required markup if it is not already present.
* @param {String or HTMLElement} p_oElement String id or HTMLElement 
* (either HTMLSelectElement or HTMLDivElement) of the source HTMLElement node.
* @param {Object} p_oUserConfig Optional. The configuration object literal 
* containing the configuration for a MenuBar instance. See 
* configuration class documentation for more details.
*/
YAHOO.widget.MenuBar.prototype.init = function(p_oElement, p_oUserConfig) {

				if(!this.ITEM_TYPE) {

					this.ITEM_TYPE = YAHOO.widget.MenuBarItem;

				}


				// Call the init of the superclass (YAHOO.widget.MenuModule)

				YAHOO.widget.MenuBar.superclass.init.call(this, p_oElement);


				this.beforeInitEvent.fire(YAHOO.widget.MenuBar);


				/*
					Set the default value for the "position" configuration property
					to "static" 
				*/
				if(!p_oUserConfig || (p_oUserConfig && !p_oUserConfig.position)) {

					this.cfg.queueProperty("position", "static");

				}

				/*
					Set the default value for the "submenualignment" configuration property
					to "tl" and "bl" 
				*/
				if(!p_oUserConfig || (p_oUserConfig && !p_oUserConfig.submenualignment)) {

					this.cfg.queueProperty("submenualignment", ["tl","bl"]);

				}


				if(p_oUserConfig) {

					this.cfg.applyConfig(p_oUserConfig, true);

				}
				
				this.initEvent.fire(YAHOO.widget.MenuBar);

};


// Constants

/**
* Constant representing the CSS class(es) to be applied to the root 
* HTMLDivElement of the MenuBar instance.
* @final
* @type String
*/
YAHOO.widget.MenuBar.prototype.CSS_CLASS_NAME = "yuimenubar"; 


/**
* @class The MenuBarItem class allows you to create and modify an item for a
* MenuBar instance.  MenuBarItem extends YAHOO.widget.MenuModuleItem to provide 
* a set of default mouse and key event behaviors.
* @constructor
* @extends YAHOO.widget.MenuModuleItem
* @base YAHOO.widget.MenuModuleItem
* @param {String or HTMLElement} p_oObject String or HTMLElement 
* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the 
* source HTMLElement node.
* @param {Object} p_oUserConfig The configuration object literal containing 
* the configuration for a MenuBarItem instance. See the configuration 
* class documentation for more details.
*/
YAHOO.widget.MenuBarItem = function(p_oObject, p_oUserConfig) {

				if(p_oObject) {

					YAHOO.widget.MenuBarItem.superclass.constructor.call(
						this, 
						p_oObject, 
						p_oUserConfig
					);

				}

};

YAHOO.widget.MenuBarItem.prototype = new YAHOO.widget.MenuModuleItem();
YAHOO.widget.MenuBarItem.prototype.constructor = YAHOO.widget.MenuBarItem;
YAHOO.widget.MenuBarItem.superclass = YAHOO.widget.MenuModuleItem.prototype;


/**
* The MenuBarItem class's initialization method. This method is automatically
* called by the constructor, and sets up all DOM references for
* pre-existing markup, and creates required markup if it is not
* already present.
* @param {String or HTMLElement} p_oObject String or HTMLElement 
* (either HTMLLIElement, HTMLOptGroupElement or HTMLOptionElement) of the 
* source HTMLElement node.
* @param {Object} p_oUserConfig The configuration object literal containing 
* the configuration for a MenuBarItem instance. See the configuration 
* class documentation for more details.
*/
YAHOO.widget.MenuBarItem.prototype.init = function(p_oObject, p_oUserConfig) {

				if(!this.SUBMENU_TYPE) {

					this.SUBMENU_TYPE = YAHOO.widget.Menu;

				}

				if(!this.SUBMENU_ITEM_TYPE) {

					this.SUBMENU_ITEM_TYPE = YAHOO.widget.MenuItem;

				}


				/* 
					Call the init of the superclass (YAHOO.widget.MenuModuleItem)
					Note: We don't pass the user config in here yet 
					because we only want it executed once, at the lowest 
					subclass level.
				*/ 

				YAHOO.widget.MenuBarItem.superclass.init.call(this, p_oObject);  


				// Add event handlers to each "MenuBarItem" instance

				this.keyDownEvent.subscribe(this._onKeyDown, this, true);


				if(p_oUserConfig) {

					this.cfg.applyConfig(p_oUserConfig, true);

				}

				this.cfg.fireQueue();

};


// Constants

/**
* Constant representing the CSS class(es) to be applied to the root 
* HTMLLIElement of the MenuBarItem.
* @final
* @type String
*/
YAHOO.widget.MenuBarItem.prototype.CSS_CLASS_NAME = "yuimenubaritem";


/**
* Constant representing the path to the image to be used for the submenu
* arrow indicator.
* @final
* @type String
*/
YAHOO.widget.MenuBarItem.prototype.SUBMENU_INDICATOR_IMAGE_PATH =
				"nt/ic/ut/bsc/menuarodwn9_nrm_1.gif";


/**
* Constant representing the path to the image to be used for the submenu
* arrow indicator when a MenuBarItem instance has focus.
* @final
* @type String
*/
YAHOO.widget.MenuBarItem.prototype.SELECTED_SUBMENU_INDICATOR_IMAGE_PATH =
				"nt/ic/ut/bsc/menuarodwn9_clk_1.gif";


/**
* Constant representing the path to the image to be used for the submenu
* arrow indicator when a MenuBarItem instance is disabled.
* @final
* @type String
*/
YAHOO.widget.MenuBarItem.prototype.DISABLED_SUBMENU_INDICATOR_IMAGE_PATH = 
				"nt/ic/ut/bsc/menuarodwn9_dim_1.gif";


// Private event handlers

/**
* "keydown" Custom Event handler for a MenuBarItem instance.
* @private
* @param {String} p_sType The name of the event that was fired.
* @param {Array} p_aArguments Collection of arguments sent when the event 
* was fired.
* @param {YAHOO.widget.MenuModule} p_oMenuModule The MenuModule instance that 
* fired the event.
*/
YAHOO.widget.MenuBarItem.prototype._onKeyDown =

				function(p_sType, p_aArguments, p_oMenuItem) {

					var oEvent = p_aArguments[0];
				
					switch(oEvent.keyCode) {
				
						case 37:    // Left arrow
						case 39:    // Right arrow
				
							var oActiveItem = this.parent.activeItem;
				
							if(this == oActiveItem && !this.cfg.getProperty("selected")) {
				
								this.cfg.setProperty("selected", true);
				
							}
							else {
				
								var oNextItem = (oEvent.keyCode == 37) ? 
										this.getPreviousEnabledSibling() : 
										this.getNextEnabledSibling();
						
								if(oNextItem) {

									this.parent.clearActiveItem();

									oNextItem.cfg.setProperty("selected", true);
						
									oNextItem.focus();
				
								}
				
							}

							YAHOO.util.Event.preventDefault(oEvent);
				
						break;
				
						case 40:    // Down arrow

							this.parent.clearActiveItem();
									
							this.cfg.setProperty("selected", true);
							
							this.focus();

							var oSubmenu = this.cfg.getProperty("submenu");
				
							if(oSubmenu) {
					
								oSubmenu.show();
								oSubmenu.setInitialSelection();
				
							}

							YAHOO.util.Event.preventDefault(oEvent);
				
						break;
				
					}
				
				};
				
				/*
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
Version: 0.10.0
*/

/**
			 *
			 * Base class for animated DOM objects.
			 * @class Base animation class that provides the interface for building animated effects.
			 * <p>Usage: var myAnim = new YAHOO.util.Anim(el, { width: { from: 10, to: 100 } }, 1, YAHOO.util.Easing.easeOut);</p>
			 * @requires YAHOO.util.AnimMgr
			 * @requires YAHOO.util.Easing
			 * @requires YAHOO.util.Dom
			 * @requires YAHOO.util.Event
			 * @requires YAHOO.util.CustomEvent
			 * @constructor
			 * @param {String or 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)
			 */

YAHOO.util.Anim = function(el, attributes, duration, method) 
{
			   if (el) {
				  this.init(el, attributes, duration, method); 
			   }
};

YAHOO.util.Anim.prototype = {
			   /**
				* Returns the value computed by the animation's "method".
				* @param {String} attribute 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(attribute, start, end) {
				  return this.method(this.currentFrame, start, end - start, this.totalFrames);
			   },
			   
			   /**
				* Applies a value to an attribute
				* @param {String} attribute 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(attribute, val, unit) {
				  YAHOO.util.Dom.setStyle(this.getEl(), attribute, val + unit); 
			   },                  
			   
			   /**
				* Returns current value of the attribute.
				* @param {String} attribute The name of the attribute.
				* @return {Number} val The current value of the attribute.
				*/
			   getAttribute: function(attribute) {
				  return parseFloat( YAHOO.util.Dom.getStyle(this.getEl(), attribute));
			   },
			   
			   /**
				* The default unit to use for all attributes if not defined per attribute.
				* @type String
				*/
			   defaultUnit: 'px',
			   
			   /**
				* Per attribute units that should be used by default.
				* @type Object
				*/
			   defaultUnits: { opacity: ' ' },

			   /**
				* @param {String or 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.
				   * @private
				   * @type Boolean
				   */
				  var isAnimated = false;
				  
				  /**
				   * A Date object that is created when the animation begins.
				   * @private
				   * @type Date
				   */
				  var startTime = null;
				  
				  /**
				   * A Date object that is created when the animation ends.
				   * @private
				   * @type Date
				   */
				  var endTime = null;
				  
				  /**
				   * The number of frames this animation was able to execute.
				   * @private
				   * @type Int
				   */
				  var actualFrames = 0;
				  
				  /**
				   * The attribute values that will be used if no "from" is supplied.
				   * @private
				   * @type Object
				   */
				  var defaultValues = {};      

				  /**
				   * The element to be animated.
				   * @private
				   * @type HTMLElement
				   */
				  el = YAHOO.util.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. 
				   * @member YAHOO#util#Anim
				   * 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).
				   * @type Object
				   */
				  this.attributes = attributes || {};
				  
				  /**
				   * The length of the animation.  Defaults to "1" (second).
				   * @type Number
				   */
				  this.duration = duration || 1;
				  
				  /**
				   * The method that will provide values to the attribute(s) during the animation. 
				   * Defaults to "YAHOO.util.Easing.easeNone".
				   * @type Function
				   */
				  this.method = method || YAHOO.util.Easing.easeNone;

				  /**
				   * Whether or not the duration should be treated as seconds.
				   * Defaults to true.
				   * @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.
				   * @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.
				   * @type Int
				   */
				  this.totalFrames = YAHOO.util.AnimMgr.fps;
				  
				  
				  /**
				   * Returns a reference to the animated element.
				   * @return {HTMLElement}
				   */
				  this.getEl = function() { return el; };
				  
				  
				  /**
				   * Sets the default value to be used when "from" is not supplied.
				   * @param {String} attribute The attribute being set.
				   * @param {Number} val The default value to be applied to the attribute.
				   */
				  this.setDefault = function(attribute, val) {
					 if ( val.constructor != Array && (val == 'auto' || isNaN(val)) ) { // if 'auto' or NaN, set defaults for well known attributes, zero for others
						switch(attribute) {
						   case'width':
							  val = el.clientWidth || el.offsetWidth; // computed width
							  break;
						   case 'height':
							  val = el.clientHeight || el.offsetHeight; // computed height
							  break;
						   case 'left':
							  if (YAHOO.util.Dom.getStyle(el, 'position') == 'absolute') {
								 val = el.offsetLeft; // computed left
							  } else {
								 val = 0;
							  }
							  break;
						   case 'top':
							  if (YAHOO.util.Dom.getStyle(el, 'position') == 'absolute') {
								 val = el.offsetTop; // computed top
							  } else {
								 val = 0;
							  }
							  break;                     
						   default:
							  val = 0;
						}
					 }

					 defaultValues[attribute] = val;
				  };
				  
				  /**
				   * Returns the default value for the given attribute.
				   * @param {String} attribute The attribute whose value will be returned.
				   */      
				  this.getDefault = function(attribute) {
					 return defaultValues[attribute];
				  };
				  
				  /**
				   * Checks whether the element is currently animated.
				   * @return {Boolean} current value of isAnimated.    
				   */
				  this.isAnimated = function() {
					 return isAnimated;
				  };
				  
				  /**
				   * Returns the animation start time.
				   * @return {Date} current value of startTime.     
				   */
				  this.getStartTime = function() {
					 return startTime;
				  };      
				  
				  /**
				   * Starts the animation by registering it with the animation manager.   
				   */
				  this.animate = function() {
					 if ( this.isAnimated() ) { return false; }
					 
					 this.onStart.fire();
					 this._onStart.fire();
					 
					 this.totalFrames = ( this.useSeconds ) ? Math.ceil(YAHOO.util.AnimMgr.fps * this.duration) : this.duration;
					 YAHOO.util.AnimMgr.registerElement(this);
					 
					 // get starting values or use defaults
					 var attributes = this.attributes;
					 var el = this.getEl();
					 var val;
					 
					 for (var attribute in attributes) {
						val = this.getAttribute(attribute);
						this.setDefault(attribute, val);
					 }
					 
					 isAnimated = true;
					 actualFrames = 0;
					 startTime = new Date();   
				  };
					
				  /**
				   * Stops the animation.  Normally called by AnimMgr when animation completes.
				   */ 
				  this.stop = function() {
					 if ( !this.isAnimated() ) { return false; } 
					 
					 this.currentFrame = 0;
					 
					 endTime = new Date();
					 
					 var data = {
						time: endTime,
						duration: endTime - startTime,
						frames: actualFrames,
						fps: actualFrames / this.duration
					 };

					 isAnimated = false;  
					 actualFrames = 0;
					 
					 this.onComplete.fire(data);
				  };
				  
				  /**
				   * 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 start;
					 var end = null;
					 var val;
					 var unit;
					 var attributes = this['attributes'];
					 
					 for (var attribute in attributes) {
						unit = attributes[attribute]['unit'] || this.defaultUnits[attribute] || this.defaultUnit;
			   
						if (typeof attributes[attribute]['from'] != 'undefined') {
						   start = attributes[attribute]['from'];
						} else {
						   start = this.getDefault(attribute);
						}
			   

						// To beats by, per SMIL 2.1 spec
						if (typeof attributes[attribute]['to'] != 'undefined') {
						   end = attributes[attribute]['to'];
						} 
						else if (typeof attributes[attribute]['by'] != 'undefined') 
						{
						   if (start.constructor == Array) {
							  end = [];
							  for (var i = 0, len = start.length; i < len; ++i)
							  {
								 end[i] = start[i] + attributes[attribute]['by'][i];
							  }
						   }
						   else
						   {
							  end = start + attributes[attribute]['by'];
						   }
						}
			   
						// if end is null, dont change value
						if (end !== null && typeof end != 'undefined') {
			   
						   val = this.doMethod(attribute, start, end);

						   // negative not allowed for these (others too, but these are most common)
						   if ( (attribute == 'width' || attribute == 'height' || attribute == 'opacity') && val < 0 ) {
							  val = 0;
						   }

						   this.setAttribute(attribute, val, unit); 
						}
					 }
					 
					 actualFrames += 1;
				  };
				  
				  /**
				   * Custom event that fires after onStart, useful in subclassing
				   * @private
				   */   
				  this._onStart = new YAHOO.util.CustomEvent('_onStart', this);
				  
				  /**
				   * Custom event that fires when animation begins
				   * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction)
				   */   
				  this.onStart = new YAHOO.util.CustomEvent('start', this);
				  
				  /**
				   * Custom event that fires between each frame
				   * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction)
				   */
				  this.onTween = new YAHOO.util.CustomEvent('tween', this);
				  
				  /**
				   * Custom event that fires after onTween
				   * @private
				   */
				  this._onTween = new YAHOO.util.CustomEvent('_tween', this);
				  
				  /**
				   * Custom event that fires when animation ends
				   * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction)
				   */
				  this.onComplete = new YAHOO.util.CustomEvent('complete', this);

				  this._onTween.subscribe(onTween);
			   }
};

/*
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
Version: 0.10.0
*/

/**
			 * @class Handles animation queueing and threading.
			 * Used by Anim and subclasses.
			 */
YAHOO.util.AnimMgr = new function() {
			   /** 
				* Reference to the animation Interval
				* @private
				* @type Int
				*/
			   var thread = null;
			   
			   /** 
				* The current queue of registered animation objects.
				* @private
				* @type Array
				*/   
			   var queue = [];

			   /** 
				* The number of active animations.
				* @private
				* @type Int
				*/      
			   var tweenCount = 0;

			   /** 
				* Base frame rate (frames per second). 
				* Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
				* @type Int
				* 
				*/
			   this.fps = 200;

			   /** 
				* Interval delay in milliseconds, defaults to fastest possible.
				* @type Int
				* 
				*/
			   this.delay = 1;

			   /**
				* Adds an animation instance to the animation queue.
				* All animation instances must be registered in order to animate.
				* @param {object} tween The Anim instance to be be registered
				*/
			   this.registerElement = function(tween) {
				  if ( tween.isAnimated() ) { return false; }// but not if already animating
				  
				  queue[queue.length] = tween;
				  tweenCount += 1;

				  this.start();
			   };
			   
			   /**
				* Starts the animation thread.
				 * Only one thread can run at a time.
				*/   
			   this.start = function() {
				  if (thread === null) { thread = setInterval(this.run, this.delay); }
			   };

			   /**
				* Stops the animation thread or a specific animation instance.
				* @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) {
						if (queue[i].isAnimated()) {
						   queue[i].stop();  
						}
					 }
					 queue = [];
					 thread = null;
					 tweenCount = 0;
				  }
				  else {
					 tween.stop();     
					 tweenCount -= 1;
					 
					 if (tweenCount <= 0) { this.stop(); }
				  }
			   };
			   
			   /**
				* Called per Interval to handle each animation frame.
				*/   
			   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();     
						tween._onTween.fire();        
					 }
					 else { YAHOO.util.AnimMgr.stop(tween); }
				  }
			   };
			   
			   /**
				* On the fly frame correction to keep animation on time.
				* @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;     
				  }
			   };
};

/*
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
Version: 0.10.0
*/

/**
			 *
			 * @class Used to calculate Bezier splines for any number of control points.
			 *
			 */
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.    
				* @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] ]; 
			   
			   };
};

/*
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
Version: 0.10.0
*/

/**
			 * @class Class for defining the acceleration rate and path of animations.
			 */
YAHOO.util.Easing = new function() {

			   /**
				* Uniform speed between points.
				* @param {Number} t Time value used to compute current value.
				* @param {Number} b Starting value.
				* @param {Number} c Delta between start and end values.
				* @param {Number} d Total length of animation.
				* @return {Number} The computed value for the current animation frame.
				*/
			   this.easeNone = function(t, b, c, d) {
				return b+c*(t/=d); 
			   };
			   
			   /**
				* Begins slowly and accelerates towards end.
				* @param {Number} t Time value used to compute current value.
				* @param {Number} b Starting value.
				* @param {Number} c Delta between start and end values.
				* @param {Number} d Total length of animation.
				* @return {Number} The computed value for the current animation frame.
				*/
			   this.easeIn = function(t, b, c, d) {
				return b+c*((t/=d)*t*t);
			   };
			   
			   /**
				* Begins quickly and decelerates towards end.
				* @param {Number} t Time value used to compute current value.
				* @param {Number} b Starting value.
				* @param {Number} c Delta between start and end values.
				* @param {Number} d Total length of animation.
				* @return {Number} The computed value for the current animation frame.
				*/
			   this.easeOut = function(t, b, c, d) {
				var ts=(t/=d)*t;
				var tc=ts*t;
				return b+c*(tc + -3*ts + 3*t);
			   };
			   
			   /**
				* Begins slowly and decelerates towards end.
				* @param {Number} t Time value used to compute current value.
				* @param {Number} b Starting value.
				* @param {Number} c Delta between start and end values.
				* @param {Number} d Total length of animation.
				* @return {Number} The computed value for the current animation frame.
				*/
			   this.easeBoth = function(t, b, c, d) {
				var ts=(t/=d)*t;
				var tc=ts*t;
				return b+c*(-2*tc + 3*ts);
			   };
			   
			   /**
				* Begins by going below staring value.
				* @param {Number} t Time value used to compute current value.
				* @param {Number} b Starting value.
				* @param {Number} c Delta between start and end values.
				* @param {Number} d Total length of animation.
				* @return {Number} The computed value for the current animation frame.
				*/
			   this.backIn = function(t, b, c, d) {
				var ts=(t/=d)*t;
				var tc=ts*t;
				return b+c*(-3.4005*tc*ts + 10.2*ts*ts + -6.2*tc + 0.4*ts);
			   };
			   
			   /**
				* End by going beyond ending value.
				* @param {Number} t Time value used to compute current value.
				* @param {Number} b Starting value.
				* @param {Number} c Delta between start and end values.
				* @param {Number} d Total length of animation.
				* @return {Number} The computed value for the current animation frame.
				*/
			   this.backOut = function(t, b, c, d) {
				var ts=(t/=d)*t;
				var tc=ts*t;
				return b+c*(8.292*tc*ts + -21.88*ts*ts + 22.08*tc + -12.69*ts + 5.1975*t);
			   };
			   
			   /**
				* Starts by going below staring value, and ends by going beyond ending value.
				* @param {Number} t Time value used to compute current value.
				* @param {Number} b Starting value.
				* @param {Number} c Delta between start and end values.
				* @param {Number} d Total length of animation.
				* @return {Number} The computed value for the current animation frame.
				*/
			   this.backBoth = function(t, b, c, d) {
				var ts=(t/=d)*t;
				var tc=ts*t;
				return b+c*(0.402*tc*ts + -2.1525*ts*ts + -3.2*tc + 8*ts + -2.05*t);
			   };
};

/*
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
Version: 0.10.0
*/

/**
			 * @class Anim subclass for moving elements along a path defined by the "points" member of "attributes".  All "points" are arrays with x, y coordinates.
			 * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
			 * @requires YAHOO.util.Anim
			 * @requires YAHOO.util.AnimMgr
			 * @requires YAHOO.util.Easing
			 * @requires YAHOO.util.Bezier
			 * @requires YAHOO.util.Dom
			 * @requires YAHOO.util.Event
			 * @requires YAHOO.util.CustomEvent 
			 * @constructor
			 * @param {String or 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)
			 */
YAHOO.util.Motion = function(el, attributes, duration, method) {
			   if (el) {
				  this.initMotion(el, attributes, duration, method);
			   }
};

YAHOO.util.Motion.prototype = new YAHOO.util.Anim();

/**
			 * Per attribute units that should be used by default.
			 * Motion points default to 'px' units.
			 * @type Object
			 */
YAHOO.util.Motion.prototype.defaultUnits.points = 'px';

/**
			 * Returns the value computed by the animation's "method".
			 * @param {String} attribute 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.
			 */
YAHOO.util.Motion.prototype.doMethod = function(attribute, start, end) {
			   var val = null;
			   
			   if (attribute == 'points') {
				  var translatedPoints = this.getTranslatedPoints();
				  var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;				
			   
				  if (translatedPoints) {
					 val = YAHOO.util.Bezier.getPosition(translatedPoints, t);
				  }
				  
			   } else {
				  val = this.method(this.currentFrame, start, end - start, this.totalFrames);
			   }
			   
			   return val;
};

/**
			 * Returns current value of the attribute.
			 * @param {String} attribute The name of the attribute.
			 * @return {Number} val The current value of the attribute.
			 */
YAHOO.util.Motion.prototype.getAttribute = function(attribute) {
			   var val = null;
			   
			   if (attribute == 'points') {
				  val = [ this.getAttribute('left'), this.getAttribute('top') ];
				  if ( isNaN(val[0]) ) { val[0] = 0; }
				  if ( isNaN(val[1]) ) { val[1] = 0; }
			   } else {
				  val = parseFloat( YAHOO.util.Dom.getStyle(this.getEl(), attribute) );
			   }
			   
			   return val;
};

/**
			 * Applies a value to an attribute
			 * @param {String} attribute 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.
			 */
YAHOO.util.Motion.prototype.setAttribute = function(attribute, val, unit) {
			   if (attribute == 'points') {
				  YAHOO.util.Dom.setStyle(this.getEl(), 'left', val[0] + unit);
				  YAHOO.util.Dom.setStyle(this.getEl(), 'top', val[1] + unit);
			   } else {
				  YAHOO.util.Dom.setStyle(this.getEl(), attribute, val + unit); 
			   }
};

/**
			 * @param {String or 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)
			 */ 
YAHOO.util.Motion.prototype.initMotion = function(el, attributes, duration, method) {
			   YAHOO.util.Anim.call(this, el, attributes, duration, method);
			   
			   attributes = attributes || {};
			   attributes.points = attributes.points || {};
			   attributes.points.control = attributes.points.control || [];
			   
			   this.attributes = attributes;
			   
			   var start;
			   var end = null;
			   var translatedPoints = null;
			   
			   this.getTranslatedPoints = function() { return translatedPoints; };
			   
			   var translateValues = function(val, self) {
				  var pageXY = YAHOO.util.Dom.getXY(self.getEl());
				  val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
			   
				  return val; 
			   };
			   
			   var onStart = function() {
				  start = this.getAttribute('points');
				  var attributes = this.attributes;
				  var control =  attributes['points']['control'] || [];

				  if (control.length > 0 && control[0].constructor != Array) { // could be single point or array of points
					 control = [control];
				  }
				  
				  if (YAHOO.util.Dom.getStyle(this.getEl(), 'position') == 'static') { // default to relative
					 YAHOO.util.Dom.setStyle(this.getEl(), 'position', 'relative');
				  }

				  if (typeof attributes['points']['from'] != 'undefined') {
					 YAHOO.util.Dom.setXY(this.getEl(), attributes['points']['from']); // set to from point
					 start = this.getAttribute('points'); // get actual offset values
				  } 
				  else if ((start[0] === 0 || start[1] === 0)) { // these sometimes up when auto
					 YAHOO.util.Dom.setXY(this.getEl(), YAHOO.util.Dom.getXY(this.getEl())); // set it to current position, giving offsets
					 start = this.getAttribute('points'); // get actual offset values
				  }

				  var i, len;
				  // TO beats BY, per SMIL 2.1 spec
				  if (typeof attributes['points']['to'] != 'undefined') {
					 end = translateValues(attributes['points']['to'], this);
					 
					 for (i = 0, len = control.length; i < len; ++i) {
						control[i] = translateValues(control[i], this);
					 }
					 
				  } else if (typeof attributes['points']['by'] != 'undefined') {
					 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1]];
					 
					 for (i = 0, len = control.length; i < len; ++i) {
						control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
					 }
				  }

				  if (end) {
					 translatedPoints = [start];
					 
					 if (control.length > 0) { translatedPoints = translatedPoints.concat(control); }
					 
					 translatedPoints[translatedPoints.length] = end;
				  }
			   };
			   
			   this._onStart.subscribe(onStart);
};

/*
Copyright (c) 2006, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
Version: 0.10.0
*/

/**
			 * @class Anim subclass for scrolling elements to a position defined by the "scroll" member of "attributes".  All "scroll" members are arrays with x, y scroll positions.
			 * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
			 * @requires YAHOO.util.Anim
			 * @requires YAHOO.util.AnimMgr
			 * @requires YAHOO.util.Easing
			 * @requires YAHOO.util.Bezier
			 * @requires YAHOO.util.Dom
			 * @requires YAHOO.util.Event
			 * @requires YAHOO.util.CustomEvent 
			 * @constructor
			 * @param {String or 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)
			 */
YAHOO.util.Scroll = function(el, attributes, duration,  method) {
			   if (el) {
				  YAHOO.util.Anim.call(this, el, attributes, duration, method);
			   }
};

YAHOO.util.Scroll.prototype = new YAHOO.util.Anim();

/**
			 * Per attribute units that should be used by default.
			 * Scroll positions default to no units.
			 * @type Object
			 */
YAHOO.util.Scroll.prototype.defaultUnits.scroll = ' ';

/**
			 * Returns the value computed by the animation's "method".
			 * @param {String} attribute 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.
			 */
YAHOO.util.Scroll.prototype.doMethod = function(attribute, start, end) {
			   var val = null;

			   if (attribute == 'scroll') {
				  val = [
					 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
					 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
				  ];
				  
			   } else {
				  val = this.method(this.currentFrame, start, end - start, this.totalFrames);
			   }
			   return val;
};

/**
			 * Returns current value of the attribute.
			 * @param {String} attribute The name of the attribute.
			 * @return {Number} val The current value of the attribute.
			 */
YAHOO.util.Scroll.prototype.getAttribute = function(attribute) {
			   var val = null;
			   var el = this.getEl();
			   
			   if (attribute == 'scroll') {
				  val = [ el.scrollLeft, el.scrollTop ];
			   } else {
				  val = parseFloat( YAHOO.util.Dom.getStyle(el, attribute) );
			   }
			   
			   return val;
};

/**
			 * Applies a value to an attribute
			 * @param {String} attribute 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.
			 */
YAHOO.util.Scroll.prototype.setAttribute = function(attribute, val, unit) {
			   var el = this.getEl();
			   
			   if (attribute == 'scroll') {
				  el.scrollLeft = val[0];
				  el.scrollTop = val[1];
			   } else {
				  YAHOO.util.Dom.setStyle(el, attribute, val + unit); 
			   }
};

var nConstantSubNav = 0;
var nActiveSubNav = 0;
var nTimeout;
var aNavItemObjects = [];

function onMenuBarItemMouseOut(p_sType, p_aArguments, p_oMenuItem) {
				navMouseOut();
}

function onMenuBarItemMouseOver(p_sType, p_aArguments, p_oMenuItem) {
				clearTimeout(nTimeout);
				if (this.element.className != 'on') {
				
					// Set active sub nav
					for (var i = 1; i < aNavItemObjects.length; i++) {
						document.getElementById('navitem-'+i).className = '';
						if (aNavItemObjects[i].name.toLowerCase() == this.element.firstChild.innerHTML.toLowerCase()) {
							nActiveSubNav = aNavItemObjects[i].pos;
							document.getElementById('navitem-'+i).className = 'on';
						}
					}
					
					fadeSubNav(false);
					setTimeout(function() {
						updateSubNav();
						fadeSubNav(true);
					}, 250);
				}
}

function updateSubNav() {
				for (var i = 0; i < aNavItemObjects.length; i++) document.getElementById('nav-sub-'+i).style.display = 'none';
				document.getElementById('nav-sub-'+nActiveSubNav).style.display = 'block';
}

function fadeSubNav(visible) {
				var oAttributes = (visible) ? {opacity:{to:1}} : {opacity:{to:0}};
				var oAnim = new YAHOO.util.Anim('nav-sub', oAttributes, .25, YAHOO.util.Easing.easeNone);
				oAnim.animate();
}

function onWindowLoad() {
				var aNavItems = document.getElementById('nav').childNodes;
				var nNavPos = 0;
				
				// Add invisible (index) nav item	
				var oEmptyLi = document.createElement('li');
				oEmptyLi.style.display = 'none';
				oEmptyLi.innerHTML = 'Represents Index. This will never render.';
				document.getElementById('nav').insertBefore(oEmptyLi, document.getElementById('nav').firstChild);
				
				// Add invisible (index) subnav item	
				var oEmptySubNav = document.createElement('ul');
				oEmptySubNav.setAttribute('id', 'nav-sub-0');
				oEmptySubNav.style.visibility = 'hidden';
				document.getElementById('nav-sub').insertBefore(oEmptySubNav, document.getElementById('nav-sub').firstChild);
				var oEmptySubNavLi = document.createElement('li');
				oEmptySubNavLi.innerHTML = 'Represents Index. This will never render.';
				document.getElementById('nav-sub-0').appendChild(oEmptySubNavLi);

				// Setup navigation
				var oMenuBar = new YAHOO.widget.MenuBar('nav-bg');
				var i = oMenuBar.getItemGroups()[0].length - 1, oMenuItem;
				var aMenuBarItems = oMenuBar.getItemGroups()[0], i = aMenuBarItems.length - 1;
				do {
					aMenuBarItems[i].mouseOverEvent.subscribe(onMenuBarItemMouseOver, this);
					aMenuBarItems[i].mouseOutEvent.subscribe(onMenuBarItemMouseOut, this);
				} while (i--);

				for (var i = 0; i < aNavItems.length; i++) {
					if (aNavItems[i].tagName == 'LI') {

						// Add each nav item to an array for reference later
						aNavItemObjects[nNavPos] = {
							name: aNavItems[i].firstChild.innerHTML,
							pos: nNavPos
						};
						
						// Give the LI an ID so that we can access it directly later
						aNavItems[i].id = 'navitem-'+aNavItemObjects[nNavPos].pos;
						
						// The site's path will be using '-' instead of spaces and 'and' instead of '&'
						var sNavInner = aNavItems[i].firstChild.innerHTML.toLowerCase().split(' ').join('-');
						sNavInner = sNavInner.split('&amp;').join('and');

						// Determine which area of the site we're in, highlight that nav item, and show its subnav
						if (window.location.toString().indexOf(sNavInner) != -1) {
							aNavItems[i].className = 'on';
							nConstantSubNav = nActiveSubNav = nNavPos;
							updateSubNav();
							fadeSubNav(true);
							var aSubNavItems = document.getElementById('nav-sub-'+nNavPos).childNodes;
							for (var j = 0; j < aSubNavItems.length; j++) {
								if (aSubNavItems[j].tagName == 'LI' && aSubNavItems[j].childNodes.length > 0) {						
									var sInnerHTML = aSubNavItems[j].firstChild.innerHTML.toLowerCase().split(' ').join('-');
									sInnerHTML = sInnerHTML.split('&amp;').join('and');						
									if (sInnerHTML != '') {
										if (window.location.toString().indexOf(sInnerHTML) != -1) {
											aSubNavItems[j].className = 'on';
										}
									}
								}
							}
						}

						// Assign events to subnav links
						if (nNavPos > 0) {
							var aNodes = document.getElementById('nav-sub-'+nNavPos).childNodes;
							for (var j = 0; j < aNodes.length; j++) {
								if (aNodes[j].tagName == 'LI') {
									aNodes[j].firstChild.onmouseout = function() { navMouseOut(); };
									aNodes[j].firstChild.onmouseover = function() { clearTimeout(nTimeout); };
								}
							}
						}

						// Add spacer LIs
						for (var k = 1; k < aNavItemObjects.length-1; k++) {
							var oSpacerLi = document.createElement('li');
							oSpacerLi.style.fontSize = '12px';
							oSpacerLi.style.padding = '0 15px';
							oSpacerLi.style.fontWeight = 'bold';
							oSpacerLi.style.visibility = 'hidden';
							oSpacerLi.innerHTML = aNavItemObjects[k].name;
							document.getElementById('nav-sub-'+nNavPos).insertBefore(oSpacerLi, document.getElementById('nav-sub-'+nNavPos).firstChild);
						}

						nNavPos++;
						bFoundFirstSubNavItem = false;
					}
				}
				if (nConstantSubNav == 0) document.getElementById('nav-sub-0').style.display = 'block';
		
}

function navMouseOut() {
				if (nActiveSubNav != nConstantSubNav) {
					nTimeout = setTimeout(function() {
						if (nConstantSubNav != 0) document.getElementById('navitem-'+nConstantSubNav).className = 'on';
						document.getElementById('navitem-'+nActiveSubNav).className = '';
						fadeSubNav(false);
						setTimeout(function() {
							nActiveSubNav = nConstantSubNav;
							updateSubNav();
							fadeSubNav(true);
						}, 250);		
					}, 1000);
				}
}

YAHOO.util.Event.addListener(window, 'load', onWindowLoad);

/**
			 * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
			 *
			 * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
			 * http://www.opensource.org/licenses/mit-license.php
			 *
			 * **SWFObject is the SWF embed script formerly known as FlashObject. The name was changed for
			 *   legal reasons.
			 */
if(typeof deconcept=="undefined"){var deconcept=new Object();}
if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}
if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}
deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a,_b){
if(!document.createElement||!document.getElementById){return;}
this.DETECT_KEY=_b?_b:"detectflash";
this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);
this.params=new Object();
this.variables=new Object();
this.attributes=new Array();
if(_1){this.setAttribute("swf",_1);}
if(id){this.setAttribute("id",id);}
if(w){this.setAttribute("width",w);}
if(h){this.setAttribute("height",h);}
if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}
this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute("version"),_7);
if(c){this.addParam("bgcolor",c);}
var q=_8?_8:"high";
this.addParam("quality",q);
this.setAttribute("useExpressInstall",_7);
this.setAttribute("doExpressInstall",false);
var _d=(_9)?_9:window.location;
this.setAttribute("xiRedirectUrl",_d);
this.setAttribute("redirectUrl","");
if(_a){this.setAttribute("redirectUrl",_a);}};
deconcept.SWFObject.prototype={setAttribute:function(_e,_f){
this.attributes[_e]=_f;
},getAttribute:function(_10){
return this.attributes[_10];
},addParam:function(_11,_12){
this.params[_11]=_12;
},getParams:function(){
return this.params;
},addVariable:function(_13,_14){
this.variables[_13]=_14;
},getVariable:function(_15){
return this.variables[_15];
},getVariables:function(){
return this.variables;
},getVariablePairs:function(){
var _16=new Array();
var key;
var _18=this.getVariables();
for(key in _18){
_16.push(key+"="+_18[key]);}
return _16;
},getSWFHTML:function(){
var _19="";
if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){
if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");}
_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\"";
_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";
var _1a=this.getParams();
for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}
var _1c=this.getVariablePairs().join("&");
if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}
_19+="/>";
}else{
if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");}
_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\">";
_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";
var _1d=this.getParams();
for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}
var _1f=this.getVariablePairs().join("&");
if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}
_19+="</object>";}
return _19;
},write:function(_20){
if(this.getAttribute("useExpressInstall")){
var _21=new deconcept.PlayerVersion([6,0,65]);
if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){
this.setAttribute("doExpressInstall",true);
this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));
document.title=document.title.slice(0,47)+" - Flash Player Installation";
this.addVariable("MMdoctitle",document.title);}}
if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){
var n=(typeof _20=="string")?document.getElementById(_20):_20;
n.innerHTML=this.getSWFHTML();
return true;
}else{
if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}
return false;}};
deconcept.SWFObjectUtil.getPlayerVersion=function(_23,_24){
var _25=new deconcept.PlayerVersion([0,0,0]);
if(navigator.plugins&&navigator.mimeTypes.length){
var x=navigator.plugins["Shockwave Flash"];
if(x&&x.description){_25=new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}
}else{try{
var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
for(var i=3;axo!=null;i++){
axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
_25=new deconcept.PlayerVersion([i,0,0]);}}
catch(e){}
if(_23&&_25.major>_23.major){return _25;}
if(!_23||((_23.minor!=0||_23.rev!=0)&&_25.major==_23.major)||_25.major!=6||_24){
try{_25=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}
catch(e){}}}
return _25;};
deconcept.PlayerVersion=function(_29){
this.major=parseInt(_29[0])!=null?parseInt(_29[0]):0;
this.minor=parseInt(_29[1])||0;
this.rev=parseInt(_29[2])||0;};
deconcept.PlayerVersion.prototype.versionIsValid=function(fv){
if(this.major<fv.major){return false;}
if(this.major>fv.major){return true;}
if(this.minor<fv.minor){return false;}
if(this.minor>fv.minor){return true;}
if(this.rev<fv.rev){return false;}return true;};
deconcept.util={getRequestParameter:function(_2b){
var q=document.location.search||document.location.hash;
if(q){
var _2d=q.indexOf(_2b+"=");
var _2e=(q.indexOf("&",_2d)>-1)?q.indexOf("&",_2d):q.length;
if(q.length>1&&_2d>-1){
return q.substring(q.indexOf("=",_2d)+1,_2e);
}}return "";}};
if(Array.prototype.push==null){
Array.prototype.push=function(_2f){
this[this.length]=_2f;
return this.length;};}
var getQueryParamValue=deconcept.util.getRequestParameter;
var FlashObject=deconcept.SWFObject; // for backwards compatibility
var SWFObject=deconcept.SWFObject;


