// FORM CLASS VALIDATION

var htmlform = new Class({

	initialize: function(obj){
		var thisForm = this;
		
		// check & create for alert layer
		var body = $E("body");
		var alertLayer = new Element("div").setProperty("id", obj.id+"Layer").addClass("alertLayer").injectInside(body);
		var closeBtn = new Element("a").setProperty("href", "javascript:;").setText("x").injectInside(alertLayer);
		closeBtn.addEvent("click", function(e){
			thisForm.hideAlertLayer();
		});
		var display = new Element("p").injectInside(alertLayer);
		
		// init form
		if (!$(obj.id)) { return false; }
		thisForm.form = $(obj.id);
		thisForm.form.layer = obj.layer;
		thisForm.form.behaviors = obj.behaviors;
		thisForm.form.errorElement = null;
		thisForm.data = obj.data;
		thisForm.alertLayer = alertLayer;
		thisForm.initForm();
	},
	
	initForm: function(){
		var thisForm = this;
		
	    for (var i = 0; i < thisForm.data.length; i++) {
	        // init elements
	        for (var j = 0; j < thisForm.form.elements.length; j++) {
	            var el = thisForm.form.elements[j];
	            if (el.name == thisForm.data[i].field) {
	                thisForm.initElement(el, thisForm.data[i]);
	            }
	        }
	    }
	    
	    // valid form on submit
	    thisForm.form.addEvent("submit", function(e){
			if (!thisForm.isValidForm(this)) {
				new Event(e).stop();
			} else {
				// call back
				if (thisForm.form.behaviors.onSubmit) {
					thisForm.form.behaviors.onSubmit(thisForm.form, thisForm);
					new Event(e).stop();
				}
			}
	    });
	},
	
	initElement: function(obj, data){
		var thisForm = this;
	    var el = $(obj);
	    
	    // add new properties
		if (!el.$form) {
			el.$form = new Object();
		}
	    for (var i in data) {
	        el.$form[i] = data[i];
	    }
		el.validated = true;
	    
	    // init behaviors
	    if (typeof(el.$form.init) != "undefined") {
	    
	        // if the input has its initialized value
			if (el.type == "text" || el.type == "textarea") {
				el.value = el.$form.init;
				el.addEvents({
					"focus": function(){
		                if (this.value == this.$form.init) {
		                    this.value = "";
		                }
					},
					"blur": function(){
		                if (this.value.trim() == "") {
		                    this.value = this.$form.init;
		                }
		            }
				});
			}
			
			if (el.type == "radio") {
				el.checked = el.$form.init;
			}
			
			if (el.type == "select-one" || el.type == "select-multiple") {
				el.selectedIndex = Number(el.$form.init);
			}
			
			if (el.type == "radio") {
				el.selectedIndex = Number(el.$form.init);
			}
	    }
		
		// apply maxlength to textarea
		if (typeof(el.$form.maxLength) != "undefined" && (el.type == "textarea" || el.type == "text" || el.type == "password")) {
			// maximum input characters
			if (el.type == "textarea"){
				el.addEvent("keypress", function(e){
		            var evt = new Event(e);
		            var code = evt.getCharCode();
		            if (this.value.length >= this.$form.maxLength && code != 0) { evt.stop(); }
		        });
			} else {
				el.maxLength = el.$form.maxLength;
			}
		}
	    
		// restrict input characters
	    if (typeof(el.$form.restrict) != "undefined" && (el.type == "textarea" || el.type == "text" || el.type == "password")) { 
			el.addEvent("keypress", function(e){
	            var evt = new Event(e);
				var key = evt.getCharKey();
	            var re = new RegExp(this.$form.restrict);
	            if (key != "" && !re.test(key)) { evt.stop(); }
	        });
	    }
		
		// hide alert & execute call back functions
		el.addEvents({
			"click": function(e){
				this.validated = thisForm.validFormElement(this);
				setCallBack(el);
			},
			"keyup": function(e){
				this.validated = thisForm.validFormElement(this);
				setCallBack(el);
			},
			"change": function(e){
				this.validated = thisForm.validFormElement(this);
				setCallBack(el);
			},
			"blur": function(e){
				this.validated = thisForm.validFormElement(this);
				setCallBack(el);
			}
		});
		
		// set call back function
		function setCallBack(elObj) {
			var form = elObj.form;
			if (elObj.$form.behaviors && elObj.$form.behaviors.onAfterChange) {elObj.$form.behaviors.onAfterChange(elObj);}
			if (form.behaviors && form.behaviors.onAfterChange) {form.behaviors.onAfterChange(elObj);}
			
			// hide alert layer
			thisForm.hideAlertLayer();
		}
	},
	
	isValidForm: function (formObj){
		var thisForm = this;
	    for (var i = 0; i < formObj.elements.length; i++) {
			formObj.elements[i].validated = thisForm.validFormElement(formObj.elements[i]);
	        if (!formObj.elements[i].validated) {
	            thisForm.showAlertLayer(formObj.elements[i]);
	            return false;
	        }
	    }
	    return true;
	},
	
	validFormElement: function(obj){
		var thisForm = this;
	    var el = $(obj);
	    
		// if (!el.$form)
		if (!el.$form) {
			return true;
		}
		
	    // valid types
	    switch (typeof(el.$form.valid)) {
	        case "function":
	            return el.$form.valid();
	            break;
	            
	        case "string":
	            
	            // no valid needed
	            if (typeof(el.$form.valid) == "undefined" || el.$form.valid == null || el.$form.valid.trim() == "" || el.$form.valid.trim() == "none") { return true; }
	            var validTag = el.$form.valid.trim();
	            
	            // compare to other input's value
	            if (validTag.indexOf("=") != -1 && validTag.indexOf(">") == -1 && validTag.indexOf("<") == -1) {
	                if (el.type == "text" || el.type == "password") {
	                    var target = $F(validTag.replace("=", ""), el.form);
	                    return !target || el.value.trim() == target.value.trim();
	                }
	                
	                // other type
	                return true;
	            }
	            if (validTag.indexOf(">") != -1) {
	                if (el.type == "text" || el.type == "password") {
	                    var target = $F(validTag.replace("=", ""), el.form);
	                    if (validTag.indexOf("=") != -1) { return !target || Number(el.value.trim()) >= Number(target.value.trim()); }
	                    else { return !target || Number(el.value.trim()) > Number(target.value.trim()); }
	                }
	                
	                // other type
	                return true;
	            }
	            if (validTag.indexOf("<") != -1) {
	                if (el.type == "text" || el.type == "password") {
	                    var target = $(validTag.replace("=", ""));
	                    if (validTag.indexOf("=") != -1) { return !target || Number(el.value.trim()) <= Number(target.value.trim()); }
	                    else { return !target || Number(el.value.trim()) < Number(target.value.trim()); }
	                }
	                
	                // other type
	                return true;
	            }
	            
	            // required value
	            if (validTag.indexOf("required") != -1) {
					if (el.type != "text" && el.type != "textarea" && el.type != "password") {
						return true;
					}

					if (!el.$form || !el.$form.init || el.$form.init == "") {
						return el.value.trim().length >= Math.max(Number(Quote(validTag, "(", ")")), 1);
					} else {
						return el.value.trim().length >= Math.max(Number(Quote(validTag, "(", ")")), 1) && el.value.trim() != el.$form.init;
					}
	                
	                // other type
	                return true;
	            }
	            
	            // range value
	            if (validTag.indexOf("range") != -1) {
	                if (el.type == "text") {
	                    var range = Quote(validTag, "(", ")").trim().split(";");
						if (range[0].trim() == "" && range[1].trim() == "") return true;
						if (range[0].trim() == "") return Number(el.value.trim()) <= Number(range[1].trim());
						if (range[1].trim() == "") return Number(el.value.trim()) >= Number(range[0].trim());
	                    return Number(el.value.trim()) >= Number(range[0].trim()) && Number(el.value.trim()) <= Number(range[1].trim());
	                }
	                
	                // other type
	                return true;
	            }
	            
	            // email value
	            if (validTag.indexOf("email") != -1) {
	            
	                if (el.type == "text" || el.type == "textarea") {
	                
	                    // if optional input & value is null or value = init value
	                    if (validTag.indexOf("[") != -1 && validTag.indexOf("]") != -1 && (isBlank(el.value) || (el.$form && el.$form.init && el.value.trim() == el.$form.init))) { return true; }
	                    
	                    // validate email(s)
						if (validTag.indexOf("emails") != -1) {
							return isEmails(el.value.trim());
						}
						return isEmail(el.value.trim());
	                }
	                
	                // other type
	                return true;
	            }
	            
	            // phone value
	            if (validTag.indexOf("date") != -1) {
	            
	                if (el.type == "text") {
	                	
						var fmt = Quote(validTag, "(", ")").trim();
						
	                    // if optional input & value is null or value = init value
	                    if (validTag.indexOf("[") != -1 && validTag.indexOf("]") != -1 && (isBlank(el.value) || (el.$form && el.$form.init && el.value.trim() == el.$form.init))) { return true; }
	                    
	                    // validate phone
	                    return isDate(fmt, el.value.trim());
	                }
	                
	                // other type
	                return true;
	            }
				
				// phone value
	            if (validTag.indexOf("phone") != -1) {
	            
	                if (el.type == "text") {
	                
	                    // if optional input & value is null or value = init value
	                    if (validTag.indexOf("[") != -1 && validTag.indexOf("]") != -1 && (isBlank(el.value) || (el.$form && el.$form.init && el.value.trim() == el.$form.init))) { return true; }
	                    
	                    // validate phone
	                    return isPhone(el.value.trim());
	                }
	                
	                // other type
	                return true;
	            }
	            
	            // image value
	            if (validTag.indexOf("image") != -1) {
	            
	                if (el.type == "text" || el.type == "file") {
	                
	                    // if optional input & value is null or value = init value
	                    if (validTag.indexOf("[") != -1 && validTag.indexOf("]") != -1 && (isBlank(el.value) || (el.$form && el.$form.init && el.value.trim() == el.$form.init))) { return true; }
	                    
	                    // validate image
	                    return isImage(el.value.trim());
	                }
	                
	                // other type
	                return true;
	            }
	            
	            // "future" compare date
	            if (validTag.indexOf("future") !== -1) {
            
	                if (el.type == "text") {

	                    // if optional input & value is null or value = init value
	                    if (validTag.indexOf("[") != -1 && validTag.indexOf("]") != -1 && (isBlank(el.value) || (el.$form && el.$form.init && el.value.trim() == el.$form.init))) { return true; }
	                    
	                    var range = Quote(validTag, "(", ")").split(",");
	                    if (range.length == 0) { return true; }
	                    if (!isDate(range[0].trim(), el.value.trim()) || (range[1] && $F(range[1].trim(), el.form) && !isDate(range[0].trim(), $F(range[1].trim(), el.form).value.trim()))) { return false; }
	                    if (range[1] && $F(range[1].trim(), el.form)) { return (compareDate(range[0].trim(), el.value.trim(), $F(range[1].trim(), el.form).value.trim()) == -1); }
	                    else { return (compareDate(range[0].trim(), el.value.trim()) == -1); }
	                }
	                
	                // other type
	                return true;
	            }
	            
	            // "checked" for checkbox & radio button
	            if (validTag == "checked") {
	            
	                if (el.type == "checkbox") { return el.checked; }
	                
	                if (el.type == "radio") {
	                    var radioGroup = el.form[el.name];
	                    
	                    // contain 1 radio button
	                    if (radioGroup && !radioGroup.length) { return radioGroup.checked; }
	                    
	                    // more than 1 radio button
	                    for (var i = 0; i < radioGroup.length; i++) {
	                        if (radioGroup[i].checked) { return true; }
	                    }
	                    return false;
	                }
	                
	                // other type
	                return true;
	            }
	            
	            // "selected" for combo box
	            if (validTag == "selected") {
	            
	                if (el.type == "select-one" || el.type == "select-multiple") {
	                    if (typeof(el.$form.init) != "undefined") { return el.selectedIndex != Number(el.$form.init); }
	                    else { return el.selectedIndex != 0; }
	                }
	                
	                // other type
	                return true;
	            }
	            
	            return true;
	            break;
	            
	        default:
	            return true;
	            break;
	    }
	},
	
	showAlertLayer: function(obj){
	    try {
	        var thisForm = this;
			var form = obj.form;
			var alertLyr = thisForm.alertLayer;
	        form.errorElement = obj;
			
	        // call back functions
			if (obj.$form.behaviors && obj.$form.behaviors.onAlertShow) {obj.$form.behaviors.onAlertShow(obj);}
			if (form.behaviors && form.behaviors.onAlertShow) {form.behaviors.onAlertShow(obj);}
	        
	        // display alert message
	        $E("p", thisForm.alertLayer).setHTML(obj.$form.alert);

	        // show alert
	        var alertType = obj.$form.layer && obj.$form.layer.type ? obj.$form.layer.type : form.layer.type ? form.layer.type : "alert";
	        var offset = obj.$form.layer && obj.$form.layer.offset ? obj.$form.layer.offset.split(",") : ["0", "0"];
			var lyrW = obj.$form.layer && obj.$form.layer.layerWidth ? obj.$form.layer.layerWidth : form.layer.layerWidth ? form.layer.layerWidth : 200;
			
	        switch (alertType) {
	            case "layer":
					var dim = $(obj).getCoordinates();
					alertLyr.setStyles({
						visibility: "visible",
						display: "block",
						top: (dim.top + dim.height + Number(offset[1].trim())) + "px",
						left: (dim.left + Number(offset[0].trim())) + "px",
						width: lyrW + "px",
						zIndex: 999
					}).addClass("layer");

	                // set Iframe to hide combo box in IE
	                showFrame(thisForm.alertLayer);
	                break;
	                
	            case "popup":
					var dim = thisForm.alertLayer.getCoordinates();
					alertLyr.setStyles({
						visibility: "visible",
						display: "block",
						top: (window.getScrollTop() + window.getHeight() / 2 - dim.height / 2 + Number(offset[1].trim())) + "px",
						left: (window.getWidth() / 2 - lyrW / 2 + Number(offset[0].trim())) + "px",
						width: lyrW + "px",
						zIndex: 999
					}).addClass("popup");
	                
	                // set Iframe to hide combo box in IE
	                showFrame(thisForm.alertLayer);
	                
	                // fade HTML content
	                if (obj.$form.layer.fadeContent == true) {
	                    showMask();
	                }
	                
	                break;
	            
				case "classic":
					alert(obj.$form.alert);
	                break;
				
	            default:
	                
	                break;
	        }
	        // set focus
	        obj.focus();
			
			// autohide alert
			setTimeout(thisForm.hideAlertLayer, 3000);
	    } catch (e) {}
	},
	
	hideAlertLayer: function(){
	    try {
			var thisForm = this;
			var obj = thisForm.form.errorElement;
			if (obj) {
				var form = obj.form;
				// call back functions
				if (obj.$form.behaviors && obj.$form.behaviors.onAlertHide) {obj.$form.behaviors.onAlertHide(obj);}
				if (form.behaviors && form.behaviors.onAlertHide) {form.behaviors.onAlertHide(obj);}
			}
	        
			// hide frame
			thisForm.alertLayer.setStyle("visibility", "hidden");
			hideFrame(thisForm.alertLayer);
			hideMask();
			
	    } catch (e) {}
	}
});