PageSourceSearch

https://iaa-aai.org/modulos/comun/formchek2.js

js iaa-aai.org collected 2026-10-02 13:03:33 UTC 60,997 bytes, 2,017 lines download raw bytes

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

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.