function insertAfter(parent, node, referenceNode) {
	parent.insertBefore(node, referenceNode.nextSibling);
}

df={
	error:[],
	errorMessage:null,
	errorClass:'error',
	errorClassLarge:'msgError',
	errorTitle:'Please fix the marked issues',
	init:function(){
		var elm;
		df.cancelValidation=false;
		df.sendButton=document.getElementById('send');

		if (!df.sendButton) {
			alert('ERROR: No send button defined, it needs to have the id "send"');
			return;
		}

		df.backButton=document.getElementById('send_back');
		if (df.backButton) {
			DOMhelp.addEvent(df.backButton,'click',df.cancel,false);		
			}
		//df.f=document.getElementsByTagName('form')[1];

		// The validation rules are held in another javascript file, so go an fetch that
		var allForms = document.getElementsByTagName('form');
		for (var i=0; i < allForms.length; i++) {
			// Validated forms have their ID's prefix with validate
			if ((allForms[i].id).substring(0, 8).toLowerCase() == 'validate')
			{
				// Hook ourselves up to the form we jsut found
				df.f=document.getElementById(allForms[i].id);
				
				// Load up the validation rules that we require
				loadValidationRules(allForms[i].id);
				
				// And don't bother looking for any more forms because we only support the one at a time (at the moment)
				break;
			}
		}
		
		DOMhelp.addEvent(df.f,'submit',df.send,false);
		

		for(var i in validationRules){
			elm=document.getElementById(i);
			if(!elm){continue;}
			DOMhelp.addEvent(elm,'blur',df.sendField,false);
		}
	},
	cancel:function(e) {
		df.cancelValidation=true;
	},
	sendField:function(e){
		var t=DOMhelp.getTarget(e);
		if(t.previousSibling && 
		   t.previousSibling.nodeName.toLowerCase()=='span' && 
		   t.previousSibling.className==df.errorClass){
			t.parentNode.removeChild(t.previousSibling);
		}
		
		var elm=document.getElementById('lbl'+t.id);
		if (elm)
			elm.className="";
		
		df.checkValue(t.id);
	},
	send:function(e){
		df.flushErrors();
		if (df.cancelValidation){ return true;}
		for(var i in validationRules){
			if(!document.getElementById(i)){continue;}
			df.checkValue(i);
		}
		if(df.error.length>0){
			df.errorMessage=document.createElement('div');
			df.errorMessage.className=df.errorClassLarge;
			var errorTitle=document.createElement('p');
			errorTitle.appendChild(document.createTextNode(df.errorTitle));
			df.errorMessage.appendChild(errorTitle);
			var sendPara=df.sendButton.parentNode;	
			sendPara.parentNode.insertBefore(df.errorMessage,sendPara);
			DOMhelp.cancelClick(e);		
		}
	},
	flushErrors:function(){
		var elm;
		df.error=[];
		if(df.errorMessage){
			df.errorMessage.parentNode.removeChild(df.errorMessage);
			df.errorMessage=null;
		}			
		for(var i in validationRules){
			elm=document.getElementById(i);
			if(!elm){continue;}
			if(elm.previousSibling && 
			   elm.previousSibling.nodeName.toLowerCase()=='span' && 
			   elm.previousSibling.className==df.errorClass){
				elm.parentNode.removeChild(elm.previousSibling);
			}
			
			elm=document.getElementById('lbl'+i);
			if (elm)
				elm.className="";
			
		}
	},
	checkValue:function(o){
		var elm=document.getElementById(o);
		switch(elm.type){
			case 'password': // Treat password inputs the same as text inputs rrobertson 15/08/2008
			case 'text':
				var bIsError = false;
				
				if (validationRules[o]['dependupon']){
					// This value is dependent upon another field, so check the other field is valid 
					// If the other field isn't valid, then we don't need to do anything else
					var elemDependent = document.getElementById(validationRules[o]['dependupon']);
					if (elemDependent) {
						// TODO: Handle the password checking properly- now done (see above)? rrobertson 15/08/2008
						if (elm.name.toLowerCase().indexOf('confirmpassword') == -1) {
							var bDependentValid = false;
	
							switch (elemDependent.type){
								case 'text':
									// Use the test pattern on the dependent field
									if (!validationRules[o]['pattern'].test(elemDependent.value))
										bDependentValid = true;
									break;
	
								case 'radio':
								case 'checkbox':
									if (elemDependent.checked)
										bDependentValid = true;
									break;
							}
									
							// If the dependent checks out, make sure we test the current control as well
							if (bDependentValid)
							{
								if (!validationRules[o]['pattern'].test(elm.value))
									bIsError = true;
							}
						} else
							if (elemDependent.value != elm.value)
								bIsError = true;
					}

				} else {
					// No depedents, so just a straight check
					if (!validationRules[o]['pattern'].test(elm.value))
						bIsError = true;
				}

				// If any of the above checks meant an error, then let's push that error to DF
				if (bIsError) {
					df.error.push(validationRules[o]['error']);
					df.addErrorMsg(elm,validationRules[o]['error']);
				}

			break;

			case 'textarea':
				if(!validationRules[o]['pattern'].test(elm.value)){
					df.error.push(validationRules[o]['error']);
					df.addErrorMsg(elm,validationRules[o]['error']);
				}
			break;

			case 'radio':
			case 'checkbox':
				// If radio's or checkboxes require validating, they a very liekly to be needing a value, so get the name
				//    of the current radio or checkbox and search for all elements that have the same name and make sure one has a value

				// Store all the values of each radio button in a big long string
				var bOneIsChecked = false;
				var allChkRads = document.getElementsByName(elm.name);
				for (var i=0; i < allChkRads.length; i++) {
					if (allChkRads[i].checked) {
						// This one is ticked, so mark as true and don't bother checking any more (because the test is that at least one is checked)
						bOneIsChecked = true;
						break;
					}
				}
				
				// If one of the check boxes were ticked, then we're all good!
				if (!bOneIsChecked) {
					df.error.push(validationRules[o]['error']);
					df.addErrorMsg(elm,validationRules[o]['error']);
				}
			break;


			case 'select-one':
				var curelm=elm.options[elm.selectedIndex].value;
				if(elm.selectedIndex==5){
					curelm=document.getElementById('otherSubject').value;
				}
				if(!validationRules[o]['pattern'].test(curelm)){
					df.error.push(validationRules[o]['error']);
					df.addErrorMsg(elm,validationRules[o]['error']);
				}
			break;
		}
	},
	addErrorMsg:function(o,msg){
		var curLabel=document.getElementById('lbl'+o.id);
		if (curLabel)
			curLabel.className='error';
			
		var errorMsg=document.createElement('span');
		errorMsg.className=df.errorClass;
		errorMsg.appendChild(document.createTextNode(msg));
		o.parentNode.insertBefore(errorMsg,o);
	}
}

DOMhelp.addEvent(window,'load',df.init,false);


