/* FILE HEADER ************************************************** ** JS Validate ** Author: Karl Seguin, Timo Haberkern ** Homepage: http://jsval.berlios.de/ ** Version: 1.3.3 ** Copyright 2003, 2005 Timo Haberkern, Karl Seguin This file is part of JS Validate. JS Validate 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 of the License, or (at your option) any later version. JS Validate 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 General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with JS Validate; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ** ** END HEADER ***************************************************/ function validateCompleteForm (objForm, strErrorClass) { return _validateInternal(objForm, strErrorClass, 0); }; function validateStandard (objForm, strErrorClass) { return _validateInternal(objForm, strErrorClass, 1); }; /*************************************************************** ** Internal functions *****************************************************************/ function _validateInternal(form, strErrorClass, nErrorThrowType){ var strErrorMessage = ""; var objFirstError = null; if (nErrorThrowType == 0){ strErrorMessage = (form.err) ? form.err : _getLanguageText("err_form"); }; var fields = _GenerateFormFields(form); for (var i = 0; i < fields.length; ++i){ var field = fields[i]; if (!field.IsValid(fields)){ field.SetClass(strErrorClass); if (nErrorThrowType == 1) { _throwError(field); return false; }else{ if (objFirstError == null){ objFirstError = field; } strErrorMessage = _handleError (field, strErrorMessage); bError = true; } } else { field.ResetClass(); } }; if (objFirstError != null) { alert(strErrorMessage); objFirstError.element.focus(); return false; }; return true; }; function _getLanguageText(id){ objTextsInternal = new _jsVal_Language(); objTexts = null; try { objTexts = new jsVal_Language(); } catch (ignored){}; switch (id) { case "err_form": strResult = (!objTexts || !objTexts.err_form) ? objTextsInternal.err_form : objTexts.err_form; break; case "err_enter": strResult = (!objTexts || !objTexts.err_enter) ? objTextsInternal.err_enter : objTexts.err_enter; break; case "err_select": strResult = (!objTexts || !objTexts.err_select) ? objTextsInternal.err_select : objTexts.err_select; break; }; return strResult; }; function _GenerateFormFields(form){ var arr = new Array(); for (var i = 0; i < form.length; ++i){ var element = form.elements[i]; var index = _getElementIndex(arr,element); //if it doesn't already exist, add it to our array, else merge the change if (index == -1){ arr[arr.length] = new Field(element, form); }else{ arr[index].Merge(element) }; }; return arr; }; function _getElementIndex(arr, element){ if (element.name) { var elementName = element.name.toLowerCase(); for (var i = 0; i < arr.length; ++i){ if (arr[i].element.name) { if (arr[i].element.name.toLowerCase() == elementName){ return i; } }; }; } return -1; }; /*************************************************************** ** Standard translation *****************************************************************/ function _jsVal_Language() { this.err_form = "Please enter/select values for the following fields:\n\n"; this.err_select = "Please select a valid \"%FIELDNAME%\""; this.err_enter = "Please enter a valid \"%FIELDNAME%\""; }; /*************************************************************** ** Field Class *****************************************************************/ function Field(element, form){ this.type = element.type; this.element = element; this.exclude = element.exclude || element.getAttribute('exclude'); this.err = element.err || element.getAttribute('err'); this.required = _parseBoolean(element.required || element.getAttribute('required')); this.realname = element.realname || element.getAttribute('realname'); this.elements = new Array(); switch (this.type){ case "textarea": case "password": case "text": case "file": this.value = element.value; this.minLength = element.minlength || element.getAttribute('minlength'); this.maxLength = element.maxlength || element.getAttribute('maxlength'); this.regexp = this._getRegEx(element); this.minValue = element.minvalue || element.getAttribute('minvalue'); this.maxValue = element.maxvalue || element.getAttribute('maxvalue'); this.equals = element.equals || element.getAttribute('equals'); this.callback = element.callback || element.getAttribute('callback'); break; case "select-one": case "select-multiple": this.values = new Array(); for (var i = 0; i < element.options.length; ++i){ if (element.options[i].selected && (!this.exclude || element.options[i].value != this.exclude)){ this.values[this.values.length] = element.options[i].value; } } this.min = element.min || element.getAttribute('min'); this.max = element.max || element.getAttribute('max'); this.equals = element.equals || element.getAttribute('equals'); break; case "checkbox": this.min = element.min || element.getAttribute('min'); this.max = element.max || element.getAttribute('max'); //no break, let it fall through to radio case "radio": this.required = _parseBoolean(this.required || element.getAttribute('required')); this.values = new Array(); if (element.checked){ this.values[0] = element.value; } this.elements[0] = element; break; }; }; Field.prototype.Merge = function(element){ //never negate a require field var required = _parseBoolean(element.getAttribute('required')); if (required){ this.required = true; }; //all other cases (except required) we only add if there isn't already a value (first come first served) if (!this.err){ this.err = element.getAttribute('err'); }; if (!this.equals){ this.equals = element.getAttribute('equals'); }; if (!this.callback){ this.callback = element.getAttribute('callback'); }; if (!this.realname){ this.realname = element.getAttribute('realname'); }; if (!this.max){ this.max = element.getAttribute('max'); }; if (!this.min){ this.min = element.getAttribute('min'); }; if (!this.regexp){ this.regexp = this._getRegEx(element); }; if (element.checked){ this.values[this.values.length] = element.value; }; this.elements[this.elements.length] = element; }; Field.prototype.IsValid = function(arrFields){ switch (this.type){ case "textarea": case "password": case "text": case "file": return this._ValidateText(arrFields); case "select-one": case "select-multiple": case "radio": case "checkbox": return this._ValidateGroup(arrFields); default: return true; }; }; Field.prototype.SetClass = function(newClassName){ if ( (newClassName) && (newClassName != "") ) { if ( (this.elements) && (this.elements.length > 0)) { for (var i = 0; i < this.elements.length; ++i){ if(this.elements[i].className != newClassName){ this.elements[i].oldClassName = this.elements[i].className; this.elements[i].className = newClassName; } } }else{ if(this.element.className != newClassName){ this.element.oldClassName = this.element.className; this.element.className = newClassName; } }; } }; Field.prototype.ResetClass = function(){ if ( (this.type != "button") && (this.type != "submit") && (this.type != "reset") ) { if ( (this.elements) && (this.elements.length > 0)) { for (var i = 0; i < this.elements.length; ++i){ if(this.elements[i].oldClassName){ this.elements[i].className = this.elements[i].oldClassName; } else { this.element.className = ""; } } }else{ if(this.elements.oldClassName){ this.element.className = this.element.oldClassName; } else { this.element.className = ""; } }; }; }; Field.prototype._getRegEx = function(element){ regex = element.regexp || element.getAttribute('regexp') if (regex == null) return null; retype = typeof(regex); if (retype.toUpperCase() == "FUNCTION") return regex; else if ( (retype.toUpperCase() == "STRING") && !(regex == "JSVAL_RX_EMAIL") && !(regex == "JSVAL_RX_TEL") && !(regex == "JSVAL_RX_PC") && !(regex == "JSVAL_RX_ZIP") && !(regex == "JSVAL_RX_MONEY") && !(regex == "JSVAL_RX_CREDITCARD") && !(regex == "JSVAL_RX_POSTALZIP")) { nBegin = 0; nEnd = regex.length-1; if (regex.charAt(0) == "/") nBegin=1; if (regex.charAt(regex.length-1) == "/") nEnd=regex.length-2; return new RegExp(regex.slice(nBegin, nEnd)); } else { return regex; }; }; Field.prototype._ValidateText = function(arrFields){ if ( (this.required) && (this.callback) ) { nCurId = this.element.id ? this.element.id : ""; nCurName = this.element.name ? this.element.name : ""; eval("bResult = "+this.callback+"('"+nCurId+"', '"+nCurName+"', '"+this.value+"');"); if (bResult == false) { return false; }; } else { //required value is empty if (this.required && !this.value){ return false; }; //value less than minlength if (this.value && (this.minLength && this.value.length < this.minLength)){ return false; }; //value is more than maxlength if (this.value && (this.maxLength && this.value.length > this.maxLength)){ return false; }; //value fails regular expression if (this.regexp){ if (!_checkRegExp(this.regexp, this.value)) { //the field isn't required, but there is a value if (!this.required && this.value){ return false; } if (this.required){ return false; } } else { return true; }; }; //check equality if (this.equals){ for (var i = 0; i < arrFields.length; ++i){ var field = arrFields[i]; if ( (field.element.name == this.equals) || (field.element.id == this.equals) ) { if (field.element.value != this.value) { return false; }; break; }; }; }; //check against minvalue and maxvalue if (this.required){ var fValue = parseFloat(this.value); if ((this.minValue || this.maxValue) && isNaN(fValue)){ return false; }; if ( (this.minValue) && (fValue < this.minValue) ) { return false; }; if ( (this.maxValue) && (fValue > this.maxValue) ) { return false }; }; } return true; }; Field.prototype._ValidateGroup = function(arrFields){ if (this.required && this.values.length == 0){ return false; }; if (this.required && this.min && this.min > this.values.length){ return false; }; if (this.required && this.max && this.max < this.values.length){ return false; }; return true; }; function _handleError (field, strErrorMessage) { var obj = field.element; strNewMessage = strErrorMessage + ( (field.realname)? field.realname : ((obj.id) ? obj.id : obj.name) ) + "\n"; return strErrorMessage; }; function _throwError(field){ var obj = field.element; switch (field.type){ case "text": case "password": case "textarea": case "file": // alert(_getError(field, "err_enter")); try { obj.focus(); } catch (ignore) {} break; case "select-one": case "select-multiple": case "radio": case "checkbox": // alert(_getError(field, "err_select")); break; }; }; function _getError(field, str){ var obj = field.element; strErrorTemp = (field.err) ? field.err : _getLanguageText(str); idx = strErrorTemp.indexOf( "\\n" ); while ( idx > -1 ) { strErrorTemp = strErrorTemp.replace( "\\n", "\n" ); idx = strErrorTemp.indexOf( "\\n" ); }; return strErrorTemp.replace("%FIELDNAME%", (field.realname)? field.realname : ((obj.id) ? obj.id : obj.name)); }; function _parseBoolean(value){ return !(!value || value == 0 || value == "0" || value == "false"); }; function _checkRegExp(regx, value){ switch (regx){ case "JSVAL_RX_EMAIL": return ((/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,5})+$/).test(value)); case "JSVAL_RX_TEL": return ((/^1?[\- ]?\(?\d{3}\)?[\- ]?\d{3}[\- ]?\d{4}$/).test(value)); case "JSVAL_RX_PC": return ((/^[a-z]\d[a-z] ?\d[a-z]\d$/i).test(value)); case "JSVAL_RX_ZIP": return ((/^\d{5}$/).test(value)); case "JSVAL_RX_MONEY": return ((/^\d+([\.]\d\d)?$/).test(value)); case "JSVAL_RX_CREDITCARD": return (!isNaN(value)); case "JSVAL_RX_POSTALZIP": if(value.length == 6 || value.length == 7) return((/^[a-zA-Z]\d[a-zA-Z] ?\d[a-zA-Z]\d$/).test(value)); if(value.length == 5 || value.length == 10) return((/^\d{5}(\-\d{4})?$/).test(value)); break; default: return (regx.test(value)); }; };