/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////SprySlidingPanels.js////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
// SprySlidingPanels.js - version 0.5 - 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.SlidingPanels = function(element, opts)
{
	this.element = this.getElement(element);
	this.enableAnimation = true;
	this.currentPanel = null;
	this.enableKeyboardNavigation = true;
	this.hasFocus = false;
	this.previousPanelKeyCode = Spry.Widget.SlidingPanels.KEY_LEFT;
	this.nextPanelKeyCode = Spry.Widget.SlidingPanels.KEY_RIGHT;

	this.currentPanelClass = "SlidingPanelsCurrentPanel";
	this.focusedClass = "SlidingPanelsFocused";
	this.animatingClass = "SlidingPanelsAnimating";

	Spry.Widget.SlidingPanels.setOptions(this, opts);

	if (this.element)
		this.element.style.overflow = "hidden";

	// Developers can specify the default panel as an index,
	// id or an actual element node. Make sure to normalize
	// it into an element node because that is what we expect
	// internally.

	if (this.defaultPanel)
	{
		if (typeof this.defaultPanel == "number")
			this.currentPanel = this.getContentPanels()[this.defaultPanel];
		else
			this.currentPanel = this.getElement(this.defaultPanel);
	}

	// If we still don't have a current panel, use the first one!

	if (!this.currentPanel)
		this.currentPanel = this.getContentPanels()[0];

	// Since we rely on the positioning information of the
	// panels, we need to wait for the onload event to fire before
	// we can attempt to show the initial panel. Once the onload
	// fires, we know that all CSS files have loaded. This is
	// especially important for Safari.

	if (Spry.Widget.SlidingPanels.onloadDidFire)
		this.attachBehaviors();
	else
		Spry.Widget.SlidingPanels.loadQueue.push(this);
};

Spry.Widget.SlidingPanels.prototype.onFocus = function(e)
{
	this.hasFocus = true;
	this.addClassName(this.element, this.focusedClass);
	return false;
};

Spry.Widget.SlidingPanels.prototype.onBlur = function(e)
{
	this.hasFocus = false;
	this.removeClassName(this.element, this.focusedClass);
	return false;
};

Spry.Widget.SlidingPanels.KEY_LEFT = 37;
Spry.Widget.SlidingPanels.KEY_UP = 38;
Spry.Widget.SlidingPanels.KEY_RIGHT = 39;
Spry.Widget.SlidingPanels.KEY_DOWN = 40;

Spry.Widget.SlidingPanels.prototype.onKeyDown = function(e)
{
	var key = e.keyCode;
	if (!this.hasFocus || (key != this.previousPanelKeyCode && key != this.nextPanelKeyCode))
		return true;

	if (key == this.nextPanelKeyCode)
		this.showNextPanel();
	else /* if (key == this.previousPanelKeyCode) */
		this.showPreviousPanel();

	if (e.preventDefault) e.preventDefault();
	else e.returnValue = false;
	if (e.stopPropagation) e.stopPropagation();
	else e.cancelBubble = true;

	return false;
};

Spry.Widget.SlidingPanels.prototype.attachBehaviors = function()
{
	var ele = this.element;
	if (!ele)
		return;

	if (this.enableKeyboardNavigation)
	{
		var focusEle = null;
		var tabIndexAttr = ele.attributes.getNamedItem("tabindex");
		if (tabIndexAttr || ele.nodeName.toLowerCase() == "a")
			focusEle = ele;
	
		if (focusEle)
		{
			var self = this;
			Spry.Widget.SlidingPanels.addEventListener(focusEle, "focus", function(e) { return self.onFocus(e || window.event); }, false);
			Spry.Widget.SlidingPanels.addEventListener(focusEle, "blur", function(e) { return self.onBlur(e || window.event); }, false);
			Spry.Widget.SlidingPanels.addEventListener(focusEle, "keydown", function(e) { return self.onKeyDown(e || window.event); }, false);
		}
	}

	if (this.currentPanel)
	{
		// Temporarily turn off animation when showing the
		// initial panel.

		var ea = this.enableAnimation;
		this.enableAnimation = false;
		this.showPanel(this.currentPanel);
		this.enableAnimation = ea;
	}
};

Spry.Widget.SlidingPanels.prototype.getElement = function(ele)
{
	if (ele && typeof ele == "string")
		return document.getElementById(ele);
	return ele;
};

Spry.Widget.SlidingPanels.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.SlidingPanels.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.SlidingPanels.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.SlidingPanels.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.SlidingPanels.prototype.getCurrentPanel = function()
{
	return this.currentPanel;
};

Spry.Widget.SlidingPanels.prototype.getContentGroup = function()
{
	return this.getElementChildren(this.element)[0];
};

Spry.Widget.SlidingPanels.prototype.getContentPanels = function()
{
	return this.getElementChildren(this.getContentGroup());
};

Spry.Widget.SlidingPanels.prototype.getContentPanelsCount = function()
{
	return this.getContentPanels().length;
};

Spry.Widget.SlidingPanels.onloadDidFire = false;
Spry.Widget.SlidingPanels.loadQueue = [];

Spry.Widget.SlidingPanels.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.Widget.SlidingPanels.processLoadQueue = function(handler)
{
	Spry.Widget.SlidingPanels.onloadDidFire = true;
	var q = Spry.Widget.SlidingPanels.loadQueue;
	var qlen = q.length;
	for (var i = 0; i < qlen; i++)
		q[i].attachBehaviors();
};

Spry.Widget.SlidingPanels.addLoadListener(Spry.Widget.SlidingPanels.processLoadQueue);

Spry.Widget.SlidingPanels.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.SlidingPanels.prototype.getContentPanelIndex = function(ele)
{
	if (ele)
	{
		ele = this.getElement(ele);
		var panels = this.getContentPanels();
		var numPanels = panels.length;
		for (var i = 0; i < numPanels; i++)
		{
			if (panels[i] == ele)
				return i;
		}
	}
	return -1;
};

Spry.Widget.SlidingPanels.prototype.showPanel = function(elementOrIndex)
{
	var pIndex = -1;
	
	if (typeof elementOrIndex == "number")
		pIndex = elementOrIndex;
	else // Must be the element for the content panel.
		pIndex = this.getContentPanelIndex(elementOrIndex);

	var numPanels = this.getContentPanelsCount();
	if (numPanels > 0)
		pIndex = (pIndex >= numPanels) ? numPanels - 1 : pIndex;
	else
		pIndex = 0;

	var panel = this.getContentPanels()[pIndex];
	var contentGroup = this.getContentGroup();

	if (panel && contentGroup)
	{
		if (this.currentPanel)
			this.removeClassName(this.currentPanel, this.currentPanelClass);
		this.currentPanel = panel;

		var nx = -panel.offsetLeft;
		var ny = -panel.offsetTop;

		if (this.enableAnimation)
		{
			if (this.animator)
				this.animator.stop();
			var cx = contentGroup.offsetLeft;
			var cy = contentGroup.offsetTop;
			if (cx != nx || cy != ny)
			{
				var self = this;
				this.addClassName(this.element, this.animatingClass);
				this.animator = new Spry.Widget.SlidingPanels.PanelAnimator(contentGroup, cx, cy, nx, ny, { duration: this.duration, fps: this.fps, transition: this.transition, finish: function()
				{
					self.removeClassName(self.element, self.animatingClass);
					self.addClassName(panel, self.currentPanelClass);
				} });
				this.animator.start();
			}
		}
		else
		{
			contentGroup.style.left = nx + "px";
			contentGroup.style.top = ny + "px";
			this.addClassName(panel, this.currentPanelClass);
		}
	}

	return panel;
};

Spry.Widget.SlidingPanels.prototype.showFirstPanel = function()
{
	return this.showPanel(0);
};

Spry.Widget.SlidingPanels.prototype.showLastPanel = function()
{
	return this.showPanel(this.getContentPanels().length - 1);
};

Spry.Widget.SlidingPanels.prototype.showPreviousPanel = function()
{
	return this.showPanel(this.getContentPanelIndex(this.currentPanel) - 1);
};

Spry.Widget.SlidingPanels.prototype.showNextPanel = function()
{
	return this.showPanel(this.getContentPanelIndex(this.currentPanel) + 1);
};

Spry.Widget.SlidingPanels.PanelAnimator = function(ele, curX, curY, dstX, dstY, opts)
{
	this.element = ele;

	this.curX = curX;
	this.curY = curY;
	this.dstX = dstX;
	this.dstY = dstY;
	this.fps = 60;
	this.duration = 500;
	this.transition = Spry.Widget.SlidingPanels.PanelAnimator.defaultTransition;
	this.startTime = 0;
	this.timerID = 0;
	this.finish = null;

	var self = this;
	this.intervalFunc = function() { self.step(); };
	
	Spry.Widget.SlidingPanels.setOptions(this, opts, true);

	this.interval = 1000/this.fps;
};

Spry.Widget.SlidingPanels.PanelAnimator.defaultTransition = function(time, begin, finish, duration) { time /= duration; return begin + ((2 - time) * time * finish); };

Spry.Widget.SlidingPanels.PanelAnimator.prototype.start = function()
{
	this.stop();
	this.startTime = (new Date()).getTime();
	this.timerID = setTimeout(this.intervalFunc, this.interval);
};

Spry.Widget.SlidingPanels.PanelAnimator.prototype.stop = function()
{
	if (this.timerID)
		clearTimeout(this.timerID);
	this.timerID = 0;
};

Spry.Widget.SlidingPanels.PanelAnimator.prototype.step = function()
{
	var elapsedTime = (new Date()).getTime() - this.startTime;
	var done = elapsedTime >= this.duration;
	var x, y;

	if (done)
	{
		x = this.curX = this.dstX;
		y = this.curY = this.dstY;
	}
	else
	{
		x = this.transition(elapsedTime, this.curX, this.dstX - this.curX, this.duration);
		y = this.transition(elapsedTime, this.curY, this.dstY - this.curY, this.duration);
	}

	this.element.style.left = x + "px";
	this.element.style.top = y + "px";

	if (!done)
		this.timerID = setTimeout(this.intervalFunc, this.interval);
	else if (this.finish)
		this.finish();
};
// SpryHTMLPanel.js - version 0.4 - 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.HTMLPanel = function(ele, opts)
{
	Spry.Widget.HTMLPanel.Notifier.call(this);

	this.element = Spry.Widget.HTMLPanel.$(ele);

	// evalScripts controls whether or not we execute any script that is within
	// an HTML fragment we load into the panel's container. The default value for
	// this comes from our global flag, but users can override this setting for
	// a specific HTMLPanel instance with an evalScripts constructor option.

	this.evalScripts = Spry.Widget.HTMLPanel.evalScripts;

	// These class names are used to identify content *inside* the panel's container
	// when the panel is first created. If the HTMLPanel finds any elements
	// with these class names, it will remove the elements from the document
	// and tuck away their content. The HTMLPanel will then inject this content
	// back into the its container at the appropriate time.
	//
	// This gives the designer an option for specifying content they want shown
	// when the HTMLPanel is loading content or has encountered an error.

	this.loadingContentClass = "HTMLPanelLoadingContent";
	this.errorContentClass = "HTMLPanelErrorContent";

	this.loadingStateContent = "";
	this.errorStateContent = "";

	// These class names are placed on the panel's container whenever the HTMLPanel
	// loads content, or has encountered an error. This is an alternative to specifying
	// content to use during loading and error states. Instead, the designer would simply
	// define CSS rules that use these class names to alter the appearance of the panel's
	// container.

	this.loadingStateClass = "HTMLPanelLoading";
	this.errorStateClass = "HTMLPanelError";

	// The current request that is pending completion.

	this.pendingRequest = null;

	Spry.Widget.HTMLPanel.setOptions(this, opts);

	// Find any content within the panel's container that is supposed to be
	// used for the loading and error states.

	var elements = this.element.getElementsByTagName("*");
	var numElements = elements.length;

	var errorEle = null;
	var loadingEle = null;

	var d = document.createElement("div");

	for (var i = 0; i < numElements && (!loadingEle || !errorEle); i++)
	{
		var e = elements[i];
		if (Spry.Widget.HTMLPanel.hasClassName(e, this.loadingContentClass))
			loadingEle = e;
		if (Spry.Widget.HTMLPanel.hasClassName(e, this.errorContentClass))
			errorEle = e;
	}

	if (loadingEle)
		this.loadingStateContent = Spry.Widget.HTMLPanel.removeAndExtractContent(loadingEle, this.loadingContentClass);
	if (errorEle)
		this.errorStateContent = Spry.Widget.HTMLPanel.removeAndExtractContent(errorEle, this.errorContentClass);
};

// Global switch that decides whether or not HTMLPanels execute
// script embedded within HTML fragments, after the fragment is inserted
// into the DOM. If false, no HTMLPanel will execute any script embedded
// within an HTML fragment.

Spry.Widget.HTMLPanel.evalScripts = false;

Spry.Widget.HTMLPanel.Notifier = function()
{
	this.observers = [];
	this.suppressNotifications = 0;
};

Spry.Widget.HTMLPanel.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.HTMLPanel.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.HTMLPanel.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.HTMLPanel.Notifier.prototype.enableNotifications = function()
{
	if (--this.suppressNotifications < 0)
	{
		this.suppressNotifications = 0;
		Spry.Debug.reportError("Unbalanced enableNotifications() call!\n");
	}
};

Spry.Widget.HTMLPanel.Notifier.prototype.disableNotifications = function()
{
	++this.suppressNotifications;
};

Spry.Widget.HTMLPanel.prototype = new Spry.Widget.HTMLPanel.Notifier();
Spry.Widget.HTMLPanel.prototype.constructor = Spry.Widget.HTMLPanel;

Spry.Widget.HTMLPanel.$ = function(ele)
{
	if (ele && typeof ele == "string")
		return document.getElementById(ele);
	return ele;
};

Spry.Widget.HTMLPanel.setOptions = function(dstObj, srcObj, ignoreUndefinedProps)
{
	if (srcObj)
	{
		for (var optionName in srcObj)
		{
			if (ignoreUndefinedProps && srcObj[optionName] == undefined)
				continue;
			dstObj[optionName] = srcObj[optionName];
		}
	}
};

Spry.Widget.HTMLPanel.addClassName = function(ele, className)
{
	ele = Spry.Widget.HTMLPanel.$(ele);
	if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1))
		return;
	ele.className += (ele.className ? " " : "") + className;
};

Spry.Widget.HTMLPanel.removeClassName = function(ele, className)
{
	ele = Spry.Widget.HTMLPanel.$(ele);
	if (Spry.Widget.HTMLPanel.hasClassName(ele, className))
		ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");
};

Spry.Widget.HTMLPanel.hasClassName = function(ele, className)
{
	ele = Spry.Widget.HTMLPanel.$(ele);
	if (!ele || !className || !ele.className || ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)
		return false;
	return true;
};

Spry.Widget.HTMLPanel.removeAndExtractContent = function(ele, className)
{
	var d = document.createElement("div");
	if (ele)
	{
		d.appendChild(ele);
		if (className)
			Spry.Widget.HTMLPanel.removeClassName(ele, className);
	}
	return d.innerHTML;
};

Spry.Widget.HTMLPanel.findNodeById = function(id, node)
{
	if (node && node.nodeType == 1 /* NODE.ELEMENT_NODE */)
	{
		if (node.id == id)
			return node;
		var child = node.firstChild;
		while (child)
		{
			var result = Spry.Widget.HTMLPanel.findNodeById(id, child);
			if (result)
				return result;
			child = child.nextSibling;
		}
	}
	return null;
};

Spry.Widget.HTMLPanel.disableSrcReferences = function (source)
{
	if (source)
		source = source.replace(/<(img|script|link|frame|iframe|input)([^>]+)>/gi, function(a,b,c) {
				// b=tag name, c=tag attributes
				return '<' + b + c.replace(/\b(src|href)\s*=/gi, function(a, b) {
					// b=attribute name
					return 'spry_'+ b + '=';
				}) + '>';
			});
	return source;
};

Spry.Widget.HTMLPanel.enableSrcReferences = function (source)
{
	source = source.replace(/<(img|script|link|frame|iframe|input)([^>]+)>/gi, function(a,b,c) {
			// b=tag name, c=tag attributes
			return '<' + b + c.replace(/\bspry_(src|href)\s*=/gi, function(a, b) {
				// b=attribute name
				return b + '=';
			}) + '>';
		});
	return source;
};

Spry.Widget.HTMLPanel.getFragByID = function(id, contentStr)
{
	var frag = Spry.Widget.HTMLPanel.disableSrcReferences(contentStr);
	var div = document.createElement("div");
	div.innerHTML = frag;

	frag = "";
	var node = Spry.Widget.HTMLPanel.findNodeById(id, div);
	if (node)
		frag = node.innerHTML;

	return Spry.Widget.HTMLPanel.enableSrcReferences(frag);
};

Spry.Widget.HTMLPanel.prototype.setContent = function(contentStr, id)
{
	var data = { content: contentStr, id: id };
	this.notifyObservers("onPreUpdate", data);

	// Observers are allowed to modify the data. Make sure
	// the fragment and id we use are from the data that was
	// past to our observers.

	contentStr = data.content;
	id = data.id;

	// If we have a valid id, extract the markup underneath
	// the element with that id from our html fragment.

	if (typeof id != "undefined")
		contentStr = Spry.Widget.HTMLPanel.getFragByID(id, contentStr);

	// Slam the html fragment into the DOM.

	Spry.Widget.HTMLPanel.setInnerHTML(this.element, contentStr, !this.evalScripts);

	this.removeStateClasses();

	this.notifyObservers("onPostUpdate", data);
};

Spry.Widget.HTMLPanel.prototype.loadContent = function(url, opts)
{
	if (!this.element)
		return;

	this.cancelLoad();

	if (!opts)
		opts = new Object;

	opts.url  = opts.url ? opts.url : url;
	opts.method = opts.method ? opts.method : "GET";
	opts.async  = opts.async ? opts.async : true;
	opts.id  = opts.id ? opts.id : undefined;

	var self = this;
	opts.errorCallback = function(req) { self.onLoadError(req); };

	this.notifyObservers("onPreLoad", opts);

	if (this.loadingStateContent)
		this.setContent(this.loadingStateContent);

	Spry.Widget.HTMLPanel.addClassName(this.element, this.loadingStateClass);
	this.pendingRequest = Spry.Widget.HTMLPanel.loadURL(opts.method, opts.url, opts.async, function(req){ self.onLoadSuccessful(req); }, opts);
};

Spry.Widget.HTMLPanel.prototype.cancelLoad = function()
{
	try
	{
		if (this.pendingRequest && this.pendingRequest.xhRequest)
		{
			var xhr = this.pendingRequest.xhRequest;
			if (xhr.abort)
				xhr.abort();
			xhr.onreadystatechange = null;
			this.notifyObservers("onLoadCancelled", this.pendingRequest);
		}
	}
	catch(e) {}
	this.pendingRequest = null;
};

Spry.Widget.HTMLPanel.prototype.removeStateClasses = function()
{
	Spry.Widget.HTMLPanel.removeClassName(this.element, this.loadingStateClass);
	Spry.Widget.HTMLPanel.removeClassName(this.element, this.errorStateClass);
};

Spry.Widget.HTMLPanel.prototype.onLoadSuccessful = function(req)
{
	this.notifyObservers("onPostLoad", req);
	this.setContent(req.xhRequest.responseText, req.id);
	this.pendingRequest = null;
};

Spry.Widget.HTMLPanel.prototype.onLoadError = function(req)
{
	this.notifyObservers("onLoadError", req);
	if (this.errorStateContent)
		this.setContent(this.errorStateContent);
	Spry.Widget.HTMLPanel.addClassName(this.element, this.errorStateClass);
	this.pendingRequest = null;
};

Spry.Widget.HTMLPanel.msProgIDs = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0"];

Spry.Widget.HTMLPanel.createXMLHttpRequest = function()
{
	var req = null;
	if (window.ActiveXObject)
	{
		while (!req && Spry.Widget.HTMLPanel.msProgIDs.length)
		{
			try { req = new ActiveXObject(Spry.Widget.HTMLPanel.msProgIDs[0]); } catch (e) { req = null; }
			if (!req)
				Spry.Widget.HTMLPanel.msProgIDs.splice(0, 1);
		}
	}
	if (!req && window.XMLHttpRequest) { try { req = new XMLHttpRequest(); } catch (e) { req = null; } }
	return req;
};

Spry.Widget.HTMLPanel.loadURL = function(method, url, async, callback, opts)
{
	var req = new Object;
	req.method = method;
	req.url = url;
	req.async = async;
	req.successCallback = callback;

	Spry.Widget.HTMLPanel.setOptions(req, opts);

	try
	{
		req.xhRequest = Spry.Widget.HTMLPanel.createXMLHttpRequest();
		if (!req.xhRequest)
			return null;

		if (req.async)
			req.xhRequest.onreadystatechange = function() { Spry.Widget.HTMLPanel.loadURL.callback(req); };

		req.xhRequest.open(method, req.url, req.async, req.username, req.password);

		if (req.headers)
		{
			for (var name in req.headers)
				req.xhRequest.setRequestHeader(name, req.headers[name]);
		}

		req.xhRequest.send(req.postData);

		if (!req.async)
			Spry.Widget.HTMLPanel.loadURL.callback(req);
	}
	catch(e) { if (req.errorCallback) req.errorCallback(req); req = null; }

	return req;
};

Spry.Widget.HTMLPanel.loadURL.callback = function(req)
{
	if (!req || req.xhRequest.readyState != 4)
		return;
	if (req.successCallback && (req.xhRequest.status == 200 || req.xhRequest.status == 0))
		req.successCallback(req);
	else if (req.errorCallback)
		req.errorCallback(req);
};

Spry.Widget.HTMLPanel.eval = function(str) { return eval(str); };

Spry.Widget.HTMLPanel.setInnerHTML = function(ele, str, preventScripts)
{
	if (!ele)
		return;
	if (!str) str = "";
	ele = Spry.Widget.HTMLPanel.$(ele);
	var scriptExpr = "<script[^>]*>(.|\s|\n|\r)*?</script>";
	ele.innerHTML = str.replace(new RegExp(scriptExpr, "img"), "");

	if (preventScripts)
		return;

	var matches = str.match(new RegExp(scriptExpr, "img"));
	if (matches)
	{
		var numMatches = matches.length;
		for (var i = 0; i < numMatches; i++)
		{
			var s = matches[i].replace(/<script[^>]*>[\s\r\n]*(<\!--)?|(-->)?[\s\r\n]*<\/script>/img, "");
			Spry.Widget.HTMLPanel.eval(s);
		}
	}
};

