diff options
Diffstat (limited to 'js/dojo/dojox/validate')
| -rw-r--r-- | js/dojo/dojox/validate/README | 62 | ||||
| -rw-r--r-- | js/dojo/dojox/validate/_base.js | 144 | ||||
| -rw-r--r-- | js/dojo/dojox/validate/br.js | 278 | ||||
| -rw-r--r-- | js/dojo/dojox/validate/ca.js | 55 | ||||
| -rw-r--r-- | js/dojo/dojox/validate/check.js | 333 | ||||
| -rw-r--r-- | js/dojo/dojox/validate/creditCard.js | 129 | ||||
| -rw-r--r-- | js/dojo/dojox/validate/isbn.js | 49 | ||||
| -rw-r--r-- | js/dojo/dojox/validate/regexp.js | 284 | ||||
| -rw-r--r-- | js/dojo/dojox/validate/us.js | 68 | ||||
| -rw-r--r-- | js/dojo/dojox/validate/web.js | 94 |
10 files changed, 1496 insertions, 0 deletions
diff --git a/js/dojo/dojox/validate/README b/js/dojo/dojox/validate/README new file mode 100644 index 0000000..9bac798 --- /dev/null +++ b/js/dojo/dojox/validate/README @@ -0,0 +1,62 @@ +------------------------------------------------------------------------------- +dojox.validate +------------------------------------------------------------------------------- +Version 0.02 +Release date: 07/12/2007 +------------------------------------------------------------------------------- +Project state: experimental / beta +------------------------------------------------------------------------------- +Credits + port: Peter Higgins (dante) + contributions: Kun Xi (bookstack at gmail com), Jared Jurkiewicz +------------------------------------------------------------------------------- +Project description + + Provides a set of validation functions to match + values against known constants for use in form + validation, such as email address, TLD, ipAddress, + country-specific phone numbers and SSN, among + others.. + + It is broken into many parts. dojox.validate._base + is required by most named modules in this project. + + ca.js provides Canadian specific functionality + + check.js provides an experimental form-management utility, + which will likely be deprecated in favor + + creditCard.js provides validation functions for most standard + credit card types. + + isbn.js validates ISBN numbers + + regexp.js provides a strange place to put regular expressions + related to validation. It was formerly polluting namespaces + and created in `dojox.regexp`. This is now `dojox.validate.regexp` + to confine values to the dojox.validate project. + + us.js provides US-Specific validation. Zip, Social, etc. + + web.js provides url and email address validation, as well as a number + of web/network related validation functions. + + br.js provides Brazil specific validators for CNPJ and CPF numbers. + +------------------------------------------------------------------------------- +Dependencies: + + Requires Base Dojo and dojo.regexp. + +------------------------------------------------------------------------------- +Installation instructions + +Grab the following from the Dojo SVN Repository: + +http://svn.dojotoolkit.org/src/dojox/trunk/validate.js +http://svn.dojotoolkit.org/src/dojox/trunk/validate + +Install into the following directory structure: +/dojox/validate/ + +...which should be at the same level as your Dojo checkout. diff --git a/js/dojo/dojox/validate/_base.js b/js/dojo/dojox/validate/_base.js new file mode 100644 index 0000000..d108c8b --- /dev/null +++ b/js/dojo/dojox/validate/_base.js @@ -0,0 +1,144 @@ +//>>built +define("dojox/validate/_base", [ + "dojo/_base/lang", + "dojo/regexp", // dojo core expressions + "dojo/number", // dojo number expressions + "./regexp" // additional expressions +], function(lang, regexp, number, xregexp) { + + var validate = lang.getObject("dojox.validate", true); + /*===== + validate = dojox.validate; + =====*/ + +validate.isText = function(/*String*/value, /*Object?*/flags){ + // summary: + // Checks if a string has non whitespace characters. + // Parameters allow you to constrain the length. + // + // value: A string + // flags: {length: Number, minlength: Number, maxlength: Number} + // flags.length If set, checks if there are exactly flags.length number of characters. + // flags.minlength If set, checks if there are at least flags.minlength number of characters. + // flags.maxlength If set, checks if there are at most flags.maxlength number of characters. + + flags = (typeof flags == "object") ? flags : {}; + + // test for text + if(/^\s*$/.test(value)){ return false; } // Boolean + + // length tests + if(typeof flags.length == "number" && flags.length != value.length){ return false; } // Boolean + if(typeof flags.minlength == "number" && flags.minlength > value.length){ return false; } // Boolean + if(typeof flags.maxlength == "number" && flags.maxlength < value.length){ return false; } // Boolean + + return true; // Boolean + +}; + +validate._isInRangeCache = {}; +validate.isInRange = function(/*String*/value, /*Object?*/flags){ + // summary: + // Validates whether a string denoting a number + // is between a max and min. + // + // value: A string + // flags: {max:Number, min:Number, decimal:String} + // flags.max A number, which the value must be less than or equal to for the validation to be true. + // flags.min A number, which the value must be greater than or equal to for the validation to be true. + // flags.decimal The character used for the decimal point. Default is ".". + + value = number.parse(value, flags); + if(isNaN(value)){ + return false; // Boolean + } + + // assign default values to missing paramters + flags = (typeof flags == "object") ? flags : {}; + var max = (typeof flags.max == "number") ? flags.max : Infinity, + min = (typeof flags.min == "number") ? flags.min : -Infinity, + dec = (typeof flags.decimal == "string") ? flags.decimal : ".", + + cache = validate._isInRangeCache, + cacheIdx = value + "max" + max + "min" + min + "dec" + dec + ; + if(typeof cache[cacheIdx] != "undefined"){ + return cache[cacheIdx]; + } + + cache[cacheIdx] = !(value < min || value > max); + return cache[cacheIdx]; // Boolean + +}; + +validate.isNumberFormat = function(/* String */value, /* Object? */flags){ + // summary: Validates any sort of number based format + // + // description: + // Validates any sort of number based format. Use it for phone numbers, + // social security numbers, zip-codes, etc. The value can be validated + // against one format or one of multiple formats. + // + // Format Definition + // | # Stands for a digit, 0-9. + // | ? Stands for an optional digit, 0-9 or nothing. + // All other characters must appear literally in the expression. + // + // example: + // | "(###) ###-####" -> (510) 542-9742 + // | "(###) ###-#### x#???" -> (510) 542-9742 x153 + // | "###-##-####" -> 506-82-1089 i.e. social security number + // | "#####-####" -> 98225-1649 i.e. zip code + // + // value: A string + // + // flags: Object? + // FIXME: make pseudo-object for this + // format: String + // + // flags.format A string or an Array of strings for multiple formats. + // + // example: + // | // returns true: + // | dojox.validate.isNumberFormat("123-45", { format:"###-##" }); + // + // example: + // Check Multiple formats: + // | dojox.validate.isNumberFormat("123-45", { + // | format:["### ##","###-##","## ###"] + // | }); + // + + var re = new RegExp("^" + xregexp.numberFormat(flags) + "$", "i"); + return re.test(value); // Boolean +}; + +validate.isValidLuhn = function(/* String */value){ + // summary: Validate a String value against the Luhn algorithm. + // description: + // Validate a String value against the Luhn algorithm to verify + // its integrity. + + var sum = 0, parity, curDigit; + if(!lang.isString(value)){ + value = String(value); + } + value = value.replace(/[- ]/g,''); //ignore dashes and whitespaces + parity = value.length % 2; + + for(var i = 0; i < value.length; i++){ + curDigit = parseInt(value.charAt(i)); + if(i % 2 == parity){ + curDigit *= 2; + } + if(curDigit > 9){ + curDigit -= 9; + } + sum += curDigit; + } + return !(sum % 10); // Boolean +}; + +return validate; + +}); diff --git a/js/dojo/dojox/validate/br.js b/js/dojo/dojox/validate/br.js new file mode 100644 index 0000000..2c12885 --- /dev/null +++ b/js/dojo/dojox/validate/br.js @@ -0,0 +1,278 @@ +//>>built +define("dojox/validate/br", ["dojo/_base/lang", "./_base"], function(lang, validate){ + +var br = lang.getObject("br", true, validate); +br.isValidCnpj = function(/*String*/value){ + // summary: + // Validates a CNPJ/CGC number + // + // value: String + // The CNPJ/CGC number in ##.###.###/####-##, ########/####-##, + // ############-## or ############## format + if(!lang.isString(value)){ + if(!value){ + return false; + } + value = value + ""; + while(value.length < 14){ + value = "0" + value; + } + } + var flags = { + format: [ + "##.###.###/####-##", + "########/####-##", + "############-##", + "##############" + ] + }; + if(validate.isNumberFormat(value, flags)){ + // Matched the initial test, so break this down into the + // parts to be validated. + value = value.replace("/", "").replace(/\./g, "").replace("-", ""); + var cgc = []; + var dv = []; + var i, j, tmp; + + // Check for obvious bad combos + // all 0s to all 9's. + for(i = 0; i < 10; i++){ + tmp = ""; + for(j = 0; j < value.length; j++){ + tmp += "" + i; + } + if(value === tmp){ + return false; + } + } + + //Split out the DV from the main number. + for(i = 0; i < 12; i++){ + cgc.push(parseInt(value.charAt(i), 10)); + } + for(i = 12; i < 14; i++){ + dv.push(parseInt(value.charAt(i), 10)); + } + + var base = [9,8,7,6,5,4,3,2,9,8,7,6].reverse(); + var sum = 0; + for(i = 0; i < cgc.length; i++){ + sum += cgc[i] * base[i]; + } + var dv0 = sum % 11; + if(dv0 == dv[0]){ + // Still seems valid, keep going. + sum = 0; + base = [9,8,7,6,5,4,3,2,9,8,7,6,5].reverse(); + cgc.push(dv0); + for(i = 0; i < cgc.length; i++){ + sum += cgc[i] * base[i]; + } + var dv1 = sum % 11; + if(dv1 === dv[1]){ + // Whew, looks valid. + return true; + } + } + } + return false; +}; + +br.computeCnpjDv = function(/*String*/value){ + // summary: Generate the DV code (checksum part) for a Cnpj number + // + // value: The CGC number in ##.###.###/#### or ############ format + if(!lang.isString(value)){ + if(!value){ + return ""; + } + value = value + ""; + while(value.length < 12){ + value = "0" + value; + } + } + var flags = { + format: [ + "##.###.###/####", + "########/####", + "############" + ] + }; + if(validate.isNumberFormat(value, flags)){ + // Matched the initial test, so break this down into the + // parts to compute the DV. + value = value.replace("/", "").replace(/\./g, ""); + var cgc = []; + var i, j, tmp; + + // Check for obvious bad combos + // all 0s to all 9's. + for(i = 0; i < 10; i++){ + tmp = ""; + for(j = 0; j < value.length; j++){ + tmp += "" + i; + } + if(value === tmp){ + return ""; + } + } + + for(i = 0; i < value.length; i++){ + cgc.push(parseInt(value.charAt(i), 10)); + } + var base = [9,8,7,6,5,4,3,2,9,8,7,6].reverse(); + var sum = 0; + for(i = 0; i < cgc.length; i++){ + sum += cgc[i] * base[i]; + } + var dv0 = sum % 11; + sum = 0; + base = [9,8,7,6,5,4,3,2,9,8,7,6,5].reverse(); + cgc.push(dv0); + for(i = 0; i < cgc.length; i++){ + sum += cgc[i] * base[i]; + } + var dv1 = sum % 11; + return ("" + dv0) + dv1; + } + return ""; +}; + + +br.isValidCpf = function(/*String*/value){ + // summary: + // Validates a CPF number + // + // value: String + // The CPF number in #########-## or ###########, + // format + if(!lang.isString(value)){ + if(!value){ + return false; + } + value = value + ""; + while(value.length < 11){ + value = "0" + value; + } + } + var flags = { + format: [ + "###.###.###-##", + "#########-##", + "###########" + ] + }; + if(validate.isNumberFormat(value, flags)){ + // Matched the initial test, so break this down into the + // parts to be validated. + value = value.replace("-", "").replace(/\./g, ""); + var cpf = []; + var dv = []; + var i, j, tmp; + + // Check for obvious bad combos + // all 0s to all 9's. + for(i = 0; i < 10; i++){ + tmp = ""; + for(j = 0; j < value.length; j++){ + tmp += "" + i; + } + if(value === tmp){ + return false; + } + } + + //Split out the DV from the main number. + for(i = 0; i < 9; i++){ + cpf.push(parseInt(value.charAt(i), 10)); + } + for(i = 9; i < 12; i++){ + dv.push(parseInt(value.charAt(i), 10)); + } + + var base = [9,8,7,6,5,4,3,2,1].reverse(); + var sum = 0; + for(i = 0; i < cpf.length; i++){ + sum += cpf[i] * base[i]; + } + var dv0 = sum % 11; + if(dv0 == dv[0]){ + // Still seems valid, keep going. + sum = 0; + base = [9,8,7,6,5,4,3,2,1,0].reverse(); + cpf.push(dv0); + for(i = 0; i < cpf.length; i++){ + sum += cpf[i] * base[i]; + } + var dv1 = sum % 11; + if(dv1 === dv[1]){ + // Whew, looks valid. + return true; + } + } + } + return false; +}; + +br.computeCpfDv = function(/*String*/value){ + // summary: + // Generate the DV code (checksum part) for a CPF number + // + // value: String + // The CPF number in ######### format + if(!lang.isString(value)){ + if(!value){ + return ""; + } + value = value + ""; + while(value.length < 9){ + value = "0" + value; + } + } + var flags = { + format: [ + "###.###.###", + "#########" + ] + }; + if(validate.isNumberFormat(value, flags)){ + // Matched the initial test, so break this down into the + // parts to compute the DV. + value = value.replace(/\./g, ""); + var cpf = []; + + // Check for obvious bad combos + // all 0s to all 9's. + for(i = 0; i < 10; i++){ + tmp = ""; + for(j = 0; j < value.length; j++){ + tmp += "" + i; + } + if(value === tmp){ + return ""; + } + } + + for(i = 0; i < value.length; i++){ + cpf.push(parseInt(value.charAt(i), 10)); + } + var base = [9,8,7,6,5,4,3,2,1].reverse(); + var sum = 0; + for(i = 0; i < cpf.length; i++){ + sum += cpf[i] * base[i]; + } + var dv0 = sum % 11; + sum = 0; + base = [9,8,7,6,5,4,3,2,1,0].reverse(); + cpf.push(dv0); + for(i = 0; i < cpf.length; i++){ + sum += cpf[i] * base[i]; + } + var dv1 = sum % 11; + return ("" + dv0) + dv1; + } + return ""; +}; + +return br; +}); diff --git a/js/dojo/dojox/validate/ca.js b/js/dojo/dojox/validate/ca.js new file mode 100644 index 0000000..498304c --- /dev/null +++ b/js/dojo/dojox/validate/ca.js @@ -0,0 +1,55 @@ +//>>built +define("dojox/validate/ca", ["dojo/_base/lang", "./_base", "./regexp", "./us"], + function(lang, validate, xregexp, us){ +/*===== + + dojox.validate.ca = { + // summary: Module which includes Canadian-specific methods for dojox.validate + } + +=====*/ + +var ca = lang.getObject("ca", true, validate); +lang.mixin(ca, { + + isPhoneNumber: function(/* String */value){ + // summary: Validates Canadian 10-digit phone number for several common formats + return us.isPhoneNumber(value); // Boolean + }, + + isProvince: function(/* String[2] */value) { + // summary: Validates Canadian province abbreviations (2 characters) + var re = new RegExp("^" + xregexp.ca.province() + "$", "i"); + return re.test(value); // Boolean + }, + + isSocialInsuranceNumber: function(/* String */value) { + // summary: Validates Canadian 9 digit social insurance number for several + // common formats + // + // description: + // Validates Canadian 9 digit social insurance number for several + // common formats. This routine only pattern matches and does not + // use the Luhn Algorithm to validate number. + // + var flags = { format: [ "###-###-###", "### ### ###", "#########" ]}; + return validate.isNumberFormat(value, flags); // Boolean + }, + + isPostalCode: function(value) { + // summary: Validates Canadian 6 digit postal code + // + // description: + // Validates Canadian 6 digit postal code. + // Canadian postal codes are in the format ANA NAN, + // where A is a letter and N is a digit, with a space + // separating the third and fourth characters. + // + var re = new RegExp("^" + xregexp.ca.postalCode() + "$", "i"); + return re.test(value); // Boolean + } + +}); + +return ca; +}); diff --git a/js/dojo/dojox/validate/check.js b/js/dojo/dojox/validate/check.js new file mode 100644 index 0000000..f7d5545 --- /dev/null +++ b/js/dojo/dojox/validate/check.js @@ -0,0 +1,333 @@ +//>>built +define("dojox/validate/check", ["dojo/_base/kernel", "dojo/_base/lang", "./_base"], + function(kernel, lang, validate){ +kernel.experimental("dojox.validate.check"); + +/*===== + + validate = dojox.validate; + +=====*/ +/** + FIXME: How much does this overlap with dojox.form.Manager and friends? + + Procedural API Description + + The main aim is to make input validation expressible in a simple format. + You define profiles which declare the required and optional fields and any constraints they might have. + The results are provided as an object that makes it easy to handle missing and invalid input. + + Usage + + var results = dojox.validate.check(form, profile); + + Profile Object + + var profile = { + // filters change the field value and are applied before validation. + trim: ["tx1", "tx2"], + uppercase: ["tx9"], + lowercase: ["tx5", "tx6", "tx7"], + ucfirst: ["tx10"], + digit: ["tx11"], + + // required input fields that are blank will be reported missing. + // required radio button groups and drop-down lists with no selection will be reported missing. + // checkbox groups and selectboxes can be required to have more than one value selected. + // List required fields by name and use this notation to require more than one value: {checkboxgroup: 2}, {selectboxname: 3}. + required: ["tx7", "tx8", "pw1", "ta1", "rb1", "rb2", "cb3", "s1", {"doubledip":2}, {"tripledip":3}], + + // dependant/conditional fields are required if the target field is present and not blank. + // At present only textbox, password, and textarea fields are supported. + dependencies: { + cc_exp: "cc_no", + cc_type: "cc_no" + }, + + // Fields can be validated using any boolean valued function. + // Use arrays to specify parameters in addition to the field value. + constraints: { + field_name1: myValidationFunction, + field_name2: dojox.validate.isInteger, + field_name3: [myValidationFunction, additional parameters], + field_name4: [dojox.validate.isValidDate, "YYYY.MM.DD"], + field_name5: [dojox.validate.isEmailAddress, false, true] + }, + + // Confirm is a sort of conditional validation. + // It associates each field in its property list with another field whose value should be equal. + // If the values are not equal, the field in the property list is reported as Invalid. Unless the target field is blank. + confirm: { + email_confirm: "email", + pw2: "pw1" + } + }; + + Results Object + + isSuccessful(): Returns true if there were no invalid or missing fields, else it returns false. + hasMissing(): Returns true if the results contain any missing fields. + getMissing(): Returns a list of required fields that have values missing. + isMissing(field): Returns true if the field is required and the value is missing. + hasInvalid(): Returns true if the results contain fields with invalid data. + getInvalid(): Returns a list of fields that have invalid values. + isInvalid(field): Returns true if the field has an invalid value. + +*/ + +validate.check = function(/*HTMLFormElement*/form, /*Object*/profile){ + // summary: validates user input of an HTML form based on input profile + // + // description: + // returns an object that contains several methods summarizing the results of the validation + // + // form: form to be validated + // profile: specifies how the form fields are to be validated + // {trim:Array, uppercase:Array, lowercase:Array, ucfirst:Array, digit:Array, + // required:Array, dependencies:Object, constraints:Object, confirm:Object} + + // Essentially private properties of results object + var missing = []; + var invalid = []; + + // results object summarizes the validation + var results = { + isSuccessful: function() {return ( !this.hasInvalid() && !this.hasMissing() );}, + hasMissing: function() {return ( missing.length > 0 );}, + getMissing: function() {return missing;}, + isMissing: function(elemname) { + for(var i = 0; i < missing.length; i++){ + if(elemname == missing[i]){ return true; } + } + return false; + }, + hasInvalid: function() {return ( invalid.length > 0 );}, + getInvalid: function() {return invalid;}, + isInvalid: function(elemname){ + for(var i = 0; i < invalid.length; i++){ + if(elemname == invalid[i]){ return true; } + } + return false; + } + }; + + var _undef = function(name,object){ + return (typeof object[name] == "undefined"); + }; + + // Filters are applied before fields are validated. + // Trim removes white space at the front and end of the fields. + if(profile.trim instanceof Array){ + for(var i = 0; i < profile.trim.length; i++){ + var elem = form[profile.trim[i]]; + if(_undef("type", elem) || elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; } + elem.value = elem.value.replace(/(^\s*|\s*$)/g, ""); + } + } + // Convert to uppercase + if(profile.uppercase instanceof Array){ + for(var i = 0; i < profile.uppercase.length; i++){ + var elem = form[profile.uppercase[i]]; + if(_undef("type", elem) || elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; } + elem.value = elem.value.toUpperCase(); + } + } + // Convert to lowercase + if(profile.lowercase instanceof Array){ + for (var i = 0; i < profile.lowercase.length; i++){ + var elem = form[profile.lowercase[i]]; + if(_undef("type", elem) || elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; } + elem.value = elem.value.toLowerCase(); + } + } + // Uppercase first letter + if(profile.ucfirst instanceof Array){ + for(var i = 0; i < profile.ucfirst.length; i++){ + var elem = form[profile.ucfirst[i]]; + if(_undef("type", elem) || elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; } + elem.value = elem.value.replace(/\b\w+\b/g, function(word) { return word.substring(0,1).toUpperCase() + word.substring(1).toLowerCase(); }); + } + } + // Remove non digits characters from the input. + if(profile.digit instanceof Array){ + for(var i = 0; i < profile.digit.length; i++){ + var elem = form[profile.digit[i]]; + if(_undef("type", elem) || elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; } + elem.value = elem.value.replace(/\D/g, ""); + } + } + + // See if required input fields have values missing. + if(profile.required instanceof Array){ + for(var i = 0; i < profile.required.length; i++){ + if(!lang.isString(profile.required[i])){ continue; } + var elem = form[profile.required[i]]; + // Are textbox, textarea, or password fields blank. + if(!_undef("type", elem) + && (elem.type == "text" || elem.type == "textarea" || elem.type == "password" || elem.type == "file") + && /^\s*$/.test(elem.value)){ + missing[missing.length] = elem.name; + } + // Does drop-down box have option selected. + else if(!_undef("type", elem) && (elem.type == "select-one" || elem.type == "select-multiple") + && (elem.selectedIndex == -1 + || /^\s*$/.test(elem.options[elem.selectedIndex].value))){ + missing[missing.length] = elem.name; + } + // Does radio button group (or check box group) have option checked. + else if(elem instanceof Array){ + var checked = false; + for(var j = 0; j < elem.length; j++){ + if (elem[j].checked) { checked = true; } + } + if(!checked){ + missing[missing.length] = elem[0].name; + } + } + } + } + + // See if checkbox groups and select boxes have x number of required values. + if(profile.required instanceof Array){ + for (var i = 0; i < profile.required.length; i++){ + if(!lang.isObject(profile.required[i])){ continue; } + var elem, numRequired; + for(var name in profile.required[i]){ + elem = form[name]; + numRequired = profile.required[i][name]; + } + // case 1: elem is a check box group + if(elem instanceof Array){ + var checked = 0; + for(var j = 0; j < elem.length; j++){ + if(elem[j].checked){ checked++; } + } + if(checked < numRequired){ + missing[missing.length] = elem[0].name; + } + } + // case 2: elem is a select box + else if(!_undef("type", elem) && elem.type == "select-multiple" ){ + var selected = 0; + for(var j = 0; j < elem.options.length; j++){ + if (elem.options[j].selected && !/^\s*$/.test(elem.options[j].value)) { selected++; } + } + if(selected < numRequired){ + missing[missing.length] = elem.name; + } + } + } + } + + // Dependent fields are required when the target field is present (not blank). + // Todo: Support dependent and target fields that are radio button groups, or select drop-down lists. + // Todo: Make the dependency based on a specific value of the target field. + // Todo: allow dependent fields to have several required values, like {checkboxgroup: 3}. + if(lang.isObject(profile.dependencies)){ + // properties of dependencies object are the names of dependent fields to be checked + for(name in profile.dependencies){ + var elem = form[name]; // the dependent element + if(_undef("type", elem)){continue;} + if(elem.type != "text" && elem.type != "textarea" && elem.type != "password"){ continue; } // limited support + if(/\S+/.test(elem.value)){ continue; } // has a value already + if(results.isMissing(elem.name)){ continue; } // already listed as missing + var target = form[profile.dependencies[name]]; + if(target.type != "text" && target.type != "textarea" && target.type != "password"){ continue; } // limited support + if(/^\s*$/.test(target.value)){ continue; } // skip if blank + missing[missing.length] = elem.name; // ok the dependent field is missing + } + } + + // Find invalid input fields. + if(lang.isObject(profile.constraints)){ + // constraint properties are the names of fields to bevalidated + for(name in profile.constraints){ + var elem = form[name]; + if(!elem) {continue;} + + // skip if blank - its optional unless required, in which case it + // is already listed as missing. + if(!_undef("tagName",elem) + && (elem.tagName.toLowerCase().indexOf("input") >= 0 + || elem.tagName.toLowerCase().indexOf("textarea") >= 0) + && /^\s*$/.test(elem.value)){ + continue; + } + + var isValid = true; + // case 1: constraint value is validation function + if(lang.isFunction(profile.constraints[name])){ + isValid = profile.constraints[name](elem.value); + }else if(lang.isArray(profile.constraints[name])){ + + // handle nested arrays for multiple constraints + if(lang.isArray(profile.constraints[name][0])){ + for (var i=0; i<profile.constraints[name].length; i++){ + isValid = validate.evaluateConstraint(profile, profile.constraints[name][i], name, elem); + if(!isValid){ break; } + } + }else{ + // case 2: constraint value is array, first elem is function, + // tail is parameters + isValid = validate.evaluateConstraint(profile, profile.constraints[name], name, elem); + } + } + + if(!isValid){ + invalid[invalid.length] = elem.name; + } + } + } + + // Find unequal confirm fields and report them as Invalid. + if(lang.isObject(profile.confirm)){ + for(name in profile.confirm){ + var elem = form[name]; // the confirm element + var target = form[profile.confirm[name]]; + if (_undef("type", elem) || _undef("type", target) || (elem.type != "text" && elem.type != "textarea" && elem.type != "password") + ||(target.type != elem.type) + ||(target.value == elem.value) // it's valid + ||(results.isInvalid(elem.name))// already listed as invalid + ||(/^\s*$/.test(target.value))) // skip if blank - only confirm if target has a value + { + continue; + } + invalid[invalid.length] = elem.name; + } + } + return results; // Object +}; + +//TODO: evaluateConstraint doesn't use profile or fieldName args? +validate.evaluateConstraint=function(profile, /*Array*/constraint, fieldName, elem){ + // summary: + // Evaluates dojo.validate.check() constraints that are specified as array + // arguments + // + // description: The arrays are expected to be in the format of: + // constraints:{ + // fieldName: [functionToCall, param1, param2, etc.], + // fieldName: [[functionToCallFirst, param1],[functionToCallSecond,param2]] + // } + // + // This function evaluates a single array function in the format of: + // [functionName, argument1, argument2, etc] + // + // The function will be parsed out and evaluated against the incoming parameters. + // + // profile: The dojo.validate.check() profile that this evaluation is against. + // constraint: The single [] array of function and arguments for the function. + // fieldName: The form dom name of the field being validated. + // elem: The form element field. + + var isValidSomething = constraint[0]; + var params = constraint.slice(1); + params.unshift(elem.value); + if(typeof isValidSomething != "undefined"){ + return isValidSomething.apply(null, params); + } + return false; // Boolean +}; + +return validate.check; +}); diff --git a/js/dojo/dojox/validate/creditCard.js b/js/dojo/dojox/validate/creditCard.js new file mode 100644 index 0000000..7b2d4c0 --- /dev/null +++ b/js/dojo/dojox/validate/creditCard.js @@ -0,0 +1,129 @@ +//>>built +define("dojox/validate/creditCard", ["dojo/_base/lang", "./_base"], function(lang, validate){ +/*===== + + dojox.validate.creditCard = { + // summary: + // Module provides validation functions for Credit Cards, using account number + // rules in conjunction with the Luhn algorigthm, with a plugable card info database. + }; + + validate = dojox.validate; + +=====*/ + +validate._cardInfo = { + // summary: A dictionary list of credit card abbreviations + // + // description: + // + // A hash of valid CC abbreviations and regular expressions + // + // mc: Mastercard + // ec: Eurocard + // vi: Visa + // ax: American Express + // dc: Diners Club + // bl: Carte Blanch + // di: Discover + // jcb: JCB + // er: Enroute + // + // example: + // Define your own card, gift-card, whatever. Starts with 7, + // is 15 total length. + // | dojo.mixin(dojox.validate._cardInfo, { + // | "my":"7[0-9]{14}" + // | }); + + 'mc':'5[1-5][0-9]{14}', + 'ec':'5[1-5][0-9]{14}', + 'vi':'4(?:[0-9]{12}|[0-9]{15})', + 'ax':'3[47][0-9]{13}', + 'dc':'3(?:0[0-5][0-9]{11}|[68][0-9]{12})', + 'bl':'3(?:0[0-5][0-9]{11}|[68][0-9]{12})', + 'di':'6011[0-9]{12}', + 'jcb':'(?:3[0-9]{15}|(2131|1800)[0-9]{11})', + 'er':'2(?:014|149)[0-9]{11}' +}; + +validate.isValidCreditCard = function(value, ccType){ + // summary: Validate a credit card number by type with Luhn checking. + // + // description: + // Checks if a credit card type matches the # scheme in a passed value, and if + // the Luhn checksum is accurate (unless its an Enroute card, in which case + // the checkSum is skipped), returning a Boolean to check against. + // + // value: String|Int + // A Value (credit card number) to validate + // + // ccType: String + // A credit-card abbreviation. + // + // example: + // | if(dojox.validate.isValidCreditCard("12345", "mc")){ + // | console.log('inconceivable'); + // | } + + return ((ccType.toLowerCase() == 'er' || validate.isValidLuhn(value)) && + validate.isValidCreditCardNumber(value, ccType.toLowerCase())); // Boolean +}; + +validate.isValidCreditCardNumber = function(value, ccType){ + // summary: + // Checks if value matches the pattern for that card or any card types if none is specified + // + // value: String|Int + // CC #, white spaces and dashes are ignored + // + // ccType: String? + // One of the abbreviation values in `dojox.validate._cardInfo` -- + // if Omitted, function returns a `|` delimited string of matching card types, + // or false if no matches found. + + value = String(value).replace(/[- ]/g,''); //ignore dashes and whitespaces + + var cardinfo = validate._cardInfo, results = []; + if(ccType){ + var expr = '^' + cardinfo[ccType.toLowerCase()] + '$'; + return expr ? !!value.match(expr) : false; // boolean + } + + for(var p in cardinfo){ + if(value.match('^' + cardinfo[p] + '$')){ + results.push(p); + } + } + return results.length ? results.join('|') : false; // String | boolean +}; + +validate.isValidCvv = function(/* String|Int */value, /* String */ccType) { + // summary: + // Validate the security code (CCV) for a passed credit-card type. + // + // description: + // + // value: + + if(!lang.isString(value)){ + value = String(value); + } + var format; + switch (ccType.toLowerCase()){ + case 'mc': + case 'ec': + case 'vi': + case 'di': + format = '###'; + break; + case 'ax': + format = '####'; + break; + } + + return !!format && value.length && validate.isNumberFormat(value, { format: format }); // Boolean +}; + +return validate; +}); diff --git a/js/dojo/dojox/validate/isbn.js b/js/dojo/dojox/validate/isbn.js new file mode 100644 index 0000000..b6f8b16 --- /dev/null +++ b/js/dojo/dojox/validate/isbn.js @@ -0,0 +1,49 @@ +//>>built +define("dojox/validate/isbn", ["dojo/_base/lang", "./_base"], function(lang, validate){ +// summary: Provides ISBN validation functions in `dojox.validate` +// + +/*===== + + validate = dojox.validate; + +=====*/ + +validate.isValidIsbn = function(/* String */value) { + // summary: Validate ISBN-10 or ISBN-13 based on the length of value + // value: String + // An ISBN to validate + // returns: Boolean + var len, sum = 0, weight; + if(!lang.isString(value)){ + value = String(value); + } + value = value.replace(/[- ]/g,''); //ignore dashes and whitespaces + len = value.length; + + switch(len){ + case 10: + weight = len; + // ISBN-10 validation algorithm + for(var i = 0; i < 9; i++){ + sum += parseInt(value.charAt(i)) * weight; + weight--; + } + var t = value.charAt(9).toUpperCase(); + sum += t == 'X' ? 10 : parseInt(t); + return sum % 11 == 0; // Boolean + break; + case 13: + weight = -1; + for(var i = 0; i< len; i++){ + sum += parseInt(value.charAt(i)) * (2 + weight); + weight *= -1; + } + return sum % 10 == 0; // Boolean + break; + } + return false; +}; + +return validate.isValidIsbn; +}); diff --git a/js/dojo/dojox/validate/regexp.js b/js/dojo/dojox/validate/regexp.js new file mode 100644 index 0000000..88a8c19 --- /dev/null +++ b/js/dojo/dojox/validate/regexp.js @@ -0,0 +1,284 @@ +//>>built +define("dojox/validate/regexp", ["dojo/_base/lang", "dojo/regexp", "dojox/main"], + function(lang, regexp, dojox){ + +var dxregexp = lang.getObject("validate.regexp", true, dojox); +dxregexp = dojox.validate.regexp = { + + ipAddress: function(/*Object?*/flags){ + // summary: Builds a RE that matches an IP Address + // + // description: + // Supports 5 formats for IPv4: dotted decimal, dotted hex, dotted octal, decimal and hexadecimal. + // Supports 2 formats for Ipv6. + // + // flags An object. All flags are boolean with default = true. + // flags.allowDottedDecimal Example, 207.142.131.235. No zero padding. + // flags.allowDottedHex Example, 0x18.0x11.0x9b.0x28. Case insensitive. Zero padding allowed. + // flags.allowDottedOctal Example, 0030.0021.0233.0050. Zero padding allowed. + // flags.allowDecimal Example, 3482223595. A decimal number between 0-4294967295. + // flags.allowHex Example, 0xCF8E83EB. Hexadecimal number between 0x0-0xFFFFFFFF. + // Case insensitive. Zero padding allowed. + // flags.allowIPv6 IPv6 address written as eight groups of four hexadecimal digits. + // FIXME: ipv6 can be written multiple ways IIRC + // flags.allowHybrid IPv6 address written as six groups of four hexadecimal digits + // followed by the usual 4 dotted decimal digit notation of IPv4. x:x:x:x:x:x:d.d.d.d + + // assign default values to missing paramters + flags = (typeof flags == "object") ? flags : {}; + if(typeof flags.allowDottedDecimal != "boolean"){ flags.allowDottedDecimal = true; } + if(typeof flags.allowDottedHex != "boolean"){ flags.allowDottedHex = true; } + if(typeof flags.allowDottedOctal != "boolean"){ flags.allowDottedOctal = true; } + if(typeof flags.allowDecimal != "boolean"){ flags.allowDecimal = true; } + if(typeof flags.allowHex != "boolean"){ flags.allowHex = true; } + if(typeof flags.allowIPv6 != "boolean"){ flags.allowIPv6 = true; } + if(typeof flags.allowHybrid != "boolean"){ flags.allowHybrid = true; } + + // decimal-dotted IP address RE. + var dottedDecimalRE = + // Each number is between 0-255. Zero padding is not allowed. + "((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])"; + + // dotted hex IP address RE. Each number is between 0x0-0xff. Zero padding is allowed, e.g. 0x00. + var dottedHexRE = "(0[xX]0*[\\da-fA-F]?[\\da-fA-F]\\.){3}0[xX]0*[\\da-fA-F]?[\\da-fA-F]"; + + // dotted octal IP address RE. Each number is between 0000-0377. + // Zero padding is allowed, but each number must have at least 4 characters. + var dottedOctalRE = "(0+[0-3][0-7][0-7]\\.){3}0+[0-3][0-7][0-7]"; + + // decimal IP address RE. A decimal number between 0-4294967295. + var decimalRE = "(0|[1-9]\\d{0,8}|[1-3]\\d{9}|4[01]\\d{8}|42[0-8]\\d{7}|429[0-3]\\d{6}|" + + "4294[0-8]\\d{5}|42949[0-5]\\d{4}|429496[0-6]\\d{3}|4294967[01]\\d{2}|42949672[0-8]\\d|429496729[0-5])"; + + // hexadecimal IP address RE. + // A hexadecimal number between 0x0-0xFFFFFFFF. Case insensitive. Zero padding is allowed. + var hexRE = "0[xX]0*[\\da-fA-F]{1,8}"; + + // IPv6 address RE. + // The format is written as eight groups of four hexadecimal digits, x:x:x:x:x:x:x:x, + // where x is between 0000-ffff. Zero padding is optional. Case insensitive. + var ipv6RE = "([\\da-fA-F]{1,4}\\:){7}[\\da-fA-F]{1,4}"; + + // IPv6/IPv4 Hybrid address RE. + // The format is written as six groups of four hexadecimal digits, + // followed by the 4 dotted decimal IPv4 format. x:x:x:x:x:x:d.d.d.d + var hybridRE = "([\\da-fA-F]{1,4}\\:){6}" + + "((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])"; + + // Build IP Address RE + var a = []; + if(flags.allowDottedDecimal){ a.push(dottedDecimalRE); } + if(flags.allowDottedHex){ a.push(dottedHexRE); } + if(flags.allowDottedOctal){ a.push(dottedOctalRE); } + if(flags.allowDecimal){ a.push(decimalRE); } + if(flags.allowHex){ a.push(hexRE); } + if(flags.allowIPv6){ a.push(ipv6RE); } + if(flags.allowHybrid){ a.push(hybridRE); } + + var ipAddressRE = ""; + if(a.length > 0){ + ipAddressRE = "(" + a.join("|") + ")"; + } + return ipAddressRE; // String + }, + + host: function(/*Object?*/flags){ + // summary: Builds a RE that matches a host + // description: A host is a named host (A-z0-9_- but not starting with -), a domain name or an IP address, possibly followed by a port number. + // flags: An object. + // flags.allowNamed Allow a named host for local networks. Default is false. + // flags.allowIP Allow an IP address for hostname. Default is true. + // flags.allowLocal Allow the host to be "localhost". Default is false. + // flags.allowPort Allow a port number to be present. Default is true. + // flags in regexp.ipAddress can be applied. + + // assign default values to missing paramters + flags = (typeof flags == "object") ? flags : {}; + + if(typeof flags.allowIP != "boolean"){ flags.allowIP = true; } + if(typeof flags.allowLocal != "boolean"){ flags.allowLocal = false; } + if(typeof flags.allowPort != "boolean"){ flags.allowPort = true; } + if(typeof flags.allowNamed != "boolean"){ flags.allowNamed = false; } + + //TODO: support unicode hostnames? + // Domain name labels can not end with a dash. + var domainLabelRE = "(?:[\\da-zA-Z](?:[-\\da-zA-Z]{0,61}[\\da-zA-Z])?)"; + var domainNameRE = "(?:[a-zA-Z](?:[-\\da-zA-Z]{0,6}[\\da-zA-Z])?)"; // restricted version to allow backwards compatibility with allowLocal, allowIP + + // port number RE + var portRE = flags.allowPort ? "(\\:\\d+)?" : ""; + + // build host RE + var hostNameRE = "((?:" + domainLabelRE + "\\.)+" + domainNameRE + "\\.?)"; + if(flags.allowIP){ hostNameRE += "|" + dxregexp.ipAddress(flags); } + if(flags.allowLocal){ hostNameRE += "|localhost"; } + if(flags.allowNamed){ hostNameRE += "|^[^-][a-zA-Z0-9_-]*"; } + return "(" + hostNameRE + ")" + portRE; // String + + }, + + url: function(/*Object?*/flags){ + // summary: Builds a regular expression that matches a URL + // + // flags: An object + // flags.scheme Can be true, false, or [true, false]. + // This means: required, not allowed, or match either one. + // flags in regexp.host can be applied. + // flags in regexp.ipAddress can be applied. + + // assign default values to missing paramters + flags = (typeof flags == "object") ? flags : {}; + if(!("scheme" in flags)){ flags.scheme = [true, false]; } + + // Scheme RE + var protocolRE = regexp.buildGroupRE(flags.scheme, + function(q){ if(q){ return "(https?|ftps?)\\://"; } return ""; } + ); + + // Path and query and anchor RE + var pathRE = "(/(?:[^?#\\s/]+/)*(?:[^?#\\s/]+(?:\\?[^?#\\s/]*)?(?:#[A-Za-z][\\w.:-]*)?)?)?"; + + return protocolRE + dxregexp.host(flags) + pathRE; + }, + + emailAddress: function(/*Object?*/flags){ + + // summary: Builds a regular expression that matches an email address + // + //flags: An object + // flags.allowCruft Allow address like <mailto:foo@yahoo.com>. Default is false. + // flags in regexp.host can be applied. + // flags in regexp.ipAddress can be applied. + + // assign default values to missing paramters + flags = (typeof flags == "object") ? flags : {}; + if (typeof flags.allowCruft != "boolean") { flags.allowCruft = false; } + flags.allowPort = false; // invalid in email addresses + + // user name RE per rfc5322 + var usernameRE = "([!#-'*+\\-\\/-9=?A-Z^-~]+[.])*[!#-'*+\\-\\/-9=?A-Z^-~]+"; + + // build emailAddress RE + var emailAddressRE = usernameRE + "@" + dxregexp.host(flags); + + // Allow email addresses with cruft + if ( flags.allowCruft ) { + emailAddressRE = "<?(mailto\\:)?" + emailAddressRE + ">?"; + } + + return emailAddressRE; // String + }, + + emailAddressList: function(/*Object?*/flags){ + // summary: Builds a regular expression that matches a list of email addresses. + // + // flags: An object. + // flags.listSeparator The character used to separate email addresses. Default is ";", ",", "\n" or " ". + // flags in regexp.emailAddress can be applied. + // flags in regexp.host can be applied. + // flags in regexp.ipAddress can be applied. + + // assign default values to missing paramters + flags = (typeof flags == "object") ? flags : {}; + if(typeof flags.listSeparator != "string"){ flags.listSeparator = "\\s;,"; } + + // build a RE for an Email Address List + var emailAddressRE = dxregexp.emailAddress(flags); + var emailAddressListRE = "(" + emailAddressRE + "\\s*[" + flags.listSeparator + "]\\s*)*" + + emailAddressRE + "\\s*[" + flags.listSeparator + "]?\\s*"; + + return emailAddressListRE; // String + }, + + numberFormat: function(/*Object?*/flags){ + // summary: Builds a regular expression to match any sort of number based format + // description: + // Use this method for phone numbers, social security numbers, zip-codes, etc. + // The RE can match one format or one of multiple formats. + // + // Format + // # Stands for a digit, 0-9. + // ? Stands for an optional digit, 0-9 or nothing. + // All other characters must appear literally in the expression. + // + // Example + // "(###) ###-####" -> (510) 542-9742 + // "(###) ###-#### x#???" -> (510) 542-9742 x153 + // "###-##-####" -> 506-82-1089 i.e. social security number + // "#####-####" -> 98225-1649 i.e. zip code + // + // flags: An object + // flags.format A string or an Array of strings for multiple formats. + + // assign default values to missing paramters + flags = (typeof flags == "object") ? flags : {}; + if(typeof flags.format == "undefined"){ flags.format = "###-###-####"; } + + // Converts a number format to RE. + var digitRE = function(format){ + // escape all special characters, except '?' + return regexp.escapeString(format, "?") + // Now replace '?' with Regular Expression + .replace(/\?/g, "\\d?") + // replace # with Regular Expression + .replace(/#/g, "\\d") + ; + }; + + // build RE for multiple number formats + return regexp.buildGroupRE(flags.format, digitRE); //String + }, + + ca: { + + postalCode: function(){ + // summary: String regular Express to match Canadain Postal Codes + return "([A-Z][0-9][A-Z] [0-9][A-Z][0-9])"; + }, + + province: function(){ + // summary: a regular expression to match Canadian Province Abbreviations + return "(AB|BC|MB|NB|NL|NS|NT|NU|ON|PE|QC|SK|YT)"; + } + + }, + + us:{ + + state: function(/*Object?*/flags){ + // summary: A regular expression to match US state and territory abbreviations + // + // flags An object. + // flags.allowTerritories Allow Guam, Puerto Rico, etc. Default is true. + // flags.allowMilitary Allow military 'states', e.g. Armed Forces Europe (AE). Default is true. + + // assign default values to missing paramters + flags = (typeof flags == "object") ? flags : {}; + if(typeof flags.allowTerritories != "boolean"){ flags.allowTerritories = true; } + if(typeof flags.allowMilitary != "boolean"){ flags.allowMilitary = true; } + + // state RE + var statesRE = + "AL|AK|AZ|AR|CA|CO|CT|DE|DC|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|" + + "NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY"; + + // territories RE + var territoriesRE = "AS|FM|GU|MH|MP|PW|PR|VI"; + + // military states RE + var militaryRE = "AA|AE|AP"; + + // Build states and territories RE + if(flags.allowTerritories){ statesRE += "|" + territoriesRE; } + if(flags.allowMilitary){ statesRE += "|" + militaryRE; } + + return "(" + statesRE + ")"; // String + } + + } + +}; + +return dxregexp; + +}); diff --git a/js/dojo/dojox/validate/us.js b/js/dojo/dojox/validate/us.js new file mode 100644 index 0000000..dcb4a5c --- /dev/null +++ b/js/dojo/dojox/validate/us.js @@ -0,0 +1,68 @@ +//>>built +define("dojox/validate/us", ["dojo/_base/lang", "./_base", "./regexp"], + function(lang, validate, xregexp){ + +var us = lang.getObject("us", true, validate); +us.isState = function(/*String*/value, /*Object?*/flags){ + // summary: Validates US state and territory abbreviations. + // + // value: A two character string + // flags: An object + // flags.allowTerritories Allow Guam, Puerto Rico, etc. Default is true. + // flags.allowMilitary Allow military 'states', e.g. Armed Forces Europe (AE). Default is true. + + var re = new RegExp("^" + xregexp.us.state(flags) + "$", "i"); + return re.test(value); // Boolean +}; + +us.isPhoneNumber = function(/*String*/value){ + // summary: Validates 10 US digit phone number for several common formats + // value: The telephone number string + + var flags = { + format: [ + "###-###-####", + "(###) ###-####", + "(###) ### ####", + "###.###.####", + "###/###-####", + "### ### ####", + "###-###-#### x#???", + "(###) ###-#### x#???", + "(###) ### #### x#???", + "###.###.#### x#???", + "###/###-#### x#???", + "### ### #### x#???", + "##########" + ] + }; + return validate.isNumberFormat(value, flags); // Boolean +}; + +us.isSocialSecurityNumber = function(/*String*/value){ + // summary: Validates social security number + var flags = { + format: [ + "###-##-####", + "### ## ####", + "#########" + ] + }; + return validate.isNumberFormat(value, flags); // Boolean +}; + +us.isZipCode = function(/*String*/value){ + // summary: Validates U.S. zip-code + var flags = { + format: [ + "#####-####", + "##### ####", + "#########", + "#####" + ] + }; + return validate.isNumberFormat(value, flags); // Boolean +}; + +return us; +}); diff --git a/js/dojo/dojox/validate/web.js b/js/dojo/dojox/validate/web.js new file mode 100644 index 0000000..bcf2cd5 --- /dev/null +++ b/js/dojo/dojox/validate/web.js @@ -0,0 +1,94 @@ +//>>built +define("dojox/validate/web", ["./_base", "./regexp"], function(validate, xregexp){ + +/*===== + + validate = dojox.validate; + +=====*/ + +validate.isIpAddress = function(/*String*/value, /*Object?*/flags) { + // summary: Validates an IP address + // + // description: + // Supports 5 formats for IPv4: dotted decimal, dotted hex, dotted octal, decimal and hexadecimal. + // Supports 2 formats for Ipv6. + // + // value A string. + // flags An object. All flags are boolean with default = true. + // flags.allowDottedDecimal Example, 207.142.131.235. No zero padding. + // flags.allowDottedHex Example, 0x18.0x11.0x9b.0x28. Case insensitive. Zero padding allowed. + // flags.allowDottedOctal Example, 0030.0021.0233.0050. Zero padding allowed. + // flags.allowDecimal Example, 3482223595. A decimal number between 0-4294967295. + // flags.allowHex Example, 0xCF8E83EB. Hexadecimal number between 0x0-0xFFFFFFFF. + // Case insensitive. Zero padding allowed. + // flags.allowIPv6 IPv6 address written as eight groups of four hexadecimal digits. + // flags.allowHybrid IPv6 address written as six groups of four hexadecimal digits + // followed by the usual 4 dotted decimal digit notation of IPv4. x:x:x:x:x:x:d.d.d.d + + var re = new RegExp("^" + xregexp.ipAddress(flags) + "$", "i"); + return re.test(value); // Boolean +}; + + +validate.isUrl = function(/*String*/value, /*Object?*/flags) { + // summary: Checks if a string could be a valid URL + // value: A string + // flags: An object + // flags.scheme Can be true, false, or [true, false]. + // This means: required, not allowed, or either. + // flags in regexp.host can be applied. + // flags in regexp.ipAddress can be applied. + // flags in regexp.tld can be applied. + + var re = new RegExp("^" + xregexp.url(flags) + "$", "i"); + return re.test(value); // Boolean +}; + +validate.isEmailAddress = function(/*String*/value, /*Object?*/flags) { + // summary: Checks if a string could be a valid email address + // + // value: A string + // flags: An object + // flags.allowCruft Allow address like <mailto:foo@yahoo.com>. Default is false. + // flags in regexp.host can be applied. + // flags in regexp.ipAddress can be applied. + // flags in regexp.tld can be applied. + + var re = new RegExp("^" + xregexp.emailAddress(flags) + "$", "i"); + return re.test(value); // Boolean +}; + +validate.isEmailAddressList = function(/*String*/value, /*Object?*/flags) { + // summary: Checks if a string could be a valid email address list. + // + // value A string. + // flags An object. + // flags.listSeparator The character used to separate email addresses. Default is ";", ",", "\n" or " ". + // flags in regexp.emailAddress can be applied. + // flags in regexp.host can be applied. + // flags in regexp.ipAddress can be applied. + // flags in regexp.tld can be applied. + + var re = new RegExp("^" + xregexp.emailAddressList(flags) + "$", "i"); + return re.test(value); // Boolean +}; + +validate.getEmailAddressList = function(/*String*/value, /*Object?*/flags) { + // summary: Check if value is an email address list. If an empty list + // is returned, the value didn't pass the test or it was empty. + // + // value: A string + // flags: An object (same as dojo.validate.isEmailAddressList) + + if(!flags) { flags = {}; } + if(!flags.listSeparator) { flags.listSeparator = "\\s;,"; } + + if ( validate.isEmailAddressList(value, flags) ) { + return value.split(new RegExp("\\s*[" + flags.listSeparator + "]\\s*")); // Array + } + return []; // Array +}; + +return validate; +}); |
