var checkObjects = new Array(); var errors = ""; var returnVal = false; var validate = true; // JScript's best attempt at creating constants... var BADCARD = 0, MC = 1, VISA = 2; var AMEX = 3, DCCB = 4, DISC = 5; var ENROUTE = 6, JCB = 7; // ---------------------------------- // START CREDITCARD OBJECT DEFINITION // ---------------------------------- //global private variable (as best as JScript can do it) //that holds the reason that the card failed validation. var FailedCause = ""; //formal definition of the CreditCard object function CreditCard(num, month, year, date) { //remove -'s or spaces from the card number //interpret the credit card number as a string //regardless of entered data type... var re = /[ \-]*/g var tmpNum = new String(num); this.ccnum = tmpNum.replace(re, ""); //add the entered date (no checks are made to //test the date when entered) this.ccmonth = month; this.ccyear = year; this.ccdate = date; } //return string indicating why card failed verification function GETCCFailureReason() { return FailedCause; } //returns entered ccnumber function GETCCNumber() { return this.ccnum; } //returns entered ccexpiration date function GETCCExpirationDate() { return this.ccdate; } //tests something passed with a passed regular expression function testCCPrefix(match, pattern) { var re = pattern return re.test(match); } //determines the type of credit card - also validates //the card by prefix. If this function returns 0, //the card is definitely not valid... otherwise it //returns a constant representing a Credit Card type //constant from above... function GETCCPrefix() { var cc = this.ccnum; var prefix = ""; if (cc.length < 13) { FailedCause = "failed due to bad card number - length"; return 0; } // MASTERCARD prefix = cc.substring(0,2); if (cc.length == 16 && prefix >= "51" && prefix <= "55") return MC; // VISA prefix = cc.substring(0,1); if ((cc.length == 13 || cc.length == 16 ) && prefix == "4") return VISA; // AMEX prefix = cc.substring(0,2); if (prefix == "34" || prefix == "37") return AMEX; // DCCB prefix = cc.substring(0,2); if (cc.length == 14 && (prefix == "36" || prefix == "38" || prefix == "30") ) return DCCB; // DISC prefix = cc.substring(0,4); if (cc.length == 16 && prefix == "6011") return DISC; // ENROUTE prefix = cc.substring(0,4); if (prefix == "2014" || prefix == "2149") return ENROUTE; // JCB prefix = cc.substring(0,4); if (prefix == "2131" || prefix == "1800") return JCB; prefix = cc.substring(0,1); if (prefix == "3" ) return JCB; FailedCause = "failed due to bad card number"; return 0; } //returns the credit card type as a string based on the //return code of GETCCPrefix( ) method function resolveCCType(ccCode) { switch(ccCode) { case MC: return "MasterCard"; case VISA: return "Visa"; case AMEX: return "American Express"; case DCCB: return "Diner's Club/Carte Blanche"; case DISC: return "Discover"; case ENROUTE: return "EnRoute"; case JCB: return "JCB"; default: return "Bad Card Prefix"; } } //returns last 4 digits of the entered ccnumber function GETLast4Digits() { var re = /(\d{4})$/ var arr = re.exec(this.ccnum); return RegExp.$1; } //determines if a number is odd... function isOdd(n) { return CBool(n %= 2); } //converts numbers to boolean function CBool(exp) { if (exp > 0) {return true;} return false; } //performs a mod10 validation on an entered ccnumber function mod10validation(cc) { var s = strReverse(cc), hOut = 0, t = ""; for (var i = 0;i < s.length; i++) { if (isOdd(i+1)) { hOut += parseInt(s.charAt(i)); } else { t = parseInt(s.charAt(i)) * 2; if (t > 9) {t -= 9;} hOut += parseInt(t); } } if (hOut % 10 == 0) {return true;} FailedCause = "failed credit card validation"; return false; } //reverses a string function strReverse(s) { var o = ""; for (var i = s.length; i > -1; i--) { o += s.charAt(i); } return o; } //validate card number and expiration date function validateCardDetails() { if (mod10validation(this.ccnum)) { //mod 10 valid - must check dates return checkExpirationDate(this.ccmonth, this.ccyear) } else { //mod 10 failed - no need to check dates return false; } } //test expiration date function checkExpirationDate(enteredMonth, enteredYear) { //first check year. //if entered year is larger than today's year, it's valid //if years match, check months... //if today's month is greater or equal to entered //month, it's valid. anything else - invalid //handy regular expression to remember the month and year //input and keep them separate... Regular expressions rule! // var re = /(\d{1,2})[ \-\/](\d{4})/ // var arr = re.exec(d); // var enteredMonth = parseInt(RegExp.$1); // var enteredYear = parseInt(RegExp.$2); // var tmpDate = new Date(); // use the server date not the clients var thisMonth = g_current_month; var thisYear = g_current_year; //alert(tmpDate); //var thisMonth = tmpDate.GETMonth( ) + 1; //var thisYear = tmpDate.GETYear( ); if (enteredYear > thisYear) {return true;} if (enteredYear == thisYear) { if (enteredMonth >= thisMonth) {return true;} } FailedCause = "failed date validation - expired card"; return false; } //return version information about this object function CreditCardObject_Version() { return "3.5"; } //publicly exported methods... //returns ccnumber CreditCard.prototype.GETNumber = GETCCNumber; //return ccdate CreditCard.prototype.GETExpirationDate = GETCCExpirationDate; //returns cctype constant CreditCard.prototype.GETPrefix = GETCCPrefix; //returns the real name of a cc based on it's constant CreditCard.prototype.GETRealName = resolveCCType; //returns the results of a mod10 validation CreditCard.prototype.isValid = validateCardDetails; //returns the last 4 numbers of the CC CreditCard.prototype.GETLast4Digits = GETLast4Digits; //returns the reason why the entered card failed... CreditCard.prototype.GETFailureMessage = GETCCFailureReason; //returns version info... CreditCard.prototype.CreditCardObject_Version = CreditCardObject_Version; // ---------------------------------- // END CREDITCARD OBJECT DEFINITION // ---------------------------------- // ----------------------------------------------------------------------------- // define - Call this function in the beginning of the page. I.e. onLoad. // n = name of the input field (Required) // type= text, textarea, num, email, date, futuredate (Required) // min = the value must have at least [min] characters (Optional) // max = the value must have maximum [max] characters (Optional) // d = (Optional) // ----------------------------------------------------------------------------- function define(n, type, HTMLname, optional, min, max, d) { var p; var i; var x; var elemname = n; if (!d) d = document; if ((p=n.indexOf("?"))>0&&parent.frames.length) { d = parent.frames[n.substring(p+1)].document; n = n.substring(0,p); } if (!(x = d[n]) && d.all) x = d.all[n]; for (i = 0; !x && i < d.forms.length; i++) { x = d.forms[i][n]; } for (i = 0; !x && d.layers && i < d.layers.length; i++) { x = define(n, type, HTMLname, min, max, d.layers[i].document); return x; } eval("V_"+n+" = new formResult(elemname, x, type, HTMLname, optional, min, max);"); checkObjects[eval(checkObjects.length)] = eval("V_"+n); } function formResult(elemname, form, type, HTMLname, required, min, max ) { this.elemname = elemname; this.form = form; this.type = type; this.HTMLname = HTMLname; this.required = required; this.min = min; this.max = max; } function verifydate(datestr, afterToday){ window.onerror=null // for all other strange errors var err=0; var psj=0; a=datestr; if (a.length != 10) err=1 mm = a.substring(0, 2)// month c = a.substring(2, 3)// '/' dd = a.substring(3, 5)// day e = a.substring(5, 6)// '/' yy = a.substring(6, 10)// year //basic error checking if (mm<1 || mm>12) err = 1 if (c != '/') err = 1 if (dd<1 || dd>31) err = 1 if (e != '/') err = 1 if (yy<0 || yy>10000) err = 1 //advanced error checking // months with 30 days if (mm==4 || mm==6 || mm==9 || mm==11){ if (dd==31) err=1 } // february, leap year if (mm==2){ // feb var g=parseInt(yy/4) if (isNaN(g)) { err=1 } if (dd>29) err=1 if (dd==29 && ((yy/4)!=parseInt(yy/4))) err=1 } /* // make this a 4-digit year if (yy >= 90) yy = 19 + yy; else yy = 20 + yy; */ // check if after todays date if requested if (afterToday) { // define todays date and the date to compare against var now = new Date(); var cdate = new Date(); // set the comparison date cdate.setMonth(mm - 1); // months start with 0 cdate.setDate(dd); cdate.setFullYear(yy); // create a variable that concat's the numbers toGETher var cdatefull = cdate.GETTime(); var nowfull = now.GETTime(); // provided date is after today's date if (cdatefull <= nowfull) err=1; } if (err==1) return false; else return true; } // A utility function that returns true if a string contains only // whitespace characters. function isblank(s) { for(var i = 0; i < s.length; i++) { var c = s.charAt(i); if ((c != ' ') && (c != '\n') && (c != '\t')) return false; } return true; } function displayData(text) { alert(text); } var expire_month = ""; var expire_year = ""; // This is the function that performs form verification. It will be invoked // from the onSubmit() event handler. The handler should return whatever // value this function returns. // function verify(f) { var msg; var empty_fields = ""; var errors = ""; var elementerrors = ""; var elem = ""; var oCC = ""; if (!validate) { returnVal = true; return true; } if (checkObjects.length > 0) { // Loop through the elements of the form, looking for all // text and textarea elements that don't have an "optional" property // defined. Then, check for fields that are empty and make a list of them. // Also, if any of these elements have a "min" or a "max" property defined, // then verify that they are numbers and that they are in the right range. // Put toGETher error messages for fields that are wrong. // for (i = 0; i < checkObjects.length; i++) { // GET the element object from the array // elem = new Object(); elem.elemname = checkObjects[i].elemname; // First check if the element name that was define in the HTML // page init function is a valid element name // var found = false; for(var x = 0; x < f.length; x++) { var e = f.elements[x]; if (e.name == elem.elemname) { found = true; break; } } // if we did not find it report a program error and skip processing // that element // if (!found) { elementerrors += "\n " + elem.elemname; continue; } // finish GETting the rest of the element data // elem.form = checkObjects[i].form; elem.HTMLname = checkObjects[i].HTMLname; elem.min = checkObjects[i].min; elem.max = checkObjects[i].max; elem.type = checkObjects[i].type; elem.required = checkObjects[i].required; // Assign the value of the gadGET // elem.value = checkObjects[i].form.value; does not work in all cases // switch (elem.type) { case 'checkbox' : for (var x=0;x < elem.form.length;x++) { var cmd = "elem.form."+ elem.elemname + "[x].checked"; if (eval(cmd)) { var cmd = "elem.form."+ elem.elemname + "[x].value"; elem.value = eval(cmd); //break; // only GET first checked item } } break; case 'radio' : for (var x=0;x < elem.form.length;x++) { var cmd = "elem.form."+ elem.elemname + "[x].checked"; if (eval(cmd)) { elem.value = "checked"; } } break; case 'selectbox': if (checkObjects[i].form.selectedIndex != -1) { elem.value = checkObjects[i].form.options[checkObjects[i].form.selectedIndex].text; } if (elem.elemname == "store_expire_month") { expire_month = elem.value; } else if (elem.elemname == "store_expire_year") { expire_year = elem.value; } break; case 'specialcheckbox' : for (var x=0;x < elem.form.length;x++) { var cmd = "elem.form."+ elem.elemname + "[x].checked"; if (eval(cmd)) { var cmd = "elem.form."+ elem.elemname + "[x].value"; elem.value = eval(cmd); //break; // only GET first checked item } } break; default : elem.len = checkObjects[i].form.value.length; elem.value = checkObjects[i].form.value; break; } // Check if the required element contains any data // if ((elem.value == null) || (elem.value == "") || isblank(elem.value)) { if (elem.required) { empty_fields += "\n " + elem.HTMLname; continue; } } // we have data // else { // Now we know that a value exists, check for correct contents switch (elem.type) { case 'text' : if (((elem.min != null) && (elem.len < elem.min)) || ((elem.max != null) && (elem.len > elem.max))) { errors += "- The field '" + elem.HTMLname + "' must be a string"; if (elem.min != null) errors += " that is greater than " + elem.min; if (elem.max != null && elem.min != null) errors += " and less than " + elem.max; else if (elem.max != null) errors += " that is less than " + elem.max; errors += " characters.\n"; } break; case 'number' : var v = parseFloat(elem.value); if (isNaN(v) || ((elem.min != null) && (v < elem.min)) || ((elem.max != null) && (v > elem.max))) { errors += "- The field '" + elem.HTMLname + "' must be a number"; if (elem.min != null) errors += " that is greater than " + elem.min; if (elem.max != null && elem.min != null) errors += " and less than " + elem.max; else if (elem.max != null) errors += " that is less than " + elem.max; errors += ".\n"; } break; case 'date' : if (!verifydate(elem.value, false)) { errors += "- The field '" + elem.HTMLname + "' must be a valid date (MM/DD/YYYY).\n"; } break; case 'futuredate' : if (!verifydate(elem.value, false)) { errors += "- The field '" + elem.HTMLname + "' must be valid date (MM/DD/YYYY)"; errors += " after today's date.\n"; } else if (!verifydate(elem.value, true)) { errors += "- The field '" + elem.HTMLname + "' must be after today's date.\n"; } break; case 'email' : // Checking existense of "@" and ".". // Length of must >= 5 and the "." must // not directly precede or follow the "@" if ((elem.value.indexOf("@") == -1) || (elem.value.charAt(0) == ".") || (elem.value.charAt(0) == "@") || (elem.len < 6) || (elem.value.indexOf(".") == -1) || (elem.value.charAt(elem.value.indexOf("@")+1) == ".") || (elem.value.charAt(elem.value.indexOf("@")-1) == ".")) { errors += "- The field '" + elem.HTMLname + "' must be valid email address."; } break; case 'selectbox' : if (elem.value == "Select State") { errors += "- The field '" + elem.HTMLname + "' must be a valid state."; } break; case 'creditcard' : oCC = new CreditCard(elem.value, expire_month, expire_year, expire_month + "/" + expire_year); //oCC = new CreditCard(elem.value, "12/2008"); if ( oCC.GETPrefix() == 0 ) { errors += "- The field 'Credit Card Number Invalid: "; errors += oCC.GETFailureMessage(); } else if (oCC.GETPrefix() == 4 || oCC.GETPrefix() == 6 || oCC.GETPrefix() == 7) { errors += "- The field 'Credit Card Number: " + oCC.GETRealName(oCC.GETPrefix()) + "\n"; errors += " We only except Visa/MasterCard/American Express/Discover"; } else if (!oCC.isValid( )) { errors += "- The field 'Credit Card' Invalid: "; errors += oCC.GETFailureMessage(); } break; case 'checkbox' : break; case 'specialcheckbox' : // need to GET the id from the checkbox value and // check if a vendor and needdate is selected and // the correct value (future date) for (var x=0;x < elem.form.length;x++) { // check if the checkbox is checked var cmd = "elem.form."+ elem.elemname + "[x].checked"; if (eval(cmd)) { // GET the value cmd = "elem.form."+ elem.elemname + "[x].value"; var elementid = eval(cmd); // verify that a vendor and needdate has been selected // here since I have the element id now. // if (elementid != null && elementid != undefined) { // Only need to check if more than one vendor // if (eval("document.the_form.Vendor_"+elementid+".length") >1) { // check if at least one vendor is selected var checked=false; for (var x=0;x < eval("document.the_form.Vendor_"+elementid+".length");x++) { cmd = "document.the_form.Vendor_"+ elementid + "[x].checked"; if (eval(cmd)) { checked = true; } } if (!checked) { errors += "- The field 'Vendor' must have at least one check per selected element.\n"; } } // check need date cmd = "document.the_form.NeedDate_"+elementid +".value"; var needdate= eval(cmd); // check if this required date exists if ((needdate == null) || (needdate == "") || isblank(needdate)) { empty_fields += "\n Need Date"; continue; } else if (!verifydate(needdate, false)) { errors += "- The field '" + elem.HTMLname + "' must be valid date (MM/DD/YYYY)"; errors += " after today's date.\n"; } else if (!verifydate(needdate, true)) { errors += "- The field '" + elem.HTMLname + "' must be after today's date.\n"; } } } } break; default : break; } } } } // Now, if there were any errors, display the messages, and // return false to prevent the form from being submitted. // Otherwise return true. if (!empty_fields && !errors) { returnVal = true; return true; } msg = "______________________________________________________\n\n" msg += "The form was not submitted because of the following error(s).\n"; msg += "Please correct these error(s) and re-submit.\n"; msg += "______________________________________________________\n\n" if (empty_fields) { msg += "- The following required field(s) are empty:" + empty_fields + "\n\n"; if (errors) msg += "\n"; } if (elementerrors) { msg += "- The following element(s) do not exist on page (Programming Error):" + elementerrors + "\n"; if (errors) msg += "\n"; } msg += errors; alert(msg); returnVal = false; return false; }