/* ------------------------------------------------------------------------- JWP FormEngine: client side validation Version 0.1 ------------------------------------------------------------------------- */ function Validators() { this.validatorInstances = new Array(); this.contextProcess = null; this.SetContextProcess = function (cp) { this.contextProcess = cp; } this.GetValidator = function (process) { if (!process) return this.validatorInstances[this.contextProcess]; else return this.validatorInstances[process];} this.AddValidator = function (process) { this.validatorInstances[process] = new Validator(process); this.SetContextProcess(process); } } var validatorContainer = new Validators(); function Validator(v_processName) { this.validatorStartText = ""; // just after this text error messages are inserted this.validatorEndText = ""; // just before this text error messages are inserted this.processName = v_processName; this.rules = new Array(); this.errors = new Array(); this.directValues = new Array(); this.indirectValues = new Array(); this.labelControls = new Array(); this.validatorControls = new Array(); this.firstErrorElement = null; this.errorNumber = 0; this.AddRule = function (rule) { this.rules.push(rule); } this.AddError = function (errorCode, errorTranslation) { this.errors.push(errorCode, errorTranslation); } this.AddDirectValue = function (fieldNameInBO, fieldValueInBO) { this.directValues.push(fieldNameInBO, fieldValueInBO); } this.AddIndirectValue = function (fieldNameInBO, formClientID) { this.indirectValues.push(fieldNameInBO, formClientID); } this.AddLabelControl = function (fieldNameInBO, labelClientID) { this.labelControls.push(fieldNameInBO, labelClientID); } this.AddValidatorControl = function (fieldNameInBO, validatorClientID) { this.validatorControls.push(fieldNameInBO, validatorClientID); } this.Validate = Validator_Validate; this.CheckCondition = Validator_CheckCondition; this.MarkError = Validator_MarkError; this.InsertError = Validator_InsertError; this.CleanErrors = Validator_CleanErrors; this.Exception = Validator_Exception; this.Write = Validator_Write; this.GetValue = Validator_GetValue; this.GetIndirectValue = Validator_GetIndirectValue; this.GetIndirectField = Validator_GetIndirectField; this.GetDirectValue = Validator_GetDirectValue; this.GetIndirectValuesString = Validator_GetIndirectValuesString; this.GetDirectValuesString = Validator_GetDirectValuesString; this.GetLabelControl = Validator_GetLabelControl; this.GetValidatorControl = Validator_GetValidatorControl; this.GetError = Validator_GetError; this.FocusFirstError = Validator_FocusFirstError; this.logger = null; this.SetLogger = function (field) { this.logger = field; } this.Log = function (msg) { if (this.logger != null) this.logger.value += msg + ""; } } function Validator_Validate() { this.Log("--------VALIDATION--------\n"); var formValid = true; this.firstErrorElement = null; this.errorNumber = 0; for (var r in this.rules) { var rule = this.rules[r]; this.MarkError(rule.field, ""); // unmark } for (var r in this.rules) { var rule = this.rules[r]; this.Log("\n"+rule+"\n"); var fieldValue = this.GetIndirectValue(rule.field) if (fieldValue == null) { this.Log("Value not available!\n"); continue; } this.Log("value("+rule.field+")="+fieldValue+"\n"); if (!this.CheckCondition(rule.BOName(), rule.condition)) { continue; } var exp = new Expression(rule.test, this); var testResult = exp.Evaluate(fieldValue+"", rule.BOName()); this.Log("testResult="+testResult+"\n"); if (!testResult) { this.errorNumber++; this.Log("errorNumber="+this.errorNumber+"\n"); this.MarkError(rule.field, rule.error); formValid = false; if (this.firstErrorElement == null) { this.firstErrorElement = this.GetIndirectField(rule.field); this.Log("firstElement:"+ rule.field+"\n"); } } } return formValid; } function Validator_CheckCondition(boName, condition) { if (condition == null || condition == "") return true; var result = true; var conditions = condition.split('~'); for (var i = 0; (i < conditions.length) && result; i++) { var equal = conditions[i].indexOf("="); var leftSide = conditions[i].substr(0, equal); var pattern = conditions[i].substr(equal + 1); var boField = leftSide; var delim = leftSide.indexOf('.'); if (delim > 0) { boName = leftSide.substr(0, delim); boField = leftSide.substr(delim + 1); } var value = this.GetValue(boName + "." + boField); this.Log("condition: value="+value); if (value == null) { this.Log("Value not available!"); return false; } var exp = new Expression(pattern, this); result = result && exp.Evaluate(value+"", boName); } this.Log(" result="+result+"\n"); return result; } // if errorMsgID is empty than the marking is removed function Validator_MarkError(fieldName, errorMsgID) { this.Log((errorMsgID==""?"unmark ":"mark ") + fieldName + ":"); var labelControlID = this.GetLabelControl(fieldName); if (labelControlID != null) { this.Log(" label="+labelControlID); var lblField = document.getElementById(labelControlID); if (lblField != null) if (errorMsgID != "") lblField.className = "sosErrorText"; else lblField.className = "sosFormText"; } var validatorControlID = this.GetValidatorControl(fieldName); if (validatorControlID != null) { this.Log(" validator="+validatorControlID); var validatorField = document.getElementById(validatorControlID); var messageField = null; if (validatorField.nodeName != "TR") { this.Log("!noTR"); messageField = validatorField; } else { this.Log("!TR"); for (var c = 0; c < validatorField.cells.length; c++) { var cell = validatorField.cells[c]; if (cell.innerHTML.toLowerCase().indexOf(this.validatorStartText) >=0) { this.Log("!TD"); messageField = cell; } } } if (messageField != null) { this.Log("!messageField"); if (errorMsgID == "") { this.Log("!hide"); validatorField.style.display = "none"; this.CleanErrors(messageField); } else { this.Log("!show"); var errorMsg = this.GetError(errorMsgID); validatorField.style.display = ""; this.InsertError(messageField, errorMsg); } } } this.Log("\n"); } function Validator_InsertError(messageField, msg) { var endPos = messageField.innerHTML.toLowerCase().lastIndexOf(this.validatorEndText); var innerHTML = messageField.innerHTML; if (innerHTML.indexOf(msg) >=0) return; messageField.innerHTML = innerHTML.substr(0, endPos) + msg + innerHTML.substr(endPos); } function Validator_CleanErrors(messageField) { var startPos = messageField.innerHTML.toLowerCase().indexOf(this.validatorStartText) + this.validatorStartText.length; var endPos = messageField.innerHTML.toLowerCase().lastIndexOf(this.validatorEndText); var innerHTML = messageField.innerHTML; this.Log(messageField.innerHTML+"\n"); messageField.innerHTML = innerHTML.substr(0, startPos) + innerHTML.substr(endPos); this.Log(messageField.innerHTML+"\n"); } function Validator_GetIndirectField(fieldName) { for (var i=0; i" + this.GetIndirectValue(this.indirectValues[i]) + "\n"; } return res; } function Validator_GetDirectValue(fieldName) { for (var i=0; iRULES
"); for (var i=0; i"); } document.writeln("DIRECT VALUES
"); for (var i=0; i"); } document.writeln("INDIRECT VALUES
"); for (var i=0; i"); } document.writeln("ERRORS
"); for (var i=0; i"); } document.writeln("LABEL CONTROLS
"); for (var i=0; i"); } document.writeln("VALIDATOR CONTROLS
"); for (var i=0; i"); } } /* ------------------------------------------------------------------------------------ */ /* ------------------------------- RULE ----------------------------------------- */ /* ------------------------------------------------------------------------------------ */ function Rule(v_field, v_condition, v_test, v_error) { this.field = v_field; this.condition = v_condition; this.test = v_test; this.error = v_error; this.BOName = Rule_BOName; } function Rule_BOName () { return this.field.substr(0, this.field.indexOf(".")); } Rule.prototype = { toString: function(){ return "[" + this.field + "],[" + this.condition + "],[" + this.test + "],[" + this.error + "]"; } }; /* ------------------------------------------------------------------------------------ */ /* ------------------------------- EXPRESSION ----------------------------------------- */ /* ------------------------------------------------------------------------------------ */ function Expression(v_expressionString, v_validator) { this.expressionString = v_expressionString; this.validator = v_validator; this.Evaluate = Expression_Evaluate; this.EvaluateReg = Expression_EvaluateReg; this.EvaluateDval = Expression_EvaluateDval; this.EvaluateOneOf = Expression_EvaluateOneOf; this.EvaluateLen = Expression_EvaluateLen; this.EvaluateMultipleEmail = Expression_EvaluateMultipleEmail; this.EvaluateDate = Expression_EvaluateDate; this.EvaluateCCExpiry = Expression_EvaluateCCExpiry; this.EvaluateCCNumber = Expression_EvaluateCCNumber; } function Expression_Evaluate(val, boName) { if (!this.expressionString) { return false; } var expr = this.expressionString; expr = expr.replace(/false/gi, "false"); expr = expr.replace(/true/gi, "true"); if (expr.indexOf("MANDATORY") >= 0) expr = expr.replace("MANDATORY", "!reg(^\\-1$|^[\\s]*$)"); if (expr.indexOf("NULL") >= 0) expr = expr.replace("NULL", "reg(^[\\s]*$)"); if (expr.indexOf("EMAIL") >= 0 && expr.toUpperCase().indexOf("MULTIPLEEMAIL") == -1) expr = expr.replace("EMAIL", "reg(^$|^[a-zA-Z0-9_]+([\\.-][a-zA-Z0-9_]+)*@[a-zA-Z0-9_]+([\\.-][a-zA-Z0-9_]+)*\\.[a-zA-Z0-9]{2,6}$)"); if (expr.indexOf("YEAR") >= 0) expr = expr.replace("YEAR", "reg((^$)|(^(19|20)\\d\\d$))"); var eval = false; var negation = false; if (expr.indexOf('!') == 0) { negation = true; expr = expr.substr(1); } if (expr.indexOf('reg(') == 0) { expr = expr.substr(4, expr.length-5); eval = this.EvaluateReg(expr, val); } else if (expr.indexOf('dval(') == 0) { expr = expr.substr(5, expr.length-6); eval = this.EvaluateDval(expr, val); } else if (expr.indexOf('oneOf(') == 0) { expr = expr.substr(6, expr.length-7); eval = this.EvaluateOneOf(expr, val); } else if (expr.indexOf('len(') == 0) { expr = expr.substr(4, expr.length-5); eval = this.EvaluateLen(expr, val); } else if (expr.indexOf('date(') == 0) { expr = expr.substr(5, expr.length - 6); eval = this.EvaluateDate(expr, val, boName); } else if (expr.indexOf('ccnr(') == 0) { expr = expr.substr(5, expr.length-6); eval = this.EvaluateCCNumber(expr, val, boName); } else if (expr.indexOf('ccexp(') == 0) { expr = expr.substr(6, expr.length-7); eval = this.EvaluateCCExpiry(expr, val, boName); } else if (expr.indexOf('MULTIPLEEMAIL(') == 0) { expr = expr.substr(14, expr.length-15); eval = this.EvaluateMultipleEmail(expr, val); } return negation ? !eval : eval; } function Expression_EvaluateDate(expr, val, boName) { if (val == null) val = ""; var split = expr.split(','); var _day = parseInt(this.validator.GetValue(boName + "." + split[0])); var _month = parseInt(this.validator.GetValue(boName + "." + split[1])); var _year = parseInt(this.validator.GetValue(boName + "." + split[2])); // date not set if ((_day == null || _day == "" || _day == "-1") && (_month == null || _month == "" || _month == "-1" || _month == -1) && (_year == null || _year == "" || _year == "-1" || isNaN(_year))) { return true; } // database limitations for date if (_year < 1753 || _year > 9999) return false; // date set var composedDate = new Date(_year, _month - 1, _day); if ((composedDate.getMonth() == (_month - 1)) && (composedDate.getDate() == _day) && (composedDate.getFullYear() == _year)) return true; else return false; } function Expression_EvaluateCCExpiry(expr, val, boName) { if (val == null) val = ""; var split = expr.split(','); var _month = parseInt(this.validator.GetValue(boName+"."+split[0])); var _year = parseInt(this.validator.GetValue(boName+"."+split[1])); var d = new Date(); var curr_month = d.getMonth()+1; var curr_year = d.getFullYear(); return (_year > curr_year) || (_year == curr_year && _month >= curr_month); } function Expression_EvaluateCCNumber(expr, val, boName) { var split = expr.split(','); var val = this.validator.GetValue(boName+"."+split[0]); // actually value is replaced here var _checkCCType = false; var _ccType = 0; if (split.length == 2) { _checkCCType = true; _ccType = parseInt(this.validator.GetValue(boName+"."+split[1])); } // no validation when * if (val.indexOf('*') >= 0) return true; // Remove non-digits var validChars = "0123456789"; var len = 0; var number = new Array(); for (var i = 0; i < val.length; i++) { if (validChars.indexOf(val.charAt(i)) >= 0) { if (len == 16) return false; // number has too many digits number[len] = parseInt(val.charAt(i)); len++; } } // Validate based on card type, first if tests length, second tests prefix if (_checkCCType) { switch (_ccType) { case 4: if (len != 16) return false; if (number[0] != 5 || number[1] == 0 || number[1] > 5) return false; break; case 1: if (len != 16 && len != 13) return false; if (number[0] != 4) return false; break; case 2: if (len != 15) return false; if (number[0] != 3 || (number[1] != 4 && number[1] != 7)) return false; break; case 3: if (len != 14) return false; if (number[0] != 3 || (number[1] != 0 && number[1] != 6 && number[1] != 8) || number[1] == 0 && number[2] > 5) return false; break; default: return false; } } // Use Luhn Algorithm to validate var sum = 0; for (var i = len - 1; i >= 0; i--) { if (i % 2 == len % 2) { var n = number[i] * 2; sum += Math.round(n/10 - 0.5) + (n % 10); } else sum += number[i]; } return (sum % 10 == 0); } function Expression_EvaluateReg(expr, val) { if (val == null) val = ""; return val.match(expr) != null; } function Expression_EvaluateDval(expr, val) { var min = Number.MIN_VALUE; var max = Number.MAX_VALUE; var f_val = parseFloat(val); if (isNaN(f_val)) return false; var comma = expr.indexOf(','); if (comma >= 0) { var s_min = expr.substr(0, comma); var s_max = expr.substr(comma + 1); min = parseFloat(s_min); if (s_max != "") max = parseFloat(s_max); } else { min = parseFloat(expr); } if (isNaN(min)) min = Number.MIN_VALUE; if (isNaN(max)) min = Number.MAX_VALUE; return min <= f_val && f_val <= max; } function Expression_EvaluateOneOf(expr, val) { expr = ',' + expr + ','; return (expr.indexOf(','+val+',') >= 0); } function Expression_EvaluateLen(expr, val) { if (val == null) val = ""; var maxLength = parseInt(expr); if (isNaN(maxLength)) maxLength = Number.MAX_VALUE; return val.length <= maxLength; } function Expression_EvaluateMultipleEmail(expr, val) { var count = parseInt(expr); if (isNaN(count)) count = 0; val = val.replace(/,/g, ";"); var emails = val.split(';'); if (emails.length > count) return false; var emExpression = new Expression("EMAIL"); for (var i in emails) { if (!emExpression.Evaluate(emails[i].trim())) return false; } return true; } /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ String.prototype.trim = function () { return this.replace(/^\s*/, "").replace(/\s*$/, ""); } function getCheckedValue(radioObj) { if(!radioObj) return ""; var group = document.getElementsByName(radioObj.name); for (var i = 0; i < group.length; i++) { if(group[i].checked) { return group[i].value; } } return ""; } /* -------------------------------ACTIVITY INDICATOR-------------------------------- */ function showActivityCursorImage(imgSrc) { document.onmousemove=followMouse document.getElementById('csvActivity').style.width="124px"; document.getElementById('csvActivity').style.height = "124px"; document.getElementById("csvActivity").innerHTML = document.getElementById("csvActivity").innerHTML; } function followMouse(e) { var activityIndicator = document.getElementById('csvActivity'); var posx = 0; var posy = 0; if (!e) var e = window.event; if (e.pageX || e.pageY) { posx = e.pageX; posy = e.pageY; } else if (e.clientX || e.clientY) { posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; } activityIndicator.style.left = posx + 7; activityIndicator.style.top = posy + 15; } function showActivityCenterImage(imgSrc) { myPopupRelocate(); document.body.onscroll = myPopupRelocate; window.onscroll = myPopupRelocate; document.getElementById('csvActivity').style.width = "124px"; document.getElementById('csvActivity').style.height = "124px"; document.getElementById("csvActivity").innerHTML = document.getElementById("csvActivity").innerHTML; } function myPopupRelocate() { var scrolledX, scrolledY; if( self.pageYOffset ) { scrolledX = self.pageXOffset; scrolledY = self.pageYOffset; } else if( document.documentElement && document.documentElement.scrollTop ) { scrolledX = document.documentElement.scrollLeft; scrolledY = document.documentElement.scrollTop; } else if( document.body ) { scrolledX = document.body.scrollLeft; scrolledY = document.body.scrollTop; } var centerX, centerY; if( self.innerHeight ) { centerX = self.innerWidth; centerY = self.innerHeight; } else if( document.documentElement && document.documentElement.clientHeight ) { centerX = document.documentElement.clientWidth; centerY = document.documentElement.clientHeight; } else if( document.body ) { centerX = document.body.clientWidth; centerY = document.body.clientHeight; } var leftOffset = scrolledX + (centerX - 124) / 2; var topOffset = scrolledY + (centerY - 124) / 2; document.getElementById("csvActivity").style.top = topOffset + "px"; document.getElementById("csvActivity").style.left = leftOffset + "px"; }