/*!
	**********
	* MARMOT  *
	**********
	Version 1.1
	Conker Media javascript library, June 2009 to March 2010.
	Created by Algy Taylor
	
	Please verify all code through JSLint (www,jslint.com), conforming to web standards are exceptionally important to ensure compatability with all future browsers.
	(partially fixed at the moment)
	
	IMPORTANT - keep the bibliography up-to-date! Anything you find useful, add it to the list! It may well be useful in the future if you want to edit stuff, plus it's
	good to acknowledge the work done by others to make our own jobs easier!
		
	BIBLIOGRAPHY
	---------------------
	[1]		SWFObject v2.2. Accessed 18th June 2009
			http://code.google.com/p/swfobject/
	[2]		How to Create an Animated, Sliding, Collapsible DIV with Javascript and CSS. Accessed 19th June 2009
			http://www.harrymaugans.com/2007/03/06/how-to-create-an-animated-sliding-collapsible-div-with-javascript-and-css/
	[3]		Namespacing your Javascript. Accessed 22nd June 2009
			http://www.dustindiaz.com/namespace-your-javascript/
	[4]		Dynamically loading an external JavaScript or CSS file. Accessed 29th June 2009
			http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
	[5]		JavaScript Form Validation. Accessed 30th June 2009
			http://www.w3schools.com/jS/js_form_validation.asp
	[6]		Get URL Parameters Using Javascript. Accessed 15th July 2009
			http://www.netlobo.com/url_query_string_javascript.html
	[7]		JavaScript Date.format. Accessed 16th July 2009
			http://jacwright.com/projects/javascript/date_format
	[8]		Using the XML HTTP Request Object. Accessed 21st July 2009
			http://jibbering.com/2002/4/httprequest.html
	[9]		Re: How to make JavaScript wait for data?. Accessed 22nd July 2009
			http://bytes.com/groups/javascript/470205-how-make-javascript-wait-data#post1809553
	[10]	JavaScript by Example: JavaScript Core Objects Pt.2. Accessed 27th July 2009
			http://www.webreference.com/programming/java_core/2/3.html
	[11]	JavaScript Best Practices. Accessed 29th July 2009
			http://dev.opera.com/articles/view/javascript-best-practices/
	[12]	Graceful Degradation versus progressive enhancement. Accessed 30th July 2009
			http://dev.opera.com/articles/view/graceful-degradation-progressive-enhance/
	[13]	DOM Element Methods. Accessed 31st July 2009
			http://www.javascriptkit.com/domref/elementmethods.shtml
*/


/* configuration goes here */
var MarmotConfig = {
	Ajax : {
		/* don't edit */
		xmlhttp:			false
	},
	Date : {
		format:				"l jS F Y"
	},
	Debug : {
		runDebug:			false,
		
		/* don't edit */
		debugString:		""
	},
	DynamicLoad : {
		/* don't edit */
		dynLoadFiles:		""
	},
	FadeIn : {
		animationLength:	300,
		tickPeriod:			5,
		
		/* don't edit these */
		timerID:			[],
		startTime:			[],
		obj:				[],
		inProgress:			true
	},
	GoogleMaps : {
		frameborder:		'0',
		scrolling:			'no',
		marginheight:		'0',
		marginwidth:		'0'
	},
	PopOut : {
		/* variables */
		animationLength:	225,
		tickPeriod:			5,
		
		/* don't edit these */
		timerID:			[],
		startTime:			[],
		obj:				[],
		endHeight:			[],
		endWidth:			[]
	},
	Slide : {
		/* variables */
		slideAniLen:		350,
		timerlen:			5,
		expand:				"more ...",
		hide:				"less ...",
		fullArticle:		"full article ...",
		linkSuffix:			"_link",
		
		/* don't edit these */
		timerID:			[],
		startTime:			[],
		obj:				[],
		endHeight:			[],
		moving:				[],
		dir:				[],
		state:				[],
		openSlideItem:		null
	},
	Validation : {
		/* variables */
		emailPattern:				/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/,
		ukPhoneNumberPattern:		/^(((\+44\s?\d{4}|\(?0\d{4}\)?)\s?\d{3}\s?\d{3})|((\+44\s?\d{3}|\(?0\d{3}\)?)\s?\d{3}\s?\d{4})|((\+44\s?\d{2}|\(?0\d{2}\)?)\s?\d{4}\s?\d{4}))(\s?\#(\d{4}|\d{3}))?$/,
		
		invalidEmailAddressText:	" is an invalid email address",
		requiredFieldText:			" is a required field"
	},
	Video : {
		/* variables */
		defaultWidth:			'201',
		defaultHeight:			'322',
		
		baseImageLocation:		'./img/',
		baseVideoLocation:		'../',
		playerLocation:			'./swf/player.swf',
		requiredFlashVersion:	'9.0.0'
	},
	Window : {
		/* variables */
		newWindowWidth:		'800',
		newWindowHeight:	'600',
		newWindowOtherVars:	'toolbar=1,location=1,status=1,menubar=1,scrollbars=1,resizable=1'
	},
	Woodchuck : {
		Interface:			'http://www.fantasyrecords.co.uk/woodchuck/woodchuck-js.php'
	}
};

/*
	this hasn't been properly namespaced yet! Sort this out. Maybe again because it deals with timers or somethiontg
*/

function endSlide(objname) {
	clearInterval(MarmotConfig.Slide.timerID[objname]);

	if (MarmotConfig.Slide.dir[objname] === "up") {
		MarmotConfig.Slide.obj[objname].style.display = "none";
	}

	MarmotConfig.Slide.obj[objname].style.height = MarmotConfig.Slide.endHeight[objname] + "px";

	delete(MarmotConfig.Slide.moving[objname]);
	delete(MarmotConfig.Slide.timerID[objname]);
	delete(MarmotConfig.Slide.startTime[objname]);
	delete(MarmotConfig.Slide.endHeight[objname]);
	delete(MarmotConfig.Slide.obj[objname]);
	delete(MarmotConfig.Slide.dir[objname]);

	return;
}

function slidetick(objname) {
	var elapsed = (new Date()).getTime() - MarmotConfig.Slide.startTime[objname];

	if (elapsed > MarmotConfig.Slide.slideAniLen) {
		endSlide(objname);
	} else {
		var d = Math.round(elapsed / MarmotConfig.Slide.slideAniLen * MarmotConfig.Slide.endHeight[objname]);
		if (MarmotConfig.Slide.dir[objname] === "up") {
			d = MarmotConfig.Slide.endHeight[objname] - d;
		}

		MarmotConfig.Slide.obj[objname].style.height = d + "px";
	}

	return;
}

/*
	PopOut functions which need (at the moment) to live outside of Marmot
*/

function clearPopOut (elementID) {
	/* stop animating */
	clearInterval (MarmotConfig.PopOut.timerID[elementID]);
	
	/* set the height & width to the final values */
	MarmotConfig.PopOut.obj[elementID].style.height = MarmotConfig.PopOut.endHeight[elementID] + "px";
	MarmotConfig.PopOut.obj[elementID].style.width = MarmotConfig.PopOut.endWidth[elementID] + "px";
	MarmotConfig.PopOut.obj[elementID].style.marginLeft = - MarmotConfig.PopOut.endWidth[elementID] - 25 + "px";
	
	/* delete any data relating to the animation */
	delete (MarmotConfig.PopOut.timerID[elementID]);
	delete (MarmotConfig.PopOut.startTime[elementID]);
	delete (MarmotConfig.PopOut.obj[elementID]);
	delete (MarmotConfig.PopOut.endHeight[elementID]);
	delete (MarmotConfig.PopOut.endWidth[elementID]);
	
	return;
}

function popOutTick (elementID) {
	/* find out how long it's been since the popout started */
	var elapsed = (new Date()).getTime() - MarmotConfig.PopOut.startTime[elementID];
	
	/* if the animation length has passed, end the animation - otherwise work out what the width & height should be */
	if (elapsed > MarmotConfig.PopOut.animationLength) {
		clearPopOut (elementID);
	} else {
		var d_height = Math.round(elapsed / MarmotConfig.PopOut.animationLength * MarmotConfig.PopOut.endHeight[elementID]);
		var d_width = Math.round(elapsed / MarmotConfig.PopOut.animationLength * MarmotConfig.PopOut.endWidth[elementID]);
		MarmotConfig.PopOut.obj[elementID].style.height = MarmotConfig.PopOut.endHeight[elementID] + "px";
		MarmotConfig.PopOut.obj[elementID].style.width = d_width + "px";
		MarmotConfig.PopOut.obj[elementID].style.marginLeft = - 25 - d_width + "px";
	}
	
	return;
}


/* fade in effect */
function clearFadeIn (elementID) {
	/* stop animating */
	clearInterval (MarmotConfig.FadeIn.timerID[elementID]);
	MarmotConfig.FadeIn.inProgress = true;
	
	/* set final opacity */
	document.getElementById(elementID).getElementsByTagName("img")[0].style.opacity = 1.0;
	document.getElementById(elementID).getElementsByTagName("img")[0].style.filter = "alpha(opacity=100)";
	
	/* delete all the related data, as it's no longer required */
	delete (MarmotConfig.FadeIn.timerID[elementID]);
	delete (MarmotConfig.FadeIn.startTime[elementID]);
	delete (MarmotConfig.FadeIn.obj[elementID]);
	
	if (MarmotConfig.Debug.runDebug && MarmotConfig.Debug.debugString !== "") {
		alert(MarmotConfig.Debug.debugString);
	}
	
	return;
}

function fadeInTick (elementID) {
	/* find out how much time there's been since the start of the effect */
	var elapsed = (new Date()).getTime() - MarmotConfig.FadeIn.startTime[elementID];
	
	if (elapsed > MarmotConfig.FadeIn.animationLength) {
		clearFadeIn(elementID);
	} else {
		var d_opacity = elapsed / MarmotConfig.FadeIn.animationLength;
		if (MarmotConfig.Debug.runDebug) {
			MarmotConfig.Debug.debugString = MarmotConfig.Debug.debugString + "_" + d_opacity;
		}
		MarmotConfig.FadeIn.obj[elementID].getElementsByTagName("img")[0].style.filter = "alpha(opacity=" + (100 * d_opacity) + ")";
		MarmotConfig.FadeIn.obj[elementID].getElementsByTagName("img")[0].style.opacity = d_opacity;
	}
	
	return;
}

var Marmot = (function () {
	/* this little function opens up a new xmlhttprequest in every browser known to man */
	function allowXMLRequest() {
		/*@cc_on @*/
		/*@if (@_jscript_version >= 5)
		// JScript gives us Conditional compilation, we can cope with old IE versions.
		// and security blocked creation of the objects.
		try {
			MarmotConfig.Ajax.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				MarmotConfig.Ajax.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (E) {
				MarmotConfig.Ajax.xmlhttp = false;
			}
		}
		@end @*/
		
		if (!MarmotConfig.Ajax.xmlhttp && typeof XMLHttpRequest !== 'undefined') {
			try {
				MarmotConfig.Ajax.xmlhttp = new XMLHttpRequest();
			} catch (ex1) {
				MarmotConfig.Ajax.xmlhttp = false;
			}
		}
		if (!MarmotConfig.Ajax.xmlhttp && window.createRequest) {
			try {
				MarmotConfig.Ajax.xmlhttp = window.createRequest();
			} catch (ex2) {
				MarmotConfig.Ajax.xmlhttp = false;
			}
		}
	}
	
	
	/* this is a simple method which just checks in realtime to make sure that no elements are moving
		I'm not convinced that it works at the moment, but hopefully it will do at some point! */
	function noMovement() {
		for (var i = 0, j = MarmotConfig.Slide.moving.length; i < j; i = i + 1) {
			if (MarmotConfig.Slide.moving[i]) {
				return false;
			}
		}
		return true;
	}
	
	/* something to do with slideup/slidedown. See the relevant reference in the bibliography */
	function startslide(objname) {
		MarmotConfig.Slide.obj[objname] = document.getElementById(objname);

		MarmotConfig.Slide.endHeight[objname] = parseInt(MarmotConfig.Slide.obj[objname].style.height, 10);
		MarmotConfig.Slide.startTime[objname] = (new Date()).getTime();

		if (MarmotConfig.Slide.dir[objname] === "down") {
			MarmotConfig.Slide.obj[objname].style.height = "1px";
		}

		MarmotConfig.Slide.obj[objname].style.display = "block";

		MarmotConfig.Slide.timerID[objname] = setInterval('slidetick(\'' + objname + '\');', MarmotConfig.Slide.timerlen);
	}
	
	/* function to make things slide down, as the name suggests. See bibliography link. */
	function slidedown(objname, fullArticle) {
		if (MarmotConfig.Slide.moving[objname]) {
			return;
		}

		if (document.getElementById(objname).style.display !== "none") {
			return; /* cannot slide down something that is already visible */
		}

		MarmotConfig.Slide.moving[objname] = true;
		MarmotConfig.Slide.dir[objname] = "down";
		startslide(objname);
		MarmotConfig.Slide.state[objname] = "down";
		
		document.getElementById(objname + MarmotConfig.Slide.linkSuffix).innerHTML = MarmotConfig.Slide.hide;
	}
	
	/* slide back up again. See bibliography link */
	function slideup(objname) {
		if (MarmotConfig.Slide.moving[objname]) {
			return;
		}

		if (document.getElementById(objname).style.display === "none") {
			return; /* cannot slide up something that is already hidden */
		}

		MarmotConfig.Slide.moving[objname] = true;
		MarmotConfig.Slide.dir[objname] = "up";
		startslide(objname);
		MarmotConfig.Slide.state[objname] = "up";
		document.getElementById(objname + MarmotConfig.Slide.linkSuffix).innerHTML = MarmotConfig.Slide.expand;
	}
	
	/* popout slide */
	function startPopOut (elementID) {
		/* initialise variables */
		MarmotConfig.PopOut.obj[elementID] = document.getElementById(elementID);
		MarmotConfig.PopOut.endHeight[elementID] = parseInt(MarmotConfig.PopOut.obj[elementID].style.height, 10);
		MarmotConfig.PopOut.endWidth[elementID] = parseInt(MarmotConfig.PopOut.obj[elementID].style.width, 10);
		MarmotConfig.PopOut.startTime[elementID] = (new Date()).getTime();
		MarmotConfig.PopOut.obj[elementID].style.height = "1px";
		MarmotConfig.PopOut.obj[elementID].style.width = "1px";
		
		/* add some styling so that if JS isn't turned on, it doesn't try to do any fancy effects. */
		MarmotConfig.PopOut.obj[elementID].style.marginTop = "50px";
		MarmotConfig.PopOut.obj[elementID].style.marginLeft = "-25px";
		MarmotConfig.PopOut.obj[elementID].getElementsByTagName("img")[0].style.visibility = "hidden";
		MarmotConfig.PopOut.obj[elementID].style.background = "url(" + MarmotConfig.PopOut.obj[elementID].getElementsByTagName("img")[0].src + ") no-repeat";
		
		MarmotConfig.PopOut.timerID[elementID] = setInterval('popOutTick(\'' + elementID + '\');', MarmotConfig.PopOut.tickPeriod);
		return;
	}
	
	function startFadeIn (elementID) {
		MarmotConfig.FadeIn.obj[elementID] = document.getElementById(elementID);
		MarmotConfig.FadeIn.obj[elementID].getElementsByTagName("img")[0].style.opacity = 0;
		/* this should sort out the initial opacity (0) for IE ... however, for some reason the stylesheet rule stays in place. Not a clue why. */
		/*MarmotConfig.FadeIn.obj[elementID].getElementsByTagName("img")[0].style.filter = "alpha(opacity=0)";*/
		
		if (MarmotConfig.FadeIn.inProgress) {
			/* initialise variables */	
			MarmotConfig.FadeIn.obj[elementID] = document.getElementById(elementID);
			MarmotConfig.FadeIn.startTime[elementID] = (new Date()).getTime();
			MarmotConfig.FadeIn.inProgress = false;
						
			MarmotConfig.FadeIn.timerID[elementID] = setInterval('fadeInTick(\'' + elementID + '\');', MarmotConfig.FadeIn.tickPeriod);
		}
		
		return;
	}
	
	/* dynamically load a file. See bibliography link */
	function dynLoad(filename, filetype) {
		var fileref;
		
		if (filetype === "js") {
			fileref = document.createElement('script');
			fileref.setAttribute("type", "text/javascript");
			fileref.setAttribute("src", filename);
		} else if (filetype === "css") {
			fileref = document.createElement('link');
			fileref.setAttribute("rel", "stylesheet");
			fileref.setAttribute("type", "text/css");
			fileref.setAttribute("href", filename);
		}
		
		if (typeof fileref !== "undefined") {
			document.getElementsByTagName("head")[0].appendChild(fileref);
		}
	}
	
	/* dynamically remove a file. See bibliography link */
	function dynRemove(filename, filetype) {
		
		var targetElement = (filetype === "js") ? "script" :
							(filetype === "css") ? "link" :
							"none",
			targetAttribute = (filetype === "js") ? "src" :
							  (filetype === "css") ? "href" :
							  "none",
			theSuspects = document.getElementsByTagName(targetElement);
		
		for (var i = theSuspects.length; i >= 0; i = i - 1) { /* search backwards */
			if (theSuspects[i] && theSuspects[i].getAttribute(targetAttribute) !== null && theSuspects[i].getAttribute(targetAttribute).indexOf(filename) !== -1) {
				theSuspects[i].parentNode.removeChild(theSuspects[i]);
			}
		}
	}
	
	/* recurssive fn to go through the list of files then remove the first one of a specific filetype. Only works if the extension is right! */
	function dynRemoveLast(listOfFiles, filetype) {
		/* check to make sure there actually is a list of files! */
		if (listOfFiles === null || listOfFiles === "") {
			return false;
		} else {
			/* now that we know that there are *some* files in the list ... */
			var lastFileStartPosition = listOfFiles.lastIndexOf("[");
			if (lastFileStartPosition !== -1) {
				var lastFile = listOfFiles.substring(lastFileStartPosition),
					extensionPosition,
					extension;
				/* remove any opening/closing brackets */
				lastFile = lastFile.replace("[", "");
				lastFile = lastFile.replace("]", "");
				
				/* test to see if the extension is right */
				extensionPosition = lastFile.lastIndexOf(".") + 1;
				extension = lastFile.substring(extensionPosition);
				
				
				if (extension === filetype) {
					/* ... then we have our file */
					Marmot.dynamicRemove(lastFile, filetype);
					return true;
				} else {
					/* ignore this file, send the amended list back to the fn */
					var newFileList = listOfFiles.replace("[" + lastFile + "]", "");
					return dynRemoveLast(newFileList, filetype);
				}
			}
		}
	}
	
	/*
		marmot form validation
	*/
	
	/* this is a simple bool call to test if it's a valid email address. So you can say if (invalidEmailAddress) { tell the person to stop being stupid } */
	function invalidEmailAddress(address) {
		return !Marmot.Validation.emailPattern.test(address);
	}
	
	/* checks if a field is empty ... not rocket science, it just makes the code more readable to us humans */
	function fieldIsEmpty(object) {
		return (object.value === null || object.value === '');
	}
		
	/*
		public api
		
		these are the bits of Marmot which can be called from outside the class (eg Marmot.checkForm()
	*/
	return {
		/* checks a form. You put in an array of fields that have to have values and an array which need to be email addresses, it sorts it all out. Handy :) */
		checkForm : function (notNullFields, emailFields) {
			/* check through the notnull fields to make sure they're not null */
			for (var i = 0, j = notNullFields.length; i < j; i = i + 1) {
				if (fieldIsEmpty(document.getElementById(notNullFields[i]))) {
					alert(notNullFields[i] + MarmotConfig.Validation.requiredFieldText);
				}
			}
			
			/* validate any email addresses */
			for (i = 0, j = emailFields.length; i < j; i = i + 1) {
				if (invalidEmailAddress(document.getElementById(emailFields[i]).value)) {
					alert(emailFields[i] + MarmotConfig.Validation.invalidEmailAddressText);
				}
			}
			
			return;
		},
		/* this is a handy little function which stops email address links being picked up automatically, antispam measure */
		compileEmailAddress : function (emailAddressData) {
			document.getElementById(emailAddressData.compileToLocation).innerHTML = "<a href='mailto:" + emailAddressData.localPart + "@" + emailAddressData.domain + "'>" + emailAddressData.localPart + "@" + emailAddressData.domain + "</a>";
			return;
		},
		Date : (function() {
			return {
				/* prints the current date inside any given html element */
				printDate : function (elementID) {
					var now = new Date();
					document.getElementById(elementID).innerHTML = now.format(MarmotConfig.Date.format);
					return;
				}
			};
		}()),
		File : (function() {
			return {
				dynamicLoad : function (filename, filetype) {
					/* this adds the dynamically loaded file to a list then runs dynLoad to actually do the work */
					if(MarmotConfig.DynamicLoad.dynLoadFiles.indexOf("[" + filename + "]") === -1) {
						dynLoad(filename, filetype);
						MarmotConfig.DynamicLoad.dynLoadFiles += "[" + filename + "]";
					}
					return;
				},
				/* dynamically removes a JS or CSS file then takes it off the list of dynamically loaded files */
				dynamicRemove : function (filename, filetype) {
					if(MarmotConfig.DynamicLoad.dynLoadFiles.indexOf("[" + filename + "]") !== -1) {
						dynRemove(filename, filetype);
						var dynLoadFilesParts = MarmotConfig.DynamicLoad.dynLoadFiles.split("[" + filename + "]");
						MarmotConfig.DynamicLoad.dynLoadFiles = dynLoadFilesParts[0] + dynLoadFilesParts[1];
					}
					return;
				},
				/* remove the last added dynamic file */
				dynamicRemoveLast : function (filetype) {
					dynRemoveLast(MarmotConfig.DynamicLoad.dynLoadFiles, filetype);
					return;
				},
				/* performs the same function as include(...) does in php */
				importFile : function (location, target) {
					if (!MarmotConfig.Ajax.xmlhttp) {
						allowXMLRequest();
					}
					
					if (MarmotConfig.Ajax.xmlhttp) {
						MarmotConfig.Ajax.xmlhttp.open("GET", location, false);
						MarmotConfig.Ajax.xmlhttp.send(null);
						document.getElementById(target).innerHTML = MarmotConfig.Ajax.xmlhttp.responseText;			
					}
					return;
				}
			};
		}()),
		/* dynamically load a JS or CSS file */
		FX : (function () {
			return {
				setFadeIn : function (elementID) {
					document.getElementById(elementID).parentNode.onmouseover = function () {
						startFadeIn(elementID);
					};
					
					document.getElementById(elementID).parentNode.onmouseout = function () {
						clearFadeIn(elementID);
					};
					
					return;
				},
				setMultipleFadeIns : function (fadeins) {
					for (var i = 0, j = fadeins.length; i < j; i = i + 1) {
						this.setFadeIn(fadeins[i]);
					}
					
					return;
				},
				setMultiplePopOuts : function (popouts) {
					for (var i = 0, j = popouts.length; i < j; i = i + 1) {
						this.setPopOut(popouts[i]);
					}
					return;
				},
				setPopOut : function (elementID) {
					document.getElementById(elementID).parentNode.onmouseover = function() {
						startPopOut(elementID);
					};
					document.getElementById(elementID).parentNode.onmouseout = function () {
						clearPopOut(elementID);
					};
					
					return;
				},
				/* allows you to change the slide speed if you want */
				setSlideTimer : function (length) {
					MarmotConfig.Slide.slideAniLen = length;
					return;
				},
				/* the slide function!!!!! Nice fancy gfx */
				slide : function (objname, linkHref) {
					if (noMovement()) {
						if (MarmotConfig.Slide.state[objname] === "down") {
							slideup(objname);
							MarmotConfig.Slide.openSlideItem = null;
						} else {
							if (objname !== MarmotConfig.Slide.openSlideItem && MarmotConfig.Slide.openSlideItem !== null) {
								slideup(MarmotConfig.Slide.openSlideItem);
							}
							slidedown(objname);
							MarmotConfig.Slide.openSlideItem = objname;
						}
					}
					return;
				}
			};
		}()),
		Stats : (function() {
			return {
				woodchuck : function (appName, data) {
					if (!MarmotConfig.Ajax.xmlhttp) {
						allowXMLRequest();
					}
					
					if (MarmotConfig.Ajax.xmlhttp) {
						MarmotConfig.Ajax.xmlhttp.open("POST", MarmotConfig.Woodchuck.Interface, false);
						MarmotConfig.Ajax.xmlhttp.send(appName, data);
					}
					return;
				}
			};
		}()),
		Tabs : (function() {
			return {
				/* used to switch between tabs in a menu. needs to be more graphical */
				tabSwitch : function (tabDiv, tabToShow) {
					/* get all of the DIV subelements of the navigation */
					var elements = document.getElementById(tabDiv).getElementsByTagName('div');
					
					/* scroll through the various navigation elements, make them hidden ... */
					for (var i = 0, j = elements.length; i < j; i = i + 1) {
						elements[i].style.display = 'none';
					}
					
					/* ... then unhide the one that's been selected */
					
					document.getElementById(tabToShow).style.display = 'block';
					return;
				}
			};
		}()),
		/* performs the same function as $_GET[''] does in php */
		get : function (name) {
			name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
			var regexS = "[\\?&]" + name + "=([^&#]*)",
				regex = new RegExp(regexS),
				results = regex.exec(window.location.href);
				
			if (results === null) {
				return "";
			} else {
				return results[1];
			}
		},
		loadGoogleMap : function (mapData) {
			document.getElementById(mapData.elementID).innerHTML = "<iframe width='" + mapData.width + "' height='" + mapData.height + "' frameborder='" + MarmotConfig.GoogleMaps.frameborder + "' scrolling='" + MarmotConfig.GoogleMaps.scrolling + "' marginheight='" + MarmotConfig.GoogleMaps.marginheight + "' marginwidth='" + MarmotConfig.GoogleMaps.marginwidth + "' src='" + mapData.src + "'></iframe>";
			return;
		},
		/* loads a video using swfobject */
		loadVideo : function (video) {
			var flashvars = {},
				params = {},
				attributes = {};
			
			flashvars.file = MarmotConfig.Video.baseVideoLocation + video.folder + "/" + video.filename;
			flashvars.image = MarmotConfig.Video.baseImageLocation + video.folder + "/" + video.image;
			
			if	(video.width === null || video.width === '' || video.height === null || video.height === '') {
				video.width = MarmotConfig.Video.defaultWidth;
				video.height = MarmotConfig.Video.defaultHeight;
			}
			
			swfobject.embedSWF(MarmotConfig.Video.playerLocation, video.elementID, video.width, video.height, MarmotConfig.Video.requiredFlashVersion, false, flashvars, params, attributes);
			return;
		},
		/* open a new window, just allows you to shorthand stuff a bit */
		openWindow : function (location) {
			/* put in something to allow optional width & height specs */
			window.open(location, "newWindow", 'width=' + MarmotConfig.Window.newWindowWidth + ',height=' + MarmotConfig.Window.newWindowHeight + "," + MarmotConfig.Window.newWindowOtherVars);
			//alert("test");
			return;
		},
		openWindowWithJavaScript : function (elementID) {
			var element = document.getElementById(elementID);
			if (element !== null && element !== '') {
				var targetLocation = element.getAttributeNode("href").value;
				
				element.removeAttribute("target");
				element.setAttribute("onclick", "Marmot.openWindow('" + targetLocation + "');");
				element.setAttribute("href", "javascript:Marmot.openWindow('" + targetLocation + "');");
				return true;
			} else {
				return false;
			}
		},
		openMultipleWindowsWithJavaScript : function (elementIDs) {
			for (var i = 0, j = elementIDs.length; i < j; i = i + 1) {
				Marmot.openWindowWithJavaScript(elementIDs[i]);
			}
			
			return;
		}
	}
}());

/*
	SWFObject
	
	opensource loveliness, see bibliography link
*/
var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();

/*
	Simulates PHP's date function
	for detailed documentation see the relevant bibliography link
*/
Date.prototype.format = function(format) {
	var returnStr = '',
		replace = Date.replaceChars;
		
	for (var i = 0, j = format.length; i < j; i = i + 1) {
		var curChar = format.charAt(i);
		if (replace[curChar]) {
			returnStr += replace[curChar].call(this);
		} else {
			returnStr += curChar;
		}
	}
	return returnStr;
};
Date.replaceChars = {
	shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
	longMonths: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
	shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
	longDays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
	
	/* Day */
	d: function() { return (this.getDate() < 10 ? '0' : '') + this.getDate(); },
	D: function() { return Date.replaceChars.shortDays[this.getDay()]; },
	j: function() { return this.getDate(); },
	l: function() { return Date.replaceChars.longDays[this.getDay()]; },
	N: function() { return this.getDay() + 1; },
	S: function() { return (this.getDate() % 10 == 1 && this.getDate() != 11 ? 'st' : (this.getDate() % 10 == 2 && this.getDate() != 12 ? 'nd' : (this.getDate() % 10 == 3 && this.getDate() != 13 ? 'rd' : 'th'))); },
	w: function() { return this.getDay(); },
	z: function() { return "Not Yet Supported"; },
	/* Week */
	W: function() { return "Not Yet Supported"; },
	/* Month */
	F: function() { return Date.replaceChars.longMonths[this.getMonth()]; },
	m: function() { return (this.getMonth() < 11 ? '0' : '') + (this.getMonth() + 1); },
	M: function() { return Date.replaceChars.shortMonths[this.getMonth()]; },
	n: function() { return this.getMonth() + 1; },
	t: function() { return "Not Yet Supported"; },
	/* Year */
	L: function() { return "Not Yet Supported"; },
	o: function() { return "Not Supported"; },
	Y: function() { return this.getFullYear(); },
	y: function() { return ('' + this.getFullYear()).substr(2); },
	/* Time */
	a: function() { return this.getHours() < 12 ? 'am' : 'pm'; },
	A: function() { return this.getHours() < 12 ? 'AM' : 'PM'; },
	B: function() { return "Not Yet Supported"; },
	g: function() { return this.getHours() % 12 || 12; },
	G: function() { return this.getHours(); },
	h: function() { return ((this.getHours() % 12 || 12) < 10 ? '0' : '') + (this.getHours() % 12 || 12); },
	H: function() { return (this.getHours() < 10 ? '0' : '') + this.getHours(); },
	i: function() { return (this.getMinutes() < 10 ? '0' : '') + this.getMinutes(); },
	s: function() { return (this.getSeconds() < 10 ? '0' : '') + this.getSeconds(); },
	/* Timezone */
	e: function() { return "Not Yet Supported"; },
	I: function() { return "Not Supported"; },
	O: function() { return (this.getTimezoneOffset() < 0 ? '-' : '+') + (this.getTimezoneOffset() / 60 < 10 ? '0' : '') + (this.getTimezoneOffset() / 60) + '00'; },
	T: function() { return "Not Yet Supported"; },
	Z: function() { return this.getTimezoneOffset() * 60; },
	/* Full Date/Time */
	c: function() { return "Not Yet Supported"; },
	r: function() { return this.toString(); },
	U: function() { return this.getTime() / 1000; }
};