
function tii_ValidatedForm(node){
	this.node=node;
	this.node.object=this;
	this.registerValidationTypes();
	this.items=new Array();
	this.makeItemsFrom("input");
	this.makeItemsFrom("textarea");
	this.items.sort(validation_itemSorter);
	if(this.node.onsubmit!=null)
		this.node.submitHandler=this.node.onsubmit;
	this.node.onsubmit=function(e){return this.object.validate(e)};
}
tii_ValidatedForm.prototype.registerValidationTypes=function(){
	this.types=new Array();
	this.registerType("text",tii_validateText,null);
	this.registerType("email",tii_validateEmail,"Emails must be in the format 'name@domain.com'");
	this.registerType("agree",tii_validateAgree,"You must agree to the terms of service");
	this.registerType("file",tii_validateFile,"","Please upload a file");
	this.registerType("url",tii_validateURL,"Links should be in the format 'http://www.somwhere.com/page'");	
	this.registerExtraTypes();
}
tii_ValidatedForm.prototype.registerExtraTypes=function(){}
function validation_itemSorter(a,b){
	return a.offset-b.offset;
}
tii_ValidatedForm.prototype.makeItemsFrom=function(tagName){
	var collection=this.node.getElementsByTagName(tagName);
	for(var i=0;i<collection.length;i++){
		var item=new tii_ValidatedItem(collection[i],this);
		if(item.type!=null){
			this.items.push(item);
		}
	}
}
tii_ValidatedForm.prototype.validate=function(e){
	this.valid=true;
	this.invalid=new Array();
	for(var i=0;i<this.items.length;i++){
		if(!this.items[i].validate()){
			this.valid=false;
			this.invalid.push(this.items[i]);
		}
	}
	if(!this.valid){
		this.printErrors();
		return false;
	}else{
		if(this.msg!=null&&this.msg.parentNode!=null)
			this.msg.parentNode.removeChild(this.msg);		
		if(this.node.submitHandler!=null)
			return this.node.submitHandler();
		else
			return true;
	}
}
tii_ValidatedForm.prototype.printErrors=function(){
	this.invalid[0].element.focus();
	if(this.msg==null){
		this.msg=document.createElement("div");
		this.msg.className="message error";
		this.msg.id="error_message";
		var parent=this.invalid[0].node.parentNode;
		parent.parentNode.insertBefore(this.msg,parent);
	}
	var msg="<h3>Form Errors</h3><p>See red field names below</p><ul>";
	for(var i=0;i<this.invalid.length;i++){
		var item=this.invalid[i];
		msg+="<li><label for="+item.element.id+">"+item.name+":</label> "+item.message+"</li>";
	}
	msg+="</ul>";
	this.msg.innerHTML=msg;
}
tii_ValidatedForm.prototype.registerType=function(className,validator,errorMsg){
	var newType=new tii_ValidationType(className,validator,errorMsg);
	this.types[newType.className]=newType;
}
var TII_REQUIRED_MSG="Please fill in this required field";
function tii_ValidationType(className,validator,errorMsg,requiredMsg){
	this.className=className;
	this.validator=validator;
	this.errorMsg=errorMsg;
	this.requiredMsg=requiredMsg;
	if(this.requiredMsg==null)
		this.requiredMsg=TII_REQUIRED_MSG;
}
function tii_ValidatedItem(element,validatedForm){
	this.validatedForm=validatedForm;
	this.max=Number.POSITIVE_INFINITY;
	this.element=element;
	this.element.item=this;
	this.message="";
	this.initialize();
	this.findType();
	this.attachMaxUpdater();
	this.offset=this.node.offsetTop+this.node.offsetLeft;
}
tii_ValidatedItem.prototype.initialize=function(){
	this.node=this.element.parentNode;
	if(this.node.getElementsByTagName("label").length>0){
		this.label=this.node.getElementsByTagName("label")[0];
		this.name=this.label.innerHTML;
	}
	this.required=this.node.className.indexOf("required")>-1;
}
tii_ValidatedItem.prototype.findType=function(){
	for (var typeName in this.validatedForm.types) {
		if(this.node.className.indexOf(typeName)>-1){
			this.type=this.validatedForm.types[typeName];
			this.validateType=this.type.validator;
			break;
		}
	}
}
tii_ValidatedItem.prototype.attachMaxUpdater=function(){
	if(this.node.className.indexOf("max")>-1){
		this.max=parseInt(this.node.className.substring(this.node.className.indexOf("max")+3));
		if(this.max<Number.POSITIVE_INFINITY&&this.type.className=="text"&&this.element.nodeName=="TEXTAREA"){
			var spans=this.node.getElementsByTagName("span");
			for(var a=0;a<spans.length;a++){
				if(spans[a].className.indexOf("max")>-1){
					this.note=spans[a];
					break;
				}
			}
			this.id=(new Date()).getTime();
			this.element.onkeydown=function(){this.item.updateCharLeft();}
			this.element.onkeyup=function(){this.item.updateCharLeft();}
			this.updateCharLeft();
		}
	}
}
tii_ValidatedItem.prototype.updateCharLeft=function(e){
	if(this.updating||this.max==Number.POSITIVE_INFINITY)return;
	this.updating=true;
	var curr=this.max-this.element.value.length;
	if(curr<0){
		this.element.value=this.element.value.substring(0,this.max);
		this.element.scrollTop=this.element.scrollHeight;
		curr=0;
	}
	if(this.note!=null&&this.last!=curr){
		this.note.firstChild.data="("+this.max+" characters max, "+(curr)+" remaining)";
		this.last=curr;
	}
	this.updating=false;
}
tii_ValidatedItem.prototype.validate=function(){
	this.value=this.element.value;
	this.valid=this.validateType();
	if(!this.valid){
		this.setMessage();
	}else{
		if(this.origClassName!=null)
			this.node.className=this.origClassName;
		this.origClassName=null
	}
	return this.valid;
}
tii_ValidatedItem.prototype.setMessage=function(){
	if(this.origClassName==null){
		this.origClassName=this.node.className;
		this.node.className+=" error";
	}
}
tii_ValidatedItem.prototype.validateRequired=function(){
	if(this.required&&this.value==""){
		this.message=this.type.requiredMsg;
		return false;
	}
	return true;
}
/*Validation for types*/
function tii_validateText(){
	if(!this.validateRequired())
		return false;
	if(this.value.length>this.max){
		this.message="There is a limit of "+this.max+" characters for this field";
		return false;
	}
	return true;
}
function tii_validateEmail(){
	if(!this.validateRequired())
		return false;
	var emails=this.value.split(",");
	if(this.max==1){
		pluralObject="email"
	}else{
		pluralObject="emails"
	}
	if(emails.length>this.max){
		this.message="There is a limit of "+this.max+" "+pluralObject+" for this field";
		return false;
	}
	for(var i=0;i<emails.length;i++){
		var email=emails[i];
		var split1=email.split("@");
		if(split1.length!=2||split1[1].split(".").length < 2){
			this.message=this.type.errorMsg;
			return false;
		}
	}
	return true;
}
function tii_validateAgree(){
	if(!this.validateRequired())
		return false;
	if(this.required&&!this.element.checked){
		this.message=this.type.errorMsg;
		return false;
	}
	return true;
}
function tii_validateURL(){
	if(!this.validateRequired())
		return false;
	if(this.value!=""){
		var split1=this.value.split("://");
		if(split1.length!=2||split1[1].split(".").length<3){
			this.message=this.type.errorMsg;
			return false;
		}
	}
	return true;
}
function tii_validateFile(){
	return this.validateRequired();
}