// SpryWidget.js - version 0.16 - Spry Pre-Release 1.7//// Copyright (c) 2009. Adobe Systems Incorporated.// All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are met:////   * Redistributions of source code must retain the above copyright notice,//     this list of conditions and the following disclaimer.//   * Redistributions in binary form must reproduce the above copyright notice,//     this list of conditions and the following disclaimer in the documentation//     and/or other materials provided with the distribution.//   * Neither the name of Adobe Systems Incorporated nor the names of its//     contributors may be used to endorse or promote products derived from this//     software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE// POSSIBILITY OF SUCH DAMAGE.(function() { // BeginSpryComponent	if (typeof Spry == "undefined" || !Spry.Utils || !Spry.$$){	alert("SpryWidget.js requires SpryDOMUtils.js");	return;}if (!Spry.Widget) Spry.Widget = {};Spry.Widget.setOptions = function(obj, optionsObj, ignoreUndefinedProps){	if (obj && optionsObj)	{		for (var optionName in optionsObj)		{			var v = optionsObj[optionName];			if (!ignoreUndefinedProps || v != undefined)				obj[optionName] = v;		}	}	return obj;};Spry.Widget.onLoadDidFire = false;Spry.Widget.onLoadQueue = [];Spry.Widget.addCallbackToOnLoadQueue = function(callbackFunc, context){	if (callbackFunc)	{		if (context)		{			var cf = callbackFunc;			callbackFunc = function() { cf.call(context); };		}		Spry.Widget.onLoadQueue.push(callbackFunc);	}};Spry.Widget.triggerCallbackAfterOnLoad = function(callbackFunc, context){	if (Spry.Widget.onLoadDidFire)		callbackFunc.call(context);	else		Spry.Widget.addCallbackToOnLoadQueue(callbackFunc, context);		};Spry.Widget.processOnLoadQueue = function(){	Spry.Widget.onLoadDidFire = true;	var q = Spry.Widget.onLoadQueue;	while (q.length)		(q.shift())();};Spry.Utils.addLoadListener(Spry.Widget.processOnLoadQueue);Spry.Widget.Base = function(){	Spry.Widget.Base.Notifier.call(this);};Spry.Widget.Base.Notifier = function(){	this.observers = [];	this.suppressNotifications = 0;};Spry.Widget.Base.Notifier.prototype.addObserver = function(observer){	if (!observer)		return;	// Make sure the observer isn't already on the list.	var len = this.observers.length;	for (var i = 0; i < len; i++)	{		if (this.observers[i] == observer)			return;	}	this.observers[len] = observer;};Spry.Widget.Base.Notifier.prototype.removeObserver = function(observer){	if (!observer)		return;	for (var i = 0; i < this.observers.length; i++)	{		if (this.observers[i] == observer)		{			this.observers.splice(i, 1);			break;		}	}};Spry.Widget.Base.Notifier.prototype.notifyObservers = function(methodName, data){	if (!methodName)		return;	if (!this.suppressNotifications)	{		var len = this.observers.length;		for (var i = 0; i < len; i++)		{			var obs = this.observers[i];			if (obs)			{				if (typeof obs == "function")					obs(methodName, this, data);				else if (obs[methodName])					obs[methodName](this, data);			}		}	}};Spry.Widget.Base.Notifier.prototype.enableNotifications = function(){	if (--this.suppressNotifications < 0)	{		this.suppressNotifications = 0;		Spry.Debug.reportError("Unbalanced enableNotifications() call!\n");	}};Spry.Widget.Base.Notifier.prototype.disableNotifications = function(){	++this.suppressNotifications;};Spry.Widget.Base.prototype = new Spry.Widget.Base.Notifier();Spry.Widget.Base.prototype.constructor = Spry.Widget.Base;Spry.Widget.Base.getElement = function(ele){	return Spry.$(ele);};Spry.Widget.Base.getElements = function(elements){	var eType = typeof elements;	if (eType == "string")		return Spry.$$(elements);	else if (eType == "object")	{		if (elements.constructor == Array)		{			var result = [];			for (var i = 0; i < elements.length; i++)				result = result.concat(Spry.Widget.Base.getElements(elements[i]));			return result;		}		else			return [elements];	}	return [];};Spry.Widget.Base.getElementsByClassName = function(root, className){	var results = [];	if (typeof root.getElementsByClassName != "undefined")	{		// Browser has a native getElementsByClassName(), so use it.		var nodeList = root.getElementsByClassName(className);		for (var i = 0; i < nodeList.length; i++)			results.push(nodeList.item(i));	}	else	{		// Browser has no native getElementsByClassName() implementation		// so do a manual search.		var re = new RegExp("\\b" + className + "\\b");		var nodeList = root.getElementsByTagName("*");		for (var i = 0; i < nodeList.length; i++)		{			var ele = nodeList.item(i);			if (ele.className.search(re) != -1)				results.push(ele);		}	}	return results;};Spry.Widget.Base.prototype.getElementChildren = function(element){	var children = [];	if (element)	{		var child = element.firstChild;		while (child)		{			if (child.nodeType == 1 /* Node.ELEMENT_NODE */)				children.push(child);			child = child.nextSibling;		}	}	return children;};Spry.Widget.Base.prototype.groupContentByDelimeter = function(delimeterElements){	var results = new Array();	var numDelims = delimeterElements.length;	for (var i = 0; i < numDelims; i++)	{		var delim = delimeterElements[i];		var group = new Array();		group.push(delim);		var nextDelim = delimeterElements[i+1];		var sib = delim.nextSibling;		while (sib && sib != nextDelim)		{			group.push(sib);			sib = sib.nextSibling;		}				results.push(group);	}	return results;};Spry.Widget.Base.prototype.createElement = function(elementName, className, parent, child){	var ele = document.createElement(elementName);	if (className) ele.className = className;	if (parent) parent.appendChild(ele);	if (child) ele.appendChild(child);	return ele;};Spry.Widget.Base.prototype.sliceLeftClassStr =   "Left";Spry.Widget.Base.prototype.sliceRightClassStr =  "Right";Spry.Widget.Base.prototype.sliceCenterClassStr = "Center";Spry.Widget.Base.prototype.sliceTopClassStr =    "Top";Spry.Widget.Base.prototype.sliceBottomClassStr = "Bottom";Spry.Widget.Base.prototype.sliceFuncs = {};Spry.Widget.Base.prototype.sliceFuncs["2slice"] = function(root, eleName, baseClassName){	var a = root ? root : document.createElement(eleName);	var b = document.createElement(eleName);	this.appendChildNodes(b, this.extractChildNodes(a)); // Transfer any children into the new content container.	a.appendChild(b);	this.addClassName(a, baseClassName + this.sliceLeftClassStr);	b.className = baseClassName + this.sliceRightClassStr;	a.contentContainer = b;	return a;};Spry.Widget.Base.prototype.sliceFuncs["3slice"] = function(root, eleName, baseClassName){	var a = root ? root : document.createElement(eleName);	var b = document.createElement(eleName);	var c = document.createElement(eleName);	this.appendChildNodes(c, this.extractChildNodes(a)); // Transfer any children into the new content container.	a.appendChild(b);	b.appendChild(c);	this.addClassName(a, baseClassName + this.sliceLeftClassStr);	b.className = baseClassName + this.sliceRightClassStr;	c.className = baseClassName + this.sliceCenterClassStr;	a.contentContainer = c;	return a;};Spry.Widget.Base.prototype.sliceFuncs["3sliceStacked"] = function(root, eleName, baseClassName){	root = root ? root : document.createElement(eleName);	var l = document.createElement(eleName);	var m = document.createElement(eleName);	var r = document.createElement(eleName);	this.appendChildNodes(m, this.extractChildNodes(root)); // Transfer any children into the new content container.	root.appendChild(l);	root.appendChild(m);	root.appendChild(r);	this.addClassName(root, baseClassName);	l.className = baseClassName + this.sliceLeftClassStr;	m.className = baseClassName + this.sliceCenterClassStr;	r.className = baseClassName + this.sliceRightClassStr;	root.contentContainer = m;	return root;};Spry.Widget.Base.prototype.sliceFuncs["9slice"] = function(root, eleName, baseClassName){	if (!root)		root = document.createElement(eleName);	this.addClassName(root, baseClassName);	var t = this.create3SliceStructure(null, eleName, baseClassName + this.sliceTopClassStr);	var m = this.create3SliceStructure(null, eleName, baseClassName);	var b = this.create3SliceStructure(null, eleName, baseClassName + this.sliceBottomClassStr);	this.appendChildNodes(m.contentContainer, this.extractChildNodes(root)); // Transfer any children into the new content container.	root.appendChild(t);	root.appendChild(m);	root.appendChild(b);	var contentContainer = m.contentContainer;	root.contentContainer = contentContainer;	contentContainer.rootContainer = root;	return root;};// XXX: REMOVE THESE AFTER WIDGETS HAVE BEEN CLEANED UP!Spry.Widget.Base.prototype.create3SliceStructure = Spry.Widget.Base.prototype.sliceFuncs["3slice"];Spry.Widget.Base.prototype.create9SliceStructure = Spry.Widget.Base.prototype.sliceFuncs["9slice"];// XXXSpry.Widget.Base.prototype.createOptionalSlicedStructure = function(root, eleName, className, sliceMap, childEleName){	// root         - null or the dom element that will serve as the root of the sliced structure.	//                If null, this function will create the root container using the element name specified.	// eleName      - The tag to use when creating the sliced structure.	// className    - The class names placed on each element within the sliced structure will be derived from this name.	//				  If a space delimited list is passed in, all of the names are assigned to the root element, but children 	//				  derive their classnames from just the first class in the list.	// sliceMap     - null or a dictionary of class name keys whose values are either "9slice", "3slice", or "none".	//                If null, the widget's sliceMap property is used.	// childEleName - If specified, the eleName arg will only be used for the first element created within the structure. All	//                other elements will be created with the specified childEleName.	if (!sliceMap)		sliceMap = this.sliceMap ? this.sliceMap : {};	if (!childEleName)		childEleName = eleName;	var sliceType = sliceMap[className];	sliceType = sliceType ? sliceType : "none";	if (!root)		root = document.createElement(eleName);	this.addClassName(root, className);	var baseClass = (className || "").split(/\s+/)[0];	var sliceFunc = this.sliceFuncs[sliceType];	if (sliceFunc)		root = sliceFunc.call(this, root, childEleName, baseClass);	else		root.contentContainer = root;	return root;};Spry.Widget.Base.prototype.extractChildNodes = function(ele){	var children = [];	while (ele.firstChild)	{		var c = ele.firstChild;		children.push(c);		ele.removeChild(c);	}	return children;};Spry.Widget.Base.prototype.appendChildNodes = function(ele, nodes){	for (var i = 0; i < nodes.length; i++)		ele.appendChild(nodes[i]);};Spry.Widget.Base.prototype.setOptions = Spry.Widget.setOptions;Spry.Widget.Base.prototype.getOnLoadDidFire = function() { return Spry.Widget.onLoadDidFire; };Spry.Widget.Base.prototype.addCallbackToOnLoadQueue = Spry.Widget.addCallbackToOnLoadQueue;Spry.Widget.Base.prototype.triggerCallbackAfterOnLoad = Spry.Widget.triggerCallbackAfterOnLoad;Spry.Widget.Base.prototype.getElement = Spry.Widget.Base.getElement;Spry.Widget.Base.prototype.getElements = Spry.Widget.Base.getElements;Spry.Widget.Base.prototype.addClassName = Spry.Utils.addClassName;Spry.Widget.Base.prototype.hasClassName = Spry.Utils.hasClassName;Spry.Widget.Base.prototype.removeClassName = Spry.Utils.removeClassName;Spry.Widget.Base.prototype.addEventListener = Spry.Utils.addEventListener;Spry.Widget.Base.prototype.removeEventListener = Spry.Utils.removeEventListener;Spry.Widget.Base.prototype.indexOf = function(a, v){	// IE6 doesn't support indexOf on Arrays so we need to check	// for built-in support first. If not found manually do the	// search.	if (a)	{		if (a.indexOf)			return a.indexOf(v);		for (var i = 0; i < a.length; i++)			if (a[i] == v)				return i;	}	return -1;};Spry.Widget.Base.prototype.initializePlugIns = function(defaultPlugIns, widgetOpts){	var evt = new Spry.Widget.Event(this);	this.notifyObservers("onPreInitializePlugIns", evt);	if (!evt.performDefaultAction)		return;	// Both defaultPlugIns and widgetOpts are optional so make sure	// we have always have something to work with.	var opts = widgetOpts ? widgetOpts : {};	var useDefaults = (typeof opts.useDefaultPlugIns == "undefined") ? true : opts.useDefaultPlugIns;	var dp = (useDefaults && defaultPlugIns) ? defaultPlugIns : [];	var np = opts.plugIns ? opts.plugIns : [];	// Build a list of unique plugins from the default and user-specified sets.	var plugIns = [];	var plist = dp.concat(np);	for (var i = 0; i < plist.length; i++)	{		var p = plist[i];		if (this.indexOf(plugIns, p) < 0)			plugIns.push(p);	}	// Sort the resulting set of plugins based on priority.	plugIns = plugIns.sort(function(a, b)	{		var ap = (typeof a.priority == "undefined") ? 50 : a.priority;		var bp = (typeof b.priority == "undefined") ? 50 : b.priority;		return ap - bp;	});	// Store the sorted list of plugins on the widget.	this.plugIns = plugIns;	// Instantiate each plugin.	for (var i = 0; plugIns && i < plugIns.length; i++)	{		if (plugIns[i].initialize)			plugIns[i].initialize(this);	}	this.notifyObservers("onPostInitializePlugIns", evt);};Spry.Widget.Base.prototype.getClientPosition = function(ele){	var pos = new Object;	pos.x = ele.offsetLeft;	pos.y = ele.offsetTop;	var parent = ele.offsetParent;	while (parent)	{		pos.x += parent.offsetLeft;		pos.y += parent.offsetTop;		parent = parent.offsetParent;	}	return pos;};Spry.Widget.Base.prototype.getStyleProp = function(element, prop){	var value;	var camelized = Spry.Utils.camelizeString(prop);	try	{		if (element.style)			value = element.style[camelized];		if (!value)		{			if (document.defaultView && document.defaultView.getComputedStyle)			{				var css = document.defaultView.getComputedStyle(element, null);				value = css ? css.getPropertyValue(prop) : null;			}			else if (element.currentStyle) 			{					value = element.currentStyle[camelized];			}		}	}	catch (e) {}	return value == 'auto' ? null : value;};Spry.Widget.Base.prototype.makePositioned = function(element){	var pos = this.getStyleProp(element, 'position');	if (!pos || pos == 'static')	{		element.style.position = 'relative';		// Opera returns the offset relative to the positioning context, when an		// element is position relative but top and left have not been defined		if (window.opera)		{			element.style.top = 0;			element.style.left = 0;		}	}};Spry.Widget.Base.prototype.clearIEAlphaFilter = function(ele){	var filter = ele.style.filter;	// IE uses an alpha() filter for opacity. The filter style	// property can contain multiple commands, so the idea here	// is to just strip out the alpha(filter) and append a new	// one, leaving any other filters untouched.	if (filter)	{		filter = filter.replace(/alpha\([^\)]*\)/, "");		filter = filter.replace(/^\s+|\s+$/, "");		ele.style.filter = filter;	}	else		filter = "";	return filter;};Spry.Widget.Base.prototype.setOpacity = function(ele, opacity){	ele.style.opacity = "" + opacity;	var filter = this.clearIEAlphaFilter(ele);	if (filter)		filter += " ";	ele.style.filter = filter + "alpha(opacity=" + (opacity*100) + ")";};Spry.Widget.Event = function(widget, opts){	this.widget = widget;	Spry.Widget.setOptions(this, opts);	this.performDefaultAction = true;};Spry.Widget.Event.prototype.preventDefault = function() { this.performDefaultAction = false; };////////////////////////////////////////////////////////Spry.Widget.Button = function(ele, opts){	Spry.Widget.Base.call(this);	this.element = Spry.$$(ele)[0];	// Initialize the button object with the global defaults.	this.setOptions(this, Spry.Widget.Button.config);		// Override the defaults with any options passed into the constructor.	this.setOptions(this, opts);	var self = this;	this.addEventListener(this.element, "mousedown", function(e) { return self.handleMouseDown(e); }, false);	this.addEventListener(this.element, "mouseover", function(e) { return self.handleMouseOver(e); }, false);	this.addEventListener(this.element, "mouseout", function(e) { return self.handleMouseOut(e); }, false);	// XXX: IE doesn't allow the setting of tabindex dynamically. This means we can't	// rely on adding the tabindex attribute if it is missing to enable keyboard navigation	// by default.	// Find the first element within the tab container that has a tabindex or the first	// anchor tag.	this.focusElement = this.getFocusElement(this.element);	if (this.focusElement)	{		this.addEventListener(this.focusElement, "focus", function(e) { return self.handleFocus(e); }, false);		this.addEventListener(this.focusElement, "blur", function(e) { return self.handleBlur(e); }, false);		this.addEventListener(this.focusElement, "keydown", function(e) { return self.handleKeyDown(e); }, false);	}	// We need to eat the onclick event so that buttons made	// from links don't follow the link.		this.addEventListener(this.element, "click", function(e) { return false; }, false);	this.mouseUpCallback = function(evt) { return self.handleMouseUp(evt); };};Spry.Widget.Button.config = {	disabled:             false,	mouseOutCancelsClick: true,	onclick:              null,	downClass:            "ButtonDown",	hoverClass:           "ButtonHover",	disabledClass:        "ButtonDisabled",	focusedClass:         "ButtonFocused"};Spry.Widget.Button.prototype = new Spry.Widget.Base();Spry.Widget.Button.prototype.constructor = Spry.Widget.Button;Spry.Widget.Button.prototype.handleMouseDown = function(evt){	if (this.disabled)		return false;	this.addClassName(this.element, this.downClass);	this.addEventListener(document, "mouseup", this.mouseUpCallback, true);	this.notifyObservers("onButtonDown", { event: evt });};Spry.Widget.Button.prototype.handleMouseUp = function(evt){	if (this.disabled)		return false;	this.removeClassName(this.element, this.downClass);	this.removeEventListener(document, "mouseup", this.mouseUpCallback, true);	if (this.onclick)		this.onclick(evt);	this.notifyObservers("onButtonUp");	this.notifyObservers("onButtonClick");};Spry.Widget.Button.prototype.handleMouseOver = function(evt){	if (this.disabled)		return false;	this.addClassName(this.element, this.hoverClass);	this.notifyObservers("onButtonEnter");};Spry.Widget.Button.prototype.handleMouseOut = function(evt){	if (this.disabled)		return false;	var ele = this.element;	this.removeClassName(ele, this.hoverClass);	if (this.mouseOutCancelsClick)	{		this.removeClassName(ele, this.downClass);		this.removeEventListener(document, "mouseup", this.mouseUpCallback, true);	}		this.notifyObservers("onButtonExit");};Spry.Widget.Button.prototype.handleFocus = function(evt){	if (this.disabled)		return false;	this.addClassName(this.element, this.focusedClass);	this.notifyObservers("onButtonFocused");};Spry.Widget.Button.prototype.handleBlur = function(evt){	if (this.disabled)		return false;	this.removeClassName(this.element, this.focusedClass);	this.notifyObservers("onButtonBlur");};Spry.Widget.Button.prototype.handleKeyDown = function(evt){	if (this.disabled)		return false;	this.notifyObservers("onButtonKeyDown", {event: evt, element: this.element});};Spry.Widget.Button.prototype.getFocusElement = function(element) {	var focusElement = null;	var indexEle = null;	var anchorEle = null;	this.preorderTraversal(element, function(node) {		if (node.nodeType == 1 /* NODE.ELEMENT_NODE */)		{			var tabIndexAttr = element.attributes.getNamedItem("tabindex");			if (tabIndexAttr)			{				indexEle = node;				return true;			}			if (!anchorEle && node.nodeName.toLowerCase() == "a")				anchorEle = node;		}		return false;	});	if (indexEle)		focusElement = indexEle;	else if (anchorEle)		focusElement = anchorEle;	return focusElement;};Spry.Widget.Button.prototype.preorderTraversal = function(root, func){	var stopTraversal = false;	if (root)	{		stopTraversal = func(root);		if (root.hasChildNodes())		{			var child = root.firstChild;			while (!stopTraversal && child)			{				stopTraversal = this.preorderTraversal(child, func);				try { child = child.nextSibling; } catch (e) { child = null; }			}		}	}	return stopTraversal;};Spry.Widget.Button.prototype.disable = function(){	this.disabled = true;	this.removeClassName(this.element, this.downClass);	this.removeClassName(this.element, this.hoverClass);	this.addClassName(this.element, this.disabledClass);	this.removeEventListener(document, "mouseup", this.mouseUpCallback, true);};Spry.Widget.Button.prototype.enable = function(){	this.disabled = false;	this.removeClassName(this.element, this.disabledClass);};Spry.Widget.Button.prototype.focus = function(){	if (this.disabled)		return false;	if (this.focusElement)		this.focusElement.focus();};})(); // EndSpryComponent