additional-methods.js 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. /*!
  2. * jQuery Validation Plugin v1.15.1
  3. *
  4. * http://jqueryvalidation.org/
  5. *
  6. * Copyright (c) 2016 Jörn Zaefferer
  7. * Released under the MIT license
  8. */
  9. (function( factory ) {
  10. if ( typeof define === "function" && define.amd ) {
  11. define( ["jquery", "./jquery.validate"], factory );
  12. } else if (typeof module === "object" && module.exports) {
  13. module.exports = factory( require( "jquery" ) );
  14. } else {
  15. factory( jQuery );
  16. }
  17. }(function( $ ) {
  18. ( function() {
  19. function stripHtml( value ) {
  20. // Remove html tags and space chars
  21. return value.replace( /<.[^<>]*?>/g, " " ).replace( /&nbsp;|&#160;/gi, " " )
  22. // Remove punctuation
  23. .replace( /[.(),;:!?%#$'\"_+=\/\-“”’]*/g, "" );
  24. }
  25. $.validator.addMethod( "maxWords", function( value, element, params ) {
  26. return this.optional( element ) || stripHtml( value ).match( /\b\w+\b/g ).length <= params;
  27. }, $.validator.format( "Please enter {0} words or less." ) );
  28. $.validator.addMethod( "minWords", function( value, element, params ) {
  29. return this.optional( element ) || stripHtml( value ).match( /\b\w+\b/g ).length >= params;
  30. }, $.validator.format( "Please enter at least {0} words." ) );
  31. $.validator.addMethod( "rangeWords", function( value, element, params ) {
  32. var valueStripped = stripHtml( value ),
  33. regex = /\b\w+\b/g;
  34. return this.optional( element ) || valueStripped.match( regex ).length >= params[ 0 ] && valueStripped.match( regex ).length <= params[ 1 ];
  35. }, $.validator.format( "Please enter between {0} and {1} words." ) );
  36. }() );
  37. // Accept a value from a file input based on a required mimetype
  38. $.validator.addMethod( "accept", function( value, element, param ) {
  39. // Split mime on commas in case we have multiple types we can accept
  40. var typeParam = typeof param === "string" ? param.replace( /\s/g, "" ) : "image/*",
  41. optionalValue = this.optional( element ),
  42. i, file, regex;
  43. // Element is optional
  44. if ( optionalValue ) {
  45. return optionalValue;
  46. }
  47. if ( $( element ).attr( "type" ) === "file" ) {
  48. // Escape string to be used in the regex
  49. // see: http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
  50. // Escape also "/*" as "/.*" as a wildcard
  51. typeParam = typeParam
  52. .replace( /[\-\[\]\/\{\}\(\)\+\?\.\\\^\$\|]/g, "\\$&" )
  53. .replace( /,/g, "|" )
  54. .replace( /\/\*/g, "/.*" );
  55. // Check if the element has a FileList before checking each file
  56. if ( element.files && element.files.length ) {
  57. regex = new RegExp( ".?(" + typeParam + ")$", "i" );
  58. for ( i = 0; i < element.files.length; i++ ) {
  59. file = element.files[ i ];
  60. // Grab the mimetype from the loaded file, verify it matches
  61. if ( !file.type.match( regex ) ) {
  62. return false;
  63. }
  64. }
  65. }
  66. }
  67. // Either return true because we've validated each file, or because the
  68. // browser does not support element.files and the FileList feature
  69. return true;
  70. }, $.validator.format( "Please enter a value with a valid mimetype." ) );
  71. $.validator.addMethod( "alphanumeric", function( value, element ) {
  72. return this.optional( element ) || /^\w+$/i.test( value );
  73. }, "Letters, numbers, and underscores only please" );
  74. /*
  75. * Dutch bank account numbers (not 'giro' numbers) have 9 digits
  76. * and pass the '11 check'.
  77. * We accept the notation with spaces, as that is common.
  78. * acceptable: 123456789 or 12 34 56 789
  79. */
  80. $.validator.addMethod( "bankaccountNL", function( value, element ) {
  81. if ( this.optional( element ) ) {
  82. return true;
  83. }
  84. if ( !( /^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test( value ) ) ) {
  85. return false;
  86. }
  87. // Now '11 check'
  88. var account = value.replace( / /g, "" ), // Remove spaces
  89. sum = 0,
  90. len = account.length,
  91. pos, factor, digit;
  92. for ( pos = 0; pos < len; pos++ ) {
  93. factor = len - pos;
  94. digit = account.substring( pos, pos + 1 );
  95. sum = sum + factor * digit;
  96. }
  97. return sum % 11 === 0;
  98. }, "Please specify a valid bank account number" );
  99. $.validator.addMethod( "bankorgiroaccountNL", function( value, element ) {
  100. return this.optional( element ) ||
  101. ( $.validator.methods.bankaccountNL.call( this, value, element ) ) ||
  102. ( $.validator.methods.giroaccountNL.call( this, value, element ) );
  103. }, "Please specify a valid bank or giro account number" );
  104. /**
  105. * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity.
  106. *
  107. * BIC pattern: BBBBCCLLbbb (8 or 11 characters long; bbb is optional)
  108. *
  109. * Validation is case-insensitive. Please make sure to normalize input yourself.
  110. *
  111. * BIC definition in detail:
  112. * - First 4 characters - bank code (only letters)
  113. * - Next 2 characters - ISO 3166-1 alpha-2 country code (only letters)
  114. * - Next 2 characters - location code (letters and digits)
  115. * a. shall not start with '0' or '1'
  116. * b. second character must be a letter ('O' is not allowed) or digit ('0' for test (therefore not allowed), '1' denoting passive participant, '2' typically reverse-billing)
  117. * - Last 3 characters - branch code, optional (shall not start with 'X' except in case of 'XXX' for primary office) (letters and digits)
  118. */
  119. $.validator.addMethod( "bic", function( value, element ) {
  120. return this.optional( element ) || /^([A-Z]{6}[A-Z2-9][A-NP-Z1-9])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test( value.toUpperCase() );
  121. }, "Please specify a valid BIC code" );
  122. /*
  123. * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities
  124. * Further rules can be found in Spanish on http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal
  125. */
  126. $.validator.addMethod( "cifES", function( value ) {
  127. "use strict";
  128. var num = [],
  129. controlDigit, sum, i, count, tmp, secondDigit;
  130. value = value.toUpperCase();
  131. // Quick format test
  132. if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) {
  133. return false;
  134. }
  135. for ( i = 0; i < 9; i++ ) {
  136. num[ i ] = parseInt( value.charAt( i ), 10 );
  137. }
  138. // Algorithm for checking CIF codes
  139. sum = num[ 2 ] + num[ 4 ] + num[ 6 ];
  140. for ( count = 1; count < 8; count += 2 ) {
  141. tmp = ( 2 * num[ count ] ).toString();
  142. secondDigit = tmp.charAt( 1 );
  143. sum += parseInt( tmp.charAt( 0 ), 10 ) + ( secondDigit === "" ? 0 : parseInt( secondDigit, 10 ) );
  144. }
  145. /* The first (position 1) is a letter following the following criteria:
  146. * A. Corporations
  147. * B. LLCs
  148. * C. General partnerships
  149. * D. Companies limited partnerships
  150. * E. Communities of goods
  151. * F. Cooperative Societies
  152. * G. Associations
  153. * H. Communities of homeowners in horizontal property regime
  154. * J. Civil Societies
  155. * K. Old format
  156. * L. Old format
  157. * M. Old format
  158. * N. Nonresident entities
  159. * P. Local authorities
  160. * Q. Autonomous bodies, state or not, and the like, and congregations and religious institutions
  161. * R. Congregations and religious institutions (since 2008 ORDER EHA/451/2008)
  162. * S. Organs of State Administration and regions
  163. * V. Agrarian Transformation
  164. * W. Permanent establishments of non-resident in Spain
  165. */
  166. if ( /^[ABCDEFGHJNPQRSUVW]{1}/.test( value ) ) {
  167. sum += "";
  168. controlDigit = 10 - parseInt( sum.charAt( sum.length - 1 ), 10 );
  169. value += controlDigit;
  170. return ( num[ 8 ].toString() === String.fromCharCode( 64 + controlDigit ) || num[ 8 ].toString() === value.charAt( value.length - 1 ) );
  171. }
  172. return false;
  173. }, "Please specify a valid CIF number." );
  174. /*
  175. * Brazillian CPF number (Cadastrado de Pessoas Físicas) is the equivalent of a Brazilian tax registration number.
  176. * CPF numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation.
  177. */
  178. $.validator.addMethod( "cpfBR", function( value ) {
  179. // Removing special characters from value
  180. value = value.replace( /([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g, "" );
  181. // Checking value to have 11 digits only
  182. if ( value.length !== 11 ) {
  183. return false;
  184. }
  185. var sum = 0,
  186. firstCN, secondCN, checkResult, i;
  187. firstCN = parseInt( value.substring( 9, 10 ), 10 );
  188. secondCN = parseInt( value.substring( 10, 11 ), 10 );
  189. checkResult = function( sum, cn ) {
  190. var result = ( sum * 10 ) % 11;
  191. if ( ( result === 10 ) || ( result === 11 ) ) {
  192. result = 0;
  193. }
  194. return ( result === cn );
  195. };
  196. // Checking for dump data
  197. if ( value === "" ||
  198. value === "00000000000" ||
  199. value === "11111111111" ||
  200. value === "22222222222" ||
  201. value === "33333333333" ||
  202. value === "44444444444" ||
  203. value === "55555555555" ||
  204. value === "66666666666" ||
  205. value === "77777777777" ||
  206. value === "88888888888" ||
  207. value === "99999999999"
  208. ) {
  209. return false;
  210. }
  211. // Step 1 - using first Check Number:
  212. for ( i = 1; i <= 9; i++ ) {
  213. sum = sum + parseInt( value.substring( i - 1, i ), 10 ) * ( 11 - i );
  214. }
  215. // If first Check Number (CN) is valid, move to Step 2 - using second Check Number:
  216. if ( checkResult( sum, firstCN ) ) {
  217. sum = 0;
  218. for ( i = 1; i <= 10; i++ ) {
  219. sum = sum + parseInt( value.substring( i - 1, i ), 10 ) * ( 12 - i );
  220. }
  221. return checkResult( sum, secondCN );
  222. }
  223. return false;
  224. }, "Please specify a valid CPF number" );
  225. // http://jqueryvalidation.org/creditcard-method/
  226. // based on http://en.wikipedia.org/wiki/Luhn_algorithm
  227. $.validator.addMethod( "creditcard", function( value, element ) {
  228. if ( this.optional( element ) ) {
  229. return "dependency-mismatch";
  230. }
  231. // Accept only spaces, digits and dashes
  232. if ( /[^0-9 \-]+/.test( value ) ) {
  233. return false;
  234. }
  235. var nCheck = 0,
  236. nDigit = 0,
  237. bEven = false,
  238. n, cDigit;
  239. value = value.replace( /\D/g, "" );
  240. // Basing min and max length on
  241. // http://developer.ean.com/general_info/Valid_Credit_Card_Types
  242. if ( value.length < 13 || value.length > 19 ) {
  243. return false;
  244. }
  245. for ( n = value.length - 1; n >= 0; n-- ) {
  246. cDigit = value.charAt( n );
  247. nDigit = parseInt( cDigit, 10 );
  248. if ( bEven ) {
  249. if ( ( nDigit *= 2 ) > 9 ) {
  250. nDigit -= 9;
  251. }
  252. }
  253. nCheck += nDigit;
  254. bEven = !bEven;
  255. }
  256. return ( nCheck % 10 ) === 0;
  257. }, "Please enter a valid credit card number." );
  258. /* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator
  259. * Redistributed under the the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0
  260. * Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)
  261. */
  262. $.validator.addMethod( "creditcardtypes", function( value, element, param ) {
  263. if ( /[^0-9\-]+/.test( value ) ) {
  264. return false;
  265. }
  266. value = value.replace( /\D/g, "" );
  267. var validTypes = 0x0000;
  268. if ( param.mastercard ) {
  269. validTypes |= 0x0001;
  270. }
  271. if ( param.visa ) {
  272. validTypes |= 0x0002;
  273. }
  274. if ( param.amex ) {
  275. validTypes |= 0x0004;
  276. }
  277. if ( param.dinersclub ) {
  278. validTypes |= 0x0008;
  279. }
  280. if ( param.enroute ) {
  281. validTypes |= 0x0010;
  282. }
  283. if ( param.discover ) {
  284. validTypes |= 0x0020;
  285. }
  286. if ( param.jcb ) {
  287. validTypes |= 0x0040;
  288. }
  289. if ( param.unknown ) {
  290. validTypes |= 0x0080;
  291. }
  292. if ( param.all ) {
  293. validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;
  294. }
  295. if ( validTypes & 0x0001 && /^(5[12345])/.test( value ) ) { // Mastercard
  296. return value.length === 16;
  297. }
  298. if ( validTypes & 0x0002 && /^(4)/.test( value ) ) { // Visa
  299. return value.length === 16;
  300. }
  301. if ( validTypes & 0x0004 && /^(3[47])/.test( value ) ) { // Amex
  302. return value.length === 15;
  303. }
  304. if ( validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test( value ) ) { // Dinersclub
  305. return value.length === 14;
  306. }
  307. if ( validTypes & 0x0010 && /^(2(014|149))/.test( value ) ) { // Enroute
  308. return value.length === 15;
  309. }
  310. if ( validTypes & 0x0020 && /^(6011)/.test( value ) ) { // Discover
  311. return value.length === 16;
  312. }
  313. if ( validTypes & 0x0040 && /^(3)/.test( value ) ) { // Jcb
  314. return value.length === 16;
  315. }
  316. if ( validTypes & 0x0040 && /^(2131|1800)/.test( value ) ) { // Jcb
  317. return value.length === 15;
  318. }
  319. if ( validTypes & 0x0080 ) { // Unknown
  320. return true;
  321. }
  322. return false;
  323. }, "Please enter a valid credit card number." );
  324. /**
  325. * Validates currencies with any given symbols by @jameslouiz
  326. * Symbols can be optional or required. Symbols required by default
  327. *
  328. * Usage examples:
  329. * currency: ["£", false] - Use false for soft currency validation
  330. * currency: ["$", false]
  331. * currency: ["RM", false] - also works with text based symbols such as "RM" - Malaysia Ringgit etc
  332. *
  333. * <input class="currencyInput" name="currencyInput">
  334. *
  335. * Soft symbol checking
  336. * currencyInput: {
  337. * currency: ["$", false]
  338. * }
  339. *
  340. * Strict symbol checking (default)
  341. * currencyInput: {
  342. * currency: "$"
  343. * //OR
  344. * currency: ["$", true]
  345. * }
  346. *
  347. * Multiple Symbols
  348. * currencyInput: {
  349. * currency: "$,£,¢"
  350. * }
  351. */
  352. $.validator.addMethod( "currency", function( value, element, param ) {
  353. var isParamString = typeof param === "string",
  354. symbol = isParamString ? param : param[ 0 ],
  355. soft = isParamString ? true : param[ 1 ],
  356. regex;
  357. symbol = symbol.replace( /,/g, "" );
  358. symbol = soft ? symbol + "]" : symbol + "]?";
  359. regex = "^[" + symbol + "([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$";
  360. regex = new RegExp( regex );
  361. return this.optional( element ) || regex.test( value );
  362. }, "Please specify a valid currency" );
  363. $.validator.addMethod( "dateFA", function( value, element ) {
  364. return this.optional( element ) || /^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test( value );
  365. }, $.validator.messages.date );
  366. /**
  367. * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
  368. *
  369. * @example $.validator.methods.date("01/01/1900")
  370. * @result true
  371. *
  372. * @example $.validator.methods.date("01/13/1990")
  373. * @result false
  374. *
  375. * @example $.validator.methods.date("01.01.1900")
  376. * @result false
  377. *
  378. * @example <input name="pippo" class="{dateITA:true}" />
  379. * @desc Declares an optional input element whose value must be a valid date.
  380. *
  381. * @name $.validator.methods.dateITA
  382. * @type Boolean
  383. * @cat Plugins/Validate/Methods
  384. */
  385. $.validator.addMethod( "dateITA", function( value, element ) {
  386. var check = false,
  387. re = /^\d{1,2}\/\d{1,2}\/\d{4}$/,
  388. adata, gg, mm, aaaa, xdata;
  389. if ( re.test( value ) ) {
  390. adata = value.split( "/" );
  391. gg = parseInt( adata[ 0 ], 10 );
  392. mm = parseInt( adata[ 1 ], 10 );
  393. aaaa = parseInt( adata[ 2 ], 10 );
  394. xdata = new Date( Date.UTC( aaaa, mm - 1, gg, 12, 0, 0, 0 ) );
  395. if ( ( xdata.getUTCFullYear() === aaaa ) && ( xdata.getUTCMonth() === mm - 1 ) && ( xdata.getUTCDate() === gg ) ) {
  396. check = true;
  397. } else {
  398. check = false;
  399. }
  400. } else {
  401. check = false;
  402. }
  403. return this.optional( element ) || check;
  404. }, $.validator.messages.date );
  405. $.validator.addMethod( "dateNL", function( value, element ) {
  406. return this.optional( element ) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test( value );
  407. }, $.validator.messages.date );
  408. // Older "accept" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept
  409. $.validator.addMethod( "extension", function( value, element, param ) {
  410. param = typeof param === "string" ? param.replace( /,/g, "|" ) : "png|jpe?g|gif";
  411. return this.optional( element ) || value.match( new RegExp( "\\.(" + param + ")$", "i" ) );
  412. }, $.validator.format( "Please enter a value with a valid extension." ) );
  413. /**
  414. * Dutch giro account numbers (not bank numbers) have max 7 digits
  415. */
  416. $.validator.addMethod( "giroaccountNL", function( value, element ) {
  417. return this.optional( element ) || /^[0-9]{1,7}$/.test( value );
  418. }, "Please specify a valid giro account number" );
  419. /**
  420. * IBAN is the international bank account number.
  421. * It has a country - specific format, that is checked here too
  422. *
  423. * Validation is case-insensitive. Please make sure to normalize input yourself.
  424. */
  425. $.validator.addMethod( "iban", function( value, element ) {
  426. // Some quick simple tests to prevent needless work
  427. if ( this.optional( element ) ) {
  428. return true;
  429. }
  430. // Remove spaces and to upper case
  431. var iban = value.replace( / /g, "" ).toUpperCase(),
  432. ibancheckdigits = "",
  433. leadingZeroes = true,
  434. cRest = "",
  435. cOperator = "",
  436. countrycode, ibancheck, charAt, cChar, bbanpattern, bbancountrypatterns, ibanregexp, i, p;
  437. // Check for IBAN code length.
  438. // It contains:
  439. // country code ISO 3166-1 - two letters,
  440. // two check digits,
  441. // Basic Bank Account Number (BBAN) - up to 30 chars
  442. var minimalIBANlength = 5;
  443. if ( iban.length < minimalIBANlength ) {
  444. return false;
  445. }
  446. // Check the country code and find the country specific format
  447. countrycode = iban.substring( 0, 2 );
  448. bbancountrypatterns = {
  449. "AL": "\\d{8}[\\dA-Z]{16}",
  450. "AD": "\\d{8}[\\dA-Z]{12}",
  451. "AT": "\\d{16}",
  452. "AZ": "[\\dA-Z]{4}\\d{20}",
  453. "BE": "\\d{12}",
  454. "BH": "[A-Z]{4}[\\dA-Z]{14}",
  455. "BA": "\\d{16}",
  456. "BR": "\\d{23}[A-Z][\\dA-Z]",
  457. "BG": "[A-Z]{4}\\d{6}[\\dA-Z]{8}",
  458. "CR": "\\d{17}",
  459. "HR": "\\d{17}",
  460. "CY": "\\d{8}[\\dA-Z]{16}",
  461. "CZ": "\\d{20}",
  462. "DK": "\\d{14}",
  463. "DO": "[A-Z]{4}\\d{20}",
  464. "EE": "\\d{16}",
  465. "FO": "\\d{14}",
  466. "FI": "\\d{14}",
  467. "FR": "\\d{10}[\\dA-Z]{11}\\d{2}",
  468. "GE": "[\\dA-Z]{2}\\d{16}",
  469. "DE": "\\d{18}",
  470. "GI": "[A-Z]{4}[\\dA-Z]{15}",
  471. "GR": "\\d{7}[\\dA-Z]{16}",
  472. "GL": "\\d{14}",
  473. "GT": "[\\dA-Z]{4}[\\dA-Z]{20}",
  474. "HU": "\\d{24}",
  475. "IS": "\\d{22}",
  476. "IE": "[\\dA-Z]{4}\\d{14}",
  477. "IL": "\\d{19}",
  478. "IT": "[A-Z]\\d{10}[\\dA-Z]{12}",
  479. "KZ": "\\d{3}[\\dA-Z]{13}",
  480. "KW": "[A-Z]{4}[\\dA-Z]{22}",
  481. "LV": "[A-Z]{4}[\\dA-Z]{13}",
  482. "LB": "\\d{4}[\\dA-Z]{20}",
  483. "LI": "\\d{5}[\\dA-Z]{12}",
  484. "LT": "\\d{16}",
  485. "LU": "\\d{3}[\\dA-Z]{13}",
  486. "MK": "\\d{3}[\\dA-Z]{10}\\d{2}",
  487. "MT": "[A-Z]{4}\\d{5}[\\dA-Z]{18}",
  488. "MR": "\\d{23}",
  489. "MU": "[A-Z]{4}\\d{19}[A-Z]{3}",
  490. "MC": "\\d{10}[\\dA-Z]{11}\\d{2}",
  491. "MD": "[\\dA-Z]{2}\\d{18}",
  492. "ME": "\\d{18}",
  493. "NL": "[A-Z]{4}\\d{10}",
  494. "NO": "\\d{11}",
  495. "PK": "[\\dA-Z]{4}\\d{16}",
  496. "PS": "[\\dA-Z]{4}\\d{21}",
  497. "PL": "\\d{24}",
  498. "PT": "\\d{21}",
  499. "RO": "[A-Z]{4}[\\dA-Z]{16}",
  500. "SM": "[A-Z]\\d{10}[\\dA-Z]{12}",
  501. "SA": "\\d{2}[\\dA-Z]{18}",
  502. "RS": "\\d{18}",
  503. "SK": "\\d{20}",
  504. "SI": "\\d{15}",
  505. "ES": "\\d{20}",
  506. "SE": "\\d{20}",
  507. "CH": "\\d{5}[\\dA-Z]{12}",
  508. "TN": "\\d{20}",
  509. "TR": "\\d{5}[\\dA-Z]{17}",
  510. "AE": "\\d{3}\\d{16}",
  511. "GB": "[A-Z]{4}\\d{14}",
  512. "VG": "[\\dA-Z]{4}\\d{16}"
  513. };
  514. bbanpattern = bbancountrypatterns[ countrycode ];
  515. // As new countries will start using IBAN in the
  516. // future, we only check if the countrycode is known.
  517. // This prevents false negatives, while almost all
  518. // false positives introduced by this, will be caught
  519. // by the checksum validation below anyway.
  520. // Strict checking should return FALSE for unknown
  521. // countries.
  522. if ( typeof bbanpattern !== "undefined" ) {
  523. ibanregexp = new RegExp( "^[A-Z]{2}\\d{2}" + bbanpattern + "$", "" );
  524. if ( !( ibanregexp.test( iban ) ) ) {
  525. return false; // Invalid country specific format
  526. }
  527. }
  528. // Now check the checksum, first convert to digits
  529. ibancheck = iban.substring( 4, iban.length ) + iban.substring( 0, 4 );
  530. for ( i = 0; i < ibancheck.length; i++ ) {
  531. charAt = ibancheck.charAt( i );
  532. if ( charAt !== "0" ) {
  533. leadingZeroes = false;
  534. }
  535. if ( !leadingZeroes ) {
  536. ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf( charAt );
  537. }
  538. }
  539. // Calculate the result of: ibancheckdigits % 97
  540. for ( p = 0; p < ibancheckdigits.length; p++ ) {
  541. cChar = ibancheckdigits.charAt( p );
  542. cOperator = "" + cRest + "" + cChar;
  543. cRest = cOperator % 97;
  544. }
  545. return cRest === 1;
  546. }, "Please specify a valid IBAN" );
  547. $.validator.addMethod( "integer", function( value, element ) {
  548. return this.optional( element ) || /^-?\d+$/.test( value );
  549. }, "A positive or negative non-decimal number please" );
  550. $.validator.addMethod( "ipv4", function( value, element ) {
  551. return this.optional( element ) || /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test( value );
  552. }, "Please enter a valid IP v4 address." );
  553. $.validator.addMethod( "ipv6", function( value, element ) {
  554. return this.optional( element ) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test( value );
  555. }, "Please enter a valid IP v6 address." );
  556. $.validator.addMethod( "lettersonly", function( value, element ) {
  557. return this.optional( element ) || /^[a-z]+$/i.test( value );
  558. }, "Letters only please" );
  559. $.validator.addMethod( "letterswithbasicpunc", function( value, element ) {
  560. return this.optional( element ) || /^[a-z\-.,()'"\s]+$/i.test( value );
  561. }, "Letters or punctuation only please" );
  562. $.validator.addMethod( "mobileNL", function( value, element ) {
  563. return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test( value );
  564. }, "Please specify a valid mobile number" );
  565. /* For UK phone functions, do the following server side processing:
  566. * Compare original input with this RegEx pattern:
  567. * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
  568. * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
  569. * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
  570. * A number of very detailed GB telephone number RegEx patterns can also be found at:
  571. * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
  572. */
  573. $.validator.addMethod( "mobileUK", function( phone_number, element ) {
  574. phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
  575. return this.optional( element ) || phone_number.length > 9 &&
  576. phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/ );
  577. }, "Please specify a valid mobile number" );
  578. /*
  579. * The número de identidad de extranjero ( NIE )is a code used to identify the non-nationals in Spain
  580. */
  581. $.validator.addMethod( "nieES", function( value ) {
  582. "use strict";
  583. value = value.toUpperCase();
  584. // Basic format test
  585. if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) {
  586. return false;
  587. }
  588. // Test NIE
  589. //T
  590. if ( /^[T]{1}/.test( value ) ) {
  591. return ( value[ 8 ] === /^[T]{1}[A-Z0-9]{8}$/.test( value ) );
  592. }
  593. //XYZ
  594. if ( /^[XYZ]{1}/.test( value ) ) {
  595. return (
  596. value[ 8 ] === "TRWAGMYFPDXBNJZSQVHLCKE".charAt(
  597. value.replace( "X", "0" )
  598. .replace( "Y", "1" )
  599. .replace( "Z", "2" )
  600. .substring( 0, 8 ) % 23
  601. )
  602. );
  603. }
  604. return false;
  605. }, "Please specify a valid NIE number." );
  606. /*
  607. * The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals
  608. */
  609. $.validator.addMethod( "nifES", function( value ) {
  610. "use strict";
  611. value = value.toUpperCase();
  612. // Basic format test
  613. if ( !value.match( "((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)" ) ) {
  614. return false;
  615. }
  616. // Test NIF
  617. if ( /^[0-9]{8}[A-Z]{1}$/.test( value ) ) {
  618. return ( "TRWAGMYFPDXBNJZSQVHLCKE".charAt( value.substring( 8, 0 ) % 23 ) === value.charAt( 8 ) );
  619. }
  620. // Test specials NIF (starts with K, L or M)
  621. if ( /^[KLM]{1}/.test( value ) ) {
  622. return ( value[ 8 ] === String.fromCharCode( 64 ) );
  623. }
  624. return false;
  625. }, "Please specify a valid NIF number." );
  626. $.validator.addMethod( "notEqualTo", function( value, element, param ) {
  627. return this.optional( element ) || !$.validator.methods.equalTo.call( this, value, element, param );
  628. }, "Please enter a different value, values must not be the same." );
  629. $.validator.addMethod( "nowhitespace", function( value, element ) {
  630. return this.optional( element ) || /^\S+$/i.test( value );
  631. }, "No white space please" );
  632. /**
  633. * Return true if the field value matches the given format RegExp
  634. *
  635. * @example $.validator.methods.pattern("AR1004",element,/^AR\d{4}$/)
  636. * @result true
  637. *
  638. * @example $.validator.methods.pattern("BR1004",element,/^AR\d{4}$/)
  639. * @result false
  640. *
  641. * @name $.validator.methods.pattern
  642. * @type Boolean
  643. * @cat Plugins/Validate/Methods
  644. */
  645. $.validator.addMethod( "pattern", function( value, element, param ) {
  646. if ( this.optional( element ) ) {
  647. return true;
  648. }
  649. if ( typeof param === "string" ) {
  650. param = new RegExp( "^(?:" + param + ")$" );
  651. }
  652. return param.test( value );
  653. }, "Invalid format." );
  654. /**
  655. * Dutch phone numbers have 10 digits (or 11 and start with +31).
  656. */
  657. $.validator.addMethod( "phoneNL", function( value, element ) {
  658. return this.optional( element ) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test( value );
  659. }, "Please specify a valid phone number." );
  660. /* For UK phone functions, do the following server side processing:
  661. * Compare original input with this RegEx pattern:
  662. * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
  663. * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
  664. * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
  665. * A number of very detailed GB telephone number RegEx patterns can also be found at:
  666. * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
  667. */
  668. $.validator.addMethod( "phoneUK", function( phone_number, element ) {
  669. phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
  670. return this.optional( element ) || phone_number.length > 9 &&
  671. phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/ );
  672. }, "Please specify a valid phone number" );
  673. /**
  674. * Matches US phone number format
  675. *
  676. * where the area code may not start with 1 and the prefix may not start with 1
  677. * allows '-' or ' ' as a separator and allows parens around area code
  678. * some people may want to put a '1' in front of their number
  679. *
  680. * 1(212)-999-2345 or
  681. * 212 999 2344 or
  682. * 212-999-0983
  683. *
  684. * but not
  685. * 111-123-5434
  686. * and not
  687. * 212 123 4567
  688. */
  689. $.validator.addMethod( "phoneUS", function( phone_number, element ) {
  690. phone_number = phone_number.replace( /\s+/g, "" );
  691. return this.optional( element ) || phone_number.length > 9 &&
  692. phone_number.match( /^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/ );
  693. }, "Please specify a valid phone number" );
  694. /* For UK phone functions, do the following server side processing:
  695. * Compare original input with this RegEx pattern:
  696. * ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
  697. * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
  698. * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
  699. * A number of very detailed GB telephone number RegEx patterns can also be found at:
  700. * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
  701. */
  702. // Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers
  703. $.validator.addMethod( "phonesUK", function( phone_number, element ) {
  704. phone_number = phone_number.replace( /\(|\)|\s+|-/g, "" );
  705. return this.optional( element ) || phone_number.length > 9 &&
  706. phone_number.match( /^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/ );
  707. }, "Please specify a valid uk phone number" );
  708. /**
  709. * Matches a valid Canadian Postal Code
  710. *
  711. * @example jQuery.validator.methods.postalCodeCA( "H0H 0H0", element )
  712. * @result true
  713. *
  714. * @example jQuery.validator.methods.postalCodeCA( "H0H0H0", element )
  715. * @result false
  716. *
  717. * @name jQuery.validator.methods.postalCodeCA
  718. * @type Boolean
  719. * @cat Plugins/Validate/Methods
  720. */
  721. $.validator.addMethod( "postalCodeCA", function( value, element ) {
  722. return this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] *\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i.test( value );
  723. }, "Please specify a valid postal code" );
  724. /*
  725. * Valida CEPs do brasileiros:
  726. *
  727. * Formatos aceitos:
  728. * 99999-999
  729. * 99.999-999
  730. * 99999999
  731. */
  732. $.validator.addMethod( "postalcodeBR", function( cep_value, element ) {
  733. return this.optional( element ) || /^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test( cep_value );
  734. }, "Informe um CEP válido." );
  735. /* Matches Italian postcode (CAP) */
  736. $.validator.addMethod( "postalcodeIT", function( value, element ) {
  737. return this.optional( element ) || /^\d{5}$/.test( value );
  738. }, "Please specify a valid postal code" );
  739. $.validator.addMethod( "postalcodeNL", function( value, element ) {
  740. return this.optional( element ) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test( value );
  741. }, "Please specify a valid postal code" );
  742. // Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)
  743. $.validator.addMethod( "postcodeUK", function( value, element ) {
  744. return this.optional( element ) || /^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test( value );
  745. }, "Please specify a valid UK postcode" );
  746. /*
  747. * Lets you say "at least X inputs that match selector Y must be filled."
  748. *
  749. * The end result is that neither of these inputs:
  750. *
  751. * <input class="productinfo" name="partnumber">
  752. * <input class="productinfo" name="description">
  753. *
  754. * ...will validate unless at least one of them is filled.
  755. *
  756. * partnumber: {require_from_group: [1,".productinfo"]},
  757. * description: {require_from_group: [1,".productinfo"]}
  758. *
  759. * options[0]: number of fields that must be filled in the group
  760. * options[1]: CSS selector that defines the group of conditionally required fields
  761. */
  762. $.validator.addMethod( "require_from_group", function( value, element, options ) {
  763. var $fields = $( options[ 1 ], element.form ),
  764. $fieldsFirst = $fields.eq( 0 ),
  765. validator = $fieldsFirst.data( "valid_req_grp" ) ? $fieldsFirst.data( "valid_req_grp" ) : $.extend( {}, this ),
  766. isValid = $fields.filter( function() {
  767. return validator.elementValue( this );
  768. } ).length >= options[ 0 ];
  769. // Store the cloned validator for future validation
  770. $fieldsFirst.data( "valid_req_grp", validator );
  771. // If element isn't being validated, run each require_from_group field's validation rules
  772. if ( !$( element ).data( "being_validated" ) ) {
  773. $fields.data( "being_validated", true );
  774. $fields.each( function() {
  775. validator.element( this );
  776. } );
  777. $fields.data( "being_validated", false );
  778. }
  779. return isValid;
  780. }, $.validator.format( "Please fill at least {0} of these fields." ) );
  781. /*
  782. * Lets you say "either at least X inputs that match selector Y must be filled,
  783. * OR they must all be skipped (left blank)."
  784. *
  785. * The end result, is that none of these inputs:
  786. *
  787. * <input class="productinfo" name="partnumber">
  788. * <input class="productinfo" name="description">
  789. * <input class="productinfo" name="color">
  790. *
  791. * ...will validate unless either at least two of them are filled,
  792. * OR none of them are.
  793. *
  794. * partnumber: {skip_or_fill_minimum: [2,".productinfo"]},
  795. * description: {skip_or_fill_minimum: [2,".productinfo"]},
  796. * color: {skip_or_fill_minimum: [2,".productinfo"]}
  797. *
  798. * options[0]: number of fields that must be filled in the group
  799. * options[1]: CSS selector that defines the group of conditionally required fields
  800. *
  801. */
  802. $.validator.addMethod( "skip_or_fill_minimum", function( value, element, options ) {
  803. var $fields = $( options[ 1 ], element.form ),
  804. $fieldsFirst = $fields.eq( 0 ),
  805. validator = $fieldsFirst.data( "valid_skip" ) ? $fieldsFirst.data( "valid_skip" ) : $.extend( {}, this ),
  806. numberFilled = $fields.filter( function() {
  807. return validator.elementValue( this );
  808. } ).length,
  809. isValid = numberFilled === 0 || numberFilled >= options[ 0 ];
  810. // Store the cloned validator for future validation
  811. $fieldsFirst.data( "valid_skip", validator );
  812. // If element isn't being validated, run each skip_or_fill_minimum field's validation rules
  813. if ( !$( element ).data( "being_validated" ) ) {
  814. $fields.data( "being_validated", true );
  815. $fields.each( function() {
  816. validator.element( this );
  817. } );
  818. $fields.data( "being_validated", false );
  819. }
  820. return isValid;
  821. }, $.validator.format( "Please either skip these fields or fill at least {0} of them." ) );
  822. /* Validates US States and/or Territories by @jdforsythe
  823. * Can be case insensitive or require capitalization - default is case insensitive
  824. * Can include US Territories or not - default does not
  825. * Can include US Military postal abbreviations (AA, AE, AP) - default does not
  826. *
  827. * Note: "States" always includes DC (District of Colombia)
  828. *
  829. * Usage examples:
  830. *
  831. * This is the default - case insensitive, no territories, no military zones
  832. * stateInput: {
  833. * caseSensitive: false,
  834. * includeTerritories: false,
  835. * includeMilitary: false
  836. * }
  837. *
  838. * Only allow capital letters, no territories, no military zones
  839. * stateInput: {
  840. * caseSensitive: false
  841. * }
  842. *
  843. * Case insensitive, include territories but not military zones
  844. * stateInput: {
  845. * includeTerritories: true
  846. * }
  847. *
  848. * Only allow capital letters, include territories and military zones
  849. * stateInput: {
  850. * caseSensitive: true,
  851. * includeTerritories: true,
  852. * includeMilitary: true
  853. * }
  854. *
  855. */
  856. $.validator.addMethod( "stateUS", function( value, element, options ) {
  857. var isDefault = typeof options === "undefined",
  858. caseSensitive = ( isDefault || typeof options.caseSensitive === "undefined" ) ? false : options.caseSensitive,
  859. includeTerritories = ( isDefault || typeof options.includeTerritories === "undefined" ) ? false : options.includeTerritories,
  860. includeMilitary = ( isDefault || typeof options.includeMilitary === "undefined" ) ? false : options.includeMilitary,
  861. regex;
  862. if ( !includeTerritories && !includeMilitary ) {
  863. regex = "^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$";
  864. } else if ( includeTerritories && includeMilitary ) {
  865. regex = "^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$";
  866. } else if ( includeTerritories ) {
  867. regex = "^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$";
  868. } else {
  869. regex = "^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$";
  870. }
  871. regex = caseSensitive ? new RegExp( regex ) : new RegExp( regex, "i" );
  872. return this.optional( element ) || regex.test( value );
  873. }, "Please specify a valid state" );
  874. // TODO check if value starts with <, otherwise don't try stripping anything
  875. $.validator.addMethod( "strippedminlength", function( value, element, param ) {
  876. return $( value ).text().length >= param;
  877. }, $.validator.format( "Please enter at least {0} characters" ) );
  878. $.validator.addMethod( "time", function( value, element ) {
  879. return this.optional( element ) || /^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test( value );
  880. }, "Please enter a valid time, between 00:00 and 23:59" );
  881. $.validator.addMethod( "time12h", function( value, element ) {
  882. return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value );
  883. }, "Please enter a valid time in 12-hour am/pm format" );
  884. // Same as url, but TLD is optional
  885. $.validator.addMethod( "url2", function( value, element ) {
  886. return this.optional( element ) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test( value );
  887. }, $.validator.messages.url );
  888. /**
  889. * Return true, if the value is a valid vehicle identification number (VIN).
  890. *
  891. * Works with all kind of text inputs.
  892. *
  893. * @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
  894. * @desc Declares a required input element whose value must be a valid vehicle identification number.
  895. *
  896. * @name $.validator.methods.vinUS
  897. * @type Boolean
  898. * @cat Plugins/Validate/Methods
  899. */
  900. $.validator.addMethod( "vinUS", function( v ) {
  901. if ( v.length !== 17 ) {
  902. return false;
  903. }
  904. var LL = [ "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" ],
  905. VL = [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9 ],
  906. FL = [ 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 ],
  907. rs = 0,
  908. i, n, d, f, cd, cdv;
  909. for ( i = 0; i < 17; i++ ) {
  910. f = FL[ i ];
  911. d = v.slice( i, i + 1 );
  912. if ( i === 8 ) {
  913. cdv = d;
  914. }
  915. if ( !isNaN( d ) ) {
  916. d *= f;
  917. } else {
  918. for ( n = 0; n < LL.length; n++ ) {
  919. if ( d.toUpperCase() === LL[ n ] ) {
  920. d = VL[ n ];
  921. d *= f;
  922. if ( isNaN( cdv ) && n === 8 ) {
  923. cdv = LL[ n ];
  924. }
  925. break;
  926. }
  927. }
  928. }
  929. rs += d;
  930. }
  931. cd = rs % 11;
  932. if ( cd === 10 ) {
  933. cd = "X";
  934. }
  935. if ( cd === cdv ) {
  936. return true;
  937. }
  938. return false;
  939. }, "The specified vehicle identification number (VIN) is invalid." );
  940. $.validator.addMethod( "zipcodeUS", function( value, element ) {
  941. return this.optional( element ) || /^\d{5}(-\d{4})?$/.test( value );
  942. }, "The specified US ZIP Code is invalid" );
  943. $.validator.addMethod( "ziprange", function( value, element ) {
  944. return this.optional( element ) || /^90[2-5]\d\{2\}-\d{4}$/.test( value );
  945. }, "Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx" );
  946. }));