
function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}
function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}


// SpryDOMUtils.js - version 0.6 - Spry Pre-Release 1.6.1
//
// Copyright (c) 2007. 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.Utils) Spry.Utils = {};

//////////////////////////////////////////////////////////////////////
//
// Define Prototype's $() convenience function, but make sure it is
// namespaced under Spry so that we avoid collisions with other
// toolkits.
//
//////////////////////////////////////////////////////////////////////

Spry.$ = function(element)
{
	if (arguments.length > 1)
	{
		for (var i = 0, elements = [], length = arguments.length; i < length; i++)
			elements.push(Spry.$(arguments[i]));
		return elements;
	}
	if (typeof element == 'string')
		element = document.getElementById(element);
	return element;
};

//////////////////////////////////////////////////////////////////////
//
// DOM Utils
//
//////////////////////////////////////////////////////////////////////

Spry.Utils.setAttribute = function(ele, name, value)
{
	ele = Spry.$(ele);
	if (!ele || !name)
		return;

	// IE doesn't allow you to set the "class" attribute. You
	// have to set the className property instead.

	if (name == "class")
		ele.className = value;
	else
		ele.setAttribute(name, value);
};

Spry.Utils.removeAttribute = function(ele, name)
{
	ele = Spry.$(ele);
	if (!ele || !name)
		return;

	try
	{
		ele.removeAttribute(name);

		// IE doesn't allow you to remove the "class" attribute.
		// It requires you to remove "className" instead, so go
		// ahead and try to remove that too.
		//
		// XXX: We should add a check for IE here instead of doing
		// it for every browser.

		if (name == "class")
			ele.removeAttribute("className");
	} catch(e) {}
};

Spry.Utils.addClassName = function(ele, className)
{
	ele = Spry.$(ele);
	if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1))
		return;
	ele.className += (ele.className ? " " : "") + className;
};

Spry.Utils.removeClassName = function(ele, className)
{
	ele = Spry.$(ele);
	if (Spry.Utils.hasClassName(ele, className))
		ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");
};

Spry.Utils.toggleClassName = function(ele, className)
{
	if (Spry.Utils.hasClassName(ele, className))
		Spry.Utils.removeClassName(ele, className);
	else
		Spry.Utils.addClassName(ele, className);
};

Spry.Utils.hasClassName = function(ele, className)
{
	ele = Spry.$(ele);
	if (!ele || !className || !ele.className || ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)
		return false;
	return true;
};

Spry.Utils.camelizeString = function(str)
{
	var cStr = "";
	var a = str.split("-");
	for (var i = 0; i < a.length; i++)
	{
		var s = a[i];
		if (s)
			cStr = cStr ? (cStr + s.charAt(0).toUpperCase() + s.substring(1)) : s;
	}
	return cStr;
};

Spry.Utils.styleStringToObject = function(styleStr)
{
	var o = {};
	if (styleStr)
	{
		pvA = styleStr.split(";");
		for (var i = 0; i < pvA.length; i++)
		{
			var pv = pvA[i];
			if (pv && pv.indexOf(":") != -1)
			{
				var nvA = pv.split(":");
				var n = nvA[0].replace(/^\s*|\s*$/g, "");			
				var v = nvA[1].replace(/^\s*|\s*$/g, "");
				if (n && v)
					o[Spry.Utils.camelizeString(n)] = v;
			}
		}
	}
	return o;
};

Spry.Utils.addEventListener = function(element, eventType, handler, capture)
{
	try
	{
		if (!Spry.Utils.eventListenerIsBoundToElement(element, eventType, handler, capture))
		{
			element = Spry.$(element);
			handler = Spry.Utils.bindEventListenerToElement(element, eventType, handler, capture);
			if (element.addEventListener)
				element.addEventListener(eventType, handler, capture);
			else if (element.attachEvent)
				element.attachEvent("on" + eventType, handler);
		}
	}
	catch (e) {}
};

Spry.Utils.removeEventListener = function(element, eventType, handler, capture)
{
	try
	{
			element = Spry.$(element);
			handler = Spry.Utils.unbindEventListenerFromElement(element, eventType, handler, capture);
			if (element.removeEventListener)
				element.removeEventListener(eventType, handler, capture);
			else if (element.detachEvent)
				element.detachEvent("on" + eventType, handler);
	}
	catch (e) {}
};

Spry.Utils.eventListenerHash = {};
Spry.Utils.nextEventListenerID = 1;

Spry.Utils.getHashForElementAndHandler = function(element, eventType, handler, capture)
{
	var hash = null;
	element = Spry.$(element);
	if (element)
	{
		if (typeof element.spryEventListenerID == "undefined")
			element.spryEventListenerID = "e" + (Spry.Utils.nextEventListenerID++);
		if (typeof handler.spryEventHandlerID == "undefined")
			handler.spryEventHandlerID = "h" + (Spry.Utils.nextEventListenerID++);	
		hash = element.spryEventListenerID + "-" + handler.spryEventHandlerID + "-" + eventType + (capture?"-capture":"");
	}
	return hash;
};

Spry.Utils.eventListenerIsBoundToElement = function(element, eventType, handler, capture)
{
	element = Spry.$(element);
	var hash = Spry.Utils.getHashForElementAndHandler(element, eventType, handler, capture);
	return Spry.Utils.eventListenerHash[hash] != undefined;
};

Spry.Utils.bindEventListenerToElement = function(element, eventType, handler, capture)
{
	element = Spry.$(element);
	var hash = Spry.Utils.getHashForElementAndHandler(element, eventType, handler, capture);
	if (Spry.Utils.eventListenerHash[hash])
		return Spry.Utils.eventListenerHash[hash];
	return Spry.Utils.eventListenerHash[hash] = function(e)
	{
		e = e || window.event;

		if (!e.preventDefault) e.preventDefault = function() { this.returnValue = false; };
		if (!e.stopPropagation) e.stopPropagation = function() { this.cancelBubble = true; };

		var result = handler.call(element, e);
		if (result == false)
		{
			e.preventDefault();
			e.stopPropagation();
		}
		return result;
	};
};

Spry.Utils.unbindEventListenerFromElement = function(element, eventType, handler, capture)
{
	element = Spry.$(element);
	var hash = Spry.Utils.getHashForElementAndHandler(element, eventType, handler, capture);
	if (Spry.Utils.eventListenerHash[hash])
	{
		handler = Spry.Utils.eventListenerHash[hash];
		Spry.Utils.eventListenerHash[hash] = undefined;
	}
	return handler;
};

Spry.Utils.addLoadListener = function(handler)
{
	if (typeof window.addEventListener != 'undefined')
		window.addEventListener('load', handler, false);
	else if (typeof document.addEventListener != 'undefined')
		document.addEventListener('load', handler, false);
	else if (typeof window.attachEvent != 'undefined')
		window.attachEvent('onload', handler);
};

Spry.Utils.getAncestor = function(ele, selector)
{
	ele = Spry.$(ele);
	if (ele)
	{
		var s = Spry.$$.tokenizeSequence(selector ? selector : "*")[0];
		var t = s ? s[0] : null;
		if (t)
		{
			var p = ele.parentNode;
			while (p)
			{
				if (t.match(p))
					return p;
				p = p.parentNode;
			}
		}
	}
	return null;
};

//////////////////////////////////////////////////////////////////////
//
// CSS Selector Matching
//
//////////////////////////////////////////////////////////////////////

Spry.$$ = function(selectorSequence, rootNode)
{
	if (!rootNode)
		rootNode = document;
	else
		rootNode = Spry.$(rootNode);

	var sequences = Spry.$$.tokenizeSequence(selectorSequence);

	var matches = [];
	Spry.$$.addExtensions(matches);
	++Spry.$$.queryID;

	var nid = 0;
	var ns = sequences.length;
	for (var i = 0; i < ns; i++)
	{
		var m = Spry.$$.processTokens(sequences[i], rootNode);
		var nm = m.length;
		for (var j = 0; j < nm; j++)
		{
			var n = m[j];
			if (!n.spry$$ID)
			{
				n.spry$$ID = ++nid;
				matches.push(n);
			}
		}
	}

	var nm = matches.length;
	for (i = 0; i < nm; i++)
		matches[i].spry$$ID = undefined;

	return matches;
};

Spry.$$.cache = {};
Spry.$$.queryID = 0;

Spry.$$.Token = function()
{
	this.type = Spry.$$.Token.SELECTOR;
	this.name = "*";
	this.id = "";
	this.classes = [];
	this.attrs = [];
	this.pseudos = [];
};

Spry.$$.Token.Attr = function(n, v)
{
	this.name = n;
	this.value = v ? new RegExp(v) : undefined;
};

Spry.$$.Token.PseudoClass = function(pstr)
{
	this.name = pstr.replace(/\(.*/, "");
	this.arg = pstr.replace(/^[^\(\)]*\(?\s*|\)\s*$/g, "");
	this.func = Spry.$$.pseudoFuncs[this.name];
};

Spry.$$.Token.SELECTOR = 0;
Spry.$$.Token.COMBINATOR = 1;

Spry.$$.Token.prototype.match = function(ele, nameAlreadyMatches)
{
	if (this.type == Spry.$$.Token.COMBINATOR)
		return false;
	if (!nameAlreadyMatches && this.name != '*' && this.name != ele.nodeName.toLowerCase())
		return false;
	if (this.id && this.id != ele.id)
		return false;
	var classes = this.classes;
	var len = classes.length;
	for (var i = 0; i < len; i++)
	{
		if (!ele.className || !classes[i].value.test(ele.className))
			return false;
	}

	var attrs = this.attrs;
	len = attrs.length;
	for (var i = 0; i < len; i++)
	{
		var a = attrs[i];
		var an = ele.attributes.getNamedItem(a.name);
		if (!an || (!a.value && an.nodeValue == undefined) || (a.value && !a.value.test(an.nodeValue)))
			return false;
	}

	var ps = this.pseudos;
	var len = ps.length;
	for (var i = 0; i < len; i++)
	{
		var p = ps[i];
		if (p && p.func && !p.func(p.arg, ele, this))
			return false;
	}

	return true;
};

Spry.$$.Token.prototype.getNodeNameIfTypeMatches = function(ele)
{
	var nodeName = ele.nodeName.toLowerCase();
	if (this.name != '*')
	{
		if (this.name != nodeName)
			return null;
		return this.name;
	}
	return nodeName;
};

Spry.$$.escapeRegExpCharsRE = /\/|\.|\*|\+|\(|\)|\[|\]|\{|\}|\\|\|/g;

Spry.$$.tokenizeSequence = function(s)
{
	var cc = Spry.$$.cache[s];
	if (cc) return cc;

	// Attribute Selector: /(\[[^\"'~\^\$\*\|\]=]+([~\^\$\*\|]?=\s*('[^']*'|"[^"]*"|[^"'\]]+))?\s*\])/g
	// Simple Selector:    /((:[^\.#:\s,>~\+\[\]]+\(([^\(\)]+|\([^\(\)]*\))*\))|[\.#:]?[^\.#:\s,>~\+\[\]]+)/g
	// Combinator:         /(\s*[\s,>~\+]\s*)/g

	var tokenExpr = /(\[[^\"'~\^\$\*\|\]=]+([~\^\$\*\|]?=\s*('[^']*'|"[^"]*"|[^"'\]]+))?\s*\])|((:[^\.#:\s,>~\+\[\]]+\(([^\(\)]+|\([^\(\)]*\))*\))|[\.#:]?[^\.#:\s,>~\+\[\]]+)|(\s*[\s,>~\+]\s*)/g;

	var tkn = new Spry.$$.Token;
	var sequence = [];
	sequence.push(tkn);
	var tokenSequences = [];
	tokenSequences.push(sequence);

	s = s.replace(/^\s*|\s*$/, "");

	var expMatch = tokenExpr.exec(s);
	while (expMatch)
	{
		var tstr = expMatch[0];
		var c = tstr.charAt(0);
		switch (c)
		{
			case '.':
				tkn.classes.push(new Spry.$$.Token.Attr("class", "\\b" + tstr.substr(1) + "\\b"));
				break;
			case '#':
				tkn.id = tstr.substr(1);
				break;
			case ':':
				tkn.pseudos.push(new Spry.$$.Token.PseudoClass(tstr));
				break;
			case '[':
				var attrComps = tstr.match(/\[([^\"'~\^\$\*\|\]=]+)(([~\^\$\*\|]?=)\s*('[^']*'|"[^"]*"|[^"'\]]+))?\s*\]/);
				var name = attrComps[1];				
				var matchType = attrComps[3];
				var val = attrComps[4];
				if (val)
				{
					val = val.replace(/^['"]|['"]$/g, "");
					val = val.replace(Spry.$$.escapeRegExpCharsRE, '\\$&');
				}

				var matchStr = undefined;

				switch(matchType)
				{
					case "=":
						matchStr = "^" + val + "$";
						break;
					case "^=":
						matchStr = "^" + val;
						break;
					case "$=":
						matchStr = val + "$";
						break;
					case "~=":
					case "|=":
						matchStr = "\\b" + val + "\\b";
						break;
					case "*=":
						matchStr = val;
						break;
				}

				tkn.attrs.push(new Spry.$$.Token.Attr(name, matchStr));
				break;
			default:
				var combiMatch = tstr.match(/^\s*([\s,~>\+])\s*$/);
				if (combiMatch)
				{
					if (combiMatch[1] == ',')
					{
						sequence = new Array;
						tokenSequences.push(sequence);
						tkn = new Spry.$$.Token;
						sequence.push(tkn);
					}
					else
					{
						tkn = new Spry.$$.Token;
						tkn.type = Spry.$$.Token.COMBINATOR;
						tkn.name = combiMatch[1];
						sequence.push(tkn);
						tkn = new Spry.$$.Token();
						sequence.push(tkn);
					}
				}
				else
					tkn.name = tstr.toLowerCase();
				break;
		}
		expMatch = tokenExpr.exec(s);
	}

	Spry.$$.cache[s] = tokenSequences;

	return tokenSequences;
};

Spry.$$.combinatorFuncs = {
	// Element Descendant

	" ": function(nodes, token)
	{
		var uid = ++Spry.$$.uniqueID;
		var results = [];
		var nn = nodes.length;
		for (var i = 0; i < nn; i++)
		{
			var n = nodes[i];
			if (uid != n.spry$$uid)
			{
				// n.spry$$uid = uid;
				var ea = nodes[i].getElementsByTagName(token.name);
				var ne = ea.length;
				for (var j = 0; j < ne; j++)
				{
					var e = ea[j];
					if (token.match(e, true))
						results.push(e);
					e.spry$$uid = uid;
				}
			}
		}
		return results;
	},

	// Element Child

	">": function(nodes, token)
	{
		var results = [];
		var nn = nodes.length;
		for (var i = 0; i < nn; i++)
		{
			var n = nodes[i].firstChild;
			while (n)
			{
				if (n.nodeType == 1 /* Node.ELEMENT_NODE */ && token.match(n))
					results.push(n);
				n = n.nextSibling;
			}
		}
		return results;
	},

	// Element Immediately Preceded By

	"+": function(nodes, token)
	{
		var results = [];
		var nn = nodes.length;
		for (var i = 0; i < nn; i++)
		{
			var n = nodes[i].nextSibling;
			while (n && n.nodeType != 1 /* Node.ELEMENT_NODE */)
				n = n.nextSibling;
			if (n && token.match(n))
				results.push(n);
		}
		return results;
	},

	// Element Preceded By

	"~": function(nodes, token)
	{
		var uid = ++Spry.$$.uniqueID;
		var results = [];
		var nn = nodes.length;
		for (var i = 0; i < nn; i++)
		{
			var n = nodes[i].nextSibling;
			while (n)
			{
				if (n.nodeType == 1 /* Node.ELEMENT_NODE */)
				{
					if (uid == n.spry$$uid)
						break;

					if (token.match(n))
					{
						results.push(n);
						n.spry$$uid = uid;
					}
				}
				n = n.nextSibling;
			}
		}
		return results;
	}
};

Spry.$$.uniqueID = 0;

Spry.$$.pseudoFuncs = {
	":first-child": function(arg, node, token)
	{
		var n = node.previousSibling;
		while (n)
		{
			if (n.nodeType == 1) return false; // Node.ELEMENT_NODE
			n = n.previousSibling;
		}

		return true;
	},

	":last-child": function(arg, node, token)
	{
		var n = node.nextSibling;
		while (n)
		{
			if (n.nodeType == 1) // Node.ELEMENT_NODE
				return false;
			n = n.nextSibling;
		}
		return true;
	},

	":empty": function(arg, node, token)
	{
		var n = node.firstChild;
		while (n)
		{
			switch(n.nodeType)
			{
				case 1: // Node.ELEMENT_NODE
				case 3: // Node.TEXT_NODE
				case 4: // Node.CDATA_NODE
				case 5: // Node.ENTITY_REFERENCE_NODE
					return false;
			}
			n = n.nextSibling;
		}
		return true;
	},

	":nth-child": function(arg, node, token)
	{
		return Spry.$$.nthChild(arg, node, token);
	},

	":nth-last-child": function(arg, node, token)
	{
		return Spry.$$.nthChild(arg, node, token, true);
	},

	":nth-of-type": function(arg, node, token)
	{
		return Spry.$$.nthChild(arg, node, token, false, true);
	},
	
	":nth-last-of-type": function(arg, node, token)
	{
		return Spry.$$.nthChild(arg, node, token, true, true);
	},
	
	":first-of-type": function(arg, node, token)
	{
		var nodeName = token.getNodeNameIfTypeMatches(node);
		if (!nodeName) return false;

		var n = node.previousSibling;
		while (n)
		{
			if (n.nodeType == 1 && nodeName == n.nodeName.toLowerCase()) return false; // Node.ELEMENT_NODE
			n = n.previousSibling;
		}

		return true;
	},

	":last-of-type": function(arg, node, token)
	{
		var nodeName = token.getNodeNameIfTypeMatches(node);
		if (!nodeName) return false;

		var n = node.nextSibling;
		while (n)
		{
			if (n.nodeType == 1 && nodeName == n.nodeName.toLowerCase()) // Node.ELEMENT_NODE
				return false;
			n = n.nextSibling;
		}
		return true;
	},

	":only-child": function(arg, node, token)
	{
		var f = Spry.$$.pseudoFuncs;
		return f[":first-child"](arg, node, token) && f[":last-child"](arg, node, token);
	},

	":only-of-type": function(arg, node, token)
	{
		var f = Spry.$$.pseudoFuncs;
		return f[":first-of-type"](arg, node, token) && f[":last-of-type"](arg, node, token);
	},

	":not": function(arg, node, token)
	{
		var s = Spry.$$.tokenizeSequence(arg)[0];
		var t = s ? s[0] : null;
		return !t || !t.match(node);
	},

	":enabled": function(arg, node, token)
	{
		return !node.disabled;
	},

	":disabled": function(arg, node, token)
	{
		return node.disabled;
	},

	":checked": function(arg, node, token)
	{
		return node.checked;
	},

	":root": function(arg, node, token)
	{
		return node.parentNode && node.ownerDocument && node.parentNode == node.ownerDocument;
	}
};

Spry.$$.nthRegExp = /((-|[0-9]+)?n)?([+-]?[0-9]*)/;

Spry.$$.nthCache = {
	  "even": { a: 2, b: 0, mode: 1, invalid: false }
	, "odd":  { a: 2, b: 1, mode: 1, invalid: false }
	, "2n":   { a: 2, b: 0, mode: 1, invalid: false }
	, "2n+1": { a: 2, b: 1, mode: 1, invalid: false }
};

Spry.$$.parseNthChildString = function(str)
{
	var o = Spry.$$.nthCache[str];
	if (!o)
	{
		var m = str.match(Spry.$$.nthRegExp);
		var n = m[1];
		var a = m[2];
		var b = m[3];

		if (!a)
		{
			// An 'a' value was not specified. Was there an 'n' present?
			// If so, we treat it as an increment of 1, otherwise we're
			// in no-repeat mode.

			a = n ? 1 : 0;
		}
		else if (a == "-")
		{
			// The string is using the "-n" short-hand which is
			// short for -1.

			a = -1;
		}
		else
		{
			// An integer repeat value for 'a' was specified. Convert
			// it into number.

			a = parseInt(a, 10);
		}

		// If a 'b' value was specified, turn it into a number.
		// If no 'b' value was specified, default to zero.

		b = b ? parseInt(b, 10) : 0;

		// Figure out the mode:
		//
		// -1 - repeat backwards
		//  0 - no repeat
		//  1 - repeat forwards

		var mode = (a == 0) ? 0 : ((a > 0) ? 1 : -1);
		var invalid = false;

		// Fix up 'a' and 'b' for proper repeating.

		if (a > 0 && b < 0)
		{
			b = b % a;
			b = ((b=(b%a)) < 0) ? a + b : b;
		}
		else if (a < 0)
		{
			if (b < 0)
				invalid = true;
			else
				a = Math.abs(a);
		}

		o = new Object;
		o.a = a;
		o.b = b;
		o.mode = mode;
		o.invalid = invalid;

		Spry.$$.nthCache[str] = o;
	}

	return o;
};

Spry.$$.nthChild = function(arg, node, token, fromLastSib, matchNodeName)
{
	if (matchNodeName)
	{
		var nodeName = token.getNodeNameIfTypeMatches(node);
		if (!nodeName) return false;
	}

	var o = Spry.$$.parseNthChildString(arg);

	if (o.invalid)
		return false;

	var qidProp = "spry$$ncQueryID";
	var posProp = "spry$$ncPos";
	var countProp = "spry$$ncCount";
	if (matchNodeName)
	{
		qidProp += nodeName;
		posProp += nodeName;
		countProp += nodeName;
	}

	var parent = node.parentNode;
	if (parent[qidProp] != Spry.$$.queryID)
	{
		var pos = 0;
		parent[qidProp] = Spry.$$.queryID;
		var c = parent.firstChild;
		while (c)
		{
			if (c.nodeType == 1 && (!matchNodeName || nodeName == c.nodeName.toLowerCase()))
				c[posProp] = ++pos;
			c = c.nextSibling;
		}
		parent[countProp] = pos;
	}

	pos = node[posProp];
	if (fromLastSib)
		pos = parent[countProp] - pos + 1;

/*
	var sib = fromLastSib ? "nextSibling" : "previousSibling";

	var pos = 1;
	var n = node[sib];
	while (n)
	{
		if (n.nodeType == 1 && (!matchNodeName || nodeName == n.nodeName.toLowerCase()))
		{
			if (n == node) break;
			++pos;
		}
		n = n[sib];
	}
*/

	if (o.mode == 0) // Exact match
		return pos == o.b;
	if (o.mode > 0) // Forward Repeat
		return (pos < o.b) ? false : (!((pos - o.b) % o.a));
	return (pos > o.b) ? false : (!((o.b - pos) % o.a)); // Backward Repeat
};

Spry.$$.processTokens = function(tokens, root)
{
	var numTokens = tokens.length;
	var nodeSet = [ root ];
	var combiFunc = null;

	for (var i = 0; i < numTokens && nodeSet.length > 0; i++)
	{
		var t = tokens[i];
		if (t.type == Spry.$$.Token.SELECTOR)
		{
			if (combiFunc)
			{
				nodeSet = combiFunc(nodeSet, t);
				combiFunc = null;
			}
			else
				nodeSet = Spry.$$.getMatchingElements(nodeSet, t);
		}
		else // Spry.$$.Token.COMBINATOR
			combiFunc = Spry.$$.combinatorFuncs[t.name];
	}
	return nodeSet;
};

Spry.$$.getMatchingElements = function(nodes, token)
{
	var results = [];
	if (token.id)
	{
		n = nodes[0];
		if (n && n.ownerDocument)
		{
			var e = n.ownerDocument.getElementById(token.id);
			if (e)
			{
				// XXX: We need to make sure that the element
				//      we found is actually underneath the root
				//      we were given!

				if (token.match(e))
					results.push(e);
			}
			return results;
		}
	}

	var nn = nodes.length;
	for (var i = 0; i < nn; i++)
	{
		var n = nodes[i];
		// if (token.match(n)) results.push(n);
		
		var ea = n.getElementsByTagName(token.name);
		var ne = ea.length;
		for (var j = 0; j < ne; j++)
		{
			var e = ea[j];
			if (token.match(e, true))
				results.push(e);
		}
	}
	return results;
};

/*
Spry.$$.dumpSequences = function(sequences)
{
	Spry.Debug.trace("<hr />Number of Sequences: " + sequences.length);
	for (var i = 0; i < sequences.length; i++)
	{
		var str = "";
		var s = sequences[i];
		Spry.Debug.trace("<hr />Sequence " + i + " -- Tokens: " + s.length);
		for (var j = 0; j < s.length; j++)
		{
			var t = s[j];
			if (t.type == Spry.$$.Token.SELECTOR)
			{
				str += "  SELECTOR:\n    Name: " + t.name + "\n    ID: " + t.id + "\n    Attrs:\n";
				for (var k = 0; k < t.classes.length; k++)
					str += "      " + t.classes[k].name + ": " + t.classes[k].value + "\n";
				for (var k = 0; k < t.attrs.length; k++)
					str += "      " + t.attrs[k].name + ": " + t.attrs[k].value + "\n";
				str += "    Pseudos:\n";
				for (var k = 0; k < t.pseudos.length; k++)
					str += "      " + t.pseudos[k].name + (t.pseudos[k].arg ? "(" + t.pseudos[k].arg + ")" : "") + "\n";
			}
			else
			{
				str += "  COMBINATOR:\n    Name: '" + t.name + "'\n"; 
			}
		}
		Spry.Debug.trace("<pre>" + Spry.Utils.encodeEntities(str) + "</pre>");
	}
};
*/

Spry.$$.addExtensions = function(a)
{
	for (var f in Spry.$$.Results)
		a[f] = Spry.$$.Results[f];
};

Spry.$$.Results = {};

Spry.$$.Results.forEach = function(func)
{
	var n = this.length;
	for (var i = 0; i < n; i++)
		func(this[i]);
	return this;
};

Spry.$$.Results.setAttribute = function(name, value)
{
	return this.forEach(function(n) { Spry.Utils.setAttribute(n, name, value); });
};

Spry.$$.Results.removeAttribute = function(name)
{
	return this.forEach(function(n) { Spry.Utils.removeAttribute(n, name); });
};

Spry.$$.Results.addClassName = function(className)
{
	return this.forEach(function(n) { Spry.Utils.addClassName(n, className); });
};

Spry.$$.Results.removeClassName = function(className)
{
	return this.forEach(function(n) { Spry.Utils.removeClassName(n, className); });
};

Spry.$$.Results.toggleClassName = function(className)
{
	return this.forEach(function(n) { Spry.Utils.toggleClassName(n, className); });
};

Spry.$$.Results.addEventListener = function(eventType, handler, capture, bindHandler)
{
	return this.forEach(function(n) { Spry.Utils.addEventListener(n, eventType, handler, capture, bindHandler); });
};

Spry.$$.Results.removeEventListener = function(eventType, handler, capture)
{
	return this.forEach(function(n) { Spry.Utils.removeEventListener(n, eventType, handler, capture); });
};

Spry.$$.Results.setStyle = function(style)
{
	if (style)
	{
		style = Spry.Utils.styleStringToObject(style);
		this.forEach(function(n)
		{
			for (var p in style)
				try { n.style[p] = style[p]; } catch (e) {}
		});
	}
	return this;
};

Spry.$$.Results.setProperty = function(prop, value)
{
	if (prop)
	{
		if (typeof prop == "string")
		{
			var p = {};
			p[prop] = value;
			prop = p;
		}

		this.forEach(function(n)
		{
			for (var p in prop)
				try { n[p] = prop[p]; } catch (e) {}
		});
	}
	return this;
};


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 = false;

	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 = 500;
	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();
	}
};

var cp_options;
function InitPage()
{
	Spry.$$(".CollapsiblePanel:not(#CollapsiblePanel1)").forEach(function(n) { window[n.id] = new Spry.Widget.CollapsiblePanel(n); });
	cp_options = new Spry.Widget.CollapsiblePanel("CollapsiblePanel1", { contentIsOpen: false, enableAnimation: true });
	
	Spry.$$(".open").addEventListener("click", function(e){ CollapsiblePanel1.open(); return false;}, false);

	Spry.$$(".close").addEventListener("click", function(e){ CollapsiblePanel1.close(); return false;}, false);
}

Spry.Utils.addLoadListener(InitPage);





