// (c) dynarch.com 2003
// Author: Mihai Bazon, http://dynarch.com/mishoo/

if (/MSIE [56].*Windows/.test(navigator.userAgent)) (function() {
	// fucked-up browser (Internet Explorer for Windows)
	var blank = new Image;
	blank.src = 'http://rogergriffiths.co.uk//images/blank.gif';
	var imgs = document.getElementsByTagName("img");
	for (var i = imgs.length; --i >= 0;) {
		var img = imgs[i];
		var src = img.src;
		if (!/\.png$/.test(src))
			continue;
		var s = img.runtimeStyle;
		s.width = img.offsetWidth + "px";
		s.height = img.offsetHeight + "px";
		s.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "',sizingMethod='scale')";
		img.src = blank.src;
	}
})();
/**
 * addEvent & removeEvent -- cross-browser event handling
 * Copyright (C) 2006  Dao Gottwald
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Contact information:
 *   Dao Gottwald  <dao at design-noir.de>
 *   Herltestraße 12
 *   D-01307, Germany
 *
 * @version  1.1.4
 */

/*@cc_on if (window.addEventListener) { @*/
	function addEvent (o, type, fn) {
		o.addEventListener (type, fn, false);
	}
	function removeEvent (o, type, fn) {
		o.removeEventListener (type, fn, false);
	}
/*@cc_on } else if (window.attachEvent) {
	function addEvent (o, type, fn) {
		if (!o._events) o._events = {};
		if (!o._events[type]) {
			o._events[type] = [fn];
			if (!o._events._callback)
				o._events._callback = function (e) { Event._callListeners (e, o) };
			o.attachEvent ('on' + type, o._events._callback);
		} else if (Event._fnIndex (o, type, fn) == -1)
			o._events[type].push (fn);
		else return;
		Event._mem.push ([o, type, fn]);
	}
	function removeEvent (o, type, fn) {
		var i = Event._fnIndex (o, type, fn);
		if (i < 0) return;
		if (o._events[type].calling) {
			delete o._events[type][i];
			if (o._events[type].removeListeners)
				o._events[type].removeListeners.push(i);
			else
				o._events[type].removeListeners = [i];
		} else
			if (o._events[type].length == 1)
				Event._detach (o, type);
			else
				o._events[type].splice (i, 1);
	}
	var Event = {
		AT_TARGET : 2,
		BUBBLING_PHASE : 3,
		stopPropagation : function() { this.cancelBubble = true },
		preventDefault : function() { this.returnValue = false },
		_mem : [],
		_callListeners : function (e, o) {
			e.stopPropagation = Event.stopPropagation;
			e.preventDefault = Event.preventDefault;
			e.currentTarget = o;
			e.target = e.srcElement;
			e.eventPhase = e.currentTarget == e.target ? Event.AT_TARGET : Event.BUBBLING_PHASE
			switch (e.type) {
				case 'click': case 'mousedown': case 'mouseup':
					if (e.button == 1) e.button = 0; // left
					else if (e.button == 4) e.button = 1; // middle
					break;
				case 'mouseover':
					e.relatedTarget = e.fromElement;
					break;
				case 'mouseout':
					e.relatedTarget = e.toElement;
			}
			o._events[e.type].calling = true;
			for (var i=0; i < o._events[e.type].length; i++)
				if (o._events[e.type][i])
					o._events[e.type][i].call(o,e);
			o._events[e.type].calling = null;
			if (!o._events[e.type].removeListeners)
				return;
			if (o._events[e.type].length == o._events[e.type].removeListeners.length) {
				Event._detach (o, e.type);
				return;
			}
			var offset = 0;
			for (var i=0; i < o._events[e.type].removeListeners.length; i++)
				o._events[e.type].splice (o._events[e.type].removeListeners[i] - offset++, 1);
			if (o._events[e.type].length == 0)
				Event._detach (o, e.type);
			else
				o._events[e.type].removeListeners = null;
		},
		_detach : function (o, type) {
			o.detachEvent ('on' + type, o._events._callback);
			delete o._events[type];
		},
		_fnIndex : function (o, type, fn) {
			if (o._events[type])
				for (var i=0; i < o._events[type].length; i++)
					if (o._events[type][i] == fn)
						return i;
			return -1;
		},
		_cleanup : function() {
			for (var i=0; i < Event._mem.length; i++)
				if (Event._mem[i][1] != 'unload' || Event._mem[i][2] == Event._cleanup)
					removeEvent (Event._mem[i][0], Event._mem[i][1], Event._mem[i][2]);
		}
	};
	addEvent (window, 'unload', Event._cleanup);
} @*/
/**
 * JavaScript general functions
 *
 * General JavaScript functions.
 *
 * @author	Philip Withnall <drbob@tecnocode.co.uk>
 * @copyright	Philip Withnall 2006
 * @package	General
 * @subpackage	JavaScript
 * @version	1.9.2
 * @license	http://tecnocode.co.uk/links/sourcecode-license.html
 * @filesource
 */

window.onload=function() { window.loaded=true; };

// Make console.* a no-op for non-supportive browsers
if(!console)
{
	var console={
		debug:function(){},
		info:function(){},
		warn:function(){},
		error:function(){},
		assert:function(){},
		dir:function(){},
		dirxml:function(){},
		trace:function(){},
		group:function(){},
		groupEnd:function(){},
		time:function(){},
		timeEnd:function(){},
		profile:function(){},
		profileEnd:function(){},
		count:function(){}
	};
}

// Fix PNG transparency for IE (http://www.twinhelix.com/css/iepngfix/)
/* TODO! */
/*if (document.all && document.styleSheets && document.styleSheets[0] && document.styleSheets[0].addRule)
	document.styleSheets[0].addRule('*','behavior: url(http://rogergriffiths.co.uk/?page=iepngfix.htc&media=js)');*/

// Sort out the Element object for IE
if(!window.Element)
{
	var Element={
		prototype:{
			hasAttribute:function(attribute_name) {
				return (this.getAttribute(attribute_name)!=null);
			}
		}
	};
}

Element.prototype.properties_populated=true;

Element.add_properties=function(our_element)
{
	if(!our_element) return our_element;
	if(!our_element.properties_populated)
	{
		for(property in Element.prototype)
		{
			our_element[property]=Element.prototype[property];
		}
		our_element.properties_populated=true;
	}
	return our_element;
};

function $(element_id)
{
	var our_element=Element.add_properties(document.getElementById(element_id));
	if(our_element && our_element.parentNode) Element.add_properties(our_element.parentNode);
	return our_element;
}

function ce(element_type)
{
	return Element.add_properties(document.createElement(element_type));
}

//document.createElement=createElement;

/*
 * Add onload hook
 *
 * Add a hook to onload so that it will be called when the page is loaded.
 *
 * @param	object		Function/Code
*/
function add_onload_hook(function_name)
{
	if(window.loaded)
	{
		function_name();
		return;
	}

	if(window.attachEvent) window.attachEvent('onload',function_name);
	else window.addEventListener('load',function_name,false);
}

// Hide the <noscript> element (IE doesn't like CSS-styled ones, for some reason, so we need to remove them).
add_onload_hook(function()
{
	var elements=document.getElementsByTagName('noscript');
	for(var i=0;i<elements.length;i++)
		elements[i].style.display='none';
});

// Go through and change all popup links
add_onload_hook(function()
{
	var links=document.getElementsByClassName('popup_link');
	for(var i=0;i<links.length;i++)
	{
		addEvent(links[i],'click',function(event)
		{
			window.open(event.currentTarget.getAttribute('href'),'popup_link_window','menubar=no,toolbar=no,location=no,directories=no,fullscreen=no,titlebar=yes,hotkeys=yes,status=no,scrollbars=yes,resizable=yes,height=400,width=500');
			event.preventDefault();
		});
	}
});

/*
 * Load JS file
 *
 * Dynamically load a JavaScript file.
 *
 * @param	string		Filename
*/
function load_js_file(url)
{
	for(var i=0;i<load_js_file.loaded.length;i++)
	{
		if(load_js_file.loaded[i]==url) return;
	}

	load_js_file.loaded.push(url);

	var script=document.createElement('script');
	script.setAttribute('type','text/javascript');
	script.setAttribute('src','http://rogergriffiths.co.uk/?media=js&page='+url);
	document.getElementsByTagName('head')[0].appendChild(script);
}

load_js_file.loaded=[];

/*
 * Load CSS file
 *
 * Dynamically load a CSS file.
 *
 * @param	string		Filename
*/
function load_css_file(url)
{
	for(var i=0;i<load_css_file.loaded.length;i++)
	{
		if(load_css_file.loaded[i]==url) return;
	}

	load_css_file.loaded.push(url);

	var link=document.createElement('link');
	link.setAttribute('rel','stylesheet');
	link.setAttribute('type','text/css');
	link.setAttribute('href','http://rogergriffiths.co.uk/?media=css&page='+url);
	document.getElementsByTagName('head')[0].appendChild(link);
}

load_css_file.loaded=[];

// Shamelessly copied from prototype
Function.prototype.bind=function()
{
	var __method=this;
	var args=[];
	for(var i=0;i<arguments.length;i++) args.push(arguments[i]);
	var object=args.shift();

	return function()
	{
		var _arguments=[];
		for(var x=0;x<arguments.length;x++) _arguments.push(arguments[x]);

		return __method.apply(object,args.concat(_arguments));
	};
};

/*
 * Get elements by class name
 *
 * Get all elements under the specified node by class name.
 *
 * @param	string			Class name
 * @return	array|false		Elements or false
*/
document.getElementsByClassName=function(classname)
{
	var a=[];
	var re=new RegExp('(^| )'+classname+'( |$)');
	var els=this.getElementsByTagName('*');

	for(var i=0,j=els.length;i<j;i++)
	{
		if(re.test(els[i].className)) a.push(els[i]);
	}

	return a;
};

Element.prototype.getElementsByClassName=document.getElementsByClassName;

/*
 * Get label by input
 *
 * Get a label for the specified form input.
 *
 * @param	object		Form
 * @param	object		Input
 * @return	string		Label value
*/
function getLabelByFormField(form,form_field)
{
	var labels=form.getElementsByTagName('label');

	for(var i=0;i<labels.length;i++)
	{
		if(labels[i].htmlFor==form_field.getAttribute('id')) return Element.add_properties(labels[i]).getTextContent();
	}

	return '(unknown)';
}

/*
 * Get legend by input
 *
 * Get a legend for the specified form input.
 *
 * @param	object		Form
 * @param	object		Input
 * @return	object|false	Legend or false
*/
function getLegendByFormField(form,form_field)
{
	var legends=form.getElementsByTagName('legend');

	for(var i=0;i<legends.length;i++)
	{
		if(legends[i].parentNode==form_field.parentNode.parentNode) return Element.add_properties(legends[i]);
	}

	return false;
}

/*
 * Get fieldset by input
 *
 * Get a fieldset for the specified form input.
 *
 * @param	object		Form
 * @param	object		Input
 * @param	object|false	Fieldset or false
*/
function getFieldsetByFormField(form,form_field)
{
	while(!form_field.isTag('fieldset'))
	{
		form_field=Element.add_properties(form_field.parentNode);
		if(form_field.isTag('body')) return false;
	}

	return Element.add_properties(form_field);
}

/*
 * Get form by input
 *
 * Get a form for the specified form input.
 *
 * @param	object		Input
 * @param	object|false	Form or false
*/
function getFormByFormField(form_field)
{
	while(form_field.isTag('form'))
	{
		form_field=form_field.parentNode;
		if(form_field.isTag('body')) return false;
	}

	return Element.add_properties(form_field);
}

/*
 * Remove children
 *
 * Remove all the children from the specified element.
 *
 * @param	object		Element
*/
function removeAllChildren(node)
{
	for(var i=0;i<node.childNodes.length;i++) node.removeChild(node.childNodes[i]);
}

/*
 * Leap year?
 *
 * Is the date's year a leap year?
 *
 * @return	boolean		Leap year?
 */
Date.prototype.isLeapYear=function()
{
	var current_year=this.getFullYear();
	return (((Math.round(current_year/4)==current_year/4) && (Math.round(current_year/100)!=current_year/100)) || ((Math.round(current_year/100)==current_year/100) && (Math.round(current_year/400)==current_year/400)));
};

Date.prototype.getMonthLengths=function()
{
	if(this.isLeapYear()) return new Array(31,29,31,30,31,30,31,31,30,31,30,31);
	else return new Array(31,28,31,30,31,30,31,31,30,31,30,31);
};

Date.prototype.getMonthLength=function(month_index)
{
	var month_lengths=this.getMonthLengths();
	return month_lengths[month_index];
};

Date.prototype.getCurrentMonthLength=function()
{
	return this.getMonthLength(this.getMonth());
}

Date.prototype.getDateZero=function()
{
	return this.getDate()-1;
};

Date.prototype.getDayZero=function()
{
	var day=this.getDay()-1;
	if(day<0) day=6;
	return day;
};

Date.prototype.decrementMonth=function()
{
	this.setMonth(-1);
};

Date.prototype.incrementMonth=function()
{
	this.setMonth(this.getMonth()+1);
};

Date.prototype.monthNamesTiny=new Array('J','F','M','A','M','J','J','A','S','O','N','D');
Date.prototype.monthNamesShort=new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
Date.prototype.monthNames=new Array('January','February','March','April','May','June','July','August','September','October','November','December');

Date.prototype.weekDaysTiny=new Array('M','T','W','T','F','S','S');
Date.prototype.weekDaysShort=new Array('Mon','Tue','Wed','Thu','Fri','Sat','Sun');
Date.prototype.weekDays=new Array('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday');

/*
 * Insert into input
 *
 * Insert text into the specified input, replacing what's currently selected, or at the current caret point.
 *
 * @param	object		Input
 * @param	string		Text
 * @return	boolean		Inverse success?
*/
function insert_into_input(form_field,text)
{
	var element=$(form_field);

	if (document.selection)
	{
		var sel=document.selection;
		var our_range=sel.createRange();
		our_range.text=our_range.text+text;
		return false;
	}
	if (element.selectionEnd)
	{
		var from=element.selectionStart;
		var to=element.selectionEnd;

		var start=element.value.substring(0,from);
		var end=element.value.substring(to,element.value.length);

		element.value=start+element.value.substring(from,to)+text+end;
		return false;
	}

	element.value+=text;

	return false;
}

/*
 * Clear form inputs
 *
 * Clear all contents of the form inputs for the specified form.
 *
 * @param	object		Form
*/
function clear_form_inputs(form)
{
	var input_elements=form.getElementsByTagName('input');
	var i;

	for(i in input_elements)
	{
		if((typeof(input_elements[i])=='object') && (!input_elements[i].hasAttribute('readonly')) && (input_elements[i].getAttribute('type')!='submit'))
		{
			input_elements[i].value='';
		}
	}

	var textarea_elements=form.getElementsByTagName('textarea');

	for(i in textarea_elements)
	{
		if((typeof(textarea_elements[i])=='object') && (!textarea_elements[i].hasAttribute('readonly')))
		{
			textarea_elements[i].value='';
		}
	}

	var select_elements=form.getElementsByTagName('select');
	var option_elements;
	var a;

	for(i in select_elements)
	{
		if(typeof(select_elements[i])=='object')
		{
			option_elements=select_elements[i].getElementsByTagName('option');

			for(a in option_elements)
			{
				if((typeof(option_elements[a])=='object') && (option_elements[a].hasAttribute('selected')))
				{
					select_elements[i].setAttribute('selectedIndex',a);
				}
			}
		}
	}
}

/*
 * Assign random ID
 *
 * Assign a random ID to the specified element.
 *
 * @return	integer		Random ID
*/
Element.prototype.assignRandomId=function()
{
	if((this.hasAttribute('id')) && (this.getAttribute('id')!='') && (this.getAttribute('id')!=null)) return this.getAttribute('id');

	var id;

	do
	{
		id=Math.floor(Math.random()*10000+Math.random()*1000+Math.random()*100+Math.random()*10);
	}
	while($(id)!=null);

	this.setAttribute('id',id);

	return id;
};

Element.prototype.getTextContent=function()
{
	if(this.textContent) return this.textContent;
	else if(this.innerText) return this.innerText;
	else return false;
}

/*
 * Has class?
 *
 * Determine if an element has a class.
 *
 * @param	string		Class name
 * @return	boolean		Has class?
*/
Element.prototype.hasClass=function(class_name)
{
	var reg_exp=new RegExp('(^| )'+class_name+'( |$)');
	return reg_exp.test(this.className);
};

/*
 * Add class
 *
 * Add a class to an element.
 *
 * @param	string		Class name
*/
Element.prototype.addClass=function(class_name)
{
	if(this.hasClass(class_name)) return;

	if(this.hasAttribute('class'))
	{
		var current_class=this.className;
		if(current_class.length>0) current_class+=' ';
		this.setAttribute('class',current_class+=class_name);
	}
	else this.setAttribute('class',class_name);
};

/*
 * Remove class
 *
 * Remove a class from an element.
 *
 * @param	string		Class name
*/
Element.prototype.removeClass=function(class_name)
{
	if(this.hasAttribute('class'))
	{
		var reg_exp=new RegExp('(^| )'+class_name+'( |$)');
		this.setAttribute('class',this.className.replace(reg_exp,' '));
	}
};

/*
 * Find previous sibling
 *
 * Find the previous non-text sibling of the element.
 *
 * @return	object		Previous sibling
*/
Element.prototype.findPreviousSibling=function()
{
	var element=this;
	do element=element.previousSibling;
	while((element) && (element.nodeType!=1));
	return element;
};

/*
 * Find next sibling
 *
 * Find the next non-text sibling of the element.
 *
 * @return	object		Next sibling
*/
Element.prototype.findNextSibling=function()
{
	var element=this;
	do element=element.nextSibling;
	while((element) && (element.nodeType!=1));
	return element;
};

/*
 * Tag match?
 *
 * Is this element of the specified (case-insensitive) tag?
 *
 * @param	string		Tag name
 * @return	boolean		Tag match?
*/
Element.prototype.isTag=function(tag_name)
{
	return (this.tagName.toLowerCase()==tag_name.toLowerCase());
};

/*
 * Wait!
 *
 * Wait a specified number of milliseconds.
 *
 * @param	double		Milliseconds
*/
function wait(milliseconds)
{
	var date=new Date();
	var current_date=null;

	do current_date=new Date();
	while(current_date-date<milliseconds);
}

/*
 * IE?
 *
 * Is the client running certified rubbish?
 *
 * @return	boolean		Running IE?
*/
function is_IE()
{
	return (navigator.appName=='Microsoft Internet Explorer'); //SCUM! SCUM! SCUM! SCUM! SCUM! SCUM! SCUM! SCUM! SCUM!
}

/*
 * Trim whitespace
 *
 * Trim whitespace from the left and right of a string.
 *
 * @param	string		String to trim
 * @return	string		Trimmed string
*/
function trim(the_string)
{
	while(the_string.substring(0,1)==' ') the_string=the_string.substring(1,the_string.length);
	while(the_string.substring(the_string.length-1,the_string.length)==' ') the_string=the_string.substring(0,the_string.length-1);

	return the_string;
}

// Functions to get the absolute position of an element
// Taken from http://www.quirksmode.org/js/findpos.html
function find_x_position(obj)
{
	var curleft=0;
	if(obj.offsetParent)
	{
		while(obj.offsetParent)
		{
			curleft+=obj.offsetLeft;
			obj=obj.offsetParent;
		}
	}
	else if(obj.x) curleft+=obj.x;
	return curleft;
}

function find_y_position(obj)
{
	var curtop=0;
	if(obj.offsetParent)
	{
		while(obj.offsetParent)
		{
			curtop+=obj.offsetTop;
			obj=obj.offsetParent;
		}
	}
	else if(obj.y) curtop+=obj.y;
	return curtop;
}

function find_width(obj)
{
	if(obj.offsetWidth) return obj.offsetWidth;
	else if(obj.clientWidth) return obj.clientWidth;
}

// Function to find the CSS width of an object (no padding, margin, or border included)
function find_css_width(obj,original_width)
{
	var width=0;
	var css_width=0;
	var object=obj;
	if(!original_width) original_width=find_width(obj);
	obj.style.width=original_width+'px';
	if(obj.offsetParent)
	{
		while(obj.offsetParent)
		{
			width+=obj.offsetWidth;
			obj=obj.offsetParent;
		}
	}
	else if(obj.clientWidth) width+=obj.clientWidth;
	css_width=original_width-(width-original_width);
	object.style.width=css_width+'px';
	return css_width;
}

function find_height(obj)
{
	if(obj.offsetHeight) return obj.offsetHeight;
	else if(obj.clientHeight) return obj.clientHeight;
}

// Function to find the CSS height of an object (no padding, margin, or border included)
function find_css_height(obj,original_height)
{
	var height=0;
	var css_height=0;
	var object=obj;
	if(!original_height) original_height=find_height(obj);
	obj.style.height=original_height+'px';
	if(obj.offsetParent)
	{
		while(obj.offsetParent)
		{
			height+=obj.offsetHeight;
			obj=obj.offsetParent;
		}
	}
	else if(obj.clientHeight) height+=obj.clientHeight;
	css_height=original_height-(height-original_height);
	object.style.height=css_height+'px';
	return css_height;
}

function get_window_width()
{
	if (typeof(window.innerWidth)=='number') return window.innerWidth;
	else if (document.documentElement && document.documentElement.clientWidth) return document.documentElement.clientWidth;
	else if (document.body && document.body.clientWidth) return document.body.clientWidth;
	return null;
}

function get_window_height()
{
	if (typeof(window.innerHeight)=='number') return window.innerHeight;
	else if (document.documentElement && document.documentElement.clientHeight) return document.documentElement.clientHeight;
	else if (document.body && document.body.clientHeight) return document.body.clientHeight;
	return null;
}

function get_x_scroll()
{
	if (typeof(window.pageXOffset)=='number') return window.pageXOffset;
	else if (document.body && document.body.scrollLeft) return document.body.scrollLeft;
	else if (document.documentElement && document.documentElement.scrollLeft) return document.documentElement.scrollLeft;
	return 0;
}

function get_y_scroll()
{
	if (typeof(window.pageYOffset) == 'number') return window.pageYOffset;
	else if (document.body && document.body.scrollTop) return document.body.scrollTop;
	else if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop;
	return 0;
}

// From http://hartshorne.ca/2006/01/23/javascript_cursor_position/
function get_cursor_position(e)
{
	e=e||window.event;
	var cursor={x:0,y:0};
	if(e.pageX||e.pageY)
	{
		cursor.x=e.pageX;
		cursor.y=e.pageY;
	} 
	else
	{
		var de=document.documentElement;
		var b=document.body;
		cursor.x=e.clientX+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||0);
		cursor.y=e.clientY+(de.scrollTop||b.scrollTop)-(de.clientTop||0);
	}
	return cursor;
}

function scroll_to_object(scroll_element)
{
	window.scroll(get_x_scroll(),find_y_position(scroll_element));
}
/**
 * JavaScript form validation
 *
 * Functions to validate forms before submission.
 *
 * @author	Philip Withnall <drbob@tecnocode.co.uk>
 * @copyright	Philip Withnall 2007
 * @package	General
 * @subpackage	JavaScript
 * @version	2.0.1
 * @license	http://tecnocode.co.uk/links/sourcecode-license.html
 * @filesource
 */

var submitted_forms=new Array();

/*
 * Form submitted?
 *
 * Mark a form as submitted so that it cannot be submitted twice. Return its
 * current submission status.
 *
 * @param	object		Form
 * @return	boolean		Submitted?
*/
function form_submitted(form)
{
	// Has this form already been submitted?
	if(!form.hasClass('multiple_submit'))
	{
		for(var a=0;a<submitted_forms.length;a++)
		{
			if(submitted_forms[a]==form.getAttribute('id'))
			{
				window.alert('You have already successfully submitted this form once.');
				return true;
			}
		}
	}

	// Add the form to the list of successfully submitted forms
	submitted_forms.push(form.getAttribute('id'));

	return false;
}

/*
 * Hide form field
 *
 * Hide a form field from the user, most likely because it's valid.
 *
 * @param	object		Form
 * @param	object		Input
*/
function hide_form_field(form,form_field)
{
	if((form_field.getAttribute('type')=='submit') || (form_field.getAttribute('type')=='button')) return;

	// Remove any messages on the form
	remove_form_message(form_field);

	if(form.hasClass('multiple_submit')) return;

	var fieldset=getFieldsetByFormField(form,form_field);
	if(!fieldset) return;

	fieldset.assignRandomId();

	// Hide it!
	var form_container=form_field;
	while((!form_container.isTag('div')) || (!form_container.hasClass('form_field')))
	{
		form_container=Element.add_properties(form_container.parentNode);
		if(form_container.isTag('body'))
		{
			form_container=form_field;
			break;
		}
	}

	Element.add_properties(form_container).addClass('form_valid');

	// Are we already hidden?
	if($(fieldset.getAttribute('id')+'_toggle_bar')) return;

	// Add the markup to hide a form field (compress it down, and add an "expand" link for the entire fieldset)
	var container_div=ce('div');
	container_div.setAttribute('id',fieldset.getAttribute('id')+'_toggle_bar');

	var links_div=ce('p');
	links_div.className='toggle_valid';
	container_div.appendChild(links_div);

	var links_a=ce('a');
	links_a.setAttribute('href','#');
	links_a.setAttribute('title','Toggle the visibility of the "'+getLegendByFormField(form,form_field).textContent+'" form element to change your (valid) input.');
	addEvent(links_a,'click',function(event) { event.preventDefault(); return toggle_form_fields(fieldset); });
	links_div.appendChild(links_a);

	var links_a_text=document.createTextNode('Show/Hide valid fields');
	links_a.appendChild(links_a_text);

	fieldset.insertBefore(container_div,fieldset.childNodes[0]);
}

/*
 * Add input message
 *
 * Add a message to a certain input for the user to read.
 *
 * @param	object		Input
 * @param	string		Message
 * @return	boolean		Valid? (Always false)
*/
function add_form_message(form_field,message)
{
	// Do we already have a message?
	if(Element.add_properties(form_field.parentNode).hasClass('form_error')) return;

	// Add a big red message to a form field
	if(message!='')
	{
		var message_p=ce('p');
		message_p.className='error';
		var message_p_text=document.createTextNode(message);

		message_p.appendChild(message_p_text);

		form_field.parentNode.insertBefore(message_p,form_field.parentNode.firstChild);
	}

	form_field.parentNode.addClass('form_error');
	form_field.parentNode.removeClass('form_valid');

	// Returns false so that we can say valid=add_form_message(...); and save ourselves a line of code
	return false;
}

/*
 * Remove input messages
 *
 * Remove any and all messages from the specified input.
 *
 * @param	object		Input
*/
function remove_form_message(form_field)
{
	var messages=form_field.parentNode.getElementsByClassName('error');
	for(var a=0;a<messages.length;a++) form_field.parentNode.removeChild(messages[a]);
	form_field.parentNode.removeClass('form_error');
}

/*
 * Toggle input visibility
 *
 * Toggle the visibility of the inputs in the specified fieldset.
 *
 * @param	object		Fieldset
*/
function toggle_form_fields(fieldset)
{
	var fields=fieldset.getElementsByClassName('form_field');
	for(var i=0;i<fields.length;i++)
	{
		if(fields[i].hasClass('form_valid')) fields[i].removeClass('form_valid');
		else if(!fields[i].hasClass('form_error')) fields[i].addClass('form_valid');
	}

	return false;
}
