1// FormChek.js 2// 3// SUMMARY 4// 5// This is a set of JavaScript functions for validating input on 6// an HTML form. Functions are provided to validate: 7// 8// - U.S. and international phone/fax numbers 9// - U.S. ZIP codes (5 or 9 digit postal codes) 10// - U.S. Postal Codes (2 letter abbreviations for names of states) 11// - U.S. Social Security Numbers (abbreviated as SSNs) 12// - email addresses 13// - dates (entry of year, month, and day and validity of combined date) 14// - credit card numbers 15// 16// Supporting utility functions validate that: 17// 18// - characters are Letter, Digit, or LetterOrDigit 19// - strings are a Signed, Positive, Negative, Nonpositive, or 20// Nonnegative integer 21// - strings are a Float or a SignedFloat 22// - strings are Alphabetic, Alphanumeric, or Whitespace 23// - strings contain an integer within a specified range 24// 25// Functions are also provided to interactively check the 26// above kinds of data and prompt the user if they have 27// been entered incorrectly. 28// 29// Other utility functions are provided to: 30// 31// - remove from a string characters which are/are not 32// in a "bag" of selected characters 33// - reformat a string, adding delimiter characters 34// - strip whitespace/leading whitespace from a string 35// - reformat U.S. phone numbers, ZIP codes, and Social 36// Security numbers 37// 38// 39// Many of the below functions take an optional parameter eok (for "emptyOK") 40// which determines whether the empty string will return true or false. 41// Default behavior is controlled by global variable defaultEmptyOK. 42// 43// BASIC DATA VALIDATION FUNCTIONS: 44// 45// isWhitespace (s) Check whether string s is empty or whitespace. 46// isLetter (c) Check whether character c is an English letter 47// isDigit (c) Check whether character c is a digit 48// isLetterOrDigit (c) Check whether character c is a letter or digit. 49// isInteger (s [,eok]) True if all characters in string s are numbers. 50// isSignedInteger (s [,eok]) True if all characters in string s are numbers; leading + or - allowed. 51// isPositiveInteger (s [,eok]) True if string s is an integer > 0. 52// isNonnegativeInteger (s [,eok]) True if string s is an integer >= 0. 53// isNegativeInteger (s [,eok]) True if s is an integer < 0. 54// isNonpositiveInteger (s [,eok]) True if s is an integer <= 0. 55// isFloat (s [,eok]) True if string s is an unsigned floating point (real) number. (Integers also OK.) 56// isSignedFloat (s [,eok]) True if string s is a floating point number; leading + or - allowed. (Integers also OK.) 57// isAlphabetic (s [,eok]) True if string s is English letters 58// isAlphanumeric (s [,eok]) True if string s is English letters and numbers only. 59// 60// isSSN (s [,eok]) True if string s is a valid U.S. Social Security Number. 61// isUSPhoneNumber (s [,eok]) True if string s is a valid U.S. Phone Number. 62// isInternationalPhoneNumber (s [,eok]) True if string s is a valid international phone number. 63// isZIPCode (s [,eok]) True if string s is a valid U.S. ZIP code. 64// isStateCode (s [,eok]) True if string s is a valid U.S. Postal Code 65// isEmail (s [,eok]) True if string s is a valid email address. 66// isYear (s [,eok]) True if string s is a valid Year number. 67// isIntegerInRange (s, a, b [,eok]) True if string s is an integer between a and b, inclusive. 68// isMonth (s [,eok]) True if string s is a valid month between 1 and 12. 69// isDay (s [,eok]) True if string s is a valid day between 1 and 31. 70// daysInFebruary (year) Returns number of days in February of that year. 71// isDate (year, month, day) True if string arguments form a valid date. 72 73 74// FUNCTIONS TO REFORMAT DATA: 75// 76// stripCharsInBag (s, bag) Removes all characters in string bag from string s. 77// stripCharsNotInBag (s, bag) Removes all characters NOT in string bag from string s. 78// stripWhitespace (s) Removes all whitespace characters from s. 79// stripInitialWhitespace (s) Removes initial (leading) whitespace characters from s. 80// reformat (TARGETSTRING, STRING, Function for inserting formatting characters or
81// INTEGER, STRING, INTEGER ... ) delimiters into TARGETSTRING. 82// reformatZIPCode (ZIPString) If 9 digits, inserts separator hyphen. 83// reformatSSN (SSN) Reformats as 123-45-6789. 84// reformatUSPhone (USPhone) Reformats as (123) 456-789. 85 86 87// FUNCTIONS TO PROMPT USER: 88// 89// prompt (s) Display prompt string s in status bar. 90// promptEntry (s) Display data entry prompt string s in status bar. 91// warnEmpty (theField, s) Notify user that required field theField is empty. 92// warnInvalid (theField, s) Notify user that contents of field theField are invalid. 93 94 95// FUNCTIONS TO INTERACTIVELY CHECK FIELD CONTENTS: 96// TOM checkInteger (theField [,eok]) Check that theField.value is a valid Number. 97// TOM checkIntegerRange (theField, a, b [,eok]) Check that theField.value is a valid Number. 98// checkString (theField, s [,eok]) Check that theField.value is not empty or all whitespace. 99// checkStateCode (theField) Check that theField.value is a valid U.S. state code. 100// checkZIPCode (theField [,eok]) Check that theField.value is a valid ZIP code. 101// checkUSPhone (theField [,eok]) Check that theField.value is a valid US Phone. 102// checkInternationalPhone (theField [,eok]) Check that theField.value is a valid International Phone. 103// checkEmail (theField [,eok]) Check that theField.value is a valid Email. 104// checkSSN (theField [,eok]) Check that theField.value is a valid SSN. 105// checkYear (theField [,eok]) Check that theField.value is a valid Year. 106// checkMonth (theField [,eok]) Check that theField.value is a valid Month. 107// checkDay (theField [,eok]) Check that theField.value is a valid Day. 108// checkDate (yearField, monthField, dayField, labelString, OKtoOmitDay) 109// Check that field values form a valid date. 110// getRadioButtonValue (radio) Get checked value from radio button. 111// checkCreditCard (radio, theField) Validate credit card info. 112 113 114// CREDIT CARD DATA VALIDATION FUNCTIONS 115// 116// isCreditCard (st) True if credit card number passes the Luhn Mod-10 test. 117// isVisa (cc) True if string cc is a valid VISA number. 118// isMasterCard (cc) True if string cc is a valid MasterCard number. 119// isAmericanExpress (cc) True if string cc is a valid American Express number. 120// isDinersClub (cc) True if string cc is a valid Diner's Club number. 121// isCarteBlanche (cc) True if string cc is a valid Carte Blanche number. 122// isDiscover (cc) True if string cc is a valid Discover card number. 123// isEnRoute (cc) True if string cc is a valid enRoute card number. 124// isJCB (cc) True if string cc is a valid JCB card number. 125// isAnyCard (cc) True if string cc is a valid card number for any of the accepted types. 126// isCardMatch (Type, Number) True if Number is valid for credic card of type Type. 127// 128// Other stub functions are retained for backward compatibility with LivePayment code. 129// See comments below for details. 130// 131// Performance hint: when you deploy this file on your website, strip out the 132// comment lines from the source code as well as any of the functions which 133// you don't need. This will give you a smaller .js file and achieve faster 134// downloads. 135// 136// 18 Feb 97 created Eric Krock 137// 138// (c) 1997 Netscape Communications Corporation 139 140 141 142// VARIABLE DECLARATIONS 143 144var digits = "0123456789"; 145 146var lowercaseLetters = "abcdefghijklmnopqrstuvwxyz" 147 148var uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 149 150 151// whitespace characters 152var whitespace = " \t\n\r"; 153 154 155// decimal point character differs by language and culture 156var decimalPointDelimiter = "." 157 158 159// non-digit characters which are allowed in phone numbers 160var phoneNumberDelimiters = "()- "; 161 162 163// characters which are allowed in US phone numbers 164var validUSPhoneChars = digits + phoneNumberDelimiters; 165 166 167// characters which are allowed in international phone numbers 168// (a leading + is OK) 169var validWorldPhoneChars = digits + phoneNumberDelimiters + "+"; 170 171 172// non-digit characters which are allowed in 173// Social Security Numbers 174var SSNDelimiters = "- "; 175 176 177 178// characters which are allowed in Social Security Numbers 179var validSSNChars = digits + SSNDelimiters; 180 181 182 183// U.S. Social Security Numbers have 9 digits. 184// They are formatted as 123-45-6789. 185var digitsInSocialSecurityNumber = 9; 186 187 188 189// U.S. phone numbers have 10 digits. 190// They are formatted as 123 456 7890 or (123) 456-7890. 191var digitsInUSPhoneNumber = 10; 192 193 194 195// non-digit characters which are allowed in ZIP Codes 196var ZIPCodeDelimiters = "-"; 197 198 199
200// our preferred delimiter for reformatting ZIP Codes 201var ZIPCodeDelimeter = "-" 202 203 204// characters which are allowed in Social Security Numbers 205var validZIPCodeChars = digits + ZIPCodeDelimiters 206 207 208 209// U.S. ZIP codes have 5 or 9 digits. 210// They are formatted as 12345 or 12345-6789. 211var digitsInZIPCode1 = 5 212var digitsInZIPCode2 = 9 213 214 215// non-digit characters which are allowed in credit card numbers 216var creditCardDelimiters = " " 217 218 219// CONSTANT STRING DECLARATIONS 220// (grouped for ease of translation and localization) 221 222// m is an abbreviation for "missing" 223 224var mPrefix = "You did not enter a value into the " 225var mSuffix = " field. This is a required field. Please enter it now." 226 227// s is an abbreviation for "string" 228 229var sUSLastName = "Last Name" 230var sUSFirstName = "First Name" 231var sWorldLastName = "Family Name" 232var sWorldFirstName = "Given Name" 233var sTitle = "Title" 234var sCompanyName = "Company Name" 235var sUSAddress = "Street Address" 236var sWorldAddress = "Address" 237var sCity = "City" 238var sStateCode = "State Code" 239var sWorldState = "State, Province, or Prefecture" 240var sCountry = "Country" 241var sZIPCode = "ZIP Code" 242var sWorldPostalCode = "Postal Code" 243var sPhone = "Phone Number" 244var sFax = "Fax Number" 245var sDateOfBirth = "Date of Birth" 246var sExpirationDate = "Expiration Date" 247var sEmail = "Email" 248var sSSN = "Social Security Number" 249var sCreditCardNumber = "Credit Card Number" 250var sOtherInfo = "Other Information" 251 252 253 254 255// i is an abbreviation for "invalid" 256 257var iStateCode = "This field must be a valid two character U.S. state abbreviation (like CA for California). Please reenter it now." 258var iZIPCode = "This field must be a 5 or 9 digit U.S. ZIP Code (like 94043). Please reenter it now." 259var iUSPhone = "This field must be a 10 digit U.S. phone number (like 415 555 1212). Please reenter it now." 260var iWorldPhone = "This field must be a valid international phone number. Please reenter it now." 261var iSSN = "This field must be a 9 digit U.S. social security number (like 123 45 6789). Please reenter it now." 262var iEmail = "This field must be a valid email address. Please Try Again." 263var iCreditCardPrefix = "This is not a valid " 264var iCreditCardSuffix = " credit card number. (Click the link on this form to see a list of sample numbers.) Please reenter it now." 265var iDay = "This field must be a day number between 1 and 31. Please reenter it now." 266var iMonth = "This field must be a month number between 1 and 12. Please reenter it now." 267var iYear = "This field must be a 4 digit year number. Please reenter it now." 268var iDatePrefix = "The Day, Month, and Year for " 269var iDateSuffix = " do not form a valid date. Please reenter them now." 270var iInteger = "This field must be a valid number." 271 272 273 274// p is an abbreviation for "prompt" 275 276var pEntryPrompt = "Please enter a " 277var pStateCode = "2 character code (like CA)." 278var pZIPCode = "5 or 9 digit U.S. ZIP Code (like 94043)." 279var pUSPhone = "10 digit U.S. phone number (like 415 555 1212)." 280var pWorldPhone = "international phone number." 281var pSSN = "9 digit U.S. social security number (like 123 45 6789)." 282var pEmail = "valid email address (like [email protected])." 283var pCreditCard = "valid credit card number." 284var pDay = "day number between 1 and 31." 285var pMonth = "month number between 1 and 12." 286var pYear = "2 or 4 digit year number." 287 288 289// Global variable defaultEmptyOK defines default return value 290// for many functions when they are passed the empty string. 291// By default, they will return defaultEmptyOK. 292// 293// defaultEmptyOK is false, which means that by default, 294// these functions will do "strict" validation. Function 295// isInteger, for example, will only return true if it is 296// passed a string containing an integer; if it is passed 297// the empty string, it will return false. 298// 299// You can change this default behavior globally (for all 300// functions which use defaultEmptyOK) by changing the value 301// of defaultEmptyOK. 302// 303// Most of these functions have an optional argument emptyOK 304// which allows you to override the default behavior for 305// the duration of a function call. 306// 307// This functionality is useful because it is possible to 308// say "if the user puts anything in this field, it must 309// be an integer (or a phone number, or a string, etc.), 310// but it's OK to leave the field empty too." 311// This is the case for fields which are optional but which
312// must have a certain kind of content if filled in. 313 314var defaultEmptyOK = false 315 316 317 318 319// Attempting to make this library run on Navigator 2.0, 320// so I'm supplying this array creation routine as per 321// JavaScript 1.0 documentation. If you're using 322// Navigator 3.0 or later, you don't need to do this; 323// you can use the Array constructor instead. 324 325 function makeArray(n) { 326 //*** BUG: If I put this line in, I get two error messages: 327 //(1) Window.length can't be set by assignment 328 //(2) daysInMonth has no property indexed by 4 329 //If I leave it out, the code works fine. 330 // this.length = n; 331 var o = {}; 332 for (var i = 1; i <= n; i++) { 333 o[this[i]] = 0; 334 } 335 return o; 336 } 337 338 339 340var daysInMonth = makeArray(12); 341daysInMonth[1] = 31; 342daysInMonth[2] = 29; // must programmatically check this 343daysInMonth[3] = 31; 344daysInMonth[4] = 30; 345daysInMonth[5] = 31; 346daysInMonth[6] = 30; 347daysInMonth[7] = 31; 348daysInMonth[8] = 31; 349daysInMonth[9] = 30; 350daysInMonth[10] = 31; 351daysInMonth[11] = 30; 352daysInMonth[12] = 31; 353 354 355 356 357// Valid U.S. Postal Codes for states, territories, armed forces, etc. 358// See http://www.usps.gov/ncsc/lookups/abbr_state.txt. 359 360var USStateCodeDelimiter = "|"; 361var USStateCodes = "AL|AK|AS|AZ|AR|CA|CO|CT|DE|DC|FM|FL|GA|GU|HI|ID|IL|IN|IA|KS|KY|LA|ME|MH|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|MP|OH|OK|OR|PW|PA|PR|RI|SC|SD|TN|TX|UT|VT|VI|VA|WA|WV|WI|WY|AE|AA|AE|AE|AP" 362 363 364 365 366// Check whether string s is empty. 367 368function isEmpty(s) 369{ return ((s == null) || (s.length == 0)) 370} 371 372 373 374// Returns true if string s is empty or 375// whitespace characters only. 376 377function isWhitespace (s) 378 379{ var i; 380 381 // Is s empty? 382 if (isEmpty(s)) return true; 383 384 // Search through string's characters one by one 385 // until we find a non-whitespace character. 386 // When we do, return false; if we don't, return true. 387 388 for (i = 0; i < s.length; i++) 389 { 390 // Check that current character isn't whitespace. 391 var c = s.charAt(i); 392 393 if (whitespace.indexOf(c) == -1) return false; 394 } 395 396 // All characters are whitespace. 397 return true; 398} 399 400 401 402// Removes all characters which appear in string bag from string s. 403 404function stripCharsInBag (s, bag) 405 406{ var i; 407 var returnString = ""; 408 409 // Search through string's characters one by one. 410 // If character is not in bag, append to returnString. 411 412 for (i = 0; i < s.length; i++) 413 { 414 // Check that current character isn't whitespace. 415 var c = s.charAt(i); 416 if (bag.indexOf(c) == -1) returnString += c; 417 } 418 419 return returnString; 420} 421 422 423 424// Removes all characters which do NOT appear in string bag 425// from string s. 426 427function stripCharsNotInBag (s, bag) 428 429{ var i; 430 var returnString = ""; 431 432 // Search through string's characters one by one. 433 // If character is in bag, append to returnString. 434 435 for (i = 0; i < s.length; i++) 436 { 437 // Check that current character isn't whitespace. 438 var c = s.charAt(i); 439 if (bag.indexOf(c) != -1) returnString += c; 440 } 441 442 return returnString; 443} 444 445 446 447// Removes all whitespace characters from s. 448// Global variable whitespace (see above) 449// defines which characters are considered whitespace. 450 451function stripWhitespace (s) 452 453{ return stripCharsInBag (s, whitespace) 454} 455 456 457 458 459// WORKAROUND FUNCTION FOR NAVIGATOR 2.0.2 COMPATIBILITY. 460// 461// The below function *should* be unnecessary. In general, 462// avoid using it. Use the standard method indexOf instead. 463// 464// However, because of an apparent bug in indexOf on 465// Navigator 2.0.2, the below loop does not work as the 466// body of stripInitialWhitespace: 467// 468// while ((i < s.length) && (whitespace.indexOf(s.charAt(i)) != -1)) 469// i++; 470// 471// ... so we provide this workaround function charInString 472// instead. 473// 474// charInString (CHARACTER c, STRING s) 475// 476// Returns true if single character c (actually a string) 477// is contained within string s. 478 479function charInString (c, s) 480{ for (i = 0; i < s.length; i++) 481 { if (s.charAt(i) == c) return true; 482 } 483 return false 484} 485 486 487 488// Removes initial (leading) whitespace characters from s. 489// Global variable whitespace (see above) 490// defines which characters are considered whitespace. 491 492function stripInitialWhitespace (s) 493 494{ var i = 0; 495 496 while ((i < s.length) && charInString (s.charAt(i), whitespace)) 497 i++; 498 499 return s.substring (i, s.length); 500} 501 502 503 504 505 506 507 508// Returns true if character c is an English letter 509// (A .. Z, a..z). 510// 511// NOTE: Need i18n version to support European characters. 512// This could be tricky due to different character 513// sets and orderings for various languages and platforms. 514 515function isLetter (c) 516{ return ( ((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")) ) 517} 518 519 520 521// Returns true if character c is a digit 522// (0 .. 9). 523 524function isDigit (c) 525{ return ((c >= "0") && (c <= "9")) 526} 527 528 529 530// Returns true if character c is a letter or digit. 531 532function isLetterOrDigit (c) 533{ return (isLetter(c) || isDigit(c)) 534} 535 536 537 538// isInteger (STRING s [, BOOLEAN emptyOK]) 539// 540// Returns true if all characters in string s are numbers. 541// 542// Accepts non-signed integers only. Does not accept floating 543// point, exponential notation, etc. 544// 545// We don't use parseInt because that would accept a string 546// with trailing non-numeric characters. 547// 548// By default, returns defaultEmptyOK if s is empty. 549// There is an optional second argument called emptyOK. 550// emptyOK is used to override for a single function call 551// the default behavior which is specified globally by 552// defaultEmptyOK. 553// If emptyOK is false (or any value other than true), 554// the function will return false if s is empty. 555// If emptyOK is true, the function will return true if s is empty. 556// 557// EXAMPLE FUNCTION CALL: RESULT: 558// isInteger ("5") true 559// isInteger ("") defaultEmptyOK 560// isInteger ("-5") false 561// isInteger ("", true) true 562// isInteger ("", false) false 563// isInteger ("5", false) true 564 565function isInteger (s) 566 567{ var i; 568 569 if (isEmpty(s)) 570 if (isInteger.arguments.length == 1) return defaultEmptyOK; 571 else return (isInteger.arguments[1] == true); 572 573 // Search through string's characters one by one 574 // until we find a non-numeric character. 575 // When we do, return false; if we don't, return true. 576 577 for (i = 0; i < s.length; i++) 578 { 579 // Check that current character is number. 580 var c = s.charAt(i); 581 582 if (!isDigit(c)) return false;
583 } 584 585 // All characters are numbers. 586 return true; 587} 588 589 590 591 592 593 594 595// isSignedInteger (STRING s [, BOOLEAN emptyOK]) 596// 597// Returns true if all characters are numbers; 598// first character is allowed to be + or - as well. 599// 600// Does not accept floating point, exponential notation, etc. 601// 602// We don't use parseInt because that would accept a string 603// with trailing non-numeric characters. 604// 605// For explanation of optional argument emptyOK, 606// see comments of function isInteger. 607// 608// EXAMPLE FUNCTION CALL: RESULT: 609// isSignedInteger ("5") true 610// isSignedInteger ("") defaultEmptyOK 611// isSignedInteger ("-5") true 612// isSignedInteger ("+5") true 613// isSignedInteger ("", false) false 614// isSignedInteger ("", true) true 615 616function isSignedInteger (s) 617 618{ if (isEmpty(s)) 619 if (isSignedInteger.arguments.length == 1) return defaultEmptyOK; 620 else return (isSignedInteger.arguments[1] == true); 621 622 else { 623 var startPos = 0; 624 var secondArg = defaultEmptyOK; 625 626 if (isSignedInteger.arguments.length > 1) 627 secondArg = isSignedInteger.arguments[1]; 628 629 // skip leading + or - 630 if ( (s.charAt(0) == "-") || (s.charAt(0) == "+") ) 631 startPos = 1; 632 return (isInteger(s.substring(startPos, s.length), secondArg)) 633 } 634} 635 636 637 638 639// isPositiveInteger (STRING s [, BOOLEAN emptyOK]) 640// 641// Returns true if string s is an integer > 0. 642// 643// For explanation of optional argument emptyOK, 644// see comments of function isInteger. 645 646function isPositiveInteger (s) 647{ var secondArg = defaultEmptyOK; 648 649 if (isPositiveInteger.arguments.length > 1) 650 secondArg = isPositiveInteger.arguments[1]; 651 652 // The next line is a bit byzantine. What it means is: 653 // a) s must be a signed integer, AND 654 // b) one of the following must be true: 655 // i) s is empty and we are supposed to return true for 656 // empty strings 657 // ii) this is a positive, not negative, number 658 659 return (isSignedInteger(s, secondArg) 660 && ( (isEmpty(s) && secondArg) || (parseInt (s) > 0) ) ); 661} 662 663 664 665 666 667 668// isNonnegativeInteger (STRING s [, BOOLEAN emptyOK]) 669// 670// Returns true if string s is an integer >= 0. 671// 672// For explanation of optional argument emptyOK, 673// see comments of function isInteger. 674 675function isNonnegativeInteger (s) 676{ var secondArg = defaultEmptyOK; 677 678 if (isNonnegativeInteger.arguments.length > 1) 679 secondArg = isNonnegativeInteger.arguments[1]; 680 681 // The next line is a bit byzantine. What it means is: 682 // a) s must be a signed integer, AND 683 // b) one of the following must be true: 684 // i) s is empty and we are supposed to return true for 685 // empty strings 686 // ii) this is a number >= 0 687 688 return (isSignedInteger(s, secondArg) 689 && ( (isEmpty(s) && secondArg) || (parseInt (s) >= 0) ) ); 690} 691 692 693 694 695 696 697// isNegativeInteger (STRING s [, BOOLEAN emptyOK]) 698// 699// Returns true if string s is an integer < 0. 700// 701// For explanation of optional argument emptyOK, 702// see comments of function isInteger. 703 704function isNegativeInteger (s) 705{ var secondArg = defaultEmptyOK; 706 707 if (isNegativeInteger.arguments.length > 1) 708 secondArg = isNegativeInteger.arguments[1]; 709 710 // The next line is a bit byzantine. What it means is: 711 // a) s must be a signed integer, AND 712 // b) one of the following must be true: 713 // i) s is empty and we are supposed to return true for 714 // empty strings 715 // ii) this is a negative, not positive, number 716 717 return (isSignedInteger(s, secondArg) 718 && ( (isEmpty(s) && secondArg) || (parseInt (s) < 0) ) ); 719} 720 721 722 723 724 725 726// isNonpositiveInteger (STRING s [, BOOLEAN emptyOK]) 727// 728// Returns true if string s is an integer <= 0. 729// 730// For explanation of optional argument emptyOK, 731// see comments of function isInteger. 732 733function isNonpositiveInteger (s) 734{ var secondArg = defaultEmptyOK; 735 736 if (isNonpositiveInteger.arguments.length > 1)
737 secondArg = isNonpositiveInteger.arguments[1]; 738 739 // The next line is a bit byzantine. What it means is: 740 // a) s must be a signed integer, AND 741 // b) one of the following must be true: 742 // i) s is empty and we are supposed to return true for 743 // empty strings 744 // ii) this is a number <= 0 745 746 return (isSignedInteger(s, secondArg) 747 && ( (isEmpty(s) && secondArg) || (parseInt (s) <= 0) ) ); 748} 749 750 751 752 753 754// isFloat (STRING s [, BOOLEAN emptyOK]) 755// 756// True if string s is an unsigned floating point (real) number. 757// 758// Also returns true for unsigned integers. If you wish 759// to distinguish between integers and floating point numbers, 760// first call isInteger, then call isFloat. 761// 762// Does not accept exponential notation. 763// 764// For explanation of optional argument emptyOK, 765// see comments of function isInteger. 766 767function isFloat (s) 768 769{ var i; 770 var seenDecimalPoint = false; 771 772 if (isEmpty(s)) 773 if (isFloat.arguments.length == 1) return defaultEmptyOK; 774 else return (isFloat.arguments[1] == true); 775 776 if (s == decimalPointDelimiter) return false; 777 778 // Search through string's characters one by one 779 // until we find a non-numeric character. 780 // When we do, return false; if we don't, return true. 781 782 for (i = 0; i < s.length; i++) 783 { 784 // Check that current character is number. 785 var c = s.charAt(i); 786 787 if ((c == decimalPointDelimiter) && !seenDecimalPoint) seenDecimalPoint = true; 788 else if (!isDigit(c)) return false; 789 } 790 791 // All characters are numbers. 792 return true; 793} 794 795 796 797 798 799 800 801// isSignedFloat (STRING s [, BOOLEAN emptyOK]) 802// 803// True if string s is a signed or unsigned floating point 804// (real) number. First character is allowed to be + or -. 805// 806// Also returns true for unsigned integers. If you wish 807// to distinguish between integers and floating point numbers, 808// first call isSignedInteger, then call isSignedFloat. 809// 810// Does not accept exponential notation. 811// 812// For explanation of optional argument emptyOK, 813// see comments of function isInteger. 814 815function isSignedFloat (s) 816 817{ if (isEmpty(s)) 818 if (isSignedFloat.arguments.length == 1) return defaultEmptyOK; 819 else return (isSignedFloat.arguments[1] == true); 820 821 else { 822 var startPos = 0; 823 var secondArg = defaultEmptyOK; 824 825 if (isSignedFloat.arguments.length > 1) 826 secondArg = isSignedFloat.arguments[1]; 827 828 // skip leading + or - 829 if ( (s.charAt(0) == "-") || (s.charAt(0) == "+") ) 830 startPos = 1; 831 return (isFloat(s.substring(startPos, s.length), secondArg)) 832 } 833} 834 835 836 837 838// isAlphabetic (STRING s [, BOOLEAN emptyOK]) 839// 840// Returns true if string s is English letters 841// (A .. Z, a..z) only. 842// 843// For explanation of optional argument emptyOK, 844// see comments of function isInteger. 845// 846// NOTE: Need i18n version to support European characters. 847// This could be tricky due to different character 848// sets and orderings for various languages and platforms. 849 850function isAlphabetic (s) 851 852{ var i; 853 854 if (isEmpty(s)) 855 if (isAlphabetic.arguments.length == 1) return defaultEmptyOK; 856 else return (isAlphabetic.arguments[1] == true); 857 858 // Search through string's characters one by one 859 // until we find a non-alphabetic character. 860 // When we do, return false; if we don't, return true. 861 862 for (i = 0; i < s.length; i++) 863 { 864 // Check that current character is letter. 865 var c = s.charAt(i); 866 867 if (!isLetter(c)) 868 return false; 869 } 870 871 // All characters are letters. 872 return true; 873} 874 875 876 877 878// isAlphanumeric (STRING s [, BOOLEAN emptyOK]) 879// 880// Returns true if string s is English letters 881// (A .. Z, a..z) and numbers only. 882// 883// For explanation of optional argument emptyOK, 884// see comments of function isInteger. 885// 886// NOTE: Need i18n version to support European characters. 887// This could be tricky due to different character 888// sets and orderings for various languages and platforms. 889 890function isAlphanumeric (s) 891 892{ var i; 893 894 if (isEmpty(s)) 895 if (isAlphanumeric.arguments.length == 1) return defaultEmptyOK; 896 else return (isAlphanumeric.arguments[1] == true); 897 898 // Search through string's characters one by one 899 // until we find a non-alphanumeric character. 900 // When we do, return false; if we don't, return true. 901 902 for (i = 0; i < s.length; i++) 903 { 904 // Check that current character is number or letter. 905 var c = s.charAt(i); 906 907 if (! (isLetter(c) || isDigit(c) ) ) 908 return false;
909 } 910 911 // All characters are numbers or letters. 912 return true; 913} 914 915 916 917 918// reformat (TARGETSTRING, STRING, INTEGER, STRING, INTEGER ... ) 919// 920// Handy function for arbitrarily inserting formatting characters 921// or delimiters of various kinds within TARGETSTRING. 922// 923// reformat takes one named argument, a string s, and any number 924// of other arguments. The other arguments must be integers or 925// strings. These other arguments specify how string s is to be 926// reformatted and how and where other strings are to be inserted 927// into it. 928// 929// reformat processes the other arguments in order one by one. 930// * If the argument is an integer, reformat appends that number 931// of sequential characters from s to the resultString. 932// * If the argument is a string, reformat appends the string 933// to the resultString. 934// 935// NOTE: The first argument after TARGETSTRING must be a string. 936// (It can be empty.) The second argument must be an integer. 937// Thereafter, integers and strings must alternate. This is to 938// provide backward compatibility to Navigator 2.0.2 JavaScript 939// by avoiding use of the typeof operator. 940// 941// It is the caller's responsibility to make sure that we do not 942// try to copy more characters from s than s.length. 943// 944// EXAMPLES: 945// 946// * To reformat a 10-digit U.S. phone number from "1234567890" 947// to "(123) 456-7890" make this function call: 948// reformat("1234567890", "(", 3, ") ", 3, "-", 4) 949// 950// * To reformat a 9-digit U.S. Social Security number from 951// "123456789" to "123-45-6789" make this function call: 952// reformat("123456789", "", 3, "-", 2, "-", 4) 953// 954// HINT: 955// 956// If you have a string which is already delimited in one way 957// (example: a phone number delimited with spaces as "123 456 7890") 958// and you want to delimit it in another way using function reformat, 959// call function stripCharsNotInBag to remove the unwanted 960// characters, THEN call function reformat to delimit as desired. 961// 962// EXAMPLE: 963// 964// reformat (stripCharsNotInBag ("123 456 7890", digits), 965// "(", 3, ") ", 3, "-", 4) 966 967function reformat (s) 968 969{ var arg; 970 var sPos = 0; 971 var resultString = ""; 972 973 for (var i = 1; i < reformat.arguments.length; i++) { 974 arg = reformat.arguments[i]; 975 if (i % 2 == 1) resultString += arg; 976 else { 977 resultString += s.substring(sPos, sPos + arg); 978 sPos += arg; 979 } 980 } 981 return resultString; 982} 983 984 985 986 987// isSSN (STRING s [, BOOLEAN emptyOK]) 988// 989// isSSN returns true if string s is a valid U.S. Social 990// Security Number. Must be 9 digits. 991// 992// NOTE: Strip out any delimiters (spaces, hyphens, etc.) 993// from string s before calling this function. 994// 995// For explanation of optional argument emptyOK, 996// see comments of function isInteger. 997 998function isSSN (s) 999{ if (isEmpty(s)) 1000 if (isSSN.arguments.length == 1) return defaultEmptyOK; 1001 else return (isSSN.arguments[1] == true); 1002 return (isInteger(s) && s.length == digitsInSocialSecurityNumber) 1003} 1004 1005 1006 1007 1008// isUSPhoneNumber (STRING s [, BOOLEAN emptyOK]) 1009// 1010// isUSPhoneNumber returns true if string s is a valid U.S. Phone 1011// Number. Must be 10 digits. 1012// 1013// NOTE: Strip out any delimiters (spaces, hyphens, parentheses, etc.) 1014// from string s before calling this function. 1015// 1016// For explanation of optional argument emptyOK, 1017// see comments of function isInteger. 1018 1019function isUSPhoneNumber (s) 1020{ if (isEmpty(s)) 1021 if (isUSPhoneNumber.arguments.length == 1) return defaultEmptyOK; 1022 else return (isUSPhoneNumber.arguments[1] == true); 1023 return (isInteger(s) && s.length == digitsInUSPhoneNumber) 1024} 1025 1026 1027 1028 1029// isInternationalPhoneNumber (STRING s [, BOOLEAN emptyOK]) 1030// 1031// isInternationalPhoneNumber returns true if string s is a valid 1032// international phone number. Must be digits only; any length OK. 1033// May be prefixed by + character. 1034// 1035// NOTE: A phone number of all zeros would not be accepted. 1036// I don't think that is a valid phone number anyway. 1037// 1038// NOTE: Strip out any delimiters (spaces, hyphens, parentheses, etc.) 1039// from string s before calling this function. You may leave in 1040// leading + character if you wish. 1041// 1042// For explanation of optional argument emptyOK, 1043// see comments of function isInteger. 1044 1045function isInternationalPhoneNumber (s) 1046{ if (isEmpty(s)) 1047 if (isInternationalPhoneNumber.arguments.length == 1) return defaultEmptyOK; 1048 else return (isInternationalPhoneNumber.arguments[1] == true); 1049 return (isPositiveInteger(s)) 1050} 1051 1052 1053 1054 1055// isZIPCode (STRING s [, BOOLEAN emptyOK]) 1056// 1057// isZIPCode returns true if string s is a valid 1058// U.S. ZIP code. Must be 5 or 9 digits only. 1059// 1060// NOTE: Strip out any delimiters (spaces, hyphens, etc.) 1061// from string s before calling this function. 1062// 1063// For explanation of optional argument emptyOK, 1064// see comments of function isInteger. 1065 1066function isZIPCode (s) 1067{ if (isEmpty(s)) 1068 if (isZIPCode.arguments.length == 1) return defaultEmptyOK; 1069 else return (isZIPCode.arguments[1] == true); 1070 return (isInteger(s) && 1071 ((s.length == digitsInZIPCode1) || 1072 (s.length == digitsInZIPCode2))) 1073} 1074 1075 1076 1077 1078 1079// isStateCode (STRING s [, BOOLEAN emptyOK]) 1080// 1081// Return true if s is a valid U.S. Postal Code 1082// (abbreviation for state). 1083// 1084// For explanation of optional argument emptyOK, 1085// see comments of function isInteger. 1086 1087function isStateCode(s) 1088{ if (isEmpty(s)) 1089 if (isStateCode.arguments.length == 1) return defaultEmptyOK; 1090 else return (isStateCode.arguments[1] == true); 1091 return ( (USStateCodes.indexOf(s) != -1) && 1092 (s.indexOf(USStateCodeDelimiter) == -1) ) 1093} 1094 1095 1096 1097 1098// isEmail (STRING s [, BOOLEAN emptyOK]) 1099// 1100// Email address must be of form [email protected] -- in other words: 1101// * there must be at least one character before the @ 1102// * there must be at least one character before and after the . 1103// * the characters @ and . are both required 1104// 1105// For explanation of optional argument emptyOK, 1106// see comments of function isInteger. 1107 1108function isEmail (s) 1109{ if (isEmpty(s)) 1110 if (isEmail.arguments.length == 1) return defaultEmptyOK; 1111 else return (isEmail.arguments[1] == true); 1112 1113 // is s whitespace? 1114 if (isWhitespace(s)) return false;
1115 1116 // there must be >= 1 character before @, so we 1117 // start looking at character position 1 1118 // (i.e. second character) 1119 var i = 1; 1120 var sLength = s.length; 1121 1122 // look for @ 1123 while ((i < sLength) && (s.charAt(i) != "@")) 1124 { i++ 1125 } 1126 1127 if ((i >= sLength) || (s.charAt(i) != "@")) return false; 1128 else i += 2; 1129 1130 // look for . 1131 while ((i < sLength) && (s.charAt(i) != ".")) 1132 { i++ 1133 } 1134 1135 // there must be at least one character after the . 1136 if ((i >= sLength - 1) || (s.charAt(i) != ".")) return false; 1137 else return true; 1138} 1139 1140 1141 1142 1143 1144// isYear (STRING s [, BOOLEAN emptyOK]) 1145// 1146// isYear returns true if string s is a valid 1147// Year number. Must be 2 or 4 digits only. 1148// 1149// For Year 2000 compliance, you are advised 1150// to use 4-digit year numbers everywhere. 1151// 1152// And yes, this function is not Year 10000 compliant, but 1153// because I am giving you 8003 years of advance notice, 1154// I don't feel very guilty about this ... 1155// 1156// For B.C. compliance, write your own function. ;-> 1157// 1158// For explanation of optional argument emptyOK, 1159// see comments of function isInteger. 1160 1161function isYear (s) 1162{ if (isEmpty(s)) 1163 if (isYear.arguments.length == 1) return defaultEmptyOK; 1164 else return (isYear.arguments[1] == true); 1165 if (!isNonnegativeInteger(s)) return false; 1166 return ((s.length == 2) || (s.length == 4)); 1167} 1168 1169 1170 1171// isIntegerInRange (STRING s, INTEGER a, INTEGER b [, BOOLEAN emptyOK]) 1172// 1173// isIntegerInRange returns true if string s is an integer 1174// within the range of integer arguments a and b, inclusive. 1175// 1176// For explanation of optional argument emptyOK, 1177// see comments of function isInteger. 1178 1179 1180function isIntegerInRange (s, a, b) 1181{ if (isEmpty(s)) 1182 if (isIntegerInRange.arguments.length == 1) return defaultEmptyOK; 1183 else return (isIntegerInRange.arguments[1] == true); 1184 1185 // Catch non-integer strings to avoid creating a NaN below, 1186 // which isn't available on JavaScript 1.0 for Windows. 1187 if (!isInteger(s, false)) return false; 1188 1189 // Now, explicitly change the type to integer via parseInt 1190 // so that the comparison code below will work both on 1191 // JavaScript 1.2 (which typechecks in equality comparisons) 1192 // and JavaScript 1.1 and before (which doesn't). 1193 var num = parseInt (s); 1194 return ((num >= a) && (num <= b)); 1195} 1196 1197 1198 1199// isMonth (STRING s [, BOOLEAN emptyOK]) 1200// 1201// isMonth returns true if string s is a valid 1202// month number between 1 and 12. 1203// 1204// For explanation of optional argument emptyOK, 1205// see comments of function isInteger. 1206 1207function isMonth (s) 1208{ if (isEmpty(s)) 1209 if (isMonth.arguments.length == 1) return defaultEmptyOK; 1210 else return (isMonth.arguments[1] == true); 1211 return isIntegerInRange (s, 1, 12); 1212} 1213 1214 1215 1216// isDay (STRING s [, BOOLEAN emptyOK]) 1217// 1218// isDay returns true if string s is a valid 1219// day number between 1 and 31. 1220// 1221// For explanation of optional argument emptyOK, 1222// see comments of function isInteger. 1223 1224function isDay (s) 1225{ if (isEmpty(s)) 1226 if (isDay.arguments.length == 1) return defaultEmptyOK; 1227 else return (isDay.arguments[1] == true); 1228 return isIntegerInRange (s, 1, 31); 1229} 1230 1231 1232 1233// daysInFebruary (INTEGER year) 1234// 1235// Given integer argument year, 1236// returns number of days in February of that year. 1237 1238function daysInFebruary (year) 1239{ // February has 29 days in any year evenly divisible by four, 1240 // EXCEPT for centurial years which are not also divisible by 400. 1241 return ( ((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0) ) ) ? 29 : 28 ); 1242} 1243 1244 1245 1246// isDate (STRING year, STRING month, STRING day) 1247// 1248// isDate returns true if string arguments year, month, and day 1249// form a valid date. 1250// 1251 1252function isDate (year, month, day) 1253{ // catch invalid years (not 2- or 4-digit) and invalid months and days. 1254 if (! (isYear(year, false) && isMonth(month, false) && isDay(day, false))) return false; 1255 1256 // Explicitly change type to integer to make code work in both 1257 // JavaScript 1.1 and JavaScript 1.2. 1258 var intYear = parseInt(year); 1259 var intMonth = parseInt(month); 1260 var intDay = parseInt(day); 1261 1262 // catch invalid days, except for February 1263 if (intDay > daysInMonth[intMonth]) return false; 1264 1265 if ((intMonth == 2) && (intDay > daysInFebruary(intYear))) return false;
1266 1267 return true; 1268} 1269 1270 1271 1272 1273/* FUNCTIONS TO NOTIFY USER OF INPUT REQUIREMENTS OR MISTAKES. */ 1274 1275 1276// Display prompt string s in status bar. 1277 1278function prompt (s) 1279{ window.status = s 1280} 1281 1282 1283 1284// Display data entry prompt string s in status bar. 1285 1286function promptEntry (s) 1287{ window.status = pEntryPrompt + s 1288} 1289 1290 1291 1292 1293// Notify user that required field theField is empty. 1294// String s describes expected contents of theField.value. 1295// Put focus in theField and return false. 1296 1297function warnEmpty (theField, s) 1298{ theField.focus() 1299 alert(mPrefix + s + mSuffix) 1300 return false 1301} 1302 1303 1304 1305// Notify user that contents of field theField are invalid. 1306// String s describes expected contents of theField.value. 1307// Put select theField, pu focus in it, and return false. 1308 1309function warnInvalid (theField, s) 1310{ theField.focus(); 1311 alert(s); 1312 return false; 1313} 1314 1315 1316 1317 1318/* FUNCTIONS TO INTERACTIVELY CHECK VARIOUS FIELDS. */ 1319 1320// checkString (TEXTFIELD theField, STRING s, [, BOOLEAN emptyOK==false]) 1321// 1322// Check that string theField.value is not all whitespace. 1323// 1324// For explanation of optional argument emptyOK, 1325// see comments of function isInteger. 1326 1327function checkString (theField, s, emptyOK) 1328{ // Next line is needed on NN3 to avoid "undefined is not a number" error 1329 // in equality comparison below. 1330 if (checkString.arguments.length == 2) emptyOK = defaultEmptyOK; 1331 if ((emptyOK == true) && (isEmpty(theField.value))) return true; 1332 if (isWhitespace(theField.value)) 1333 return warnEmpty (theField, s); 1334 else return true; 1335} 1336 1337 1338 1339// checkStateCode (TEXTFIELD theField [, BOOLEAN emptyOK==false]) 1340// 1341// Check that string theField.value is a valid U.S. state code. 1342// 1343// For explanation of optional argument emptyOK, 1344// see comments of function isInteger. 1345 1346function checkStateCode (theField, emptyOK) 1347{ if (checkStateCode.arguments.length == 1) emptyOK = defaultEmptyOK; 1348 if ((emptyOK == true) && (isEmpty(theField.value))) return true; 1349 else 1350 { theField.value = theField.value.toUpperCase(); 1351 if (!isStateCode(theField.value, false)) 1352 return warnInvalid (theField, iStateCode); 1353 else return true; 1354 } 1355} 1356 1357 1358 1359// takes ZIPString, a string of 5 or 9 digits; 1360// if 9 digits, inserts separator hyphen 1361 1362function reformatZIPCode (ZIPString) 1363{ if (ZIPString.length == 5) return ZIPString; 1364 else return (reformat (ZIPString, "", 5, "-", 4)); 1365} 1366 1367 1368 1369 1370// checkZIPCode (TEXTFIELD theField [, BOOLEAN emptyOK==false]) 1371// 1372// Check that string theField.value is a valid ZIP code. 1373// 1374// For explanation of optional argument emptyOK, 1375// see comments of function isInteger. 1376 1377function checkZIPCode (theField, emptyOK) 1378{ if (checkZIPCode.arguments.length == 1) emptyOK = defaultEmptyOK; 1379 if ((emptyOK == true) && (isEmpty(theField.value))) return true; 1380 else 1381 { var normalizedZIP = stripCharsInBag(theField.value, ZIPCodeDelimiters) 1382 if (!isZIPCode(normalizedZIP, false)) 1383 return warnInvalid (theField, iZIPCode); 1384 else 1385 { // if you don't want to insert a hyphen, comment next line out 1386 theField.value = reformatZIPCode(normalizedZIP) 1387 return true; 1388 } 1389 } 1390} 1391 1392 1393 1394// takes USPhone, a string of 10 digits 1395// and reformats as (123) 456-789 1396 1397function reformatUSPhone (USPhone) 1398{ return (reformat (USPhone, "(", 3, ") ", 3, "-", 4)) 1399} 1400 1401 1402 1403// checkUSPhone (TEXTFIELD theField [, BOOLEAN emptyOK==false]) 1404// 1405// Check that string theField.value is a valid US Phone. 1406// 1407// For explanation of optional argument emptyOK, 1408// see comments of function isInteger. 1409 1410function checkUSPhone (theField, emptyOK) 1411{ if (checkUSPhone.arguments.length == 1) emptyOK = defaultEmptyOK; 1412 if ((emptyOK == true) && (isEmpty(theField.value))) return true; 1413 else 1414 { var normalizedPhone = stripCharsInBag(theField.value, phoneNumberDelimiters) 1415 if (!isUSPhoneNumber(normalizedPhone, false)) 1416 return warnInvalid (theField, iUSPhone); 1417 else 1418 { // if you don't want to reformat as (123) 456-789, comment next line out 1419 theField.value = reformatUSPhone(normalizedPhone) 1420 return true; 1421 } 1422 } 1423} 1424 1425 1426 1427// checkInternationalPhone (TEXTFIELD theField [, BOOLEAN emptyOK==false]) 1428// 1429// Check that string theField.value is a valid International Phone. 1430// 1431// For explanation of optional argument emptyOK, 1432// see comments of function isInteger. 1433 1434function checkInternationalPhone (theField, emptyOK) 1435{ if (checkInternationalPhone.arguments.length == 1) emptyOK = defaultEmptyOK; 1436 if ((emptyOK == true) && (isEmpty(theField.value))) return true; 1437 else 1438 { if (!isInternationalPhoneNumber(theField.value, false))
1439 return warnInvalid (theField, iWorldPhone); 1440 else return true; 1441 } 1442} 1443 1444 1445 1446// checkEmail (TEXTFIELD theField [, BOOLEAN emptyOK==false]) 1447// 1448// Check that string theField.value is a valid Email. 1449// 1450// For explanation of optional argument emptyOK, 1451// see comments of function isInteger. 1452 1453function checkEmail (theField, emptyOK) 1454{ if (checkEmail.arguments.length == 1) emptyOK = defaultEmptyOK; 1455 if ((emptyOK == true) && (isEmpty(theField.value))) return true; 1456 else if (!isEmail(theField.value, false)) 1457 return warnInvalid (theField, iEmail); 1458 else return true; 1459} 1460 1461 1462 1463// takes SSN, a string of 9 digits 1464// and reformats as 123-45-6789 1465 1466function reformatSSN (SSN) 1467{ return (reformat (SSN, "", 3, "-", 2, "-", 4)) 1468} 1469 1470 1471// Check that string theField.value is a valid SSN. 1472// 1473// For explanation of optional argument emptyOK, 1474// see comments of function isInteger. 1475 1476function checkSSN (theField, emptyOK) 1477{ if (checkSSN.arguments.length == 1) emptyOK = defaultEmptyOK; 1478 if ((emptyOK == true) && (isEmpty(theField.value))) return true; 1479 else 1480 { var normalizedSSN = stripCharsInBag(theField.value, SSNDelimiters) 1481 if (!isSSN(normalizedSSN, false)) 1482 return warnInvalid (theField, iSSN); 1483 else 1484 { // if you don't want to reformats as 123-456-7890, comment next line out 1485 theField.value = reformatSSN(normalizedSSN) 1486 return true; 1487 } 1488 } 1489} 1490 1491 1492 1493 1494// Check that string theField.value is a valid Year. 1495// 1496// For explanation of optional argument emptyOK, 1497// see comments of function isInteger. 1498 1499function checkYear (theField, emptyOK) 1500{ if (checkYear.arguments.length == 1) emptyOK = defaultEmptyOK; 1501 if ((emptyOK == true) && (isEmpty(theField.value))) return true; 1502 if (!isYear(theField.value, false)) 1503 return warnInvalid (theField, iYear); 1504 else return true; 1505} 1506 1507// Check that string theField.value is a valid Number. 1508// 1509// For explanation of optional argument emptyOK, 1510// see comments of function isInteger. 1511 1512function checkInteger (theField, emptyOK) 1513{ if (checkInteger.arguments.length == 1) emptyOK = defaultEmptyOK; 1514 if ((emptyOK == true) && (isEmpty(theField.value))) return true; 1515 if (!isInteger(theField.value, false)) 1516 return warnInvalid (theField, iInteger); 1517 else return true; 1518} 1519 1520// Check that string theField.value is a valid Number in a range. 1521// 1522// For explanation of optional argument emptyOK, 1523// see comments of function isInteger. 1524 1525function checkIntegerRange (theField, lowNum, highNum, emptyOK) 1526{ if (checkIntegerRange.arguments.length == 3) emptyOK = defaultEmptyOK; 1527 if ((emptyOK == true) && (isEmpty(theField.value))) return true; 1528 if (!isIntegerInRange(theField.value, lowNum, highNum)) 1529 return warnInvalid (theField, iInteger); 1530 else return true; 1531} 1532 1533// Check that string theField.value is a valid Month. 1534// 1535// For explanation of optional argument emptyOK, 1536// see comments of function isInteger. 1537 1538function checkMonth (theField, emptyOK) 1539{ if (checkMonth.arguments.length == 1) emptyOK = defaultEmptyOK; 1540 if ((emptyOK == true) && (isEmpty(theField.value))) return true; 1541 if (!isMonth(theField.value, false)) 1542 return warnInvalid (theField, iMonth); 1543 else return true; 1544} 1545 1546 1547// Check that string theField.value is a valid Day. 1548// 1549// For explanation of optional argument emptyOK, 1550// see comments of function isInteger. 1551 1552function checkDay (theField, emptyOK) 1553{ if (checkDay.arguments.length == 1) emptyOK = defaultEmptyOK; 1554 if ((emptyOK == true) && (isEmpty(theField.value))) return true; 1555 if (!isDay(theField.value, false)) 1556 return warnInvalid (theField, iDay); 1557 else return true; 1558} 1559 1560 1561 1562// checkDate (yearField, monthField, dayField, STRING labelString [, OKtoOmitDay==false]) 1563// 1564// Check that yearField.value, monthField.value, and dayField.value 1565// form a valid date. 1566// 1567// If they don't, labelString (the name of the date, like "Birth Date") 1568// is displayed to tell the user which date field is invalid. 1569// 1570// If it is OK for the day field to be empty, set optional argument 1571// OKtoOmitDay to true. It defaults to false. 1572 1573function checkDate (yearField, monthField, dayField, labelString, OKtoOmitDay) 1574{ // Next line is needed on NN3 to avoid "undefined is not a number" error 1575 // in equality comparison below. 1576 if (checkDate.arguments.length == 4) OKtoOmitDay = false;
1577 if (!isYear(yearField.value)) return warnInvalid (yearField, iYear); 1578 if (!isMonth(monthField.value)) return warnInvalid (monthField, iMonth); 1579 if ( (OKtoOmitDay == true) && isEmpty(dayField.value) ) return true; 1580 else if (!isDay(dayField.value)) 1581 return warnInvalid (dayField, iDay); 1582 if (isDate (yearField.value, monthField.value, dayField.value)) 1583 return true; 1584 alert (iDatePrefix + labelString + iDateSuffix) 1585 return false 1586} 1587 1588 1589 1590// Get checked value from radio button. 1591 1592function getRadioButtonValue (radio) 1593{ for (var i = 0; i < radio.length; i++) 1594 { if (radio[i].checked) { break } 1595 } 1596 return radio[i].value 1597} 1598 1599// Get checked value from selected index. 1600function getSelectValue (dropdown) 1601{ return dropdown.options[dropdown.selectedIndex].value 1602} 1603 1604 1605 1606 1607// Validate credit card info. 1608 1609function checkCreditCard (radio, theField) 1610{ var cardType = getRadioButtonValue (radio) 1611 var normalizedCCN = stripCharsInBag(theField.value, creditCardDelimiters) 1612 if (!isCardMatch(cardType, normalizedCCN)) 1613 return warnInvalid (theField, iCreditCardPrefix + cardType + iCreditCardSuffix); 1614 else 1615 { theField.value = normalizedCCN 1616 return true 1617 } 1618} 1619 1620 1621 1622/* ================================================================ 1623 Credit card verification functions 1624 Originally included as Starter Application 1.0.0 in LivePayment. 1625 20 Feb 1997 modified by egk: 1626 changed naming convention to initial lowercase 1627 (isMasterCard instead of IsMasterCard, etc.) 1628 changed isCC to isCreditCard 1629 retained functions named with older conventions from 1630 LivePayment as stub functions for backward 1631 compatibility only 1632 added "AMERICANEXPRESS" as equivalent of "AMEX" 1633 for naming consistency 1634 ================================================================ */ 1635 1636 1637/* ================================================================ 1638 FUNCTION: isCreditCard(st) 1639 1640 INPUT: st - a string representing a credit card number 1641 1642 RETURNS: true, if the credit card number passes the Luhn Mod-10 1643 test. 1644 false, otherwise 1645 ================================================================ */ 1646 1647function isCreditCard(st) { 1648 // Encoding only works on cards with less than 19 digits 1649 if (st.length > 19) 1650 return (false); 1651 1652 sum = 0; mul = 1; l = st.length; 1653 for (i = 0; i < l; i++) { 1654 digit = st.substring(l-i-1,l-i); 1655 tproduct = parseInt(digit ,10)*mul; 1656 if (tproduct >= 10) 1657 sum += (tproduct % 10) + 1; 1658 else 1659 sum += tproduct; 1660 if (mul == 1) 1661 mul++; 1662 else 1663 mul--; 1664 } 1665// Uncomment the following line to help create credit card numbers 1666// 1. Create a dummy number with a 0 as the last digit 1667// 2. Examine the sum written out 1668// 3. Replace the last digit with the difference between the sum and 1669// the next multiple of 10. 1670 1671// document.writeln("<BR>Sum = ",sum,"<BR>"); 1672// alert("Sum = " + sum); 1673 1674 if ((sum % 10) == 0) 1675 return (true); 1676 else 1677 return (false); 1678 1679} // END FUNCTION isCreditCard() 1680 1681 1682 1683/* ================================================================ 1684 FUNCTION: isVisa() 1685 1686 INPUT: cc - a string representing a credit card number 1687 1688 RETURNS: true, if the credit card number is a valid VISA number. 1689 1690 false, otherwise 1691 1692 Sample number: 4111 1111 1111 1111 (16 digits) 1693 ================================================================ */ 1694 1695function isVisa(cc) 1696{ 1697 if (((cc.length == 16) || (cc.length == 13)) && 1698 (cc.substring(0,1) == 4)) 1699 return isCreditCard(cc); 1700 return false; 1701} // END FUNCTION isVisa() 1702 1703 1704 1705 1706/* ================================================================ 1707 FUNCTION: isMasterCard() 1708 1709 INPUT: cc - a string representing a credit card number 1710 1711 RETURNS: true, if the credit card number is a valid MasterCard 1712 number. 1713 1714 false, otherwise 1715 1716 Sample number: 5500 0000 0000 0004 (16 digits) 1717 ================================================================ */ 1718 1719function isMasterCard(cc) 1720{ 1721 firstdig = cc.substring(0,1); 1722 seconddig = cc.substring(1,2); 1723 if ((cc.length == 16) && (firstdig == 5) && 1724 ((seconddig >= 1) && (seconddig <= 5))) 1725 return isCreditCard(cc); 1726 return false;
1727 1728} // END FUNCTION isMasterCard() 1729 1730 1731 1732 1733 1734/* ================================================================ 1735 FUNCTION: isAmericanExpress() 1736 1737 INPUT: cc - a string representing a credit card number 1738 1739 RETURNS: true, if the credit card number is a valid American 1740 Express number. 1741 1742 false, otherwise 1743 1744 Sample number: 340000000000009 (15 digits) 1745 ================================================================ */ 1746 1747function isAmericanExpress(cc) 1748{ 1749 firstdig = cc.substring(0,1); 1750 seconddig = cc.substring(1,2); 1751 if ((cc.length == 15) && (firstdig == 3) && 1752 ((seconddig == 4) || (seconddig == 7))) 1753 return isCreditCard(cc); 1754 return false; 1755 1756} // END FUNCTION isAmericanExpress() 1757 1758 1759 1760 1761/* ================================================================ 1762 FUNCTION: isDinersClub() 1763 1764 INPUT: cc - a string representing a credit card number 1765 1766 RETURNS: true, if the credit card number is a valid Diner's 1767 Club number. 1768 1769 false, otherwise 1770 1771 Sample number: 30000000000004 (14 digits) 1772 ================================================================ */ 1773 1774function isDinersClub(cc) 1775{ 1776 firstdig = cc.substring(0,1); 1777 seconddig = cc.substring(1,2); 1778 if ((cc.length == 14) && (firstdig == 3) && 1779 ((seconddig == 0) || (seconddig == 6) || (seconddig == 8))) 1780 return isCreditCard(cc); 1781 return false; 1782} 1783 1784 1785 1786/* ================================================================ 1787 FUNCTION: isCarteBlanche() 1788 1789 INPUT: cc - a string representing a credit card number 1790 1791 RETURNS: true, if the credit card number is a valid Carte 1792 Blanche number. 1793 1794 false, otherwise 1795 ================================================================ */ 1796 1797function isCarteBlanche(cc) 1798{ 1799 return isDinersClub(cc); 1800} 1801 1802 1803 1804 1805/* ================================================================ 1806 FUNCTION: isDiscover() 1807 1808 INPUT: cc - a string representing a credit card number 1809 1810 RETURNS: true, if the credit card number is a valid Discover 1811 card number. 1812 1813 false, otherwise 1814 1815 Sample number: 6011000000000004 (16 digits) 1816 ================================================================ */ 1817 1818function isDiscover(cc) 1819{ 1820 first4digs = cc.substring(0,4); 1821 if ((cc.length == 16) && (first4digs == "6011")) 1822 return isCreditCard(cc); 1823 return false; 1824 1825} // END FUNCTION isDiscover() 1826 1827 1828 1829 1830 1831/* ================================================================ 1832 FUNCTION: isEnRoute() 1833 1834 INPUT: cc - a string representing a credit card number 1835 1836 RETURNS: true, if the credit card number is a valid enRoute 1837 card number. 1838 1839 false, otherwise 1840 1841 Sample number: 201400000000009 (15 digits) 1842 ================================================================ */ 1843 1844function isEnRoute(cc) 1845{ 1846 first4digs = cc.substring(0,4); 1847 if ((cc.length == 15) && 1848 ((first4digs == "2014") || 1849 (first4digs == "2149"))) 1850 return isCreditCard(cc); 1851 return false; 1852} 1853 1854 1855 1856/* ================================================================ 1857 FUNCTION: isJCB() 1858 1859 INPUT: cc - a string representing a credit card number 1860 1861 RETURNS: true, if the credit card number is a valid JCB 1862 card number. 1863 1864 false, otherwise 1865 ================================================================ */ 1866 1867function isJCB(cc) 1868{ 1869 first4digs = cc.substring(0,4); 1870 if ((cc.length == 16) && 1871 ((first4digs == "3088") || 1872 (first4digs == "3096") || 1873 (first4digs == "3112") || 1874 (first4digs == "3158") || 1875 (first4digs == "3337") || 1876 (first4digs == "3528"))) 1877 return isCreditCard(cc); 1878 return false; 1879 1880} // END FUNCTION isJCB() 1881 1882 1883 1884/* ================================================================ 1885 FUNCTION: isAnyCard() 1886 1887 INPUT: cc - a string representing a credit card number 1888 1889 RETURNS: true, if the credit card number is any valid credit 1890 card number for any of the accepted card types. 1891 1892 false, otherwise 1893 ================================================================ */ 1894 1895function isAnyCard(cc) 1896{ 1897 if (!isCreditCard(cc)) 1898 return false;
1899 if (!isMasterCard(cc) && !isVisa(cc) && !isAmericanExpress(cc) && !isDinersClub(cc) && 1900 !isDiscover(cc) && !isEnRoute(cc) && !isJCB(cc)) { 1901 return false; 1902 } 1903 return true; 1904 1905} // END FUNCTION isAnyCard() 1906 1907 1908 1909/* ================================================================ 1910 FUNCTION: isCardMatch() 1911 1912 INPUT: cardType - a string representing the credit card type 1913 cardNumber - a string representing a credit card number 1914 1915 RETURNS: true, if the credit card number is valid for the particular 1916 credit card type given in "cardType". 1917 1918 false, otherwise 1919 ================================================================ */ 1920 1921function isCardMatch (cardType, cardNumber) 1922{ 1923 1924 cardType = cardType.toUpperCase(); 1925 var doesMatch = true; 1926 1927 if ((cardType == "VISA") && (!isVisa(cardNumber))) 1928 doesMatch = false; 1929 if ((cardType == "MASTERCARD") && (!isMasterCard(cardNumber))) 1930 doesMatch = false; 1931 if ( ( (cardType == "AMERICANEXPRESS") || (cardType == "AMEX") ) 1932 && (!isAmericanExpress(cardNumber))) doesMatch = false; 1933 if ((cardType == "DISCOVER") && (!isDiscover(cardNumber))) 1934 doesMatch = false; 1935 if ((cardType == "JCB") && (!isJCB(cardNumber))) 1936 doesMatch = false; 1937 if ((cardType == "DINERS") && (!isDinersClub(cardNumber))) 1938 doesMatch = false; 1939 if ((cardType == "CARTEBLANCHE") && (!isCarteBlanche(cardNumber))) 1940 doesMatch = false; 1941 if ((cardType == "ENROUTE") && (!isEnRoute(cardNumber))) 1942 doesMatch = false; 1943 return doesMatch; 1944 1945} // END FUNCTION CardMatch() 1946 1947 1948 1949 1950/* ================================================================ 1951 The below stub functions are retained for backward compatibility 1952 with the original LivePayment code so that it should be possible 1953 in principle to swap in this new module as a replacement for the 1954 older module without breaking existing code. (There are no 1955 guarantees, of course, but it should work.) 1956 1957 When writing new code, do not use these stub functions; use the 1958 functions defined above. 1959 ================================================================ */ 1960 1961function IsCC (st) { 1962 return isCreditCard(st); 1963} 1964 1965function IsVisa (cc) { 1966 return isVisa(cc); 1967} 1968 1969function IsVISA (cc) { 1970 return isVisa(cc); 1971} 1972 1973function IsMasterCard (cc) { 1974 return isMasterCard(cc); 1975} 1976 1977function IsMastercard (cc) { 1978 return isMasterCard(cc); 1979} 1980 1981function IsMC (cc) { 1982 return isMasterCard(cc); 1983} 1984 1985function IsAmericanExpress (cc) { 1986 return isAmericanExpress(cc); 1987} 1988 1989function IsAmEx (cc) { 1990 return isAmericanExpress(cc); 1991} 1992 1993function IsDinersClub (cc) { 1994 return isDinersClub(cc); 1995} 1996 1997function IsDC (cc) { 1998 return isDinersClub(cc); 1999} 2000 2001function IsDiners (cc) { 2002 return isDinersClub(cc); 2003} 2004 2005function IsCarteBlanche (cc) { 2006 return isCarteBlanche(cc); 2007} 2008 2009function IsCB (cc) { 2010 return isCarteBlanche(cc); 2011} 2012 2013function IsDiscover (cc) { 2014 return isDiscover(cc); 2015} 2016 2017function IsEnRoute (cc) { 2018 return isEnRoute(cc); 2019} 2020 2021function IsenRoute (cc) { 2022 return isEnRoute(cc); 2023} 2024 2025function IsJCB (cc) { 2026 return isJCB(cc); 2027} 2028 2029function IsAnyCard(cc) { 2030 return isAnyCard(cc); 2031} 2032 2033function IsCardMatch (cardType, cardNumber) { 2034 return isCardMatch (cardType, cardNumber); 2035} 2036 2037function smeConvertMonth (realMonth) { 2038switch (realMonth) { 2039case "JAN": chkMonth = '0'; break; 2040case "FEB": chkMonth = '1'; break; 2041case "MAR": chkMonth = '2'; break; 2042case "APR": chkMonth = '3'; break; 2043case "MAY": chkMonth = '4'; break; 2044case "JUN": chkMonth = '5'; break; 2045case "JUL": chkMonth = '6'; break; 2046case "AUG": chkMonth = '7'; break; 2047case "SEP": chkMonth = '8'; break; 2048case "OCT": chkMonth = '9'; break; 2049case "NOV": chkMonth = '10'; break; 2050case "DEC": chkMonth = '11'; break; 2051default: result = '-1'; 2052} 2053 return chkMonth; 2054}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.