//base code from oreilly javascript, 5th edition,  example in chapter 18.  
//Modified to handle additional pattern and other complex  validation
// M Marrah,  7/07
(function() { 
	// Do everything in this one anonymous function
    // When the document finishes loading, call init()
    if (window.addEventListener) window.addEventListener("load", init, false);
    else if (window.attachEvent) window.attachEvent("onload", init);

    // Define event handlers for any forms and form elements that need them.
    function init() {
        // Loop through all forms in the document
        for(var i = 0; i < document.forms.length; i++) {
            var f = document.forms[i];  // the form we're working on now

            // Assume, for now, that this form does not need any validation
            var needsValidation = false;

            // Now loop through the elements in our form
            for(j = 0; j < f.elements.length; j++) {
                var e = f.elements[j];  // the element we're working on
                // We're only interested in <input type="text"> textfields or selects or textareas
                var checkIt = false;
                if ((e.nodeName == "INPUT" && e.type != "text") && (e.nodeName != "SELECT" && e.nodeName != "TEXTAREA") ) continue;
                // We could use e.hasAttribute() but IE doesn't support it
                var required = e.getAttribute("required") != null;
				switch(e.nodeName){
					case "INPUT":
						var pattern = e.getAttribute("pattern");
                		// Required is just a shortcut for a simple pattern in input node
                		if (required && !pattern) {
                    		pattern = "\\S";
                    		e.setAttribute("pattern", pattern);
                			}
						checkIt = e.getAttribute("pattern") != null;
						break;
					case "SELECT":
						if(required){checkIt = true;}
						break;
					case "TEXTAREA":
					    checkIt = e.getAttribute("maxchars") != null;
					    if(checkIt){
							e.onkeyup = limitChars;
						}
						break;
					default:
						alert("unknown nodeName "+e.nodeName);
					
				}            
                // If this element requires validation,
                if (checkIt) {
                    // validate the element each time it changes
                    e.onchange = validateOnChange;
                    //alert("54 "+e.nodeName);
                    // Remember to add an onsubmit handler to this form
                    needsValidation = true;
                }	                
            }
            // If at least one of the form elements needed validation,
            // we also need an onsubmit event handler for the form
            if (needsValidation) {f.onsubmit = validateOnSubmit;}
        }
    }
     
	//function to limit the number of characters typed in a text box
	function limitChars(){
		var textfield = this;                            // the textfield
        var maxChars = textfield.getAttribute("maxchars"); // the pattern
        var value = this.value;
		if(value.length > maxChars){
			this.value = value.substr(0,maxChars);// cut it off at maxchars
			alert(maxChars+" character limit reached");
		}  
	}
	   
    // This function is the onchange event handler for textfields that 
    // require validation.  Remember that we converted the required attribute
    // to a pattern attribute in init().
    function validateOnChange() {
        var textfield = this;                            // the textfield
        var pattern = textfield.getAttribute("pattern"); // the pattern
        var value = this.value;                          // the user's input
        // If the value does not match the pattern set the class to "invalid".
        switch(textfield.nodeName){
			case "INPUT":
				if (value.search(pattern) == -1){textfield.className = "invalid";} 
        		else {textfield.className = "valid";}
        		break;
        	case "SELECT":
        	    if(textfield.selectedIndex < 1){textfield.className = "invalid";}
        		else {textfield.className = "valid";}
        		break;
        	case "TEXTAREA":
        	    var maxChars = textfield.getAttribute("maxchars");
        	    if(value.length > maxChars  ) {textfield.className = "invalid";	}
        		else {textfield.className = "valid";}
        		break;
		}
		//alert("checked node "+textfield.nodeName+" name = "+textfield.name+ " value = "+value+" className  = "+textfield.className);
        
    }

    // This function is the onsubmit event handler for any form that 
    // requires validation.
    function validateOnSubmit() {
        // When the form is submitted, we revalidate all the fields in the
        // form and then check their classNames to see if they are invalid.
        // If any of those fields are invalid, display an alert and prevent
        // form submission.
        var invalid = false;  // Start by assuming everything is valid
        // Loop through all form elements
        for(var i = 0; i < this.elements.length; i++) {
            var e = this.elements[i];
            // If the element is a text field and has our onchange handler
            if ((e.type == "text" || e.nodeName == "SELECT" || e.nodeName == "TEXTAREA") && e.onchange == validateOnChange) {
                e.onchange(); // Invoke the handler to re-validate
                // If validation fails for the element, it fails for the form
                if (e.className == "invalid") invalid = true;
            }
        }

        // If the form is invalid, alert user and block submission
        if (invalid) {
            alert("The form is incompletely or incorrectly filled out.\n" +
                  "Please correct the  highlighted fields and try again.");
            return false;
        }
    }
})();