// SpryCollapsiblePanel.js - version 0.7 - Spry Pre-Release 1.6.1//// Copyright (c) 2006. 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.var Spry;if (!Spry) Spry = {};if (!Spry.Widget) Spry.Widget = {};Spry.Widget.CollapsiblePanel = function(element, opts){	this.element = this.getElement(element);	this.focusElement = null;	this.hoverClass = "CollapsiblePanelTabHover";	this.openClass = "CollapsiblePanelOpen";	this.closedClass = "CollapsiblePanelClosed";	this.focusedClass = "CollapsiblePanelFocused";	this.enableAnimation = true;	this.enableKeyboardNavigation = true;	this.animator = null;	this.hasFocus = false;	this.contentIsOpen = true;	this.openPanelKeyCode = Spry.Widget.CollapsiblePanel.KEY_DOWN;	this.closePanelKeyCode = Spry.Widget.CollapsiblePanel.KEY_UP;	Spry.Widget.CollapsiblePanel.setOptions(this, opts);	this.attachBehaviors();};Spry.Widget.CollapsiblePanel.prototype.getElement = function(ele){	if (ele && typeof ele == "string")		return document.getElementById(ele);	return ele;};Spry.Widget.CollapsiblePanel.prototype.addClassName = function(ele, className){	if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1))		return;	ele.className += (ele.className ? " " : "") + className;};Spry.Widget.CollapsiblePanel.prototype.removeClassName = function(ele, className){	if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1))		return;	ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");};Spry.Widget.CollapsiblePanel.prototype.hasClassName = function(ele, className){	if (!ele || !className || !ele.className || ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)		return false;	return true;};Spry.Widget.CollapsiblePanel.prototype.setDisplay = function(ele, display){	if( ele )		ele.style.display = display;};Spry.Widget.CollapsiblePanel.setOptions = function(obj, optionsObj, ignoreUndefinedProps){	if (!optionsObj)		return;	for (var optionName in optionsObj)	{		if (ignoreUndefinedProps && optionsObj[optionName] == undefined)			continue;		obj[optionName] = optionsObj[optionName];	}};Spry.Widget.CollapsiblePanel.prototype.onTabMouseOver = function(e){	this.addClassName(this.getTab(), this.hoverClass);	return false;};Spry.Widget.CollapsiblePanel.prototype.onTabMouseOut = function(e){	this.removeClassName(this.getTab(), this.hoverClass);	return false;};Spry.Widget.CollapsiblePanel.prototype.open = function(){	this.contentIsOpen = true;	if (this.enableAnimation)	{		if (this.animator)			this.animator.stop();		this.animator = new Spry.Widget.CollapsiblePanel.PanelAnimator(this, true, { duration: this.duration, fps: this.fps, transition: this.transition });		this.animator.start();	}	else		this.setDisplay(this.getContent(), "block");	this.removeClassName(this.element, this.closedClass);	this.addClassName(this.element, this.openClass);};Spry.Widget.CollapsiblePanel.prototype.close = function(){	this.contentIsOpen = false;	if (this.enableAnimation)	{		if (this.animator)			this.animator.stop();		this.animator = new Spry.Widget.CollapsiblePanel.PanelAnimator(this, false, { duration: this.duration, fps: this.fps, transition: this.transition });		this.animator.start();	}	else		this.setDisplay(this.getContent(), "none");	this.removeClassName(this.element, this.openClass);	this.addClassName(this.element, this.closedClass);};Spry.Widget.CollapsiblePanel.prototype.onTabClick = function(e){	if (this.isOpen())		this.close();	else		this.open();	this.focus();	return this.stopPropagation(e);};Spry.Widget.CollapsiblePanel.prototype.onFocus = function(e){	this.hasFocus = true;	this.addClassName(this.element, this.focusedClass);	return false;};Spry.Widget.CollapsiblePanel.prototype.onBlur = function(e){	this.hasFocus = false;	this.removeClassName(this.element, this.focusedClass);	return false;};Spry.Widget.CollapsiblePanel.KEY_UP = 38;Spry.Widget.CollapsiblePanel.KEY_DOWN = 40;Spry.Widget.CollapsiblePanel.prototype.onKeyDown = function(e){	var key = e.keyCode;	if (!this.hasFocus || (key != this.openPanelKeyCode && key != this.closePanelKeyCode))		return true;	if (this.isOpen() && key == this.closePanelKeyCode)		this.close();	else if ( key == this.openPanelKeyCode)		this.open();		return this.stopPropagation(e);};Spry.Widget.CollapsiblePanel.prototype.stopPropagation = function(e){	if (e.preventDefault) e.preventDefault();	else e.returnValue = false;	if (e.stopPropagation) e.stopPropagation();	else e.cancelBubble = true;	return false;};Spry.Widget.CollapsiblePanel.prototype.attachPanelHandlers = function(){	var tab = this.getTab();	if (!tab)		return;	var self = this;	Spry.Widget.CollapsiblePanel.addEventListener(tab, "click", function(e) { return self.onTabClick(e); }, false);	Spry.Widget.CollapsiblePanel.addEventListener(tab, "mouseover", function(e) { return self.onTabMouseOver(e); }, false);	Spry.Widget.CollapsiblePanel.addEventListener(tab, "mouseout", function(e) { return self.onTabMouseOut(e); }, false);	if (this.enableKeyboardNavigation)	{		// 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.				var tabIndexEle = null;		var tabAnchorEle = null;		this.preorderTraversal(tab, function(node) {			if (node.nodeType == 1 /* NODE.ELEMENT_NODE */)			{				var tabIndexAttr = tab.attributes.getNamedItem("tabindex");				if (tabIndexAttr)				{					tabIndexEle = node;					return true;				}				if (!tabAnchorEle && node.nodeName.toLowerCase() == "a")					tabAnchorEle = node;			}			return false;		});		if (tabIndexEle)			this.focusElement = tabIndexEle;		else if (tabAnchorEle)			this.focusElement = tabAnchorEle;		if (this.focusElement)		{			Spry.Widget.CollapsiblePanel.addEventListener(this.focusElement, "focus", function(e) { return self.onFocus(e); }, false);			Spry.Widget.CollapsiblePanel.addEventListener(this.focusElement, "blur", function(e) { return self.onBlur(e); }, false);			Spry.Widget.CollapsiblePanel.addEventListener(this.focusElement, "keydown", function(e) { return self.onKeyDown(e); }, false);		}	}};Spry.Widget.CollapsiblePanel.addEventListener = function(element, eventType, handler, capture){	try	{		if (element.addEventListener)			element.addEventListener(eventType, handler, capture);		else if (element.attachEvent)			element.attachEvent("on" + eventType, handler);	}	catch (e) {}};Spry.Widget.CollapsiblePanel.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.CollapsiblePanel.prototype.attachBehaviors = function(){	var panel = this.element;	var tab = this.getTab();	var content = this.getContent();	if (this.contentIsOpen || this.hasClassName(panel, this.openClass))	{		this.addClassName(panel, this.openClass);		this.removeClassName(panel, this.closedClass);		this.setDisplay(content, "block");		this.contentIsOpen = true;	}	else	{		this.removeClassName(panel, this.openClass);		this.addClassName(panel, this.closedClass);		this.setDisplay(content, "none");		this.contentIsOpen = false;	}	this.attachPanelHandlers();};Spry.Widget.CollapsiblePanel.prototype.getTab = function(){	return this.getElementChildren(this.element)[0];};Spry.Widget.CollapsiblePanel.prototype.getContent = function(){	return this.getElementChildren(this.element)[1];};Spry.Widget.CollapsiblePanel.prototype.isOpen = function(){	return this.contentIsOpen;};Spry.Widget.CollapsiblePanel.prototype.getElementChildren = function(element){	var children = [];	var child = element.firstChild;	while (child)	{		if (child.nodeType == 1 /* Node.ELEMENT_NODE */)			children.push(child);		child = child.nextSibling;	}	return children;};Spry.Widget.CollapsiblePanel.prototype.focus = function(){	if (this.focusElement && this.focusElement.focus)		this.focusElement.focus();};/////////////////////////////////////////////////////Spry.Widget.CollapsiblePanel.PanelAnimator = function(panel, doOpen, opts){	this.timer = null;	this.interval = 0;	this.fps = 60;	this.duration = 250;	this.startTime = 0;	this.transition = Spry.Widget.CollapsiblePanel.PanelAnimator.defaultTransition;	this.onComplete = null;	this.panel = panel;	this.content = panel.getContent();	this.doOpen = doOpen;	Spry.Widget.CollapsiblePanel.setOptions(this, opts, true);	this.interval = Math.floor(1000 / this.fps);	var c = this.content;	var curHeight = c.offsetHeight ? c.offsetHeight : 0;	this.fromHeight = (doOpen && c.style.display == "none") ? 0 : curHeight;	if (!doOpen)		this.toHeight = 0;	else	{		if (c.style.display == "none")		{			// The content area is not displayed so in order to calculate the extent			// of the content inside it, we have to set its display to block.			c.style.visibility = "hidden";			c.style.display = "block";		}		// Clear the height property so we can calculate		// the full height of the content we are going to show.		c.style.height = "";		this.toHeight = c.offsetHeight;	}	this.distance = this.toHeight - this.fromHeight;	this.overflow = c.style.overflow;	c.style.height = this.fromHeight + "px";	c.style.visibility = "visible";	c.style.overflow = "hidden";	c.style.display = "block";};Spry.Widget.CollapsiblePanel.PanelAnimator.defaultTransition = function(time, begin, finish, duration) { time /= duration; return begin + ((2 - time) * time * finish); };Spry.Widget.CollapsiblePanel.PanelAnimator.prototype.start = function(){	var self = this;	this.startTime = (new Date).getTime();	this.timer = setTimeout(function() { self.stepAnimation(); }, this.interval);};Spry.Widget.CollapsiblePanel.PanelAnimator.prototype.stop = function(){	if (this.timer)	{		clearTimeout(this.timer);		// If we're killing the timer, restore the overflow property.		this.content.style.overflow = this.overflow;	}	this.timer = null;};Spry.Widget.CollapsiblePanel.PanelAnimator.prototype.stepAnimation = function(){	var curTime = (new Date).getTime();	var elapsedTime = curTime - this.startTime;	if (elapsedTime >= this.duration)	{		if (!this.doOpen)			this.content.style.display = "none";		this.content.style.overflow = this.overflow;		this.content.style.height = this.toHeight + "px";		if (this.onComplete)			this.onComplete();		return;	}	var ht = this.transition(elapsedTime, this.fromHeight, this.distance, this.duration);	this.content.style.height = ((ht < 0) ? 0 : ht) + "px";	var self = this;	this.timer = setTimeout(function() { self.stepAnimation(); }, this.interval);};Spry.Widget.CollapsiblePanelGroup = function(element, opts){	this.element = this.getElement(element);	this.opts = opts;	this.attachBehaviors();};Spry.Widget.CollapsiblePanelGroup.prototype.setOptions = Spry.Widget.CollapsiblePanel.prototype.setOptions;Spry.Widget.CollapsiblePanelGroup.prototype.getElement = Spry.Widget.CollapsiblePanel.prototype.getElement;Spry.Widget.CollapsiblePanelGroup.prototype.getElementChildren = Spry.Widget.CollapsiblePanel.prototype.getElementChildren;Spry.Widget.CollapsiblePanelGroup.prototype.setElementWidget = function(element, widget){	if (!element || !widget)		return;	if (!element.spry)		element.spry = new Object;	element.spry.collapsiblePanel = widget;};Spry.Widget.CollapsiblePanelGroup.prototype.getElementWidget = function(element){	return (element && element.spry && element.spry.collapsiblePanel) ? element.spry.collapsiblePanel : null;};Spry.Widget.CollapsiblePanelGroup.prototype.getPanels = function(){	if (!this.element)		return [];	return this.getElementChildren(this.element);};Spry.Widget.CollapsiblePanelGroup.prototype.getPanel = function(panelIndex){	return this.getPanels()[panelIndex];};Spry.Widget.CollapsiblePanelGroup.prototype.attachBehaviors = function(){	if (!this.element)		return;	var cpanels = this.getPanels();	var numCPanels = cpanels.length;	for (var i = 0; i < numCPanels; i++)	{		var cpanel = cpanels[i];		this.setElementWidget(cpanel, new Spry.Widget.CollapsiblePanel(cpanel, this.opts));	}};Spry.Widget.CollapsiblePanelGroup.prototype.openPanel = function(panelIndex){	var w = this.getElementWidget(this.getPanel(panelIndex));	if (w && !w.isOpen())		w.open();};Spry.Widget.CollapsiblePanelGroup.prototype.closePanel = function(panelIndex){	var w = this.getElementWidget(this.getPanel(panelIndex));	if (w && w.isOpen())		w.close();};Spry.Widget.CollapsiblePanelGroup.prototype.openAllPanels = function(){	var cpanels = this.getPanels();	var numCPanels = cpanels.length;	for (var i = 0; i < numCPanels; i++)	{		var w = this.getElementWidget(cpanels[i]);		if (w && !w.isOpen())			w.open();	}};Spry.Widget.CollapsiblePanelGroup.prototype.closeAllPanels = function(){	var cpanels = this.getPanels();	var numCPanels = cpanels.length;	for (var i = 0; i < numCPanels; i++)	{		var w = this.getElementWidget(cpanels[i]);		if (w && w.isOpen())			w.close();	}};