/**
 * SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * **SWFObject is the SWF embed script formarly known as FlashObject. The name was changed for
 *   legal reasons.
 */
if(typeof deconcept == "undefined") var deconcept = new Object();
if(typeof deconcept.util == "undefined") deconcept.util = new Object();
if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
deconcept.SWFObject = function(swf, id, w, h, ver, c, useExpressInstall, quality, xiRedirectUrl, redirectUrl, detectKey){
	if (!document.createElement || !document.getElementById) { return; }
	this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
	this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
	this.params = new Object();
	this.variables = new Object();
	this.attributes = new Array();
	if(swf) { this.setAttribute('swf', swf); }
	if(id) { this.setAttribute('id', id); }
	if(w) { this.setAttribute('width', w); }
	if(h) { this.setAttribute('height', h); }
	if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
	this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute('version'), useExpressInstall);
	if(c) { this.addParam('bgcolor', c); }
	var q = quality ? quality : 'high';
	this.addParam('quality', q);
	this.setAttribute('useExpressInstall', useExpressInstall);
	this.setAttribute('doExpressInstall', false);
	var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
	this.setAttribute('xiRedirectUrl', xir);
	this.setAttribute('redirectUrl', '');
	if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
}
deconcept.SWFObject.prototype = {
	setAttribute: function(name, value){
		this.attributes[name] = value;
	},
	getAttribute: function(name){
		return this.attributes[name];
	},
	addParam: function(name, value){
		this.params[name] = value;
	},
	getParams: function(){
		return this.params;
	},
	addVariable: function(name, value){
		this.variables[name] = value;
	},
	getVariable: function(name){
		return this.variables[name];
	},
	getVariables: function(){
		return this.variables;
	},
	getVariablePairs: function(){
		var variablePairs = new Array();
		var key;
		var variables = this.getVariables();
		for(key in variables){
			variablePairs.push(key +"="+ variables[key]);
		}
		return variablePairs;
	},
	getSWFHTML: function() {
		var swfNode = "";
		if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
			if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "PlugIn");
			swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'"';
			swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
			var params = this.getParams();
			 for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
			var pairs = this.getVariablePairs().join("&");
			 if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
			swfNode += '/>';
		} else { // PC IE
			if (this.getAttribute("doExpressInstall")) this.addVariable("MMplayerType", "ActiveX");
			swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'">';
			swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
			var params = this.getParams();
			for(var key in params) {
			 swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
			}
			var pairs = this.getVariablePairs().join("&");
			if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
			swfNode += "</object>";
		}
		return swfNode;
	},
	write: function(elementId){
		if(this.getAttribute('useExpressInstall')) {
			// check to see if we need to do an express install
			var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
			if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
				this.setAttribute('doExpressInstall', true);
				this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
				document.title = document.title.slice(0, 47) + " - Flash Player Installation";
				this.addVariable("MMdoctitle", document.title);
			}
		}
		if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
			var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
			n.innerHTML = this.getSWFHTML();
			return true;
		}else{
			if(this.getAttribute('redirectUrl') != "") {
				document.location.replace(this.getAttribute('redirectUrl'));
			}
		}
		return false;
	}
}

/* ---- detection functions ---- */
deconcept.SWFObjectUtil.getPlayerVersion = function(reqVer, xiInstall){
	var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
	if(navigator.plugins && navigator.mimeTypes.length){
		var x = navigator.plugins["Shockwave Flash"];
		if(x && x.description) {
			PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
		}
	}else{
		try{
			var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
			for (var i=3; axo!=null; i++) {
				axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
				PlayerVersion = new deconcept.PlayerVersion([i,0,0]);
			}
		}catch(e){}
		if (reqVer && PlayerVersion.major > reqVer.major) return PlayerVersion; // version is ok, skip minor detection
		// this only does the minor rev lookup if the user's major version 
		// is not 6 or we are checking for a specific minor or revision number
		// see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
		if (!reqVer || ((reqVer.minor != 0 || reqVer.rev != 0) && PlayerVersion.major == reqVer.major) || PlayerVersion.major != 6 || xiInstall) {
			try{
				PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
			}catch(e){}
		}
	}
	return PlayerVersion;
}
deconcept.PlayerVersion = function(arrVersion){
	this.major = parseInt(arrVersion[0]) != null ? parseInt(arrVersion[0]) : 0;
	this.minor = parseInt(arrVersion[1]) || 0;
	this.rev = parseInt(arrVersion[2]) || 0;
}
deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
	if(this.major < fv.major) return false;
	if(this.major > fv.major) return true;
	if(this.minor < fv.minor) return false;
	if(this.minor > fv.minor) return true;
	if(this.rev < fv.rev) return false;
	return true;
}
/* ---- get value of query string param ---- */
deconcept.util = {
	getRequestParameter: function(param){
		var q = document.location.search || document.location.hash;
		if(q){
			var startIndex = q.indexOf(param +"=");
			var endIndex = (q.indexOf("&", startIndex) > -1) ? q.indexOf("&", startIndex) : q.length;
			if (q.length > 1 && startIndex > -1) {
				return q.substring(q.indexOf("=", startIndex)+1, endIndex);
			}
		}
		return "";
	}
}

/* add Array.push if needed (ie5) */
if (Array.prototype.push == null) { Array.prototype.push = function(item) { this[this.length] = item; return this.length; }}

/* add some aliases for ease of use/backwards compatibility */
var getQueryParamValue = deconcept.util.getRequestParameter;
var FlashObject = deconcept.SWFObject; // for legacy support
var SWFObject = deconcept.SWFObject;
/*
	Lightbox JS: Fullsize Image Overlays 
	by Lokesh Dhakar - http://www.huddletogether.com

	For more information on this script, visit:
	http://huddletogether.com/projects/lightbox/

	Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
	(basically, do anything you want, just leave my name and link)
	
	Table of Contents
	-----------------
	Configuration
	
	Functions
	- getPageScroll()
	- getPageSize()
	- pause()
	- getKey()
	- listenKey()
	- showLightbox()
	- hideLightbox()
	- initLightbox()
	- addLoadEvent()
	
	Function Calls
	- addLoadEvent(initLightbox)

*/



//
// Configuration
//

// If you would like to use a custom loading image or close button reference them in the next two lines.
var loadingImage = 'js/loading.gif';		
var closeButton = 'js/close.gif';		





//
// getPageScroll()
// Returns array with x,y page scroll values.
// Core code from - quirksmode.org
//
function getPageScroll(){

	var yScroll;

	if (self.pageYOffset) {
		yScroll = self.pageYOffset;
	} else if (document.documentElement && document.documentElement.scrollTop){	 // Explorer 6 Strict
		yScroll = document.documentElement.scrollTop;
	} else if (document.body) {// all other Explorers
		yScroll = document.body.scrollTop;
	}

	arrayPageScroll = new Array('',yScroll) 
	return arrayPageScroll;
}



//
// getPageSize()
// Returns array with page width, height and window width, height
// Core code from - quirksmode.org
// Edit for Firefox by pHaez
//
function getPageSize(){
	
	var xScroll, yScroll;
	
	if (window.innerHeight && window.scrollMaxY) {	
		xScroll = document.body.scrollWidth;
		yScroll = window.innerHeight + window.scrollMaxY;
	} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}
	
	var windowWidth, windowHeight;
	if (self.innerHeight) {	// all except Explorer
		windowWidth = self.innerWidth;
		windowHeight = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	} else if (document.body) { // other Explorers
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}	
	
	// for small pages with total height less then height of the viewport
	if(yScroll < windowHeight){
		pageHeight = windowHeight;
	} else { 
		pageHeight = yScroll;
	}

	// for small pages with total width less then width of the viewport
	if(xScroll < windowWidth){	
		pageWidth = windowWidth;
	} else {
		pageWidth = xScroll;
	}


	arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight) 
	return arrayPageSize;
}


//
// pause(numberMillis)
// Pauses code execution for specified time. Uses busy code, not good.
// Code from http://www.faqts.com/knowledge_base/view.phtml/aid/1602
//
function pause(numberMillis) {
	var now = new Date();
	var exitTime = now.getTime() + numberMillis;
	while (true) {
		now = new Date();
		if (now.getTime() > exitTime)
			return;
	}
}

//
// getKey(key)
// Gets keycode. If 'x' is pressed then it hides the lightbox.
//

function getKey(e){
	if (e == null) { // ie
		keycode = event.keyCode;
	} else { // mozilla
		keycode = e.which;
	}
	key = String.fromCharCode(keycode).toLowerCase();
	
	if(key == 'x'){ hideLightbox(); }
}


//
// listenKey()
//
function listenKey () {	document.onkeypress = getKey; }
	

//
// showLightbox()
// Preloads images. Pleaces new image in lightbox then centers and displays.
//
function showLightbox(objLink)
{
	
	// prep objects
	var objOverlay = document.getElementById('overlay');
	var objLightbox = document.getElementById('lightbox');
	var objCaption = document.getElementById('lightboxCaption');
	var objImage = document.getElementById('lightboxImage');
	var objLoadingImage = document.getElementById('loadingImage');
	var objLightboxDetails = document.getElementById('lightboxDetails');

	
	var arrayPageSize = getPageSize();
	var arrayPageScroll = getPageScroll();

	// center loadingImage if it exists
	if (objLoadingImage) {
		objLoadingImage.style.top = (arrayPageScroll[1] + ((arrayPageSize[3] - 35 - objLoadingImage.height) / 2) + 'px');
		objLoadingImage.style.left = (((arrayPageSize[0] - 20 - objLoadingImage.width) / 2) + 'px');
		objLoadingImage.style.display = 'block';
	}

	// set height of Overlay to take up whole page and show
	objOverlay.style.height = (arrayPageSize[1] + 'px');
	objOverlay.style.display = 'block';

	// preload image
	imgPreload = new Image();

	imgPreload.onload=function(){
		objImage.src = objLink.href;

		// center lightbox and make sure that the top and left values are not negative
		// and the image placed outside the viewport
		var lightboxTop = arrayPageScroll[1] + ((arrayPageSize[3] - 35 - imgPreload.height) / 2);
		var lightboxLeft = ((arrayPageSize[0] - 20 - imgPreload.width) / 2);
		
		objLightbox.style.top = (lightboxTop < 0) ? "0px" : lightboxTop + "px";
		objLightbox.style.left = (lightboxLeft < 0) ? "0px" : lightboxLeft + "px";


		objLightboxDetails.style.width = imgPreload.width + 'px';
		
		if(objLink.getAttribute('title')){
			objCaption.style.display = 'block';
			//objCaption.style.width = imgPreload.width + 'px';
			objCaption.innerHTML = objLink.getAttribute('title');
		} else {
			objCaption.style.display = 'none';
		}
		
		// A small pause between the image loading and displaying is required with IE,
		// this prevents the previous image displaying for a short burst causing flicker.
		if (navigator.appVersion.indexOf("MSIE")!=-1){
			pause(250);
		} 

		if (objLoadingImage) {	objLoadingImage.style.display = 'none'; }

		// Hide select boxes as they will 'peek' through the image in IE
		selects = document.getElementsByTagName("select");
        for (i = 0; i != selects.length; i++) {
                selects[i].style.visibility = "hidden";
        }

	
		objLightbox.style.display = 'block';

		// After image is loaded, update the overlay height as the new image might have
		// increased the overall page height.
		arrayPageSize = getPageSize();
		objOverlay.style.height = (arrayPageSize[1] + 'px');
		
		// Check for 'x' keypress
		listenKey();

		return false;
	}

	imgPreload.src = objLink.href;
	
}




//
// flashLightbox()
// Preloads images. Pleaces new image in lightbox then centers and displays.
//
function flashLightbox(imgURL,flashTitle)
{
	
	
	// prep objects
	var objOverlay = document.getElementById('overlay');
	var objLightbox = document.getElementById('lightbox');
	var objCaption = document.getElementById('lightboxCaption');
	var objImage = document.getElementById('lightboxImage');
	var objLoadingImage = document.getElementById('loadingImage');
	var objLightboxDetails = document.getElementById('lightboxDetails');

	
	var arrayPageSize = getPageSize();
	var arrayPageScroll = getPageScroll();

	// center loadingImage if it exists
	if (objLoadingImage) {
		objLoadingImage.style.top = (arrayPageScroll[1] + ((arrayPageSize[3] - 35 - objLoadingImage.height) / 2) + 'px');
		objLoadingImage.style.left = (((arrayPageSize[0] - 20 - objLoadingImage.width) / 2) + 'px');
		objLoadingImage.style.display = 'block';
	}

	// set height of Overlay to take up whole page and show
	objOverlay.style.height = (arrayPageSize[1] + 'px');
	objOverlay.style.display = 'block';

	// preload image
	imgPreload = new Image();

	imgPreload.onload=function(){
		objImage.src = imgURL;

		// center lightbox and make sure that the top and left values are not negative
		// and the image placed outside the viewport
		var lightboxTop = arrayPageScroll[1] + ((arrayPageSize[3] - 35 - imgPreload.height) / 2);
		var lightboxLeft = ((arrayPageSize[0] - 20 - imgPreload.width) / 2);
		
		objLightbox.style.top = (lightboxTop < 0) ? "0px" : lightboxTop + "px";
		objLightbox.style.left = (lightboxLeft < 0) ? "0px" : lightboxLeft + "px";


		objLightboxDetails.style.width = imgPreload.width + 'px';
		
		if(flashTitle!=undefined){
			objCaption.style.display = 'block';
			//objCaption.style.width = imgPreload.width + 'px';
			objCaption.innerHTML = flashTitle;
		} else {
			objCaption.style.display = 'none';
		}
		
		// A small pause between the image loading and displaying is required with IE,
		// this prevents the previous image displaying for a short burst causing flicker.
		if (navigator.appVersion.indexOf("MSIE")!=-1){
			pause(250);
		} 

		if (objLoadingImage) {	objLoadingImage.style.display = 'none'; }

		// Hide select boxes as they will 'peek' through the image in IE
		selects = document.getElementsByTagName("select");
        for (i = 0; i != selects.length; i++) {
                selects[i].style.visibility = "hidden";
        }

	
		objLightbox.style.display = 'block';

		// After image is loaded, update the overlay height as the new image might have
		// increased the overall page height.
		arrayPageSize = getPageSize();
		objOverlay.style.height = (arrayPageSize[1] + 'px');
		
		// Check for 'x' keypress
		listenKey();

		return false;
	}

	imgPreload.src = imgURL;
	
}





//
// hideLightbox()
//
function hideLightbox()
{
	// get objects
	objOverlay = document.getElementById('overlay');
	objLightbox = document.getElementById('lightbox');

	// hide lightbox and overlay
	objOverlay.style.display = 'none';
	objLightbox.style.display = 'none';

	// make select boxes visible
	selects = document.getElementsByTagName("select");
    for (i = 0; i != selects.length; i++) {
		selects[i].style.visibility = "visible";
	}

	// disable keypress listener
	document.onkeypress = '';
}




//
// initLightbox()
// Function runs on window load, going through link tags looking for rel="lightbox".
// These links receive onclick events that enable the lightbox display for their targets.
// The function also inserts html markup at the top of the page which will be used as a
// container for the overlay pattern and the inline image.
//
function initLightbox()
{
	
	if (!document.getElementsByTagName){ return; }
	var anchors = document.getElementsByTagName("a");

	// loop through all anchor tags
	for (var i=0; i<anchors.length; i++){
		var anchor = anchors[i];

		if (anchor.getAttribute("href") && (anchor.getAttribute("rel") == "lightbox")){
			anchor.onclick = function () {showLightbox(this); return false;}
		}
	}

	// the rest of this code inserts html at the top of the page that looks like this:
	//
	// <div id="overlay">
	//		<a href="#" onclick="hideLightbox(); return false;"><img id="loadingImage" /></a>
	//	</div>
	// <div id="lightbox">
	//		<a href="#" onclick="hideLightbox(); return false;" title="Click anywhere to close image">
	//			<img id="closeButton" />		
	//			<img id="lightboxImage" />
	//		</a>
	//		<div id="lightboxDetails">
	//			<div id="lightboxCaption"></div>
	//			<div id="keyboardMsg"></div>
	//		</div>
	// </div>
	
	var objBody = document.getElementsByTagName("body").item(0);
	
	// create overlay div and hardcode some functional styles (aesthetic styles are in CSS file)
	var objOverlay = document.createElement("div");
	objOverlay.setAttribute('id','overlay');
	objOverlay.onclick = function () {hideLightbox(); return false;}
	objOverlay.style.display = 'none';
	objOverlay.style.position = 'absolute';
	objOverlay.style.top = '0';
	objOverlay.style.left = '0';
	objOverlay.style.zIndex = '90';
 	objOverlay.style.width = '100%';
	objBody.insertBefore(objOverlay, objBody.firstChild);
	
	var arrayPageSize = getPageSize();
	var arrayPageScroll = getPageScroll();

	// preload and create loader image
	var imgPreloader = new Image();
	
	// if loader image found, create link to hide lightbox and create loadingimage
	imgPreloader.onload=function(){

		var objLoadingImageLink = document.createElement("a");
		objLoadingImageLink.setAttribute('href','#');
		objLoadingImageLink.onclick = function () {hideLightbox(); return false;}
		objOverlay.appendChild(objLoadingImageLink);
		
		var objLoadingImage = document.createElement("img");
		objLoadingImage.src = loadingImage;
		objLoadingImage.setAttribute('id','loadingImage');
		objLoadingImage.style.position = 'absolute';
		objLoadingImage.style.zIndex = '150';
		objLoadingImageLink.appendChild(objLoadingImage);

		imgPreloader.onload=function(){};	//	clear onLoad, as IE will flip out w/animated gifs

		return false;
	}

	imgPreloader.src = loadingImage;

	// create lightbox div, same note about styles as above
	var objLightbox = document.createElement("div");
	objLightbox.setAttribute('id','lightbox');
	objLightbox.style.display = 'none';
	objLightbox.style.position = 'absolute';
	objLightbox.style.zIndex = '100';	
	objBody.insertBefore(objLightbox, objOverlay.nextSibling);
	
	// create link
	var objLink = document.createElement("a");
	objLink.setAttribute('href','#');
	objLink.setAttribute('title','Click to close');
	objLink.onclick = function () {hideLightbox(); return false;}
	objLightbox.appendChild(objLink);

	// preload and create close button image
	var imgPreloadCloseButton = new Image();

	// if close button image found, 
	imgPreloadCloseButton.onload=function(){

		var objCloseButton = document.createElement("img");
		objCloseButton.src = closeButton;
		objCloseButton.setAttribute('id','closeButton');
		objCloseButton.style.position = 'absolute';
		objCloseButton.style.zIndex = '200';
		objLink.appendChild(objCloseButton);

		return false;
	}

	imgPreloadCloseButton.src = closeButton;

	// create image
	var objImage = document.createElement("img");
	objImage.setAttribute('id','lightboxImage');
	objLink.appendChild(objImage);
	
	// create details div, a container for the caption and keyboard message
	var objLightboxDetails = document.createElement("div");
	objLightboxDetails.setAttribute('id','lightboxDetails');
	objLightbox.appendChild(objLightboxDetails);

	// create caption
	var objCaption = document.createElement("div");
	objCaption.setAttribute('id','lightboxCaption');
	objCaption.style.display = 'none';
	objLightboxDetails.appendChild(objCaption);

	// create keyboard message
	var objKeyboardMsg = document.createElement("div");
	objKeyboardMsg.setAttribute('id','keyboardMsg');
	objKeyboardMsg.innerHTML = 'press <kbd>x</kbd> to close';
	objLightboxDetails.appendChild(objKeyboardMsg);


}




//
// addLoadEvent()
// Adds event to window.onload without overwriting currently assigned onload functions.
// Function found at Simon Willison's weblog - http://simon.incutio.com/
//
function addLoadEvent(func)
{	
	var oldonload = window.onload;
	if (typeof window.onload != 'function'){
    	window.onload = func;
	} else {
		window.onload = function(){
		oldonload();
		func();
		}
	}

}



addLoadEvent(initLightbox);	// run initLightbox onLoadvar gotIE = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;
var gotNS = (navigator.appName == 'Netscape') ? true : false;
var ns=document.layers;
var ie=document.all;
var ns6=document.getElementById&&!document.all;
var flag=0;



function popWin( url, name, width, height, scroller ) {

	if (gotIE) {
	var left = (screen.Width/2) - width/2;
	var top = (screen.Height/2) - height/2;
	} else if (gotNS) {
	var left = (screen.availWidth/2) - width/2;
	var top = (screen.availHeight/2) - height/2;
	} else {
	var left = (screen.Width/2) - width/2;
	var top = (screen.Height/2) - height/2;
	}

var outStr = 'left='+left+',top='+top+',height=' + height + ',width=' + width;

	if (scroller == true) {
		 outStr = outStr + ',menubar=no,toolbar=no,location=no,directories=no,status=yes,scrollbars=1,resizable=no';
	 } else {
		 outStr = outStr + ',menubar=no,toolbar=no,location=no,directories=no,status=yes,scrollbars=no,resizable=no';
	 }

window.open(url, name, outStr);

}

function checklogin(form)
{
    if (flag == 1)
       return false;

if (! form.email.value){
alert("Please Enter Your Email Address");
form.email.focus();
form.email.select();
return false;
}

if (! (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(form.email.value))){
alert("Invalid E-mail Address")
form.email.focus();
form.email.select();
return false;
}

if (! form.pass.value){
alert("Please Enter Your Password");
form.pass.focus();
form.pass.select();
return false;
}

flag = 1;
return true;
}


function search(form)
{
    if (flag == 1)
       return false;

if (! form.skeyword.value){
alert("Please Enter A Search Term");
form.skeyword.focus();
form.skeyword.select();
return false;
}

flag = 1;
return true;
}




function signup(form)
{
    if (flag == 1)
       return false;

if (! form.fname.value){
alert("Please Enter Your First Name");
form.fname.focus();
form.fname.select();
return false;
}

if (! form.lname.value){
alert("Please Enter Your Last Name");
form.lname.focus();
form.lname.select();
return false;
}

if (! form.email.value){
alert("Please Enter Your Email Address");
form.email.focus();
form.email.select();
return false;
}

if (! (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(form.email.value))){
alert("Invalid E-mail Address")
form.email.focus();
form.email.select();
return false;
}

if (! form.pass.value){
alert("Please Enter A Password");
form.pass.focus();
form.pass.select();
return false;
}


 str = form.pass.value
 var validChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-';
 if ((str.length < 3)) {
 alert("Your password must be at least 3 characters.")
 form.pass.focus();
 form.pass.select();
 return false;
 }
 for (var j = 0; j < str.length; j++){
   if(validChars.indexOf(str.charAt(j)) == -1) {
 alert("Your password can only contain letters and numbers.")
 form.pass.focus();
 form.pass.select();
 return false;
 }
 }
	Ctrl = form.pass2;
	if (Ctrl.value =="") {
		validatePromt(Ctrl,"Please Confirm Your Password");
		return false;
	}
	if (form.pass.value != form.pass2.value) {
		validatePromt(Ctrl,"Your passwords do not match");
 		form.pass2.focus();
 		form.pass2.select();
		return false;
	}


flag = 1;
return true;
}



function enewsletter(form)
{
    if (flag == 1)
       return false;

if (form.ea.value == ''){
alert("Please Enter Your Email Address");
form.email_addr.focus();
form.email_addr.select();
return false;
}

if (! (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(form.ea.value))){
alert("Invalid E-mail Address")
form.ea.focus();
form.ea.select();
return false;
}

flag = 1;
return true;


}


function showStatus(sMsg) {
    window.status = sMsg ;
    return true ;
}


function add_email() {

//var fobj = new Array("fname", "lname");
//var cmdoutput = "";
  /*
   for(var i = 0;i < fobj.length;i++)
   {

	cmdoutput += fobj[i] + "=" + escape(eval("document.enewsletter."+fobj[i]+".value")) + "&";
   }
	*/
	var email = document.enewsletter.ea.value;
    	var strURL = "/inc_js/add_email.php";
        var querystring = "email="+email;
	var xmlHttpReq = false;

    if (enewsletter(document.enewsletter)){

    // Mozilla/Safari
    if (window.XMLHttpRequest) {
        xmlHttpReq = new XMLHttpRequest();
            if (xmlHttpReq.overrideMimeType) {
                xmlHttpReq.overrideMimeType('text/xml');
	    }
    }
    // IE
    else if (window.ActiveXObject) {
        xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlHttpReq.open('POST', strURL, true);
    xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xmlHttpReq.onreadystatechange = function() {
        if (xmlHttpReq.readyState == 4) {
            updatenewsletter(xmlHttpReq.responseText);
        }
    }

    xmlHttpReq.send(querystring);


   }
}


function updatenewsletter(str){

	var strarray = str;

    document.getElementById("newslettersignup").innerHTML = strarray;


}

function showlightbox(imagen, imageset){
var imagesub = 'photo_gallery';

	if (imagen == imagesub+'/01.jpg'){
		var previousimage = '';
		var previousimagetext = "";
		var nextimage = imagesub+'/02.jpg';
		var nextimagetext = "Copy 1";
	} else if (imagen == imagesub+'/02.jpg'){
		var previousimage = imagesub+'/01.jpg';
		var previousimagetext = "Copy 1";
		var nextimage = imagesub+'/03.jpg';
		var nextimagetext = 'Copy 2';
	} else if (imagen == imagesub+'/03.jpg'){
		var previousimage = imagesub+'/02.jpg';
		var previousimagetext = "Copy 2";
		var nextimage = imagesub+'/04.jpg';
		var nextimagetext = 'Copy 3';
	} else if (imagen == imagesub+'/04.jpg'){
		var previousimage = imagesub+'/03.jpg';
		var previousimagetext = "Copy 3";
		var nextimage = imagesub+'/05.jpg';
		var nextimagetext = 'Copy 4';
	} else if (imagen == imagesub+'/05.jpg'){
		var previousimage = imagesub+'/04.jpg';
		var previousimagetext = "Copy 4";
		var nextimage = imagesub+'/06.jpg';
		var nextimagetext = 'Copy 5';
	} else if (imagen == imagesub+'/06.jpg'){
		var previousimage = imagesub+'/05.jpg';
		var previousimagetext = "Copy 5";
		var nextimage = imagesub+'/07.jpg';
		var nextimagetext = 'Copy 6';
	} else if (imagen == imagesub+'/07.jpg'){
		var previousimage = imagesub+'/06.jpg';
		var previousimagetext = "Copy 6";
		var nextimage = imagesub+'/08.jpg';
		var nextimagetext = 'Copy 7';
	} else if (imagen == imagesub+'/08.jpg'){
		var previousimage = imagesub+'/07.jpg';
		var previousimagetext = "Copy 7";
		var nextimage = imagesub+'/09.jpg';
		var nextimagetext = 'Copy 8';
	} else if (imagen == imagesub+'/09.jpg'){
		var previousimage = imagesub+'/08.jpg';
		var previousimagetext = "Copy 8";
		var nextimage = imagesub+'/10.jpg';
		var nextimagetext = 'Copy 9';
	} else if (imagen == imagesub+'/10.jpg'){
		var previousimage = imagesub+'/09.jpg';
		var previousimagetext = "Copy 9";
		var nextimage = imagesub+'/11.jpg';
		var nextimagetext = 'Copy 10';
	} else if (imagen == imagesub+'/11.jpg'){
		var previousimage = imagesub+'/10.jpg';
		var previousimagetext = "Copy 10";
		var nextimage = imagesub+'/12.jpg';
		var nextimagetext = 'Copy 11';
	} else if (imagen == imagesub+'/12.jpg'){
		var previousimage = imagesub+'/11.jpg';
		var previousimagetext = "Copy 11";
		var nextimage = imagesub+'/13.jpg';
		var nextimagetext = 'Copy 12';
	} else if (imagen == imagesub+'/13.jpg'){
		var previousimage = imagesub+'/12.jpg';
		var previousimagetext = "Copy 12";
		var nextimage = imagesub+'/14.jpg';
		var nextimagetext = 'Copy 13';
	} else if (imagen == imagesub+'/14.jpg'){
		var previousimage = imagesub+'/13.jpg';
		var previousimagetext = "Copy 13";
		var nextimage = imagesub+'/15.jpg';
		var nextimagetext = 'Copy 14';
	} else if (imagen == imagesub+'/15.jpg'){
		var previousimage = imagesub+'/14.jpg';
		var previousimagetext = "Copy 14";
		var nextimage = imagesub+'/16.jpg';
		var nextimagetext = 'Copy 15';
	} else if (imagen == imagesub+'/16.jpg'){
		var previousimage = imagesub+'/15.jpg';
		var previousimagetext = "Copy 15";
		var nextimage = imagesub+'/17.jpg';
		var nextimagetext = 'Copy 16';
	} else if (imagen == imagesub+'/17.jpg'){
		var previousimage = imagesub+'/16.jpg';
		var previousimagetext = "Copy 16";
		var nextimage = imagesub+'/18.jpg';
		var nextimagetext = 'Copy 17';
	} else if (imagen == imagesub+'/18.jpg'){
		var previousimage = imagesub+'/17.jpg';
		var previousimagetext = "Copy 17";
		var nextimage = imagesub+'/19.jpg';
		var nextimagetext = 'Copy 18';
	} else if (imagen == imagesub+'/19.jpg'){
		var previousimage = imagesub+'/18.jpg';
		var previousimagetext = "Copy 18";
		var nextimage = imagesub+'/20.jpg';
		var nextimagetext = 'Copy 19';
	} else if (imagen == imagesub+'/20.jpg'){
		var previousimage = imagesub+'/19.jpg';
		var previousimagetext = "Copy 19";
		var nextimage = '';
		var nextimagetext = '';

	}

	//myLightbox.startNoHref(0, new Array(imagen));

	var caption = '';

		if (previousimage!='')
			caption = caption+"<a href=\"javascript:showlightbox('"+previousimage+"', '"+previousimagetext+"', 1);\"><img src=\"js/previous_btn.gif\" border=0 hspace=5 vspace=5></a>";

		if (nextimage!='')
			caption = caption+"<a href=\"javascript:showlightbox('"+nextimage+"', '"+nextimagetext+"', 1);\"><img src=\"js/next_btn.gif\" border=0 hspace=10 vspace=5></a>";

	flashLightbox(imagen, caption);

}


function send_friend(pid){

var okcode = 1;

if (document.formshare.yname.value == ''){
alert("Please Enter Your Name");
document.formshare.yname.focus();
document.formshare.yname.select();
okcode=2;
}
if (okcode==1){
if (document.formshare.yemail.value == ''){
alert("Please Enter Your Email Address");
document.formshare.yemail.focus();
document.formshare.yemail.select();
okcode=2;
}}
if (okcode==1){
if (! (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(document.formshare.yemail.value))){
alert("Invalid E-mail Address")
document.formshare.yemail.focus();
document.formshare.yemail.select();
okcode=2;
}}
if (okcode==1){
if (document.formshare.yphone.value == ''){
alert("Please Enter Your Phone");
document.formshare.yphone.focus();
document.formshare.yphone.select();
okcode=2;
}}
	if (okcode==1){
    	var strURL = "/inc_js/send_request.php";
        var querystring = 'id='+pid+'&yemail='+escape(eval("document.formshare.yemail.value"))+'&yname='+escape(eval("document.formshare.yname.value"))+'&yphone='+escape(eval("document.formshare.yphone.value"));
	var xmlHttpReq = false;


    // Mozilla/Safari
    if (window.XMLHttpRequest) {
        xmlHttpReq = new XMLHttpRequest();
            if (xmlHttpReq.overrideMimeType) {
                xmlHttpReq.overrideMimeType('text/xml');
	    }
    }
    // IE
    else if (window.ActiveXObject) {
        xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlHttpReq.open('POST', strURL, true);
    xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xmlHttpReq.onreadystatechange = function() {
        if (xmlHttpReq.readyState == 4) {
 			//alert(xmlHttpReq.responseText);
			//tellfriendsignup
 			document.getElementById('request_form').innerHTML=" <table width='205' height='117' border='0' cellspacing='0' cellpadding='0' style='background:#DED8C0;padding:5px;margin-bottom:20px;'><tr><td align='center'><br/><br/><br/><br/><img src='images/trips/thankyou.gif' alt='thank you'/><br/><br/><br/><br/><br/></td></tr></table>";
			//alert("Email has been sent.");
			//eval("document.formshare.yemail.value = ''");
			//eval("document.formshare.yname.value = ''");
			//eval("document.formshare.yphone.value = ''");
			//document.getElementById('request_form').innerHHTML = "TEST";
		}
        }

    xmlHttpReq.send(querystring);

	}


}




function clearText(thefield){
	if (thefield.defaultValue==thefield.value)
		thefield.value = ""
}/******************************************************************************
Name:    Highslide JS
Version: 3.3.6 (January 6 2008)
Config:  default +inline +ajax +iframe +flash +packed
Author:  Torstein Hønsi
Support: http://vikjavev.no/highslide/forum

Licence:
Highslide JS is licensed under a Creative Commons Attribution-NonCommercial 2.5
License (http://creativecommons.org/licenses/by-nc/2.5/).

You are free:
	* to copy, distribute, display, and perform the work
	* to make derivative works

Under the following conditions:
	* Attribution. You must attribute the work in the manner  specified by  the
	  author or licensor.
	* Noncommercial. You may not use this work for commercial purposes.

* For  any  reuse  or  distribution, you  must make clear to others the license
  terms of this work.
* Any  of  these  conditions  can  be  waived  if  you  get permission from the 
  copyright holder.

Your fair use and other rights are in no way affected by the above.
******************************************************************************/
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('m f={4J:\'O/8E/\',6o:\'8x.7d\',7D:10,5Z:6Y,7i:10,6T:6Y,3X:15,5Q:15,3I:15,2Q:15,4j:8K,6f:\'56 V 1C 2f, 9f 6B 8T V 2T. 8W 90 8X Z 1D 6B 4W.\',7r:\'8S...\',7e:\'56 V 9c\',7p:0.75,8o:\'56 V 9a V 97\',62:M,5E:5,6d:1,5l:1i,2t:2,6b:3,6Z:\'8v V 8w 3e\',7v:\'7b 79\',7u:1,81:M,6z:\'8J 2R <i>8f 8s</i>\',7Y:\'8I://8H.8F/O/\',80:\'9e V 9d 8f 8s 96\',71:M,6J:\'91\',6I:\'8D\',6G:\'8C\',6R:\'8A\',6L:\'56 V 1C\',6H:\'8N\',4D:1i,5O:M,45:M,2k:\'3p\',5y:M,3F:K,46:30,3d:K,2h:87,2C:87,4C:M,1p:\'8O-9b\',4I:\'O-J\',4f:[],5I:M,L:[],5T:[\'4C\',\'1p\',\'2t\',\'46\',\'3F\',\'4o\',\'6m\',\'5X\',\'4D\',\'5O\',\'45\',\'2r\',\'5y\',\'36\',\'4g\',\'2k\',\'24\',\'4I\',\'2h\',\'2C\',\'3d\'],1K:[],4R:[],43:{},2Z:[],5e:[],3H:[],4u:{},5F:{},1g:(Y.93&&!1A.4h),3G:/92/.1z(3r.7N),3Z:/8U.+8R:1\\.[0-8].+8Q/.1z(3r.7N),$:q(1f){F Y.5H(1f)},3n:q(2U,7M){2U[2U.1e]=7M},W:q(4G,2W,3j,3V,7J){m r=Y.W(4G);k(2W)f.7L(r,2W);k(7J)f.19(r,{6N:0,8t:\'2c\',7C:0});k(3j)f.19(r,3j);k(3V)3V.1E(r);F r},7L:q(r,2W){Z(m x 5q 2W)r[x]=2W[x]},19:q(r,3j){Z(m x 5q 3j){Q{k(f.1g&&x==\'1w\')r.u.7k=\'8Y(1w=\'+(3j[x]*2E)+\')\';R r.u[x]=3j[x]}P(e){}}},2Y:q(){2U=3r.7H.7U("8V");F 7s(2U[1])},5J:q(){m 4p=Y.6a&&Y.6a!="7O"?Y.5L:Y.1b;m I=f.1g?4p.8c:(Y.5L.8c||8i.9g),E=f.1g?4p.8L:8i.8G;F{I:I,E:E,4H:f.1g?4p.4H:8B,4E:f.1g?4p.4E:8P}},1d:q(r){m p={x:r.7y,y:r.5N};49(r.6A){r=r.6A;p.x+=r.7y;p.y+=r.5N;k(r!=Y.1b&&r!=Y.5L){p.x-=r.4H;p.y-=r.4E}}F p},4Q:q(a,1N,3c){k(a.3Y)F 1N;Q{1I f.3U(a,1N,3c);F 1i}P(e){F M}},7x:q(a,1N,3c){k(a.3Y)F 1N;Z(m i=0;i<f.2Z.1e;i++){k(f.2Z[i]&&f.2Z[i].a==a){f.2Z[i].7w();f.2Z[i]=K;F 1i}}Q{f.7c=M;1I f.3U(a,1N,3c,\'3l\');F 1i}P(e){F M}},4k:q(r,3t,T){m 1c=r.3u(3t);Z(m i=0;i<1c.1e;i++){k(1c[i].T==T){F 1c[i]}}},5W:q(){m s=\'<1a 2G="O-98"><6y>\'+\'<2B 2G="O-4W"><a 2j="F f.4W(b)" 1L="#">\'+f.6J+\'</a></2B>\'+\'<2B 2G="O-1D"><a 2j="F f.1D(b)" 1L="#">\'+f.6I+\'</a></2B>\'+\'<2B 2G="O-2T"><a 1L="#" 2j="F 1i">\'+f.6G+\'</a></2B>\'+\'<2B 2G="O-1C"><a 2j="F f.1C(b)" 2F="\'+f.6L+\'" 1L="#">\'+f.6R+\'</a></2B>\'+\'</6y></1a>\'+\'<1a 2G="O-1b"></1a>\'+\'<1a 2G="O-8Z"><1a>\'+\'<B 2G="O-3h" 2F="\'+f.6H+\'"><B></B></B>\'+\'</1a></1a>\';F f.W(\'1a\',{T:\'O-3l-G\',1x:s})},5r:q(a){Z(m i=0;i<f.3H.1e;i++){k(f.3H[i][0]==a){m c=f.3H[i][1];f.3H[i][1]=c.4e(1);F c}}},7V:q(e){m 3x=Y.3u(\'A\');m a,22;Z(m i=0;i<3x.1e;i++){a=3x[i];22=f.3L(a);k(22&&22[0]==\'f.7x\'&&f.3E(a,\'2r\')==\'29\'&&f.3E(a,\'5y\')){f.3n(f.5e,a)}}f.5w(0)},5w:q(i){k(!f.5e[i])F;m a=f.5e[i];m 4d=f.4m(f.3E(a,\'5X\'));k(!4d)4d=f.5W();m 29=1I f.52(a,4d,1);29.5o=q(){};29.2d=q(){f.3n(f.3H,[a,4d]);f.5w(i+1)};29.5n()},77:q(){m 5v=0,5d=-1;Z(m i=0;i<f.L.1e;i++){k(f.L[i]){k(f.L[i].J.u.1r&&f.L[i].J.u.1r>5v){5v=f.L[i].J.u.1r;5d=i}}}k(5d==-1)f.21=-1;R f.L[5d].2D()},5m:q(N,1Z){m 3s=Y.3u(\'A\'),5u={},5z=-1,j=0;Z(m i=0;i<3s.1e;i++){k(f.3L(3s[i])&&((f.L[N].3d==f.3E(3s[i],\'3d\')))){5u[j]=3s[i];k(f.L[N]&&3s[i]==f.L[N].a){5z=j}j++}}F 5u[5z+1Z]},3E:q(a,32){a.3Y=a.2j;m p=a.3Y();a.3Y=K;F(p&&1Y p[32]!=\'48\')?p[32]:f[32]},2y:q(a){m 16=f.3E(a,\'16\');k(16)F 16;F a.1L},4m:q(1f){m 1n=f.$(1f),35=f.5F[1f],a={};k(!1n&&!35)F K;k(!35){35=1n.4e(M);35.1f=\'\';f.5F[1f]=35;F 1n}R{F 35.4e(M)}},3N:q(d){k(!f.1g)F;m a=d.5K,i,l,n;k(a){l=a.1e;Z(m i=0;i<l;i+=1){n=a[i].2I;k(1Y d[n]===\'q\'){d[n]=K}}}a=d.3J;k(a){l=a.1e;Z(m i=0;i<l;i+=1){f.3N(d.3J[i])}}},53:q(r,1Z){m C=f.3P(r);Q{m 7q=f.94=f.5m(C.N,1Z);7q.2j()}P(e){}Q{C.1C()}P(e){}F 1i},4W:q(r){F f.53(r,-1)},1D:q(r){F f.53(r,1)},5a:q(e){k(!e)e=1A.1H;k(!e.2q)e.2q=e.6u;k(e.2q.76)F;m 1Z=K;8u(e.8y){2O 34:2O 39:2O 40:1Z=1;6l;2O 33:2O 37:2O 38:1Z=-1;6l;2O 27:2O 13:1Z=0}k(1Z!==K){f.47(Y,\'65\',f.5a);Q{k(!f.71)F M}P(e){}k(e.4Z)e.4Z();R e.8z=1i;k(1Z==0){Q{f.3P().1C()}P(e){}F 1i}R{F f.53(f.21,1Z)}}R F M},8M:q(1t){f.3n(f.1K,1t)},6k:q(5C){m r,22=/^O-J-([0-9]+)$/;r=5C;49(r.23){k(r.1f&&22.1z(r.1f))F r.1f.1T(22,"$1");r=r.23}r=5C;49(r.23){k(r.3t&&f.3L(r)){Z(m N=0;N<f.L.1e;N++){C=f.L[N];k(C&&C.a==r)F N}}r=r.23}},3P:q(r){Q{k(!r)F f.L[f.21];k(1Y r==\'4i\')F f.L[r];k(1Y r==\'67\')r=f.$(r);F f.L[f.6k(r)]}P(e){}},3L:q(a){F(a.2j&&a.2j.7W().1T(/\\s/g,\' \').2v(/f.(99|e)9j/))},82:q(){Z(m i=0;i<f.L.1e;i++)k(f.L[i]&&f.L[i].68)f.77()},5x:q(e){k(!e)e=1A.1H;k(e.ae>1)F M;k(!e.2q)e.2q=e.6u;m r=e.2q;49(r.23&&!(/O-(2f|2T|3l|3h)/.1z(r.T))){r=r.23}m C=f.3P(r);k(C&&e.2A==\'5t\'){k(e.2q.76)F;m 2v=r.T.2v(/O-(2f|2T|3h)/);k(2v){f.1h={C:C,2A:2v[1],11:C.x.H,I:C.x.B,1j:C.y.H,E:C.y.B,72:e.73,6V:e.6W};k(f.1h.2A==\'2f\')C.G.u.2a=\'2T\';f.2x(Y,\'74\',f.5D);k(e.4Z)e.4Z();k(/O-(2f|3l)-3W/.1z(C.G.T)){C.2D();f.5B=M}F 1i}R k(/O-3l/.1z(r.T)&&f.21!=C.N){C.2D();C.5c()}}R k(e.2A==\'7j\'){f.47(Y,\'74\',f.5D);k(f.1h){k(f.1h.2A==\'2f\')f.1h.C.G.u.2a=f.42;m 51=(3C.78(f.1h.3y)+3C.78(f.1h.3D)>0);k(!51&&!f.5B&&!/(2T|3h)/.1z(f.1h.2A)){C.1C()}R k(51||(!51&&f.7c)){f.1h.C.5c()}k(f.1h.C.2n)f.1h.C.2n.u.1Q=\'2c\';f.5B=1i;f.1h=K}R k(/O-2f-3W/.1z(r.T)){r.u.2a=f.42}}},5D:q(e){k(!f.1h)F;k(!e)e=1A.1H;m C=f.1h.C;k(C.S){k(!C.2n)C.2n=f.W(\'1a\',K,{1d:\'1X\',I:C.x.B+\'D\',E:C.y.B+\'D\',11:0,1j:0,1r:4,6x:(f.1g?\'9V\':\'2c\'),1w:0.9Z},C.J,M);k(C.2n.u.1Q==\'2c\')C.2n.u.1Q=\'\'}f.1h.3y=e.73-f.1h.72;f.1h.3D=e.6W-f.1h.6V;k(f.1h.2A==\'3h\')C.3h(f.1h);R C.2T(f.1h);F 1i},2x:q(r,1H,2M){Q{r.2x(1H,2M,1i)}P(e){Q{r.6U(\'4n\'+1H,2M);r.a2(\'4n\'+1H,2M)}P(e){r[\'4n\'+1H]=2M}}},47:q(r,1H,2M){Q{r.47(1H,2M,1i)}P(e){Q{r.6U(\'4n\'+1H,2M)}P(e){r[\'4n\'+1H]=K}}},5G:q(i){k(f.5I&&f.4f[i]&&f.4f[i]!=\'48\'){m 1l=Y.W(\'1l\');1l.3g=q(){f.5G(i+1)};1l.16=f.4f[i]}},6F:q(4i){k(4i&&1Y 4i!=\'a1\')f.5E=4i;m a,22,j=0;m 3x=Y.3u(\'A\');Z(m i=0;i<3x.1e;i++){a=3x[i];22=f.3L(a);k(22&&22[0]==\'f.4Q\'){k(j<f.5E){f.4f[j]=f.2y(a);j++}}}1I f.41(f.1p,q(){f.5G(0)});m 7d=f.W(\'1l\',{16:f.4J+f.6o})},4v:q(){k(!f.1P){f.1P=f.W(\'1a\',K,{1d:\'1X\',11:0,1j:0,I:\'2E%\',1r:f.4j},Y.1b,M);f.1v=f.W(\'a\',{T:\'O-1v\',2F:f.7e,1x:f.7r,1L:\'70:a3(0)\'},{1d:\'1X\',1w:f.7p,11:\'-3O\',1r:1},f.1P);f.2m=f.W(\'1a\',K,{8g:\'8n\',a4:\'a0\'},K,M)}},4M:q(r,o,4T,i,3B){k(3B==K)m 3B=4T>o?1:-1;o=7s(o);r.u.1k=(o<=0)?\'X\':\'1S\';k(o<0||(3B==1&&o>4T))F;k(i==K)i=f.4R.1e;k(1Y(r.i)!=\'48\'&&r.i!=i){a6(f.4R[r.i]);o=r.7t}r.i=i;r.7t=o;r.u.1k=(o<=0)?\'X\':\'1S\';f.19(r,{1w:o});f.4R[i]=2p(q(){f.4M(r,3C.4w((o+0.1*3B)*2E)/2E,4T,i,3B)},25)},1C:q(r){Q{f.3P(r).1C()}P(e){}F 1i}};f.41=q(1p,2d){b.2d=2d;b.1p=1p;m v=f.2Y(),58;b.4t=f.1g&&v>=5.5&&v<7;k(!1p){k(2d)2d();F}f.4v();b.1o=f.W(\'1o\',{9W:0},{1k:\'X\',1d:\'1X\',9X:\'9Y\'},f.1P,M);b.5s=f.W(\'5s\',K,K,b.1o,1);b.1s=[];Z(m i=0;i<=8;i++){k(i%3==0)58=f.W(\'58\',K,{E:\'1B\'},b.5s,M);b.1s[i]=f.W(\'1s\',K,K,58,M);m u=i!=4?{a5:0,a9:0}:{1d:\'3k\'};f.19(b.1s[i],u)}b.1s[4].T=1p;b.7f()};f.41.5R={7f:q(){m 16=f.4J+(f.ag||"af/")+b.1p+".ac";m 7m=f.3G?f.1P:K;b.2S=f.W(\'1l\',K,{1d:\'1X\',11:\'-3O\',1j:\'-3O\'},7m,M);m 2w=b;b.2S.3g=q(){2w.7l()};b.2S.16=16},7l:q(){m o=b.1V=b.2S.I/4,2s=[[0,0],[0,-4],[-2,0],[0,-8],0,[-2,-8],[0,-2],[0,-6],[-2,-2]],4q={E:(2*o)+\'D\',I:(2*o)+\'D\'};Z(m i=0;i<=8;i++){k(2s[i]){k(b.4t){m w=(i==1||i==7)?\'2E%\':b.2S.I+\'D\';m 1a=f.W(\'1a\',K,{I:\'2E%\',E:\'2E%\',1d:\'3k\',2o:\'X\'},b.1s[i],M);f.W(\'1a\',K,{7k:"a8:a7.7B.ad(aa=ab, 16=\'"+b.2S.16+"\')",1d:\'1X\',I:w,E:b.2S.E+\'D\',11:(2s[i][0]*o)+\'D\',1j:(2s[i][1]*o)+\'D\'},1a,M)}R{f.19(b.1s[i],{6x:\'6C(\'+b.2S.16+\') \'+(2s[i][0]*o)+\'D \'+(2s[i][1]*o)+\'D\'})}k(1A.4h&&(i==3||i==5))f.W(\'1a\',K,4q,b.1s[i],M);f.19(b.1s[i],4q)}}f.43[b.1p]=b;k(b.2d)b.2d()},3b:q(C,x,y,w,h,6E){k(6E)b.1o.u.1k=(h>=4*b.1V)?\'1S\':\'X\';b.1o.u.11=(x-b.1V)+\'D\';b.1o.u.1j=(y-b.1V)+\'D\';b.1o.u.I=(w+2*(C.1U+b.1V))+\'D\';w+=2*(C.1U-b.1V);h+=+2*(C.2e-b.1V);b.1s[4].u.I=w>=0?w+\'D\':0;b.1s[4].u.E=h>=0?h+\'D\':0;k(b.4t)b.1s[3].u.E=b.1s[5].u.E=b.1s[4].u.E},6c:q(6D){k(6D)b.1o.u.1k=\'X\';R{f.3N(b.1o);Q{b.1o.23.2V(b.1o)}P(e){}}}};f.3U=q(a,1N,3c,2l){b.a=a;b.3c=3c;b.2l=2l||\'2f\';b.26=(2l==\'3l\');b.3M=!b.26;f.5I=1i;f.4v();m N=b.N=f.L.1e;Z(m i=0;i<f.5T.1e;i++){m 2I=f.5T[i];b[2I]=1N&&1Y 1N[2I]!=\'48\'?1N[2I]:f[2I]}m r=b.59=(1N?f.$(1N.6v):K)||a.3u(\'9T\')[0]||a;b.4X=r.1f||a.1f;Z(m i=0;i<f.L.1e;i++){k(f.L[i]&&f.L[i].a==a){f.L[i].2D();F 1i}}Z(m i=0;i<f.L.1e;i++){k(f.L[i]&&f.L[i].59!=r&&!f.L[i].4s){f.L[i].5g()}}f.L[b.N]=b;k(!f.62){Q{f.L[N-1].1C()}P(e){}Q{f.L[f.21].1C()}P(e){}}b.1K=[];m 2s=f.1d(r);b.1O=r.I?r.I:r.1q;b.28=r.E?r.E:r.18;b.2J=2s.x;b.2K=2s.y;b.3v=(b.59.1q-b.1O)/2;b.4a=(b.59.18-b.28)/2;b.J=f.W(\'1a\',{1f:\'O-J-\'+b.N,T:b.4I},{1k:\'X\',1d:\'1X\',1r:f.4j++},K,M);b.J.9u=q(e){Q{f.L[N].66(e)}P(e){}};b.J.9t=q(e){Q{f.L[N].66(e)}P(e){}};k(b.2l==\'2f\'&&b.2t==2)b.2t=0;k(f.43[b.1p]){b.5U();b[b.2l+\'5S\']()}R k(!b.1p){b[b.2l+\'5S\']()}R{b.4K();m C=b;1I f.41(b.1p,q(){C.5U();C[C.2l+\'5S\']()})}};f.3U.5R={5U:q(x,y){m w=f.43[b.1p];b.12=w;w.1o.u.1r=b.J.u.1r;f.43[b.1p]=K},4K:q(){k(b.4s||b.1v)F;b.5k=b.a.u.2a;b.a.u.2a=\'9s\';b.1v=f.1v;m C=b;b.1v.2j=q(){C.5g()};b.1v.u.1j=(b.2K+(b.28-b.1v.18)/2)+\'D\';m C=b,11=(b.2J+b.3v+(b.1O-b.1v.1q)/2)+\'D\';2p(q(){k(C.1v)C.1v.u.11=11},2E)},9v:q(){m C=b;m 1l=Y.W(\'1l\');b.G=1l;1l.3g=q(){k(f.L[C.N])C.3z()};1l.T=\'O-2f\';1l.u.1k=\'X\';1l.u.1Q=\'4l\';1l.u.1d=\'1X\';1l.u.9w=\'2c\';1l.u.1r=3;1l.2F=f.6f;k(f.3G)f.1P.1E(1l);1l.16=f.2y(b.a);b.4K()},9z:q(){b.5Y=f.W(\'1a\',{T:b.4I},{6N:\'0 \'+f.5Q+\'D 0 \'+f.3X+\'D\',1k:\'X\'},f.1P);b.G=f.5r(b.a);k(!b.G)b.G=f.4m(b.5X);k(!b.G)b.G=f.5W();b.14=b.G;k(b.24||b.2r==\'S\')b.5P(b.14);b.5Y.1E(b.14);f.19(b.14,{1d:\'3k\',1k:\'X\'});b.14.T+=\' O-1Q-4l\';k(b.14.1q<b.2h)b.14.u.I=b.2h+\'D\';b.G=f.W(\'1a\',{T:\'O-3l\'},{1d:\'3k\',1r:3,2o:\'X\',I:b.1O+\'D\',E:b.28+\'D\'});k(b.2r==\'29\'&&!f.5r(b.a)){m 29=1I f.52(b.a,b.14);m C=b;29.2d=q(){C.3z()};29.5o=q(){57.1L=f.2y(b.a)};29.5n()}R k(b.2r==\'S\'&&b.2k==\'3p\'){b.55()}R b.3z()},3z:q(){Q{k(!b.G)F;k(b.4s)F;R b.4s=M;k(b.1v){b.1v.u.11=\'-3O\';b.1v=K;b.a.u.2a=b.5k||\'\'}b.2Q=f.2Q;k(b.3M){b.1M=b.G.I;b.1J=b.G.E;b.3R=b.1M;b.7h=b.1J;b.G.u.I=b.1O+\'D\';b.G.u.E=b.28+\'D\';b.7X()}R k(b.5M)b.5M();b.J.1E(b.G);b.G.u.1d=\'3k\';k(b.U)b.J.1E(b.U);b.J.u.11=b.2J+\'D\';b.J.u.1j=b.2K+\'D\';f.1P.1E(b.J);b.1U=(b.G.1q-b.1O)/2;b.2e=(b.G.18-b.28)/2;m 6Q=f.5Q+2*b.1U;b.2Q+=2*b.2e;m 2N=b.1M/b.1J;m 2h=b.4C?b.2h:b.1M;m 2C=b.4C?b.2C:b.1J;m 3q={x:\'1B\',y:\'1B\'};m 3S=f.5J();b.x={H:1u(b.2J)-b.1U+b.3v,B:b.1M,2i:(b.1M<2h&&!f.5l)?b.1M:2h,1W:f.3X,31:6Q,3i:3S.4H,3a:3S.I,5i:b.1O};m 9y=b.x.H+1u(b.1O);b.x=b.3q(b.x);b.y={H:1u(b.2K)-b.2e+b.4a,B:b.1J,2i:b.1J<2C?b.1J:2C,1W:f.3I,31:b.2Q,3i:3S.4E,3a:3S.E,5i:b.28};m 9x=b.y.H+1u(b.28);b.y=b.3q(b.y);k(b.26)b.8p();k(b.3M)b.8b(2N);m x=b.x;m y=b.y;b.60()}P(e){1A.57.1L=f.2y(b.a)}},5P:q(3V,1B){m c=f.4k(3V,\'54\',\'O-1b\');k(b.2r==\'S\'){k(b.36)c.u.I=b.36+\'D\';k(b.4g)c.u.E=b.4g+\'D\'}k(b.24){c.u.I=b.24.5K.I+\'D\';c.u.E=b.24.5K.E+\'D\'}},55:q(9r){k(b.8e)F;m C=b;b.1b=f.4k(b.14,\'54\',\'O-1b\');k(b.2r==\'S\'){b.4K();b.4A=f.2m.4e(1);b.1b.1E(b.4A);b.1M=b.14.1q;k(!b.36)b.36=b.4A.1q;m 2L=b.14.18-b.1b.18;m h=b.4g||(f.5J()).E-2L-f.3I-f.2Q;m 3g=(f.1g&&b.2k==\'3p\')?\'3g="Q {f.L[\'+b.N+\'].3z()} P(e){}"\':\'\';m 4G=f.1g?\'<S 2I="8q\'+b.N+\'" \'+3g+\'/>\':\'S\';b.S=f.W(4G,{2I:\'8q\'+b.N,9k:0,9U:M},{I:b.36+\'D\',E:h+\'D\'},b.1b);k(b.2k==\'3p\'){k(!f.1g)b.S.3g=q(){Q{C.3z()}P(e){}}}k(f.3G)b.S.16=K;b.S.16=f.2y(b.a);k(b.2k==\'6g\')b.5p()}R k(b.24){b.1b.1f=b.1b.1f||\'f-9h-1f-\'+b.N;b.24.6O(b.1b.1f)}b.8e=M},5M:q(){k(b.S&&!b.4g){Q{m 1R=b.S.5V||b.S.4V.Y;m 2m=1R.W(\'1a\');2m.u.8g=\'8n\';1R.1b.1E(2m);m h=2m.5N;k(f.1g)h+=1u(1R.1b.4N.3I)+1u(1R.1b.4N.2Q)-1;b.S.u.E=b.1b.u.E=h+\'D\'}P(e){b.S.u.E=\'9i\'}}b.14.1E(f.2m);k(!b.1M)b.1M=b.14.1q;b.1J=b.14.18;b.14.2V(f.2m);k(f.1g&&b.1J>1u(b.14.4N.E)){b.1J=1u(b.14.4N.E)}},5p:q(){m 2u=b.14.1q-b.4A.1q;k(2u<0)2u=0;m 2L=b.14.18-b.1b.18;f.19(b.S,{I:(b.x.B-2u)+\'D\',E:(b.y.B-2L)+\'D\'});f.19(b.1b,{I:b.S.u.I,E:b.S.u.E});b.3K=b.S;b.1F=b.3K},8p:q(){b.5P(b.14);k(b.24&&b.2k==\'3p\')b.55();k(b.x.B<b.1M&&!b.4D)b.x.B=b.1M;k(b.y.B<b.1J&&!b.5O)b.y.B=b.1J;b.1F=b.14;b.44=f.W(\'1a\',K,{I:b.x.B+\'D\',1d:\'3k\',11:(b.x.H-b.2J)+\'D\',1j:(b.y.H-b.2K)+\'D\'},b.G,M);b.44.1E(b.14);f.1P.2V(b.5Y);f.19(b.14,{8t:\'2c\',I:\'1B\',E:\'1B\'});m 1n=f.4k(b.14,\'54\',\'O-1b\');k(1n&&!b.24&&b.2r!=\'S\'){m 3A=1n;1n=f.W(3A.9l,K,{2o:\'X\'},K,M);3A.23.9m(1n,3A);1n.1E(f.2m);1n.1E(3A);m 2u=b.14.1q-1n.1q;m 2L=b.14.18-1n.18;1n.2V(f.2m);m 4B=f.3G||3r.7A==\'7z\'?1:0;f.19(1n,{I:(b.x.B-2u-4B)+\'D\',E:(b.y.B-2L)+\'D\',2o:\'1B\',1d:\'3k\'});k(4B&&3A.18>1n.18){1n.u.I=(1u(1n.u.I)+4B)+\'D\'}b.3K=1n;b.1F=b.3K}k(b.S&&b.2k==\'3p\')b.5p();k(!b.3K&&b.y.B<b.44.18)b.1F=b.G;k(b.1F==b.G&&!b.4D&&b.2r!=\'S\'){b.x.B+=17}k(b.1F&&b.1F.18>b.1F.23.18){2p("Q { f.L["+b.N+"].1F.u.2o = \'1B\'; } P(e) {}",f.5Z)}},3q:q(p){m 9o,4q=p==b.x?\'x\':\'y\';m 5h=1i;m 3o=M;p.H=3C.4w(p.H-((p.B-p.5i)/2)); k(p.H<p.3i+p.1W){p.H=p.3i+p.1W;5h=M}k(p.B<p.2i){p.B=p.2i;3o=1i}k(p.H+p.B>p.3i+p.3a-p.31){k(5h&&3o){p.B=p.3a-p.1W-p.31}R k(p.B<p.3a-p.1W-p.31){p.H=p.3i+p.3a-p.B-p.1W-p.31}R{p.H=p.3i+p.1W;k(3o)p.B=p.3a-p.1W-p.31}}k(p.B<p.2i){p.B=p.2i;3o=1i}k(p.H<p.1W){7Q=p.H;p.H=p.1W;k(3o)p.B=p.B-(p.H-7Q)}F p},8b:q(2N){m x=b.x;m y=b.y;m 4O=1i;k(x.B/y.B>2N){ m 9O=x.B;x.B=y.B*2N;k(x.B<x.2i){k(f.5l)x.4c=x.B;x.B=x.2i;k(!x.4c)y.B=x.B/2N}4O=M}R k(x.B/y.B<2N){ m 9N=y.B;y.B=x.B/2N;4O=M}k(4O){x.H=1u(b.2J)-b.1U+b.3v;x.2i=x.B;b.x=b.3q(x);y.H=1u(b.2K)-b.2e+b.4a;y.2i=y.B;b.y=b.3q(y)}},60:q(){m 1y={x:b.x.H-20,y:b.y.H-20,w:b.x.B+40,h:b.y.B+40+b.46};f.4r=(f.1g&&f.2Y()<7);k(f.4r)b.2b(\'64\',\'X\',1y);f.4x=((1A.4h&&3r.7H<9)||3r.7A==\'7z\'||(f.1g&&f.2Y()<5.5));k(f.4x)b.2b(\'6h\',\'X\',1y);k(f.3Z)b.2b(\'*\',\'X\',1y);k(b.x.4c)b.G.u.7C=\'0 1B\';b.63(1,{x:b.2J+b.3v-b.1U,y:b.2K+b.4a-b.2e,w:b.1O,h:b.28,2H:b.1O,o:f.6b},{x:b.x.H,y:b.y.H,w:b.x.B,h:b.y.B,2H:b.x.4c,o:b.12?b.12.1V:0},f.5Z,f.7D)},63:q(3m,1m,V,85,2g){k(3m&&b.12&&!b.2t)b.12.3b(b,b.x.H,b.y.H,b.x.B,b.y.B);R k(!3m&&b.12){k(b.2t)b.12.3b(b,1m.x,1m.y,1m.w,1m.h);R b.12.6c((b.26&&b.45))}k(!3m){m n=b.J.3J.1e;Z(m i=n-1;i>=0;i--){m 5f=b.J.3J[i];k(5f!=b.G){f.3N(5f);b.J.2V(5f)}}}m 7F=(V.w-1m.w)/2g,7E=(V.2H-1m.2H)/2g,7R=(V.h-1m.h)/2g,3y=(V.x-1m.x)/2g,3D=(V.y-1m.y)/2g,7S=(V.o-1m.o)/2g,t,C=b;Z(m i=1;i<=2g;i++){1m.w+=7F;1m.2H+=7E;1m.h+=7R;1m.x+=3y;1m.y+=3D;1m.o+=7S;t=3C.4w(i*(85/2g));(q(){m 3e=i<2g?1m:V,32={},86=i;Z(m x 5q 3e)32[x]=3e[x];2p(q(){k(3m&&86==1){C.G.u.1k=\'1S\';C.a.T+=\' O-8m-8h\'}C.89(32)},t)})()}k(3m){2p(q(){k(C.12)C.12.1o.u.1k="1S"},t);2p(q(){k(C.U)C.7G();C.88()},t+50)}R 2p(q(){C.6w()},t)},89:q(V){Q{k(b.26){f.19(b.G,{I:V.w+\'D\',E:V.h+\'D\'});f.19(b.44,{11:(b.x.H-V.x)+\'D\',1j:(b.y.H-V.y)+\'D\'});b.14.u.1k=\'1S\'}R{b.J.u.I=(V.w+2*b.1U)+\'D\';b.G.u.I=(V.2H||V.w)+\'D\';b.G.u.E=V.h+\'D\'}k(b.12&&b.2t){m o=b.12.1V-V.o;b.12.3b(b,V.x+o,V.y+o,V.w-2*o,V.h-2*o,1)}f.19(b.J,{\'1k\':\'1S\',\'11\':V.x+\'D\',\'1j\':V.y+\'D\'})}P(e){1A.57.1L=f.2y(b.a)}},88:q(){b.68=M;b.2D();k(b.26&&b.2k==\'6g\')b.55();k(b.26){k(b.S){Q{m C=b,1R=b.S.5V||b.S.4V.Y;f.2x(1R,\'5t\',q(){k(f.21!=C.N)C.2D()})}P(e){}k(f.1g&&1Y b.4S!=\'9S\')b.S.u.I=(b.36-1)+\'D\'}}b.8d();k(f.81)b.7Z();k(b.3R>b.x.B)b.6X();k(!b.U)b.69()},69:q(){m N=b.N;m 1p=b.1p;1I f.41(1p,q(){Q{f.L[N].7T()}P(e){}})},7T:q(){m 1D=f.5m(b.N,1);k(1D.2j.7W().2v(/f\\.4Q/))m 1l=f.W(\'1l\',{16:f.2y(1D)})},5g:q(){f.L[b.N]=K;b.a.u.2a=b.5k;k(b.1v)f.1v.u.11=\'-3O\'},7Z:q(){m 6s=f.W(\'a\',{1L:f.7Y,T:\'O-6s\',1x:f.6z,2F:f.80});b.4P({61:6s,1d:\'1j 11\'})},7X:q(){k(!b.3F&&b.4X)b.3F=\'U-Z-\'+b.4X;k(b.3F)b.U=f.4m(b.3F);k(!b.U&&!b.4o&&b.6m)Q{b.4o=9R(b.6m)}P(e){}k(!b.U&&b.4o)b.U=f.W(\'1a\',{T:\'O-U\',1x:b.4o});k(!b.U){m 1D=b.a.83;49(1D&&!f.3L(1D)){k(/O-U/.1z(1D.T)){b.U=1D.4e(1);6l}1D=1D.83}}k(b.U){b.2Q+=b.46}},7G:q(){Q{f.19(b.J,{I:b.J.1q+\'D\',E:b.J.18+\'D\'});f.19(b.U,{1k:\'X\',3I:f.3G?0:\'-\'+b.y.B+\'D\'});b.U.T+=\' O-1Q-4l\';m E,C=b;k(f.1g&&(f.2Y()<6||Y.6a==\'7O\')){E=b.U.18}R{m 7P=f.W(\'1a\',{1x:b.U.1x},K,K,M);b.U.1x=\'\';b.U.1E(7P);E=b.U.3J[0].18;b.U.1x=b.U.3J[0].1x}f.19(b.U,{2o:\'X\',E:0,1r:2,3I:0});b.J.u.E=\'1B\';k(f.6d){m 6e=(3C.4w(E/50)||1)*f.6d}R{b.6i(E,1);F}Z(m h=E%6e,t=0;h<=E;h+=6e,t+=10){(q(){m 8a=h,4y=(h==E)?1:0;2p(q(){C.6i(8a,4y)},t)})()}}P(e){}},6i:q(E,4y){k(!b.U)F;b.U.u.E=E+\'D\';b.U.u.1k=\'1S\';b.y.B=b.J.18-2*b.2e;m o=b.12;k(o){o.1s[4].u.E=(b.J.18-2*b.12.1V)+\'D\';k(o.4t)o.1s[3].u.E=o.1s[5].u.E=o.1s[4].u.E}k(4y)b.69()},2b:q(3t,1k,1y){m 1c=Y.3u(3t);m 3w=3t==\'*\'?\'2o\':\'1k\';Z(m i=0;i<1c.1e;i++){k(3w==\'1k\'||(Y.9L.9K(1c[i],"").9E(\'2o\')==\'1B\'||1c[i].3Q(\'X-2R\')!=K)){m 1G=1c[i].3Q(\'X-2R\');k(1k==\'1S\'&&1G){1G=1G.1T(\'[\'+b.N+\']\',\'\');1c[i].3f(\'X-2R\',1G);k(!1G)1c[i].u[3w]=1c[i].6r}R k(1k==\'X\'){m 2z=f.1d(1c[i]);2z.w=1c[i].1q;2z.h=1c[i].18;m 8j=(2z.x+2z.w<1y.x||2z.x>1y.x+1y.w);m 8r=(2z.y+2z.h<1y.y||2z.y>1y.y+1y.h);m 6j=f.6k(1c[i]);k(!8j&&!8r&&6j!=b.N){k(!1G){1c[i].3f(\'X-2R\',\'[\'+b.N+\']\');1c[i].6r=1c[i].u[3w];1c[i].u[3w]=\'X\'}R k(!1G.2v(\'[\'+b.N+\']\')){1c[i].3f(\'X-2R\',1G+\'[\'+b.N+\']\')}}R k(1G==\'[\'+b.N+\']\'||f.21==6j){1c[i].3f(\'X-2R\',\'\');1c[i].u[3w]=1c[i].6r||\'\'}R k(1G&&1G.2v(\'[\'+b.N+\']\')){1c[i].3f(\'X-2R\',1G.1T(\'[\'+b.N+\']\',\'\'))}}}}},2D:q(){b.J.u.1r=f.4j++;Z(m i=0;i<f.L.1e;i++){k(f.L[i]&&i==f.21){m 2P=f.L[i];2P.G.T+=\' O-\'+2P.2l+\'-3W\';k(2P.U){2P.U.T+=\' O-U-3W\'}k(2P.3M){2P.G.u.2a=f.1g?\'6S\':\'6q\';2P.G.2F=f.8o}}}k(b.12)b.12.1o.u.1r=b.J.u.1r;b.G.T=\'O-\'+b.2l;k(b.U){b.U.T=b.U.T.1T(\' O-U-3W\',\'\')}k(b.3M){b.G.2F=f.6f;f.42=1A.4h?\'6q\':\'6C(\'+f.4J+f.6o+\'), 6q\';k(f.1g&&f.2Y()<6)f.42=\'6S\';b.G.u.2a=f.42}f.21=b.N;f.2x(Y,\'65\',f.5a)},2T:q(e){b.x.H=e.11+e.3y;b.y.H=e.1j+e.3D;f.19(b.J,{11:b.x.H+\'D\',1j:b.y.H+\'D\'});k(b.12)b.12.3b(b,b.x.H,b.y.H,b.x.B,b.y.B)},3h:q(e){b.x.B=e.I+e.3y;b.y.B=e.E+e.3D;k(b.x.B<b.2h)b.x.B=b.2h;k(b.y.B<b.2C)b.y.B=b.2C;m d=b.1F;k(1Y b.2u==\'48\'){b.2u=b.14.1q-d.1q;b.2L=b.14.18-d.18}f.19(d,{I:(b.x.B-b.2u)+\'D\',E:(b.y.B-b.2L)+\'D\'});m 3e={I:b.x.B+\'D\',E:b.y.B+\'D\'};f.19(b.G,3e);k(b.2n)f.19(b.2n,3e);b.44.u.I=\'1B\';f.19(b.1b,{I:\'1B\',E:\'1B\'});Z(m i=0;i<b.1K.1e;i++)b.5b(b.1K[i]);k(b.12)b.12.3b(b,b.x.H,b.y.H,b.x.B,b.y.B)},1C:q(){k(b.4S||!b.68)F;b.4S=M;f.47(Y,\'65\',f.5a);Q{k(b.26)b.7g();b.G.u.2a=\'9G\';b.63(0,{x:b.x.H,y:b.y.H,w:b.x.B,h:1u(b.G.u.E),2H:b.x.4c,o:b.12?b.12.1V:0},{x:b.2J-b.1U+b.3v,y:b.2K-b.2e+b.4a,w:b.1O,h:b.28,2H:b.1O,o:f.6b},f.6T,f.7i)}P(e){b.6w()}},7g:q(){k(f.3Z){k(!f.3T)f.3T=f.W(\'1a\',K,{1d:\'1X\'},f.1P);f.19(f.3T,{I:b.x.B+\'D\',E:b.y.B+\'D\',11:b.x.H+\'D\',1j:b.y.H+\'D\',1Q:\'4l\'})}k(b.24)Q{f.$(b.24.3Q(\'1f\')).9J()}P(e){}k(b.2k==\'6g\'&&!b.45)b.7o();k(b.1F&&b.1F!=b.3K)b.1F.u.2o=\'X\'},7o:q(){k(f.1g&&b.S)Q{b.S.4V.Y.1b.1x=\'\'}P(e){}b.1b.1x=\'\'},7K:q(){k(b.12)b.12.1o.T=\'O-1Q-2c\';b.2n=K;b.J.T+=\' O-1Q-2c\';f.3n(f.2Z,b)},7w:q(){f.L[b.N]=b;k(!f.62&&f.21!=b.N){Q{f.L[f.21].1C()}P(e){}}b.J.T=b.J.T.1T(/O-1Q-2c/,\'\');m z=f.4j++;b.J.u.1r=z;b.4S=1i;k(o=b.12){k(!b.2t)o.1o.u.1k=\'X\';o.1o.T=K;o.1o.u.1r=z}b.60()},4P:q(o){m r=o.61;k(1Y r==\'67\')r=f.4m(r);k(!r||1Y r==\'67\')F;m 1t=f.W(\'1a\',K,{\'11\':0,\'1j\':0,\'1d\':\'1X\',\'1r\':3,\'1k\':\'X\'},b.J,M);k(o.1w)f.19(r,{1w:o.1w});r.T+=\' O-1Q-4l\';1t.1E(r);1t.7a=o.1d;b.5b(1t);k(o.4L)1t.3f(\'4L\',M);k(!o.1w)o.1w=1;1t.3f(\'1w\',o.1w);f.4M(1t,0,o.1w);f.3n(b.1K,1t)},5b:q(1t){m 11=b.1U;m 6t=b.x.B-1t.1q;m 1j=b.2e;m 6p=1u(b.G.u.E)-1t.18;m p=1t.7a||\'4Y 4Y\';k(/^7b/.1z(p))1j+=6p;k(/^4Y/.1z(p))1j+=6p/2;k(/79$/.1z(p))11+=6t;k(/4Y$/.1z(p))11+=6t/2;1t.u.11=11+\'D\';1t.u.1j=1j+\'D\'},8d:q(){Z(m i=0;i<f.1K.1e;i++){m o=f.1K[i];k((!o.6v&&!o.3d)||o.6v==b.4X||o.3d===b.3d){k(b.3M||(b.26&&o.9H))b.4P(o)}}},6X:q(){m a=f.W(\'a\',{1L:\'70:f.L[\'+b.N+\'].7n();\',2F:f.6Z,T:\'O-9I-4Q\'});b.4U=a;b.4P({61:a,1d:f.7v,4L:M,1w:f.7u})},7n:q(){Q{f.3N(b.4U);b.4U.23.2V(b.4U);b.2D();b.x.H=1u(b.J.u.11)-(b.3R-b.G.I)/2;k(b.x.H<f.3X)b.x.H=f.3X;b.J.u.11=b.x.H+\'D\';f.19(b.G,{I:b.3R+\'D\',E:b.7h+\'D\'});b.x.B=b.3R;b.J.u.I=(b.x.B+2*b.1U)+\'D\';b.y.B=b.J.18-2*b.2e;k(b.12)b.12.3b(b,b.x.H,b.y.H,b.x.B,b.y.B);Z(m i=0;i<b.1K.1e;i++)b.5b(b.1K[i]);b.5c()}P(e){1A.57.1L=b.G.16}},5c:q(){m 1y={x:1u(b.J.u.11)-20,y:1u(b.J.u.1j)-20,w:b.G.1q+40,h:b.G.18+40+b.46};k(f.4r)b.2b(\'64\',\'X\',1y);k(f.4x)b.2b(\'6h\',\'X\',1y);k(f.3Z)b.2b(\'*\',\'X\',1y)},66:q(e){k(!e)e=1A.1H;m 4F=/9F/i.1z(e.2A);k(!e.2q)e.2q=e.6u;k(!e.6n)e.6n=4F?e.9C:e.9D;k(f.3P(e.6n)==b||f.1h)F;Z(m i=0;i<b.1K.1e;i++){m o=b.1K[i];k(o.3Q(\'4L\')){m 1m=4F?0:o.3Q(\'1w\'),V=4F?o.3Q(\'1w\'):0;f.4M(o,1m,V)}}},6w:q(){b.a.T=b.a.T.1T(\'O-8m-8h\',\'\');k(f.4r)b.2b(\'64\',\'1S\');k(f.4x)b.2b(\'6h\',\'1S\');k(f.3Z)b.2b(\'*\',\'1S\');k(b.26&&b.45)b.7K();R{k(b.12&&b.2t)b.12.6c();f.3N(b.J);k(f.1g&&f.2Y()<5.5)b.J.1x=\'\';R b.J.23.2V(b.J)}k(f.3T)f.3T.u.1Q=\'2c\';f.L[b.N]=K;f.82()}};f.52=q(a,G,4z){b.a=a;b.G=G;b.4z=4z};f.52.5R={5n:q(){b.16=f.2y(b.a);k(b.16.2v(\'#\')){m 2U=b.16.7U(\'#\');b.16=2U[0];b.1f=2U[1]}k(f.4u[b.16]){b.8l=f.4u[b.16];k(b.1f)b.5j();R b.4b();F}Q{b.2X=1I 9Q()}P(e){Q{b.2X=1I 84("9P.7I")}P(e){Q{b.2X=1I 84("7B.7I")}P(e){b.5o()}}}m 2w=b;b.2X.9M=q(){k(2w.2X.9B==4){k(2w.1f)2w.5j();R 2w.4b()}};b.2X.6P("9A",b.16,M);b.2X.9n(K)},5j:q(){f.4v();m 2W=1A.4h?{16:b.16}:K;b.S=f.W(\'S\',2W,{1d:\'1X\',11:\'-3O\'},f.1P);Q{b.4b()}P(e){m 2w=b;2p(q(){2w.4b()},1)}},4b:q(){m s=b.8l||b.2X.9p;k(b.4z)f.4u[b.16]=s;k(!f.1g||f.2Y()>=5.5){s=s.1T(/\\s/g,\' \');k(b.S){s=s.1T(1I 5A(\'<9q[^>]*>\',\'6K\'),\'\');s=s.1T(1I 5A(\'<6M[^>]*>.*?</6M>\',\'6K\'),\'\');m 1R=b.S.5V||b.S.4V.Y;1R.6P();1R.6O(s);1R.1C();Q{s=1R.5H(b.1f).1x}P(e){Q{s=b.S.Y.5H(b.1f).1x}P(e){}}f.1P.2V(b.S)}R{s=s.1T(1I 5A(\'^.*?<1b[^>]*>(.*?)</1b>.*?$\',\'i\'),\'$1\')}}f.4k(b.G,\'54\',\'O-1b\').1x=s;b.2d()}};m 95=f.3U;f.2x(Y,\'5t\',f.5x);f.2x(Y,\'7j\',f.5x);f.2x(1A,\'8k\',f.6F);f.2x(1A,\'8k\',f.7V);',62,637,'|||||||||||this||||hs|||||if||var||||function|el|||style|||||||span|exp|px|height|return|content|min|width|wrapper|null|expanders|true|key|highslide|catch|try|else|iframe|className|caption|to|createElement|hidden|document|for||left|objOutline||innerContent||src||offsetHeight|setStyles|div|body|els|position|length|id|ie|dragArgs|false|top|visibility|img|from|node|table|outlineType|offsetWidth|zIndex|td|overlay|parseInt|loading|opacity|innerHTML|imgPos|test|window|auto|close|next|appendChild|scrollerDiv|hiddenBy|event|new|newHeight|overlays|href|newWidth|params|thumbWidth|container|display|doc|visible|replace|offsetBorderW|offset|marginMin|absolute|typeof|op||focusKey|re|parentNode|swfObject||isHtml||thumbHeight|ajax|cursor|showHideElements|none|onLoad|offsetBorderH|image|steps|minWidth|minSpan|onclick|objectLoadTime|contentType|clearing|releaseMask|overflow|setTimeout|target|objectType|pos|outlineWhileAnimating|wDiff|match|pThis|addEventListener|getSrc|elPos|type|li|minHeight|focus|100|title|class|imgW|name|thumbLeft|thumbTop|hDiff|func|ratio|case|blurExp|marginBottom|by|graphic|move|arr|removeChild|attribs|xmlHttp|ieVersion|sleeping||marginMax|param|||clone|objectWidth||||clientSpan|setPosition|custom|slideshowGroup|size|setAttribute|onload|resize|scroll|styles|relative|html|up|push|allowReduce|before|justify|navigator|aAr|tagName|getElementsByTagName|thumbOffsetBorderW|prop|aTags|dX|contentLoaded|cNode|dir|Math|dY|getParam|captionId|safari|cacheBindings|marginTop|childNodes|scrollingContent|isHsAnchor|isImage|purge|9999px|getExpander|getAttribute|fullExpandWidth|page|mask|Expander|parent|blur|marginLeft|getParams|geckoMac||Outline|styleRestoreCursor|pendingOutlines|mediumContent|preserveContent|spaceForCaption|removeEventListener|undefined|while|thumbOffsetBorderH|loadHTML|imgSpan|cache|cloneNode|preloadTheseImages|objectHeight|opera|number|zIndexCounter|getElementByClass|block|getNode|on|captionText|iebody|dim|hideSelects|onLoadStarted|hasAlphaImageLoader|cachedGets|genContainer|round|hideIframes|end|pre|ruler|kdeBugCorr|allowSizeReduction|allowWidthReduction|scrollTop|over|tag|scrollLeft|wrapperClassName|graphicsDir|displayLoading|hideOnMouseOut|fade|currentStyle|changed|createOverlay|expand|faders|isClosing|oFinal|fullExpandLabel|contentWindow|previous|thumbsUserSetId|center|preventDefault||hasDragged|Ajax|previousOrNext|DIV|writeExtendedContent|Click|location|tr|thumb|keyHandler|positionOverlay|redoShowHide|topmostKey|preloadTheseAjax|child|cancelLoading|hasMovedMin|thumbSpan|getElementContent|originalCursor|padToMinWidth|getAdjacentAnchor|run|onError|correctIframeSize|in|getCacheBinding|tbody|mousedown|hsAr|topZ|preloadAjaxElement|mouseClickHandler|cacheAjax|activeI|RegExp|hasFocused|element|dragHandler|numberOfImagesToPreload|clones|preloadFullImage|getElementById|continuePreloading|getPageSize|attributes|documentElement|htmlGetSize|offsetTop|allowHeightReduction|setObjContainerSize|marginRight|prototype|Create|overrides|connectOutline|contentDocument|getSelfRendered|contentId|tempContainer|expandDuration|show|overlayId|allowMultipleInstances|changeSize|SELECT|keydown|wrapperMouseHandler|string|isExpanded|prepareNextOutline|compatMode|outlineStartOffset|destroy|captionSlideSpeed|step|restoreTitle|after|IFRAME|placeCaption|wrapperKey|getWrapperKey|break|captionEval|relatedTarget|restoreCursor|dTop|pointer|origProp|credits|dLeft|srcElement|thumbnailId|afterClose|background|ul|creditsText|offsetParent|and|url|hide|vis|preloadImages|moveText|resizeTitle|nextText|previousText|gi|closeTitle|script|padding|write|open|modMarginRight|closeText|hand|restoreDuration|detachEvent|clickY|clientY|createFullExpand|250|fullExpandTitle|javascript|enableKeyListener|clickX|clientX|mousemove||form|focusTopmost|abs|right|hsPos|bottom|hasHtmlexpanders|cur|loadingTitle|preloadGraphic|htmlPrepareClose|fullExpandHeight|restoreSteps|mouseup|filter|onGraphicLoad|appendTo|doFullExpand|destroyObject|loadingOpacity|adj|loadingText|parseFloat|tempOpacity|fullExpandOpacity|fullExpandPosition|awake|htmlExpand|offsetLeft|KDE|vendor|Microsoft|margin|expandSteps|dImgW|dW|writeCaption|appVersion|XMLHTTP|nopad|sleep|setAttribs|val|userAgent|BackCompat|temp|tmpMin|dH|dO|preloadNext|split|preloadAjax|toString|getCaption|creditsHref|writeCredits|creditsTitle|showCredits|cleanUp|nextSibling|ActiveXObject|dur|pI|200|afterExpand|setSize|pH|correctRatio|clientWidth|createOverlays|hasExtendedContent|Highslide|clear|anchor|self|clearsX|load|cachedGet|active|both|focusTitle|htmlSizeOperations|hsIframe|clearsY|JS|border|switch|Expand|actual|zoomout|keyCode|returnValue|Close|pageXOffset|Move|Next|graphics|no|innerHeight|vikjavev|http|Powered|1001|clientHeight|registerOverlay|Resize|drop|pageYOffset|Gecko|rv|Loading|drag|Macintosh|MSIE|Use|keys|alpha|footer|arrow|Previous|Safari|all|upcoming|HsExpander|homepage|front|header|htmlE|bring|shadow|cancel|the|Go|click|innerWidth|flash|300px|xpand|frameBorder|nodeName|insertBefore|send|tgt|responseText|link|loadTime|wait|onmouseout|onmouseover|imageCreate|maxWidth|oldBottom|oldRight|htmlCreate|GET|readyState|fromElement|toElement|getPropertyValue|mouseover|default|useOnHtml|full|StopPlay|getComputedStyle|defaultView|onreadystatechange|tmpHeight|tmpWidth|Msxml2|XMLHttpRequest|eval|boolean|IMG|allowTransparency|white|cellSpacing|borderCollapse|collapse|01|1px|object|attachEvent|void|paddingTop|lineHeight|clearTimeout|DXImageTransform|progid|fontSize|sizingMethod|scale|png|AlphaImageLoader|button|outlines|outlinesDir'.split('|'),0,{}))
/*  Prototype JavaScript framework, version 1.5.0
 *  (c) 2005-2007 Sam Stephenson
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://prototype.conio.net/
 *
/*--------------------------------------------------------------------------*/

var Prototype = {
  Version: '1.5.0',
  BrowserFeatures: {
    XPath: !!document.evaluate
  },

  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
  emptyFunction: function() {},
  K: function(x) { return x }
}

var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}

var Abstract = new Object();

Object.extend = function(destination, source) {
  for (var property in source) {
    destination[property] = source[property];
  }
  return destination;
}

Object.extend(Object, {
  inspect: function(object) {
    try {
      if (object === undefined) return 'undefined';
      if (object === null) return 'null';
      return object.inspect ? object.inspect() : object.toString();
    } catch (e) {
      if (e instanceof RangeError) return '...';
      throw e;
    }
  },

  keys: function(object) {
    var keys = [];
    for (var property in object)
      keys.push(property);
    return keys;
  },

  values: function(object) {
    var values = [];
    for (var property in object)
      values.push(object[property]);
    return values;
  },

  clone: function(object) {
    return Object.extend({}, object);
  }
});

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

Function.prototype.bindAsEventListener = function(object) {
  var __method = this, args = $A(arguments), object = args.shift();
  return function(event) {
    return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
  }
}

Object.extend(Number.prototype, {
  toColorPart: function() {
    var digits = this.toString(16);
    if (this < 16) return '0' + digits;
    return digits;
  },

  succ: function() {
    return this + 1;
  },

  times: function(iterator) {
    $R(0, this, true).each(iterator);
    return this;
  }
});

var Try = {
  these: function() {
    var returnValue;

    for (var i = 0, length = arguments.length; i < length; i++) {
      var lambda = arguments[i];
      try {
        returnValue = lambda();
        break;
      } catch (e) {}
    }

    return returnValue;
  }
}

/*--------------------------------------------------------------------------*/

var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

  registerCallback: function() {
    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  stop: function() {
    if (!this.timer) return;
    clearInterval(this.timer);
    this.timer = null;
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.callback(this);
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
}
String.interpret = function(value){
  return value == null ? '' : String(value);
}

Object.extend(String.prototype, {
  gsub: function(pattern, replacement) {
    var result = '', source = this, match;
    replacement = arguments.callee.prepareReplacement(replacement);

    while (source.length > 0) {
      if (match = source.match(pattern)) {
        result += source.slice(0, match.index);
        result += String.interpret(replacement(match));
        source  = source.slice(match.index + match[0].length);
      } else {
        result += source, source = '';
      }
    }
    return result;
  },

  sub: function(pattern, replacement, count) {
    replacement = this.gsub.prepareReplacement(replacement);
    count = count === undefined ? 1 : count;

    return this.gsub(pattern, function(match) {
      if (--count < 0) return match[0];
      return replacement(match);
    });
  },

  scan: function(pattern, iterator) {
    this.gsub(pattern, iterator);
    return this;
  },

  truncate: function(length, truncation) {
    length = length || 30;
    truncation = truncation === undefined ? '...' : truncation;
    return this.length > length ?
      this.slice(0, length - truncation.length) + truncation : this;
  },

  strip: function() {
    return this.replace(/^\s+/, '').replace(/\s+$/, '');
  },

  stripTags: function() {
    return this.replace(/<\/?[^>]+>/gi, '');
  },

  stripScripts: function() {
    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
  },

  extractScripts: function() {
    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
    return (this.match(matchAll) || []).map(function(scriptTag) {
      return (scriptTag.match(matchOne) || ['', ''])[1];
    });
  },

  evalScripts: function() {
    return this.extractScripts().map(function(script) { return eval(script) });
  },

  escapeHTML: function() {
    var div = document.createElement('div');
    var text = document.createTextNode(this);
    div.appendChild(text);
    return div.innerHTML;
  },

  unescapeHTML: function() {
    var div = document.createElement('div');
    div.innerHTML = this.stripTags();
    return div.childNodes[0] ? (div.childNodes.length > 1 ?
      $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) :
      div.childNodes[0].nodeValue) : '';
  },

  toQueryParams: function(separator) {
    var match = this.strip().match(/([^?#]*)(#.*)?$/);
    if (!match) return {};

    return match[1].split(separator || '&').inject({}, function(hash, pair) {
      if ((pair = pair.split('='))[0]) {
        var name = decodeURIComponent(pair[0]);
        var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;

        if (hash[name] !== undefined) {
          if (hash[name].constructor != Array)
            hash[name] = [hash[name]];
          if (value) hash[name].push(value);
        }
        else hash[name] = value;
      }
      return hash;
    });
  },

  toArray: function() {
    return this.split('');
  },

  succ: function() {
    return this.slice(0, this.length - 1) +
      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
  },

  camelize: function() {
    var parts = this.split('-'), len = parts.length;
    if (len == 1) return parts[0];

    var camelized = this.charAt(0) == '-'
      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
      : parts[0];

    for (var i = 1; i < len; i++)
      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

    return camelized;
  },

  capitalize: function(){
    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
  },

  underscore: function() {
    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
  },

  dasherize: function() {
    return this.gsub(/_/,'-');
  },

  inspect: function(useDoubleQuotes) {
    var escapedString = this.replace(/\\/g, '\\\\');
    if (useDoubleQuotes)
      return '"' + escapedString.replace(/"/g, '\\"') + '"';
    else
      return "'" + escapedString.replace(/'/g, '\\\'') + "'";
  }
});

String.prototype.gsub.prepareReplacement = function(replacement) {
  if (typeof replacement == 'function') return replacement;
  var template = new Template(replacement);
  return function(match) { return template.evaluate(match) };
}

String.prototype.parseQuery = String.prototype.toQueryParams;

var Template = Class.create();
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
Template.prototype = {
  initialize: function(template, pattern) {
    this.template = template.toString();
    this.pattern  = pattern || Template.Pattern;
  },

  evaluate: function(object) {
    return this.template.gsub(this.pattern, function(match) {
      var before = match[1];
      if (before == '\\') return match[2];
      return before + String.interpret(object[match[3]]);
    });
  }
}

var $break    = new Object();
var $continue = new Object();

var Enumerable = {
  each: function(iterator) {
    var index = 0;
    try {
      this._each(function(value) {
        try {
          iterator(value, index++);
        } catch (e) {
          if (e != $continue) throw e;
        }
      });
    } catch (e) {
      if (e != $break) throw e;
    }
    return this;
  },

  eachSlice: function(number, iterator) {
    var index = -number, slices = [], array = this.toArray();
    while ((index += number) < array.length)
      slices.push(array.slice(index, index+number));
    return slices.map(iterator);
  },

  all: function(iterator) {
    var result = true;
    this.each(function(value, index) {
      result = result && !!(iterator || Prototype.K)(value, index);
      if (!result) throw $break;
    });
    return result;
  },

  any: function(iterator) {
    var result = false;
    this.each(function(value, index) {
      if (result = !!(iterator || Prototype.K)(value, index))
        throw $break;
    });
    return result;
  },

  collect: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      results.push((iterator || Prototype.K)(value, index));
    });
    return results;
  },

  detect: function(iterator) {
    var result;
    this.each(function(value, index) {
      if (iterator(value, index)) {
        result = value;
        throw $break;
      }
    });
    return result;
  },

  findAll: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (iterator(value, index))
        results.push(value);
    });
    return results;
  },

  grep: function(pattern, iterator) {
    var results = [];
    this.each(function(value, index) {
      var stringValue = value.toString();
      if (stringValue.match(pattern))
        results.push((iterator || Prototype.K)(value, index));
    })
    return results;
  },

  include: function(object) {
    var found = false;
    this.each(function(value) {
      if (value == object) {
        found = true;
        throw $break;
      }
    });
    return found;
  },

  inGroupsOf: function(number, fillWith) {
    fillWith = fillWith === undefined ? null : fillWith;
    return this.eachSlice(number, function(slice) {
      while(slice.length < number) slice.push(fillWith);
      return slice;
    });
  },

  inject: function(memo, iterator) {
    this.each(function(value, index) {
      memo = iterator(memo, value, index);
    });
    return memo;
  },

  invoke: function(method) {
    var args = $A(arguments).slice(1);
    return this.map(function(value) {
      return value[method].apply(value, args);
    });
  },

  max: function(iterator) {
    var result;
    this.each(function(value, index) {
      value = (iterator || Prototype.K)(value, index);
      if (result == undefined || value >= result)
        result = value;
    });
    return result;
  },

  min: function(iterator) {
    var result;
    this.each(function(value, index) {
      value = (iterator || Prototype.K)(value, index);
      if (result == undefined || value < result)
        result = value;
    });
    return result;
  },

  partition: function(iterator) {
    var trues = [], falses = [];
    this.each(function(value, index) {
      ((iterator || Prototype.K)(value, index) ?
        trues : falses).push(value);
    });
    return [trues, falses];
  },

  pluck: function(property) {
    var results = [];
    this.each(function(value, index) {
      results.push(value[property]);
    });
    return results;
  },

  reject: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (!iterator(value, index))
        results.push(value);
    });
    return results;
  },

  sortBy: function(iterator) {
    return this.map(function(value, index) {
      return {value: value, criteria: iterator(value, index)};
    }).sort(function(left, right) {
      var a = left.criteria, b = right.criteria;
      return a < b ? -1 : a > b ? 1 : 0;
    }).pluck('value');
  },

  toArray: function() {
    return this.map();
  },

  zip: function() {
    var iterator = Prototype.K, args = $A(arguments);
    if (typeof args.last() == 'function')
      iterator = args.pop();

    var collections = [this].concat(args).map($A);
    return this.map(function(value, index) {
      return iterator(collections.pluck(index));
    });
  },

  size: function() {
    return this.toArray().length;
  },

  inspect: function() {
    return '#<Enumerable:' + this.toArray().inspect() + '>';
  }
}

Object.extend(Enumerable, {
  map:     Enumerable.collect,
  find:    Enumerable.detect,
  select:  Enumerable.findAll,
  member:  Enumerable.include,
  entries: Enumerable.toArray
});
var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}

Object.extend(Array.prototype, Enumerable);

if (!Array.prototype._reverse)
  Array.prototype._reverse = Array.prototype.reverse;

Object.extend(Array.prototype, {
  _each: function(iterator) {
    for (var i = 0, length = this.length; i < length; i++)
      iterator(this[i]);
  },

  clear: function() {
    this.length = 0;
    return this;
  },

  first: function() {
    return this[0];
  },

  last: function() {
    return this[this.length - 1];
  },

  compact: function() {
    return this.select(function(value) {
      return value != null;
    });
  },

  flatten: function() {
    return this.inject([], function(array, value) {
      return array.concat(value && value.constructor == Array ?
        value.flatten() : [value]);
    });
  },

  without: function() {
    var values = $A(arguments);
    return this.select(function(value) {
      return !values.include(value);
    });
  },

  indexOf: function(object) {
    for (var i = 0, length = this.length; i < length; i++)
      if (this[i] == object) return i;
    return -1;
  },

  reverse: function(inline) {
    return (inline !== false ? this : this.toArray())._reverse();
  },

  reduce: function() {
    return this.length > 1 ? this : this[0];
  },

  uniq: function() {
    return this.inject([], function(array, value) {
      return array.include(value) ? array : array.concat([value]);
    });
  },

  clone: function() {
    return [].concat(this);
  },

  size: function() {
    return this.length;
  },

  inspect: function() {
    return '[' + this.map(Object.inspect).join(', ') + ']';
  }
});

Array.prototype.toArray = Array.prototype.clone;

function $w(string){
  string = string.strip();
  return string ? string.split(/\s+/) : [];
}

if(window.opera){
  Array.prototype.concat = function(){
    var array = [];
    for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
    for(var i = 0, length = arguments.length; i < length; i++) {
      if(arguments[i].constructor == Array) {
        for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
          array.push(arguments[i][j]);
      } else {
        array.push(arguments[i]);
      }
    }
    return array;
  }
}
var Hash = function(obj) {
  Object.extend(this, obj || {});
};

Object.extend(Hash, {
  toQueryString: function(obj) {
    var parts = [];

	  this.prototype._each.call(obj, function(pair) {
      if (!pair.key) return;

      if (pair.value && pair.value.constructor == Array) {
        var values = pair.value.compact();
        if (values.length < 2) pair.value = values.reduce();
        else {
        	key = encodeURIComponent(pair.key);
          values.each(function(value) {
            value = value != undefined ? encodeURIComponent(value) : '';
            parts.push(key + '=' + encodeURIComponent(value));
          });
          return;
        }
      }
      if (pair.value == undefined) pair[1] = '';
      parts.push(pair.map(encodeURIComponent).join('='));
	  });

    return parts.join('&');
  }
});

Object.extend(Hash.prototype, Enumerable);
Object.extend(Hash.prototype, {
  _each: function(iterator) {
    for (var key in this) {
      var value = this[key];
      if (value && value == Hash.prototype[key]) continue;

      var pair = [key, value];
      pair.key = key;
      pair.value = value;
      iterator(pair);
    }
  },

  keys: function() {
    return this.pluck('key');
  },

  values: function() {
    return this.pluck('value');
  },

  merge: function(hash) {
    return $H(hash).inject(this, function(mergedHash, pair) {
      mergedHash[pair.key] = pair.value;
      return mergedHash;
    });
  },

  remove: function() {
    var result;
    for(var i = 0, length = arguments.length; i < length; i++) {
      var value = this[arguments[i]];
      if (value !== undefined){
        if (result === undefined) result = value;
        else {
          if (result.constructor != Array) result = [result];
          result.push(value)
        }
      }
      delete this[arguments[i]];
    }
    return result;
  },

  toQueryString: function() {
    return Hash.toQueryString(this);
  },

  inspect: function() {
    return '#<Hash:{' + this.map(function(pair) {
      return pair.map(Object.inspect).join(': ');
    }).join(', ') + '}>';
  }
});

function $H(object) {
  if (object && object.constructor == Hash) return object;
  return new Hash(object);
};
ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
  initialize: function(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  },

  _each: function(iterator) {
    var value = this.start;
    while (this.include(value)) {
      iterator(value);
      value = value.succ();
    }
  },

  include: function(value) {
    if (value < this.start)
      return false;
    if (this.exclusive)
      return value < this.end;
    return value <= this.end;
  }
});

var $R = function(start, end, exclusive) {
  return new ObjectRange(start, end, exclusive);
}

var Ajax = {
  getTransport: function() {
    return Try.these(
      function() {return new XMLHttpRequest()},
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
    ) || false;
  },

  activeRequestCount: 0
}

Ajax.Responders = {
  responders: [],

  _each: function(iterator) {
    this.responders._each(iterator);
  },

  register: function(responder) {
    if (!this.include(responder))
      this.responders.push(responder);
  },

  unregister: function(responder) {
    this.responders = this.responders.without(responder);
  },

  dispatch: function(callback, request, transport, json) {
    this.each(function(responder) {
      if (typeof responder[callback] == 'function') {
        try {
          responder[callback].apply(responder, [request, transport, json]);
        } catch (e) {}
      }
    });
  }
};

Object.extend(Ajax.Responders, Enumerable);

Ajax.Responders.register({
  onCreate: function() {
    Ajax.activeRequestCount++;
  },
  onComplete: function() {
    Ajax.activeRequestCount--;
  }
});

Ajax.Base = function() {};
Ajax.Base.prototype = {
  setOptions: function(options) {
    this.options = {
      method:       'post',
      asynchronous: true,
      contentType:  'application/x-www-form-urlencoded',
      encoding:     'UTF-8',
      parameters:   ''
    }
    Object.extend(this.options, options || {});

    this.options.method = this.options.method.toLowerCase();
    if (typeof this.options.parameters == 'string')
      this.options.parameters = this.options.parameters.toQueryParams();
  }
}

Ajax.Request = Class.create();
Ajax.Request.Events =
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];

Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
  _complete: false,

  initialize: function(url, options) {
    this.transport = Ajax.getTransport();
    this.setOptions(options);
    this.request(url);
  },

  request: function(url) {
    this.url = url;
    this.method = this.options.method;
    var params = this.options.parameters;

    if (!['get', 'post'].include(this.method)) {
      // simulate other verbs over post
      params['_method'] = this.method;
      this.method = 'post';
    }

    params = Hash.toQueryString(params);
    if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='

    // when GET, append parameters to URL
    if (this.method == 'get' && params)
      this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params;

    try {
      Ajax.Responders.dispatch('onCreate', this, this.transport);

      this.transport.open(this.method.toUpperCase(), this.url,
        this.options.asynchronous);

      if (this.options.asynchronous)
        setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);

      this.transport.onreadystatechange = this.onStateChange.bind(this);
      this.setRequestHeaders();

      var body = this.method == 'post' ? (this.options.postBody || params) : null;

      this.transport.send(body);

      /* Force Firefox to handle ready state 4 for synchronous requests */
      if (!this.options.asynchronous && this.transport.overrideMimeType)
        this.onStateChange();

    }
    catch (e) {
      this.dispatchException(e);
    }
  },

  onStateChange: function() {
    var readyState = this.transport.readyState;
    if (readyState > 1 && !((readyState == 4) && this._complete))
      this.respondToReadyState(this.transport.readyState);
  },

  setRequestHeaders: function() {
    var headers = {
      'X-Requested-With': 'XMLHttpRequest',
      'X-Prototype-Version': Prototype.Version,
      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
    };

    if (this.method == 'post') {
      headers['Content-type'] = this.options.contentType +
        (this.options.encoding ? '; charset=' + this.options.encoding : '');

      /* Force "Connection: close" for older Mozilla browsers to work
       * around a bug where XMLHttpRequest sends an incorrect
       * Content-length header. See Mozilla Bugzilla #246651.
       */
      if (this.transport.overrideMimeType &&
          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
            headers['Connection'] = 'close';
    }

    // user-defined headers
    if (typeof this.options.requestHeaders == 'object') {
      var extras = this.options.requestHeaders;

      if (typeof extras.push == 'function')
        for (var i = 0, length = extras.length; i < length; i += 2)
          headers[extras[i]] = extras[i+1];
      else
        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
    }

    for (var name in headers)
      this.transport.setRequestHeader(name, headers[name]);
  },

  success: function() {
    return !this.transport.status
        || (this.transport.status >= 200 && this.transport.status < 300);
  },

  respondToReadyState: function(readyState) {
    var state = Ajax.Request.Events[readyState];
    var transport = this.transport, json = this.evalJSON();

    if (state == 'Complete') {
      try {
        this._complete = true;
        (this.options['on' + this.transport.status]
         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
         || Prototype.emptyFunction)(transport, json);
      } catch (e) {
        this.dispatchException(e);
      }

      if ((this.getHeader('Content-type') || 'text/javascript').strip().
        match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
          this.evalResponse();
    }

    try {
      (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
      Ajax.Responders.dispatch('on' + state, this, transport, json);
    } catch (e) {
      this.dispatchException(e);
    }

    if (state == 'Complete') {
      // avoid memory leak in MSIE: clean up
      this.transport.onreadystatechange = Prototype.emptyFunction;
    }
  },

  getHeader: function(name) {
    try {
      return this.transport.getResponseHeader(name);
    } catch (e) { return null }
  },

  evalJSON: function() {
    try {
      var json = this.getHeader('X-JSON');
      return json ? eval('(' + json + ')') : null;
    } catch (e) { return null }
  },

  evalResponse: function() {
    try {
      return eval(this.transport.responseText);
    } catch (e) {
      this.dispatchException(e);
    }
  },

  dispatchException: function(exception) {
    (this.options.onException || Prototype.emptyFunction)(this, exception);
    Ajax.Responders.dispatch('onException', this, exception);
  }
});

Ajax.Updater = Class.create();

Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
  initialize: function(container, url, options) {
    this.container = {
      success: (container.success || container),
      failure: (container.failure || (container.success ? null : container))
    }

    this.transport = Ajax.getTransport();
    this.setOptions(options);

    var onComplete = this.options.onComplete || Prototype.emptyFunction;
    this.options.onComplete = (function(transport, param) {
      this.updateContent();
      onComplete(transport, param);
    }).bind(this);

    this.request(url);
  },

  updateContent: function() {
    var receiver = this.container[this.success() ? 'success' : 'failure'];
    var response = this.transport.responseText;

    if (!this.options.evalScripts) response = response.stripScripts();

    if (receiver = $(receiver)) {
      if (this.options.insertion)
        new this.options.insertion(receiver, response);
      else
        receiver.update(response);
    }

    if (this.success()) {
      if (this.onComplete)
        setTimeout(this.onComplete.bind(this), 10);
    }
  }
});

Ajax.PeriodicalUpdater = Class.create();
Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
  initialize: function(container, url, options) {
    this.setOptions(options);
    this.onComplete = this.options.onComplete;

    this.frequency = (this.options.frequency || 2);
    this.decay = (this.options.decay || 1);

    this.updater = {};
    this.container = container;
    this.url = url;

    this.start();
  },

  start: function() {
    this.options.onComplete = this.updateComplete.bind(this);
    this.onTimerEvent();
  },

  stop: function() {
    this.updater.options.onComplete = undefined;
    clearTimeout(this.timer);
    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
  },

  updateComplete: function(request) {
    if (this.options.decay) {
      this.decay = (request.responseText == this.lastText ?
        this.decay * this.options.decay : 1);

      this.lastText = request.responseText;
    }
    this.timer = setTimeout(this.onTimerEvent.bind(this),
      this.decay * this.frequency * 1000);
  },

  onTimerEvent: function() {
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
  }
});
function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (typeof element == 'string')
    element = document.getElementById(element);
  return Element.extend(element);
}

if (Prototype.BrowserFeatures.XPath) {
  document._getElementsByXPath = function(expression, parentElement) {
    var results = [];
    var query = document.evaluate(expression, $(parentElement) || document,
      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (var i = 0, length = query.snapshotLength; i < length; i++)
      results.push(query.snapshotItem(i));
    return results;
  };
}

document.getElementsByClassName = function(className, parentElement) {
  if (Prototype.BrowserFeatures.XPath) {
    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
    return document._getElementsByXPath(q, parentElement);
  } else {
    var children = ($(parentElement) || document.body).getElementsByTagName('*');
    var elements = [], child;
    for (var i = 0, length = children.length; i < length; i++) {
      child = children[i];
      if (Element.hasClassName(child, className))
        elements.push(Element.extend(child));
    }
    return elements;
  }
};

/*--------------------------------------------------------------------------*/

if (!window.Element)
  var Element = new Object();

Element.extend = function(element) {
  if (!element || _nativeExtensions || element.nodeType == 3) return element;

  if (!element._extended && element.tagName && element != window) {
    var methods = Object.clone(Element.Methods), cache = Element.extend.cache;

    if (element.tagName == 'FORM')
      Object.extend(methods, Form.Methods);
    if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
      Object.extend(methods, Form.Element.Methods);

    Object.extend(methods, Element.Methods.Simulated);

    for (var property in methods) {
      var value = methods[property];
      if (typeof value == 'function' && !(property in element))
        element[property] = cache.findOrStore(value);
    }
  }

  element._extended = true;
  return element;
};

Element.extend.cache = {
  findOrStore: function(value) {
    return this[value] = this[value] || function() {
      return value.apply(null, [this].concat($A(arguments)));
    }
  }
};

Element.Methods = {
  visible: function(element) {
    return $(element).style.display != 'none';
  },

  toggle: function(element) {
    element = $(element);
    Element[Element.visible(element) ? 'hide' : 'show'](element);
    return element;
  },

  hide: function(element) {
    $(element).style.display = 'none';
    return element;
  },

  show: function(element) {
    $(element).style.display = '';
    return element;
  },

  remove: function(element) {
    element = $(element);
    element.parentNode.removeChild(element);
    return element;
  },

  update: function(element, html) {
    html = typeof html == 'undefined' ? '' : html.toString();
    $(element).innerHTML = html.stripScripts();
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  },

  replace: function(element, html) {
    element = $(element);
    html = typeof html == 'undefined' ? '' : html.toString();
    if (element.outerHTML) {
      element.outerHTML = html.stripScripts();
    } else {
      var range = element.ownerDocument.createRange();
      range.selectNodeContents(element);
      element.parentNode.replaceChild(
        range.createContextualFragment(html.stripScripts()), element);
    }
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  },

  inspect: function(element) {
    element = $(element);
    var result = '<' + element.tagName.toLowerCase();
    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
      var property = pair.first(), attribute = pair.last();
      var value = (element[property] || '').toString();
      if (value) result += ' ' + attribute + '=' + value.inspect(true);
    });
    return result + '>';
  },

  recursivelyCollect: function(element, property) {
    element = $(element);
    var elements = [];
    while (element = element[property])
      if (element.nodeType == 1)
        elements.push(Element.extend(element));
    return elements;
  },

  ancestors: function(element) {
    return $(element).recursivelyCollect('parentNode');
  },

  descendants: function(element) {
    return $A($(element).getElementsByTagName('*'));
  },

  immediateDescendants: function(element) {
    if (!(element = $(element).firstChild)) return [];
    while (element && element.nodeType != 1) element = element.nextSibling;
    if (element) return [element].concat($(element).nextSiblings());
    return [];
  },

  previousSiblings: function(element) {
    return $(element).recursivelyCollect('previousSibling');
  },

  nextSiblings: function(element) {
    return $(element).recursivelyCollect('nextSibling');
  },

  siblings: function(element) {
    element = $(element);
    return element.previousSiblings().reverse().concat(element.nextSiblings());
  },

  match: function(element, selector) {
    if (typeof selector == 'string')
      selector = new Selector(selector);
    return selector.match($(element));
  },

  up: function(element, expression, index) {
    return Selector.findElement($(element).ancestors(), expression, index);
  },

  down: function(element, expression, index) {
    return Selector.findElement($(element).descendants(), expression, index);
  },

  previous: function(element, expression, index) {
    return Selector.findElement($(element).previousSiblings(), expression, index);
  },

  next: function(element, expression, index) {
    return Selector.findElement($(element).nextSiblings(), expression, index);
  },

  getElementsBySelector: function() {
    var args = $A(arguments), element = $(args.shift());
    return Selector.findChildElements(element, args);
  },

  getElementsByClassName: function(element, className) {
    return document.getElementsByClassName(className, element);
  },

  readAttribute: function(element, name) {
    element = $(element);
    if (document.all && !window.opera) {
      var t = Element._attributeTranslations;
      if (t.values[name]) return t.values[name](element, name);
      if (t.names[name])  name = t.names[name];
      var attribute = element.attributes[name];
      if(attribute) return attribute.nodeValue;
    }
    return element.getAttribute(name);
  },

  getHeight: function(element) {
    return $(element).getDimensions().height;
  },

  getWidth: function(element) {
    return $(element).getDimensions().width;
  },

  classNames: function(element) {
    return new Element.ClassNames(element);
  },

  hasClassName: function(element, className) {
    if (!(element = $(element))) return;
    var elementClassName = element.className;
    if (elementClassName.length == 0) return false;
    if (elementClassName == className ||
        elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
      return true;
    return false;
  },

  addClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element).add(className);
    return element;
  },

  removeClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element).remove(className);
    return element;
  },

  toggleClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
    return element;
  },

  observe: function() {
    Event.observe.apply(Event, arguments);
    return $A(arguments).first();
  },

  stopObserving: function() {
    Event.stopObserving.apply(Event, arguments);
    return $A(arguments).first();
  },

  // removes whitespace-only text node children
  cleanWhitespace: function(element) {
    element = $(element);
    var node = element.firstChild;
    while (node) {
      var nextNode = node.nextSibling;
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
        element.removeChild(node);
      node = nextNode;
    }
    return element;
  },

  empty: function(element) {
    return $(element).innerHTML.match(/^\s*$/);
  },

  descendantOf: function(element, ancestor) {
    element = $(element), ancestor = $(ancestor);
    while (element = element.parentNode)
      if (element == ancestor) return true;
    return false;
  },

  scrollTo: function(element) {
    element = $(element);
    var pos = Position.cumulativeOffset(element);
    window.scrollTo(pos[0], pos[1]);
    return element;
  },

  getStyle: function(element, style) {
    element = $(element);
    if (['float','cssFloat'].include(style))
      style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat');
    style = style.camelize();
    var value = element.style[style];
    if (!value) {
      if (document.defaultView && document.defaultView.getComputedStyle) {
        var css = document.defaultView.getComputedStyle(element, null);
        value = css ? css[style] : null;
      } else if (element.currentStyle) {
        value = element.currentStyle[style];
      }
    }

    if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none'))
      value = element['offset'+style.capitalize()] + 'px';

    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
      if (Element.getStyle(element, 'position') == 'static') value = 'auto';
    if(style == 'opacity') {
      if(value) return parseFloat(value);
      if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
        if(value[1]) return parseFloat(value[1]) / 100;
      return 1.0;
    }
    return value == 'auto' ? null : value;
  },

  setStyle: function(element, style) {
    element = $(element);
    for (var name in style) {
      var value = style[name];
      if(name == 'opacity') {
        if (value == 1) {
          value = (/Gecko/.test(navigator.userAgent) &&
            !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0;
          if(/MSIE/.test(navigator.userAgent) && !window.opera)
            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
        } else if(value == '') {
          if(/MSIE/.test(navigator.userAgent) && !window.opera)
            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
        } else {
          if(value < 0.00001) value = 0;
          if(/MSIE/.test(navigator.userAgent) && !window.opera)
            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
              'alpha(opacity='+value*100+')';
        }
      } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat';
      element.style[name.camelize()] = value;
    }
    return element;
  },

  getDimensions: function(element) {
    element = $(element);
    var display = $(element).getStyle('display');
    if (display != 'none' && display != null) // Safari bug
      return {width: element.offsetWidth, height: element.offsetHeight};

    // All *Width and *Height properties give 0 on elements with display none,
    // so enable the element temporarily
    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    var originalDisplay = els.display;
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = 'block';
    var originalWidth = element.clientWidth;
    var originalHeight = element.clientHeight;
    els.display = originalDisplay;
    els.position = originalPosition;
    els.visibility = originalVisibility;
    return {width: originalWidth, height: originalHeight};
  },

  makePositioned: function(element) {
    element = $(element);
    var pos = Element.getStyle(element, 'position');
    if (pos == 'static' || !pos) {
      element._madePositioned = true;
      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;
      }
    }
    return element;
  },

  undoPositioned: function(element) {
    element = $(element);
    if (element._madePositioned) {
      element._madePositioned = undefined;
      element.style.position =
        element.style.top =
        element.style.left =
        element.style.bottom =
        element.style.right = '';
    }
    return element;
  },

  makeClipping: function(element) {
    element = $(element);
    if (element._overflow) return element;
    element._overflow = element.style.overflow || 'auto';
    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
      element.style.overflow = 'hidden';
    return element;
  },

  undoClipping: function(element) {
    element = $(element);
    if (!element._overflow) return element;
    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
    element._overflow = null;
    return element;
  }
};

Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf});

Element._attributeTranslations = {};

Element._attributeTranslations.names = {
  colspan:   "colSpan",
  rowspan:   "rowSpan",
  valign:    "vAlign",
  datetime:  "dateTime",
  accesskey: "accessKey",
  tabindex:  "tabIndex",
  enctype:   "encType",
  maxlength: "maxLength",
  readonly:  "readOnly",
  longdesc:  "longDesc"
};

Element._attributeTranslations.values = {
  _getAttr: function(element, attribute) {
    return element.getAttribute(attribute, 2);
  },

  _flag: function(element, attribute) {
    return $(element).hasAttribute(attribute) ? attribute : null;
  },

  style: function(element) {
    return element.style.cssText.toLowerCase();
  },

  title: function(element) {
    var node = element.getAttributeNode('title');
    return node.specified ? node.nodeValue : null;
  }
};

Object.extend(Element._attributeTranslations.values, {
  href: Element._attributeTranslations.values._getAttr,
  src:  Element._attributeTranslations.values._getAttr,
  disabled: Element._attributeTranslations.values._flag,
  checked:  Element._attributeTranslations.values._flag,
  readonly: Element._attributeTranslations.values._flag,
  multiple: Element._attributeTranslations.values._flag
});

Element.Methods.Simulated = {
  hasAttribute: function(element, attribute) {
    var t = Element._attributeTranslations;
    attribute = t.names[attribute] || attribute;
    return $(element).getAttributeNode(attribute).specified;
  }
};

// IE is missing .innerHTML support for TABLE-related elements
if (document.all && !window.opera){
  Element.Methods.update = function(element, html) {
    element = $(element);
    html = typeof html == 'undefined' ? '' : html.toString();
    var tagName = element.tagName.toUpperCase();
    if (['THEAD','TBODY','TR','TD'].include(tagName)) {
      var div = document.createElement('div');
      switch (tagName) {
        case 'THEAD':
        case 'TBODY':
          div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>';
          depth = 2;
          break;
        case 'TR':
          div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>';
          depth = 3;
          break;
        case 'TD':
          div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>';
          depth = 4;
      }
      $A(element.childNodes).each(function(node){
        element.removeChild(node)
      });
      depth.times(function(){ div = div.firstChild });

      $A(div.childNodes).each(
        function(node){ element.appendChild(node) });
    } else {
      element.innerHTML = html.stripScripts();
    }
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  }
};

Object.extend(Element, Element.Methods);

var _nativeExtensions = false;

if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
  ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
    var className = 'HTML' + tag + 'Element';
    if(window[className]) return;
    var klass = window[className] = {};
    klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
  });

Element.addMethods = function(methods) {
  Object.extend(Element.Methods, methods || {});

  function copy(methods, destination, onlyIfAbsent) {
    onlyIfAbsent = onlyIfAbsent || false;
    var cache = Element.extend.cache;
    for (var property in methods) {
      var value = methods[property];
      if (!onlyIfAbsent || !(property in destination))
        destination[property] = cache.findOrStore(value);
    }
  }

  if (typeof HTMLElement != 'undefined') {
    copy(Element.Methods, HTMLElement.prototype);
    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
    copy(Form.Methods, HTMLFormElement.prototype);
    [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
      copy(Form.Element.Methods, klass.prototype);
    });
    _nativeExtensions = true;
  }
}

var Toggle = new Object();
Toggle.display = Element.toggle;

/*--------------------------------------------------------------------------*/

Abstract.Insertion = function(adjacency) {
  this.adjacency = adjacency;
}

Abstract.Insertion.prototype = {
  initialize: function(element, content) {
    this.element = $(element);
    this.content = content.stripScripts();

    if (this.adjacency && this.element.insertAdjacentHTML) {
      try {
        this.element.insertAdjacentHTML(this.adjacency, this.content);
      } catch (e) {
        var tagName = this.element.tagName.toUpperCase();
        if (['TBODY', 'TR'].include(tagName)) {
          this.insertContent(this.contentFromAnonymousTable());
        } else {
          throw e;
        }
      }
    } else {
      this.range = this.element.ownerDocument.createRange();
      if (this.initializeRange) this.initializeRange();
      this.insertContent([this.range.createContextualFragment(this.content)]);
    }

    setTimeout(function() {content.evalScripts()}, 10);
  },

  contentFromAnonymousTable: function() {
    var div = document.createElement('div');
    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
    return $A(div.childNodes[0].childNodes[0].childNodes);
  }
}

var Insertion = new Object();

Insertion.Before = Class.create();
Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
  initializeRange: function() {
    this.range.setStartBefore(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.parentNode.insertBefore(fragment, this.element);
    }).bind(this));
  }
});

Insertion.Top = Class.create();
Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(true);
  },

  insertContent: function(fragments) {
    fragments.reverse(false).each((function(fragment) {
      this.element.insertBefore(fragment, this.element.firstChild);
    }).bind(this));
  }
});

Insertion.Bottom = Class.create();
Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.appendChild(fragment);
    }).bind(this));
  }
});

Insertion.After = Class.create();
Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
  initializeRange: function() {
    this.range.setStartAfter(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.parentNode.insertBefore(fragment,
        this.element.nextSibling);
    }).bind(this));
  }
});

/*--------------------------------------------------------------------------*/

Element.ClassNames = Class.create();
Element.ClassNames.prototype = {
  initialize: function(element) {
    this.element = $(element);
  },

  _each: function(iterator) {
    this.element.className.split(/\s+/).select(function(name) {
      return name.length > 0;
    })._each(iterator);
  },

  set: function(className) {
    this.element.className = className;
  },

  add: function(classNameToAdd) {
    if (this.include(classNameToAdd)) return;
    this.set($A(this).concat(classNameToAdd).join(' '));
  },

  remove: function(classNameToRemove) {
    if (!this.include(classNameToRemove)) return;
    this.set($A(this).without(classNameToRemove).join(' '));
  },

  toString: function() {
    return $A(this).join(' ');
  }
};

Object.extend(Element.ClassNames.prototype, Enumerable);
var Selector = Class.create();
Selector.prototype = {
  initialize: function(expression) {
    this.params = {classNames: []};
    this.expression = expression.toString().strip();
    this.parseExpression();
    this.compileMatcher();
  },

  parseExpression: function() {
    function abort(message) { throw 'Parse error in selector: ' + message; }

    if (this.expression == '')  abort('empty expression');

    var params = this.params, expr = this.expression, match, modifier, clause, rest;
    while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
      params.attributes = params.attributes || [];
      params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
      expr = match[1];
    }

    if (expr == '*') return this.params.wildcard = true;

    while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
      modifier = match[1], clause = match[2], rest = match[3];
      switch (modifier) {
        case '#':       params.id = clause; break;
        case '.':       params.classNames.push(clause); break;
        case '':
        case undefined: params.tagName = clause.toUpperCase(); break;
        default:        abort(expr.inspect());
      }
      expr = rest;
    }

    if (expr.length > 0) abort(expr.inspect());
  },

  buildMatchExpression: function() {
    var params = this.params, conditions = [], clause;

    if (params.wildcard)
      conditions.push('true');
    if (clause = params.id)
      conditions.push('element.readAttribute("id") == ' + clause.inspect());
    if (clause = params.tagName)
      conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
    if ((clause = params.classNames).length > 0)
      for (var i = 0, length = clause.length; i < length; i++)
        conditions.push('element.hasClassName(' + clause[i].inspect() + ')');
    if (clause = params.attributes) {
      clause.each(function(attribute) {
        var value = 'element.readAttribute(' + attribute.name.inspect() + ')';
        var splitValueBy = function(delimiter) {
          return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
        }

        switch (attribute.operator) {
          case '=':       conditions.push(value + ' == ' + attribute.value.inspect()); break;
          case '~=':      conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
          case '|=':      conditions.push(
                            splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
                          ); break;
          case '!=':      conditions.push(value + ' != ' + attribute.value.inspect()); break;
          case '':
          case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break;
          default:        throw 'Unknown operator ' + attribute.operator + ' in selector';
        }
      });
    }

    return conditions.join(' && ');
  },

  compileMatcher: function() {
    this.match = new Function('element', 'if (!element.tagName) return false; \
      element = $(element); \
      return ' + this.buildMatchExpression());
  },

  findElements: function(scope) {
    var element;

    if (element = $(this.params.id))
      if (this.match(element))
        if (!scope || Element.childOf(element, scope))
          return [element];

    scope = (scope || document).getElementsByTagName(this.params.tagName || '*');

    var results = [];
    for (var i = 0, length = scope.length; i < length; i++)
      if (this.match(element = scope[i]))
        results.push(Element.extend(element));

    return results;
  },

  toString: function() {
    return this.expression;
  }
}

Object.extend(Selector, {
  matchElements: function(elements, expression) {
    var selector = new Selector(expression);
    return elements.select(selector.match.bind(selector)).map(Element.extend);
  },

  findElement: function(elements, expression, index) {
    if (typeof expression == 'number') index = expression, expression = false;
    return Selector.matchElements(elements, expression || '*')[index || 0];
  },

  findChildElements: function(element, expressions) {
    return expressions.map(function(expression) {
      return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) {
        var selector = new Selector(expr);
        return results.inject([], function(elements, result) {
          return elements.concat(selector.findElements(result || element));
        });
      });
    }).flatten();
  }
});

function $$() {
  return Selector.findChildElements(document, $A(arguments));
}
var Form = {
  reset: function(form) {
    $(form).reset();
    return form;
  },

  serializeElements: function(elements, getHash) {
    var data = elements.inject({}, function(result, element) {
      if (!element.disabled && element.name) {
        var key = element.name, value = $(element).getValue();
        if (value != undefined) {
          if (result[key]) {
            if (result[key].constructor != Array) result[key] = [result[key]];
            result[key].push(value);
          }
          else result[key] = value;
        }
      }
      return result;
    });

    return getHash ? data : Hash.toQueryString(data);
  }
};

Form.Methods = {
  serialize: function(form, getHash) {
    return Form.serializeElements(Form.getElements(form), getHash);
  },

  getElements: function(form) {
    return $A($(form).getElementsByTagName('*')).inject([],
      function(elements, child) {
        if (Form.Element.Serializers[child.tagName.toLowerCase()])
          elements.push(Element.extend(child));
        return elements;
      }
    );
  },

  getInputs: function(form, typeName, name) {
    form = $(form);
    var inputs = form.getElementsByTagName('input');

    if (!typeName && !name) return $A(inputs).map(Element.extend);

    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
      var input = inputs[i];
      if ((typeName && input.type != typeName) || (name && input.name != name))
        continue;
      matchingInputs.push(Element.extend(input));
    }

    return matchingInputs;
  },

  disable: function(form) {
    form = $(form);
    form.getElements().each(function(element) {
      element.blur();
      element.disabled = 'true';
    });
    return form;
  },

  enable: function(form) {
    form = $(form);
    form.getElements().each(function(element) {
      element.disabled = '';
    });
    return form;
  },

  findFirstElement: function(form) {
    return $(form).getElements().find(function(element) {
      return element.type != 'hidden' && !element.disabled &&
        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
    });
  },

  focusFirstElement: function(form) {
    form = $(form);
    form.findFirstElement().activate();
    return form;
  }
}

Object.extend(Form, Form.Methods);

/*--------------------------------------------------------------------------*/

Form.Element = {
  focus: function(element) {
    $(element).focus();
    return element;
  },

  select: function(element) {
    $(element).select();
    return element;
  }
}

Form.Element.Methods = {
  serialize: function(element) {
    element = $(element);
    if (!element.disabled && element.name) {
      var value = element.getValue();
      if (value != undefined) {
        var pair = {};
        pair[element.name] = value;
        return Hash.toQueryString(pair);
      }
    }
    return '';
  },

  getValue: function(element) {
    element = $(element);
    var method = element.tagName.toLowerCase();
    return Form.Element.Serializers[method](element);
  },

  clear: function(element) {
    $(element).value = '';
    return element;
  },

  present: function(element) {
    return $(element).value != '';
  },

  activate: function(element) {
    element = $(element);
    element.focus();
    if (element.select && ( element.tagName.toLowerCase() != 'input' ||
      !['button', 'reset', 'submit'].include(element.type) ) )
      element.select();
    return element;
  },

  disable: function(element) {
    element = $(element);
    element.disabled = true;
    return element;
  },

  enable: function(element) {
    element = $(element);
    element.blur();
    element.disabled = false;
    return element;
  }
}

Object.extend(Form.Element, Form.Element.Methods);
var Field = Form.Element;
var $F = Form.Element.getValue;

/*--------------------------------------------------------------------------*/

Form.Element.Serializers = {
  input: function(element) {
    switch (element.type.toLowerCase()) {
      case 'checkbox':
      case 'radio':
        return Form.Element.Serializers.inputSelector(element);
      default:
        return Form.Element.Serializers.textarea(element);
    }
  },

  inputSelector: function(element) {
    return element.checked ? element.value : null;
  },

  textarea: function(element) {
    return element.value;
  },

  select: function(element) {
    return this[element.type == 'select-one' ?
      'selectOne' : 'selectMany'](element);
  },

  selectOne: function(element) {
    var index = element.selectedIndex;
    return index >= 0 ? this.optionValue(element.options[index]) : null;
  },

  selectMany: function(element) {
    var values, length = element.length;
    if (!length) return null;

    for (var i = 0, values = []; i < length; i++) {
      var opt = element.options[i];
      if (opt.selected) values.push(this.optionValue(opt));
    }
    return values;
  },

  optionValue: function(opt) {
    // extend element because hasAttribute may not be native
    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
  }
}

/*--------------------------------------------------------------------------*/

Abstract.TimedObserver = function() {}
Abstract.TimedObserver.prototype = {
  initialize: function(element, frequency, callback) {
    this.frequency = frequency;
    this.element   = $(element);
    this.callback  = callback;

    this.lastValue = this.getValue();
    this.registerCallback();
  },

  registerCallback: function() {
    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  onTimerEvent: function() {
    var value = this.getValue();
    var changed = ('string' == typeof this.lastValue && 'string' == typeof value
      ? this.lastValue != value : String(this.lastValue) != String(value));
    if (changed) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  }
}

Form.Element.Observer = Class.create();
Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.Observer = Class.create();
Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  getValue: function() {
    return Form.serialize(this.element);
  }
});

/*--------------------------------------------------------------------------*/

Abstract.EventObserver = function() {}
Abstract.EventObserver.prototype = {
  initialize: function(element, callback) {
    this.element  = $(element);
    this.callback = callback;

    this.lastValue = this.getValue();
    if (this.element.tagName.toLowerCase() == 'form')
      this.registerFormCallbacks();
    else
      this.registerCallback(this.element);
  },

  onElementEvent: function() {
    var value = this.getValue();
    if (this.lastValue != value) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  },

  registerFormCallbacks: function() {
    Form.getElements(this.element).each(this.registerCallback.bind(this));
  },

  registerCallback: function(element) {
    if (element.type) {
      switch (element.type.toLowerCase()) {
        case 'checkbox':
        case 'radio':
          Event.observe(element, 'click', this.onElementEvent.bind(this));
          break;
        default:
          Event.observe(element, 'change', this.onElementEvent.bind(this));
          break;
      }
    }
  }
}

Form.Element.EventObserver = Class.create();
Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.EventObserver = Class.create();
Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  getValue: function() {
    return Form.serialize(this.element);
  }
});
if (!window.Event) {
  var Event = new Object();
}

Object.extend(Event, {
  KEY_BACKSPACE: 8,
  KEY_TAB:       9,
  KEY_RETURN:   13,
  KEY_ESC:      27,
  KEY_LEFT:     37,
  KEY_UP:       38,
  KEY_RIGHT:    39,
  KEY_DOWN:     40,
  KEY_DELETE:   46,
  KEY_HOME:     36,
  KEY_END:      35,
  KEY_PAGEUP:   33,
  KEY_PAGEDOWN: 34,

  element: function(event) {
    return event.target || event.srcElement;
  },

  isLeftClick: function(event) {
    return (((event.which) && (event.which == 1)) ||
            ((event.button) && (event.button == 1)));
  },

  pointerX: function(event) {
    return event.pageX || (event.clientX +
      (document.documentElement.scrollLeft || document.body.scrollLeft));
  },

  pointerY: function(event) {
    return event.pageY || (event.clientY +
      (document.documentElement.scrollTop || document.body.scrollTop));
  },

  stop: function(event) {
    if (event.preventDefault) {
      event.preventDefault();
      event.stopPropagation();
    } else {
      event.returnValue = false;
      event.cancelBubble = true;
    }
  },

  // find the first node with the given tagName, starting from the
  // node the event was triggered on; traverses the DOM upwards
  findElement: function(event, tagName) {
    var element = Event.element(event);
    while (element.parentNode && (!element.tagName ||
        (element.tagName.toUpperCase() != tagName.toUpperCase())))
      element = element.parentNode;
    return element;
  },

  observers: false,

  _observeAndCache: function(element, name, observer, useCapture) {
    if (!this.observers) this.observers = [];
    if (element.addEventListener) {
      this.observers.push([element, name, observer, useCapture]);
      element.addEventListener(name, observer, useCapture);
    } else if (element.attachEvent) {
      this.observers.push([element, name, observer, useCapture]);
      element.attachEvent('on' + name, observer);
    }
  },

  unloadCache: function() {
    if (!Event.observers) return;
    for (var i = 0, length = Event.observers.length; i < length; i++) {
      Event.stopObserving.apply(this, Event.observers[i]);
      Event.observers[i][0] = null;
    }
    Event.observers = false;
  },

  observe: function(element, name, observer, useCapture) {
    element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.attachEvent))
      name = 'keydown';

    Event._observeAndCache(element, name, observer, useCapture);
  },

  stopObserving: function(element, name, observer, useCapture) {
    element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.detachEvent))
      name = 'keydown';

    if (element.removeEventListener) {
      element.removeEventListener(name, observer, useCapture);
    } else if (element.detachEvent) {
      try {
        element.detachEvent('on' + name, observer);
      } catch (e) {}
    }
  }
});

/* prevent memory leaks in IE */
if (navigator.appVersion.match(/\bMSIE\b/))
  Event.observe(window, 'unload', Event.unloadCache, false);
var Position = {
  // set to true if needed, warning: firefox performance problems
  // NOT neeeded for page scrolling, only if draggable contained in
  // scrollable elements
  includeScrollOffsets: false,

  // must be called before calling withinIncludingScrolloffset, every time the
  // page is scrolled
  prepare: function() {
    this.deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
    this.deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
  },

  realOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.scrollTop  || 0;
      valueL += element.scrollLeft || 0;
      element = element.parentNode;
    } while (element);
    return [valueL, valueT];
  },

  cumulativeOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    } while (element);
    return [valueL, valueT];
  },

  positionedOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
      if (element) {
        if(element.tagName=='BODY') break;
        var p = Element.getStyle(element, 'position');
        if (p == 'relative' || p == 'absolute') break;
      }
    } while (element);
    return [valueL, valueT];
  },

  offsetParent: function(element) {
    if (element.offsetParent) return element.offsetParent;
    if (element == document.body) return element;

    while ((element = element.parentNode) && element != document.body)
      if (Element.getStyle(element, 'position') != 'static')
        return element;

    return document.body;
  },

  // caches x/y coordinate pair to use with overlap
  within: function(element, x, y) {
    if (this.includeScrollOffsets)
      return this.withinIncludingScrolloffsets(element, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = this.cumulativeOffset(element);

    return (y >= this.offset[1] &&
            y <  this.offset[1] + element.offsetHeight &&
            x >= this.offset[0] &&
            x <  this.offset[0] + element.offsetWidth);
  },

  withinIncludingScrolloffsets: function(element, x, y) {
    var offsetcache = this.realOffset(element);

    this.xcomp = x + offsetcache[0] - this.deltaX;
    this.ycomp = y + offsetcache[1] - this.deltaY;
    this.offset = this.cumulativeOffset(element);

    return (this.ycomp >= this.offset[1] &&
            this.ycomp <  this.offset[1] + element.offsetHeight &&
            this.xcomp >= this.offset[0] &&
            this.xcomp <  this.offset[0] + element.offsetWidth);
  },

  // within must be called directly before
  overlap: function(mode, element) {
    if (!mode) return 0;
    if (mode == 'vertical')
      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
        element.offsetHeight;
    if (mode == 'horizontal')
      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
        element.offsetWidth;
  },

  page: function(forElement) {
    var valueT = 0, valueL = 0;

    var element = forElement;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;

      // Safari fix
      if (element.offsetParent==document.body)
        if (Element.getStyle(element,'position')=='absolute') break;

    } while (element = element.offsetParent);

    element = forElement;
    do {
      if (!window.opera || element.tagName=='BODY') {
        valueT -= element.scrollTop  || 0;
        valueL -= element.scrollLeft || 0;
      }
    } while (element = element.parentNode);

    return [valueL, valueT];
  },

  clone: function(source, target) {
    var options = Object.extend({
      setLeft:    true,
      setTop:     true,
      setWidth:   true,
      setHeight:  true,
      offsetTop:  0,
      offsetLeft: 0
    }, arguments[2] || {})

    // find page position of source
    source = $(source);
    var p = Position.page(source);

    // find coordinate system to use
    target = $(target);
    var delta = [0, 0];
    var parent = null;
    // delta [0,0] will do fine with position: fixed elements,
    // position:absolute needs offsetParent deltas
    if (Element.getStyle(target,'position') == 'absolute') {
      parent = Position.offsetParent(target);
      delta = Position.page(parent);
    }

    // correct by body offsets (fixes Safari)
    if (parent == document.body) {
      delta[0] -= document.body.offsetLeft;
      delta[1] -= document.body.offsetTop;
    }

    // set position
    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
  },

  absolutize: function(element) {
    element = $(element);
    if (element.style.position == 'absolute') return;
    Position.prepare();

    var offsets = Position.positionedOffset(element);
    var top     = offsets[1];
    var left    = offsets[0];
    var width   = element.clientWidth;
    var height  = element.clientHeight;

    element._originalLeft   = left - parseFloat(element.style.left  || 0);
    element._originalTop    = top  - parseFloat(element.style.top || 0);
    element._originalWidth  = element.style.width;
    element._originalHeight = element.style.height;

    element.style.position = 'absolute';
    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.width  = width + 'px';
    element.style.height = height + 'px';
  },

  relativize: function(element) {
    element = $(element);
    if (element.style.position == 'relative') return;
    Position.prepare();

    element.style.position = 'relative';
    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.height = element._originalHeight;
    element.style.width  = element._originalWidth;
  }
}

// Safari returns margins on body which is incorrect if the child is absolutely
// positioned.  For performance reasons, redefine Position.cumulativeOffset for
// KHTML/WebKit only.
if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  Position.cumulativeOffset = function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      if (element.offsetParent == document.body)
        if (Element.getStyle(element, 'position') == 'absolute') break;

      element = element.offsetParent;
    } while (element);

    return [valueL, valueT];
  }
}

Element.addMethods();/**
 * @author Ryan Johnson <ryan@livepipe.net>
 * @copyright 2007 LivePipe LLC
 * @package Control.Tabs
 * @license MIT
 * @url http://livepipe.net/projects/control_tabs/
 * @version 2.1.1
 */

if(typeof(Control) == 'undefined')
	var Control = {};
Control.Tabs = Class.create();
Object.extend(Control.Tabs,{
	instances: [],
	findByTabId: function(id){
		return Control.Tabs.instances.find(function(tab){
			return tab.links.find(function(link){
				return link.key == id;
			});
		});
	}
});
Object.extend(Control.Tabs.prototype,{
	initialize: function(tab_list_container,options){
		this.activeContainer = false;
		this.activeLink = false;
		this.containers = $H({});
		this.links = [];
		Control.Tabs.instances.push(this);
		this.options = {
			beforeChange: Prototype.emptyFunction,
			afterChange: Prototype.emptyFunction,
			hover: false,
			linkSelector: 'li a',
			setClassOnContainer: false,
			activeClassName: 'active',
			defaultTab: 'first',
			autoLinkExternal: true,
			targetRegExp: /#(.+)$/,
			showFunction: Element.show,
			hideFunction: Element.hide
		};
		Object.extend(this.options,options || {});
		(typeof(this.options.linkSelector == 'string')
			? $(tab_list_container).getElementsBySelector(this.options.linkSelector)
			: this.options.linkSelector($(tab_list_container))
		).findAll(function(link){
			return (/^#/).exec(link.href.replace(window.location.href.split('#')[0],''));
		}).each(function(link){
			this.addTab(link);
		}.bind(this));
		this.containers.values().each(this.options.hideFunction);
		if(this.options.defaultTab == 'first')
			this.setActiveTab(this.links.first());
		else if(this.options.defaultTab == 'last')
			this.setActiveTab(this.links.last());
		else
			this.setActiveTab(this.options.defaultTab);
		var targets = this.options.targetRegExp.exec(window.location);
		if(targets && targets[1]){
			targets[1].split(',').each(function(target){
				this.links.each(function(target,link){
					if(link.key == target){
						this.setActiveTab(link);
						throw $break;
					}
				}.bind(this,target));
			}.bind(this));
		}
		if(this.options.autoLinkExternal){
			$A(document.getElementsByTagName('a')).each(function(a){
				if(!this.links.include(a)){
					var clean_href = a.href.replace(window.location.href.split('#')[0],'');
					if(clean_href.substring(0,1) == '#'){
						if(this.containers.keys().include(clean_href.substring(1))){
							$(a).observe('click',function(event,clean_href){
								this.setActiveTab(clean_href.substring(1));
							}.bindAsEventListener(this,clean_href));
						}
					}
				}
			}.bind(this));
		}
	},
	addTab: function(link){
		this.links.push(link);
		link.key = link.getAttribute('href').replace(window.location.href.split('#')[0],'').split('/').last().replace(/#/,'');
		this.containers[link.key] = $(link.key);
		link[this.options.hover ? 'onmouseover' : 'onclick'] = function(link){
			if(window.event)
				Event.stop(window.event);
			this.setActiveTab(link);
			return false;
		}.bind(this,link);
	},
	setActiveTab: function(link){
		if(!link)
			return;
		if(typeof(link) == 'string'){
			this.links.each(function(_link){
				if(_link.key == link){
					this.setActiveTab(_link);
					throw $break;
				}
			}.bind(this));
		}else{
			this.notify('beforeChange',this.activeContainer);
			if(this.activeContainer)
				this.options.hideFunction(this.activeContainer);
			this.links.each(function(item){
				(this.options.setClassOnContainer ? $(item.parentNode) : item).removeClassName(this.options.activeClassName);
			}.bind(this));
			(this.options.setClassOnContainer ? $(link.parentNode) : link).addClassName(this.options.activeClassName);
			this.activeContainer = this.containers[link.key];
			this.activeLink = link;
			this.options.showFunction(this.containers[link.key]);
			this.notify('afterChange',this.containers[link.key]);
		}
	},
	next: function(){
		this.links.each(function(link,i){
			if(this.activeLink == link && this.links[i + 1]){
				this.setActiveTab(this.links[i + 1]);
				throw $break;
			}
		}.bind(this));
		return false;
	},
	previous: function(){
		this.links.each(function(link,i){
			if(this.activeLink == link && this.links[i - 1]){
				this.setActiveTab(this.links[i - 1]);
				throw $break;
			}
		}.bind(this));
		return false;
	},
	first: function(){
		this.setActiveTab(this.links.first());
		return false;
	},
	last: function(){
		this.setActiveTab(this.links.last());
		return false;
	},
	notify: function(event_name){
		try{
			if(this.options[event_name])
				return [this.options[event_name].apply(this.options[event_name],$A(arguments).slice(1))];
		}catch(e){
			if(e != $break)
				throw e;
			else
				return false;
		}
	}
});
if(typeof(Object.Event) != 'undefined')
	Object.Event.extend(Control.Tabs);
