jQuery validate 及自定义验证规则

﹏ヽ暗。殇╰゛Y 2022-05-22 12:56 716阅读 0赞

jQuery validate.js

  1. /*!
  2. * jQuery Validation Plugin v1.14.0
  3. *
  4. * http://jqueryvalidation.org/
  5. *
  6. * Copyright (c) 2015 Jörn Zaefferer
  7. * Released under the MIT license
  8. */
  9. (function( factory ) {
  10. if ( typeof define === "function" && define.amd ) {
  11. define( ["jquery"], factory );
  12. } else {
  13. factory( jQuery );
  14. }
  15. }(function( $ ) {
  16. $.extend($.fn, {
  17. // http://jqueryvalidation.org/validate/
  18. validate: function( options ) {
  19. // if nothing is selected, return nothing; can't chain anyway
  20. if ( !this.length ) {
  21. if ( options && options.debug && window.console ) {
  22. console.warn( "Nothing selected, can't validate, returning nothing." );
  23. }
  24. return;
  25. }
  26. // check if a validator for this form was already created
  27. var validator = $.data( this[ 0 ], "validator" );
  28. if ( validator ) {
  29. return validator;
  30. }
  31. // Add novalidate tag if HTML5.
  32. this.attr( "novalidate", "novalidate" );
  33. validator = new $.validator( options, this[ 0 ] );
  34. $.data( this[ 0 ], "validator", validator );
  35. if ( validator.settings.onsubmit ) {
  36. this.on( "click.validate", ":submit", function( event ) {
  37. if ( validator.settings.submitHandler ) {
  38. validator.submitButton = event.target;
  39. }
  40. // allow suppressing validation by adding a cancel class to the submit button
  41. if ( $( this ).hasClass( "cancel" ) ) {
  42. validator.cancelSubmit = true;
  43. }
  44. // allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
  45. if ( $( this ).attr( "formnovalidate" ) !== undefined ) {
  46. validator.cancelSubmit = true;
  47. }
  48. });
  49. // validate the form on submit
  50. this.on( "submit.validate", function( event ) {
  51. if ( validator.settings.debug ) {
  52. // prevent form submit to be able to see console output
  53. event.preventDefault();
  54. }
  55. function handle() {
  56. var hidden, result;
  57. if ( validator.settings.submitHandler ) {
  58. if ( validator.submitButton ) {
  59. // insert a hidden input as a replacement for the missing submit button
  60. hidden = $( "<input type='hidden'/>" )
  61. .attr( "name", validator.submitButton.name )
  62. .val( $( validator.submitButton ).val() )
  63. .appendTo( validator.currentForm );
  64. }
  65. result = validator.settings.submitHandler.call( validator, validator.currentForm, event );
  66. if ( validator.submitButton ) {
  67. // and clean up afterwards; thanks to no-block-scope, hidden can be referenced
  68. hidden.remove();
  69. }
  70. if ( result !== undefined ) {
  71. return result;
  72. }
  73. return false;
  74. }
  75. return true;
  76. }
  77. // prevent submit for invalid forms or custom submit handlers
  78. if ( validator.cancelSubmit ) {
  79. validator.cancelSubmit = false;
  80. return handle();
  81. }
  82. if ( validator.form() ) {
  83. if ( validator.pendingRequest ) {
  84. validator.formSubmitted = true;
  85. return false;
  86. }
  87. return handle();
  88. } else {
  89. validator.focusInvalid();
  90. return false;
  91. }
  92. });
  93. }
  94. return validator;
  95. },
  96. // http://jqueryvalidation.org/valid/
  97. valid: function() {
  98. var valid, validator, errorList;
  99. if ( $( this[ 0 ] ).is( "form" ) ) {
  100. valid = this.validate().form();
  101. } else {
  102. errorList = [];
  103. valid = true;
  104. validator = $( this[ 0 ].form ).validate();
  105. this.each( function() {
  106. valid = validator.element( this ) && valid;
  107. errorList = errorList.concat( validator.errorList );
  108. });
  109. validator.errorList = errorList;
  110. }
  111. return valid;
  112. },
  113. // http://jqueryvalidation.org/rules/
  114. rules: function( command, argument ) {
  115. var element = this[ 0 ],
  116. settings, staticRules, existingRules, data, param, filtered;
  117. if ( command ) {
  118. settings = $.data( element.form, "validator" ).settings;
  119. staticRules = settings.rules;
  120. existingRules = $.validator.staticRules( element );
  121. switch ( command ) {
  122. case "add":
  123. $.extend( existingRules, $.validator.normalizeRule( argument ) );
  124. // remove messages from rules, but allow them to be set separately
  125. delete existingRules.messages;
  126. staticRules[ element.name ] = existingRules;
  127. if ( argument.messages ) {
  128. settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );
  129. }
  130. break;
  131. case "remove":
  132. if ( !argument ) {
  133. delete staticRules[ element.name ];
  134. return existingRules;
  135. }
  136. filtered = {};
  137. $.each( argument.split( /\s/ ), function( index, method ) {
  138. filtered[ method ] = existingRules[ method ];
  139. delete existingRules[ method ];
  140. if ( method === "required" ) {
  141. $( element ).removeAttr( "aria-required" );
  142. }
  143. });
  144. return filtered;
  145. }
  146. }
  147. data = $.validator.normalizeRules(
  148. $.extend(
  149. {},
  150. $.validator.classRules( element ),
  151. $.validator.attributeRules( element ),
  152. $.validator.dataRules( element ),
  153. $.validator.staticRules( element )
  154. ), element );
  155. // make sure required is at front
  156. if ( data.required ) {
  157. param = data.required;
  158. delete data.required;
  159. data = $.extend( { required: param }, data );
  160. $( element ).attr( "aria-required", "true" );
  161. }
  162. // make sure remote is at back
  163. if ( data.remote ) {
  164. param = data.remote;
  165. delete data.remote;
  166. data = $.extend( data, { remote: param });
  167. }
  168. return data;
  169. }
  170. });
  171. // Custom selectors
  172. $.extend( $.expr[ ":" ], {
  173. // http://jqueryvalidation.org/blank-selector/
  174. blank: function( a ) {
  175. return !$.trim( "" + $( a ).val() );
  176. },
  177. // http://jqueryvalidation.org/filled-selector/
  178. filled: function( a ) {
  179. return !!$.trim( "" + $( a ).val() );
  180. },
  181. // http://jqueryvalidation.org/unchecked-selector/
  182. unchecked: function( a ) {
  183. return !$( a ).prop( "checked" );
  184. }
  185. });
  186. // constructor for validator
  187. $.validator = function( options, form ) {
  188. this.settings = $.extend( true, {}, $.validator.defaults, options );
  189. this.currentForm = form;
  190. this.init();
  191. };
  192. // http://jqueryvalidation.org/jQuery.validator.format/
  193. $.validator.format = function( source, params ) {
  194. if ( arguments.length === 1 ) {
  195. return function() {
  196. var args = $.makeArray( arguments );
  197. args.unshift( source );
  198. return $.validator.format.apply( this, args );
  199. };
  200. }
  201. if ( arguments.length > 2 && params.constructor !== Array ) {
  202. params = $.makeArray( arguments ).slice( 1 );
  203. }
  204. if ( params.constructor !== Array ) {
  205. params = [ params ];
  206. }
  207. $.each( params, function( i, n ) {
  208. source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() {
  209. return n;
  210. });
  211. });
  212. return source;
  213. };
  214. $.extend( $.validator, {
  215. defaults: {
  216. messages: {},
  217. groups: {},
  218. rules: {},
  219. errorClass: "error",
  220. validClass: "valid",
  221. errorElement: "label",
  222. focusCleanup: false,
  223. focusInvalid: true,
  224. errorContainer: $( [] ),
  225. errorLabelContainer: $( [] ),
  226. onsubmit: true,
  227. ignore: ":hidden",
  228. ignoreTitle: false,
  229. onfocusin: function( element ) {
  230. this.lastActive = element;
  231. // Hide error label and remove error class on focus if enabled
  232. if ( this.settings.focusCleanup ) {
  233. if ( this.settings.unhighlight ) {
  234. this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
  235. }
  236. this.hideThese( this.errorsFor( element ) );
  237. }
  238. },
  239. onfocusout: function( element ) {
  240. if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
  241. this.element( element );
  242. }
  243. },
  244. onkeyup: function( element, event ) {
  245. // Avoid revalidate the field when pressing one of the following keys
  246. // Shift => 16
  247. // Ctrl => 17
  248. // Alt => 18
  249. // Caps lock => 20
  250. // End => 35
  251. // Home => 36
  252. // Left arrow => 37
  253. // Up arrow => 38
  254. // Right arrow => 39
  255. // Down arrow => 40
  256. // Insert => 45
  257. // Num lock => 144
  258. // AltGr key => 225
  259. var excludedKeys = [
  260. 16, 17, 18, 20, 35, 36, 37,
  261. 38, 39, 40, 45, 144, 225
  262. ];
  263. if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) {
  264. return;
  265. } else if ( element.name in this.submitted || element === this.lastElement ) {
  266. this.element( element );
  267. }
  268. },
  269. onclick: function( element ) {
  270. // click on selects, radiobuttons and checkboxes
  271. if ( element.name in this.submitted ) {
  272. this.element( element );
  273. // or option elements, check parent select in that case
  274. } else if ( element.parentNode.name in this.submitted ) {
  275. this.element( element.parentNode );
  276. }
  277. },
  278. highlight: function( element, errorClass, validClass ) {
  279. if ( element.type === "radio" ) {
  280. this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
  281. } else {
  282. $( element ).addClass( errorClass ).removeClass( validClass );
  283. }
  284. },
  285. unhighlight: function( element, errorClass, validClass ) {
  286. if ( element.type === "radio" ) {
  287. this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
  288. } else {
  289. $( element ).removeClass( errorClass ).addClass( validClass );
  290. }
  291. }
  292. },
  293. // http://jqueryvalidation.org/jQuery.validator.setDefaults/
  294. setDefaults: function( settings ) {
  295. $.extend( $.validator.defaults, settings );
  296. },
  297. messages: {
  298. required: "This field is required.",
  299. remote: "Please fix this field.",
  300. email: "Please enter a valid email address.",
  301. url: "Please enter a valid URL.",
  302. date: "Please enter a valid date.",
  303. dateISO: "Please enter a valid date ( ISO ).",
  304. number: "Please enter a valid number.",
  305. digits: "Please enter only digits.",
  306. creditcard: "Please enter a valid credit card number.",
  307. equalTo: "Please enter the same value again.",
  308. maxlength: $.validator.format( "Please enter no more than {0} characters." ),
  309. minlength: $.validator.format( "Please enter at least {0} characters." ),
  310. rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ),
  311. range: $.validator.format( "Please enter a value between {0} and {1}." ),
  312. max: $.validator.format( "Please enter a value less than or equal to {0}." ),
  313. min: $.validator.format( "Please enter a value greater than or equal to {0}." )
  314. },
  315. autoCreateRanges: false,
  316. prototype: {
  317. init: function() {
  318. this.labelContainer = $( this.settings.errorLabelContainer );
  319. this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );
  320. this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );
  321. this.submitted = {};
  322. this.valueCache = {};
  323. this.pendingRequest = 0;
  324. this.pending = {};
  325. this.invalid = {};
  326. this.reset();
  327. var groups = ( this.groups = {} ),
  328. rules;
  329. $.each( this.settings.groups, function( key, value ) {
  330. if ( typeof value === "string" ) {
  331. value = value.split( /\s/ );
  332. }
  333. $.each( value, function( index, name ) {
  334. groups[ name ] = key;
  335. });
  336. });
  337. rules = this.settings.rules;
  338. $.each( rules, function( key, value ) {
  339. rules[ key ] = $.validator.normalizeRule( value );
  340. });
  341. function delegate( event ) {
  342. var validator = $.data( this.form, "validator" );
  343. if ( !validator ) {
  344. validator = new $.validator( {}, this.form );
  345. $.data( this.form, "validator", validator );
  346. }
  347. var eventType = "on" + event.type.replace( /^validate/, "" ),
  348. settings = validator.settings;
  349. if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) {
  350. settings[ eventType ].call( validator, this, event );
  351. }
  352. }
  353. $( this.currentForm )
  354. .on( "focusin.validate focusout.validate keyup.validate",
  355. ":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " +
  356. "[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " +
  357. "[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " +
  358. "[type='radio'], [type='checkbox']", delegate)
  359. // Support: Chrome, oldIE
  360. // "select" is provided as event.target when clicking a option
  361. .on("click.validate", "select, option, [type='radio'], [type='checkbox']", delegate);
  362. if ( this.settings.invalidHandler ) {
  363. $( this.currentForm ).on( "invalid-form.validate", this.settings.invalidHandler );
  364. }
  365. // Add aria-required to any Static/Data/Class required fields before first validation
  366. // Screen readers require this attribute to be present before the initial submission http://www.w3.org/TR/WCAG-TECHS/ARIA2.html
  367. $( this.currentForm ).find( "[required], [data-rule-required], .required" ).attr( "aria-required", "true" );
  368. },
  369. // http://jqueryvalidation.org/Validator.form/
  370. form: function() {
  371. this.checkForm();
  372. $.extend( this.submitted, this.errorMap );
  373. this.invalid = $.extend({}, this.errorMap );
  374. if ( !this.valid() ) {
  375. $( this.currentForm ).triggerHandler( "invalid-form", [ this ]);
  376. }
  377. this.showErrors();
  378. return this.valid();
  379. },
  380. checkForm: function() {
  381. this.prepareForm();
  382. for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {
  383. this.check( elements[ i ] );
  384. }
  385. return this.valid();
  386. },
  387. // http://jqueryvalidation.org/Validator.element/
  388. element: function( element ) {
  389. var cleanElement = this.clean( element ),
  390. checkElement = this.validationTargetFor( cleanElement ),
  391. result = true;
  392. this.lastElement = checkElement;
  393. if ( checkElement === undefined ) {
  394. delete this.invalid[ cleanElement.name ];
  395. } else {
  396. this.prepareElement( checkElement );
  397. this.currentElements = $( checkElement );
  398. result = this.check( checkElement ) !== false;
  399. if ( result ) {
  400. delete this.invalid[ checkElement.name ];
  401. } else {
  402. this.invalid[ checkElement.name ] = true;
  403. }
  404. }
  405. // Add aria-invalid status for screen readers
  406. $( element ).attr( "aria-invalid", !result );
  407. if ( !this.numberOfInvalids() ) {
  408. // Hide error containers on last error
  409. this.toHide = this.toHide.add( this.containers );
  410. }
  411. this.showErrors();
  412. return result;
  413. },
  414. // http://jqueryvalidation.org/Validator.showErrors/
  415. showErrors: function( errors ) {
  416. if ( errors ) {
  417. // add items to error list and map
  418. $.extend( this.errorMap, errors );
  419. this.errorList = [];
  420. for ( var name in errors ) {
  421. this.errorList.push({
  422. message: errors[ name ],
  423. element: this.findByName( name )[ 0 ]
  424. });
  425. }
  426. // remove items from success list
  427. this.successList = $.grep( this.successList, function( element ) {
  428. return !( element.name in errors );
  429. });
  430. }
  431. if ( this.settings.showErrors ) {
  432. this.settings.showErrors.call( this, this.errorMap, this.errorList );
  433. } else {
  434. this.defaultShowErrors();
  435. }
  436. },
  437. // http://jqueryvalidation.org/Validator.resetForm/
  438. resetForm: function() {
  439. if ( $.fn.resetForm ) {
  440. $( this.currentForm ).resetForm();
  441. }
  442. this.submitted = {};
  443. this.lastElement = null;
  444. this.prepareForm();
  445. this.hideErrors();
  446. var i, elements = this.elements()
  447. .removeData( "previousValue" )
  448. .removeAttr( "aria-invalid" );
  449. if ( this.settings.unhighlight ) {
  450. for ( i = 0; elements[ i ]; i++ ) {
  451. this.settings.unhighlight.call( this, elements[ i ],
  452. this.settings.errorClass, "" );
  453. }
  454. } else {
  455. elements.removeClass( this.settings.errorClass );
  456. }
  457. },
  458. numberOfInvalids: function() {
  459. return this.objectLength( this.invalid );
  460. },
  461. objectLength: function( obj ) {
  462. /* jshint unused: false */
  463. var count = 0,
  464. i;
  465. for ( i in obj ) {
  466. count++;
  467. }
  468. return count;
  469. },
  470. hideErrors: function() {
  471. this.hideThese( this.toHide );
  472. },
  473. hideThese: function( errors ) {
  474. errors.not( this.containers ).text( "" );
  475. this.addWrapper( errors ).hide();
  476. },
  477. valid: function() {
  478. return this.size() === 0;
  479. },
  480. size: function() {
  481. return this.errorList.length;
  482. },
  483. focusInvalid: function() {
  484. if ( this.settings.focusInvalid ) {
  485. try {
  486. $( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [])
  487. .filter( ":visible" )
  488. .focus()
  489. // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
  490. .trigger( "focusin" );
  491. } catch ( e ) {
  492. // ignore IE throwing errors when focusing hidden elements
  493. }
  494. }
  495. },
  496. findLastActive: function() {
  497. var lastActive = this.lastActive;
  498. return lastActive && $.grep( this.errorList, function( n ) {
  499. return n.element.name === lastActive.name;
  500. }).length === 1 && lastActive;
  501. },
  502. elements: function() {
  503. var validator = this,
  504. rulesCache = {};
  505. // select all valid inputs inside the form (no submit or reset buttons)
  506. return $( this.currentForm )
  507. .find( "input, select, textarea" )
  508. .not( ":submit, :reset, :image, :disabled" )
  509. .not( this.settings.ignore )
  510. .filter( function() {
  511. if ( !this.name && validator.settings.debug && window.console ) {
  512. console.error( "%o has no name assigned", this );
  513. }
  514. // select only the first element for each name, and only those with rules specified
  515. if ( this.name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
  516. return false;
  517. }
  518. rulesCache[ this.name ] = true;
  519. return true;
  520. });
  521. },
  522. clean: function( selector ) {
  523. return $( selector )[ 0 ];
  524. },
  525. errors: function() {
  526. var errorClass = this.settings.errorClass.split( " " ).join( "." );
  527. return $( this.settings.errorElement + "." + errorClass, this.errorContext );
  528. },
  529. reset: function() {
  530. this.successList = [];
  531. this.errorList = [];
  532. this.errorMap = {};
  533. this.toShow = $( [] );
  534. this.toHide = $( [] );
  535. this.currentElements = $( [] );
  536. },
  537. prepareForm: function() {
  538. this.reset();
  539. this.toHide = this.errors().add( this.containers );
  540. },
  541. prepareElement: function( element ) {
  542. this.reset();
  543. this.toHide = this.errorsFor( element );
  544. },
  545. elementValue: function( element ) {
  546. var val,
  547. $element = $( element ),
  548. type = element.type;
  549. if ( type === "radio" || type === "checkbox" ) {
  550. return this.findByName( element.name ).filter(":checked").val();
  551. } else if ( type === "number" && typeof element.validity !== "undefined" ) {
  552. return element.validity.badInput ? false : $element.val();
  553. }
  554. val = $element.val();
  555. if ( typeof val === "string" ) {
  556. return val.replace(/\r/g, "" );
  557. }
  558. return val;
  559. },
  560. check: function( element ) {
  561. element = this.validationTargetFor( this.clean( element ) );
  562. var rules = $( element ).rules(),
  563. rulesCount = $.map( rules, function( n, i ) {
  564. return i;
  565. }).length,
  566. dependencyMismatch = false,
  567. val = this.elementValue( element ),
  568. result, method, rule;
  569. for ( method in rules ) {
  570. rule = { method: method, parameters: rules[ method ] };
  571. try {
  572. result = $.validator.methods[ method ].call( this, val, element, rule.parameters );
  573. // if a method indicates that the field is optional and therefore valid,
  574. // don't mark it as valid when there are no other rules
  575. if ( result === "dependency-mismatch" && rulesCount === 1 ) {
  576. dependencyMismatch = true;
  577. continue;
  578. }
  579. dependencyMismatch = false;
  580. if ( result === "pending" ) {
  581. this.toHide = this.toHide.not( this.errorsFor( element ) );
  582. return;
  583. }
  584. if ( !result ) {
  585. this.formatAndAdd( element, rule );
  586. return false;
  587. }
  588. } catch ( e ) {
  589. if ( this.settings.debug && window.console ) {
  590. console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e );
  591. }
  592. if ( e instanceof TypeError ) {
  593. e.message += ". Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.";
  594. }
  595. throw e;
  596. }
  597. }
  598. if ( dependencyMismatch ) {
  599. return;
  600. }
  601. if ( this.objectLength( rules ) ) {
  602. this.successList.push( element );
  603. }
  604. return true;
  605. },
  606. // return the custom message for the given element and validation method
  607. // specified in the element's HTML5 data attribute
  608. // return the generic message if present and no method specific message is present
  609. customDataMessage: function( element, method ) {
  610. return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() +
  611. method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" );
  612. },
  613. // return the custom message for the given element name and validation method
  614. customMessage: function( name, method ) {
  615. var m = this.settings.messages[ name ];
  616. return m && ( m.constructor === String ? m : m[ method ]);
  617. },
  618. // return the first defined argument, allowing empty strings
  619. findDefined: function() {
  620. for ( var i = 0; i < arguments.length; i++) {
  621. if ( arguments[ i ] !== undefined ) {
  622. return arguments[ i ];
  623. }
  624. }
  625. return undefined;
  626. },
  627. defaultMessage: function( element, method ) {
  628. return this.findDefined(
  629. this.customMessage( element.name, method ),
  630. this.customDataMessage( element, method ),
  631. // title is never undefined, so handle empty string as undefined
  632. !this.settings.ignoreTitle && element.title || undefined,
  633. $.validator.messages[ method ],
  634. "<strong>Warning: No message defined for " + element.name + "</strong>"
  635. );
  636. },
  637. formatAndAdd: function( element, rule ) {
  638. var message = this.defaultMessage( element, rule.method ),
  639. theregex = /\$?\{(\d+)\}/g;
  640. if ( typeof message === "function" ) {
  641. message = message.call( this, rule.parameters, element );
  642. } else if ( theregex.test( message ) ) {
  643. message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters );
  644. }
  645. this.errorList.push({
  646. message: message,
  647. element: element,
  648. method: rule.method
  649. });
  650. this.errorMap[ element.name ] = message;
  651. this.submitted[ element.name ] = message;
  652. },
  653. addWrapper: function( toToggle ) {
  654. if ( this.settings.wrapper ) {
  655. toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
  656. }
  657. return toToggle;
  658. },
  659. defaultShowErrors: function() {
  660. var i, elements, error;
  661. for ( i = 0; this.errorList[ i ]; i++ ) {
  662. error = this.errorList[ i ];
  663. if ( this.settings.highlight ) {
  664. this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
  665. }
  666. this.showLabel( error.element, error.message );
  667. }
  668. if ( this.errorList.length ) {
  669. this.toShow = this.toShow.add( this.containers );
  670. }
  671. if ( this.settings.success ) {
  672. for ( i = 0; this.successList[ i ]; i++ ) {
  673. this.showLabel( this.successList[ i ] );
  674. }
  675. }
  676. if ( this.settings.unhighlight ) {
  677. for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {
  678. this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass );
  679. }
  680. }
  681. this.toHide = this.toHide.not( this.toShow );
  682. this.hideErrors();
  683. this.addWrapper( this.toShow ).show();
  684. },
  685. validElements: function() {
  686. return this.currentElements.not( this.invalidElements() );
  687. },
  688. invalidElements: function() {
  689. return $( this.errorList ).map(function() {
  690. return this.element;
  691. });
  692. },
  693. showLabel: function( element, message ) {
  694. var place, group, errorID,
  695. error = this.errorsFor( element ),
  696. elementID = this.idOrName( element ),
  697. describedBy = $( element ).attr( "aria-describedby" );
  698. if ( error.length ) {
  699. // refresh error/success class
  700. error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
  701. // replace message on existing label
  702. error.html( message );
  703. } else {
  704. // create error element
  705. error = $( "<" + this.settings.errorElement + ">" )
  706. .attr( "id", elementID + "-error" )
  707. .addClass( this.settings.errorClass )
  708. .html( message || "" );
  709. // Maintain reference to the element to be placed into the DOM
  710. place = error;
  711. if ( this.settings.wrapper ) {
  712. // make sure the element is visible, even in IE
  713. // actually showing the wrapped element is handled elsewhere
  714. place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent();
  715. }
  716. if ( this.labelContainer.length ) {
  717. this.labelContainer.append( place );
  718. } else if ( this.settings.errorPlacement ) {
  719. this.settings.errorPlacement( place, $( element ) );
  720. } else {
  721. place.insertAfter( element );
  722. }
  723. // Link error back to the element
  724. if ( error.is( "label" ) ) {
  725. // If the error is a label, then associate using 'for'
  726. error.attr( "for", elementID );
  727. } else if ( error.parents( "label[for='" + elementID + "']" ).length === 0 ) {
  728. // If the element is not a child of an associated label, then it's necessary
  729. // to explicitly apply aria-describedby
  730. errorID = error.attr( "id" ).replace( /(:|\.|\[|\]|\$)/g, "\\$1");
  731. // Respect existing non-error aria-describedby
  732. if ( !describedBy ) {
  733. describedBy = errorID;
  734. } else if ( !describedBy.match( new RegExp( "\\b" + errorID + "\\b" ) ) ) {
  735. // Add to end of list if not already present
  736. describedBy += " " + errorID;
  737. }
  738. $( element ).attr( "aria-describedby", describedBy );
  739. // If this element is grouped, then assign to all elements in the same group
  740. group = this.groups[ element.name ];
  741. if ( group ) {
  742. $.each( this.groups, function( name, testgroup ) {
  743. if ( testgroup === group ) {
  744. $( "[name='" + name + "']", this.currentForm )
  745. .attr( "aria-describedby", error.attr( "id" ) );
  746. }
  747. });
  748. }
  749. }
  750. }
  751. if ( !message && this.settings.success ) {
  752. error.text( "" );
  753. if ( typeof this.settings.success === "string" ) {
  754. error.addClass( this.settings.success );
  755. } else {
  756. this.settings.success( error, element );
  757. }
  758. }
  759. this.toShow = this.toShow.add( error );
  760. },
  761. errorsFor: function( element ) {
  762. var name = this.idOrName( element ),
  763. describer = $( element ).attr( "aria-describedby" ),
  764. selector = "label[for='" + name + "'], label[for='" + name + "'] *";
  765. // aria-describedby should directly reference the error element
  766. if ( describer ) {
  767. selector = selector + ", #" + describer.replace( /\s+/g, ", #" );
  768. }
  769. return this
  770. .errors()
  771. .filter( selector );
  772. },
  773. idOrName: function( element ) {
  774. return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name );
  775. },
  776. validationTargetFor: function( element ) {
  777. // If radio/checkbox, validate first element in group instead
  778. if ( this.checkable( element ) ) {
  779. element = this.findByName( element.name );
  780. }
  781. // Always apply ignore filter
  782. return $( element ).not( this.settings.ignore )[ 0 ];
  783. },
  784. checkable: function( element ) {
  785. return ( /radio|checkbox/i ).test( element.type );
  786. },
  787. findByName: function( name ) {
  788. return $( this.currentForm ).find( "[name='" + name + "']" );
  789. },
  790. getLength: function( value, element ) {
  791. switch ( element.nodeName.toLowerCase() ) {
  792. case "select":
  793. return $( "option:selected", element ).length;
  794. case "input":
  795. if ( this.checkable( element ) ) {
  796. return this.findByName( element.name ).filter( ":checked" ).length;
  797. }
  798. }
  799. return value.length;
  800. },
  801. depend: function( param, element ) {
  802. return this.dependTypes[typeof param] ? this.dependTypes[typeof param]( param, element ) : true;
  803. },
  804. dependTypes: {
  805. "boolean": function( param ) {
  806. return param;
  807. },
  808. "string": function( param, element ) {
  809. return !!$( param, element.form ).length;
  810. },
  811. "function": function( param, element ) {
  812. return param( element );
  813. }
  814. },
  815. optional: function( element ) {
  816. var val = this.elementValue( element );
  817. return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch";
  818. },
  819. startRequest: function( element ) {
  820. if ( !this.pending[ element.name ] ) {
  821. this.pendingRequest++;
  822. this.pending[ element.name ] = true;
  823. }
  824. },
  825. stopRequest: function( element, valid ) {
  826. this.pendingRequest--;
  827. // sometimes synchronization fails, make sure pendingRequest is never < 0
  828. if ( this.pendingRequest < 0 ) {
  829. this.pendingRequest = 0;
  830. }
  831. delete this.pending[ element.name ];
  832. if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {
  833. $( this.currentForm ).submit();
  834. this.formSubmitted = false;
  835. } else if (!valid && this.pendingRequest === 0 && this.formSubmitted ) {
  836. $( this.currentForm ).triggerHandler( "invalid-form", [ this ]);
  837. this.formSubmitted = false;
  838. }
  839. },
  840. previousValue: function( element ) {
  841. return $.data( element, "previousValue" ) || $.data( element, "previousValue", {
  842. old: null,
  843. valid: true,
  844. message: this.defaultMessage( element, "remote" )
  845. });
  846. },
  847. // cleans up all forms and elements, removes validator-specific events
  848. destroy: function() {
  849. this.resetForm();
  850. $( this.currentForm )
  851. .off( ".validate" )
  852. .removeData( "validator" );
  853. }
  854. },
  855. classRuleSettings: {
  856. required: { required: true },
  857. email: { email: true },
  858. url: { url: true },
  859. date: { date: true },
  860. dateISO: { dateISO: true },
  861. number: { number: true },
  862. digits: { digits: true },
  863. creditcard: { creditcard: true }
  864. },
  865. addClassRules: function( className, rules ) {
  866. if ( className.constructor === String ) {
  867. this.classRuleSettings[ className ] = rules;
  868. } else {
  869. $.extend( this.classRuleSettings, className );
  870. }
  871. },
  872. classRules: function( element ) {
  873. var rules = {},
  874. classes = $( element ).attr( "class" );
  875. if ( classes ) {
  876. $.each( classes.split( " " ), function() {
  877. if ( this in $.validator.classRuleSettings ) {
  878. $.extend( rules, $.validator.classRuleSettings[ this ]);
  879. }
  880. });
  881. }
  882. return rules;
  883. },
  884. normalizeAttributeRule: function( rules, type, method, value ) {
  885. // convert the value to a number for number inputs, and for text for backwards compability
  886. // allows type="date" and others to be compared as strings
  887. if ( /min|max/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
  888. value = Number( value );
  889. // Support Opera Mini, which returns NaN for undefined minlength
  890. if ( isNaN( value ) ) {
  891. value = undefined;
  892. }
  893. }
  894. if ( value || value === 0 ) {
  895. rules[ method ] = value;
  896. } else if ( type === method && type !== "range" ) {
  897. // exception: the jquery validate 'range' method
  898. // does not test for the html5 'range' type
  899. rules[ method ] = true;
  900. }
  901. },
  902. attributeRules: function( element ) {
  903. var rules = {},
  904. $element = $( element ),
  905. type = element.getAttribute( "type" ),
  906. method, value;
  907. for ( method in $.validator.methods ) {
  908. // support for <input required> in both html5 and older browsers
  909. if ( method === "required" ) {
  910. value = element.getAttribute( method );
  911. // Some browsers return an empty string for the required attribute
  912. // and non-HTML5 browsers might have required="" markup
  913. if ( value === "" ) {
  914. value = true;
  915. }
  916. // force non-HTML5 browsers to return bool
  917. value = !!value;
  918. } else {
  919. value = $element.attr( method );
  920. }
  921. this.normalizeAttributeRule( rules, type, method, value );
  922. }
  923. // maxlength may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs
  924. if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {
  925. delete rules.maxlength;
  926. }
  927. return rules;
  928. },
  929. dataRules: function( element ) {
  930. var rules = {},
  931. $element = $( element ),
  932. type = element.getAttribute( "type" ),
  933. method, value;
  934. for ( method in $.validator.methods ) {
  935. value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );
  936. this.normalizeAttributeRule( rules, type, method, value );
  937. }
  938. return rules;
  939. },
  940. staticRules: function( element ) {
  941. var rules = {},
  942. validator = $.data( element.form, "validator" );
  943. if ( !validator ) {
  944. validator = new $.validator( {}, element.form );
  945. $.data( element.form, "validator", validator );
  946. }
  947. if ( validator.settings.rules ) {
  948. rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};
  949. }
  950. return rules;
  951. },
  952. normalizeRules: function( rules, element ) {
  953. // handle dependency check
  954. $.each( rules, function( prop, val ) {
  955. // ignore rule when param is explicitly false, eg. required:false
  956. if ( val === false ) {
  957. delete rules[ prop ];
  958. return;
  959. }
  960. if ( val.param || val.depends ) {
  961. var keepRule = true;
  962. switch ( typeof val.depends ) {
  963. case "string":
  964. keepRule = !!$( val.depends, element.form ).length;
  965. break;
  966. case "function":
  967. keepRule = val.depends.call( element, element );
  968. break;
  969. }
  970. if ( keepRule ) {
  971. rules[ prop ] = val.param !== undefined ? val.param : true;
  972. } else {
  973. delete rules[ prop ];
  974. }
  975. }
  976. });
  977. // evaluate parameters
  978. $.each( rules, function( rule, parameter ) {
  979. rules[ rule ] = $.isFunction( parameter ) ? parameter( element ) : parameter;
  980. });
  981. // clean number parameters
  982. $.each([ "minlength", "maxlength" ], function() {
  983. if ( rules[ this ] ) {
  984. rules[ this ] = Number( rules[ this ] );
  985. }
  986. });
  987. $.each([ "rangelength", "range" ], function() {
  988. var parts;
  989. if ( rules[ this ] ) {
  990. if ( $.isArray( rules[ this ] ) ) {
  991. rules[ this ] = [ Number( rules[ this ][ 0 ]), Number( rules[ this ][ 1 ] ) ];
  992. } else if ( typeof rules[ this ] === "string" ) {
  993. parts = rules[ this ].replace(/[\[\]]/g, "" ).split( /[\s,]+/ );
  994. rules[ this ] = [ Number( parts[ 0 ]), Number( parts[ 1 ] ) ];
  995. }
  996. }
  997. });
  998. if ( $.validator.autoCreateRanges ) {
  999. // auto-create ranges
  1000. if ( rules.min != null && rules.max != null ) {
  1001. rules.range = [ rules.min, rules.max ];
  1002. delete rules.min;
  1003. delete rules.max;
  1004. }
  1005. if ( rules.minlength != null && rules.maxlength != null ) {
  1006. rules.rangelength = [ rules.minlength, rules.maxlength ];
  1007. delete rules.minlength;
  1008. delete rules.maxlength;
  1009. }
  1010. }
  1011. return rules;
  1012. },
  1013. // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
  1014. normalizeRule: function( data ) {
  1015. if ( typeof data === "string" ) {
  1016. var transformed = {};
  1017. $.each( data.split( /\s/ ), function() {
  1018. transformed[ this ] = true;
  1019. });
  1020. data = transformed;
  1021. }
  1022. return data;
  1023. },
  1024. // http://jqueryvalidation.org/jQuery.validator.addMethod/
  1025. addMethod: function( name, method, message ) {
  1026. $.validator.methods[ name ] = method;
  1027. $.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];
  1028. if ( method.length < 3 ) {
  1029. $.validator.addClassRules( name, $.validator.normalizeRule( name ) );
  1030. }
  1031. },
  1032. methods: {
  1033. // http://jqueryvalidation.org/required-method/
  1034. required: function( value, element, param ) {
  1035. // check if dependency is met
  1036. if ( !this.depend( param, element ) ) {
  1037. return "dependency-mismatch";
  1038. }
  1039. if ( element.nodeName.toLowerCase() === "select" ) {
  1040. // could be an array for select-multiple or a string, both are fine this way
  1041. var val = $( element ).val();
  1042. return val && val.length > 0;
  1043. }
  1044. if ( this.checkable( element ) ) {
  1045. return this.getLength( value, element ) > 0;
  1046. }
  1047. return value.length > 0;
  1048. },
  1049. // http://jqueryvalidation.org/email-method/
  1050. email: function( value, element ) {
  1051. // From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address
  1052. // Retrieved 2014-01-14
  1053. // If you have a problem with this implementation, report a bug against the above spec
  1054. // Or use custom methods to implement your own email validation
  1055. return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );
  1056. },
  1057. // http://jqueryvalidation.org/url-method/
  1058. url: function( value, element ) {
  1059. // Copyright (c) 2010-2013 Diego Perini, MIT licensed
  1060. // https://gist.github.com/dperini/729294
  1061. // see also https://mathiasbynens.be/demo/url-regex
  1062. // modified to allow protocol-relative URLs
  1063. return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value );
  1064. },
  1065. // http://jqueryvalidation.org/date-method/
  1066. date: function( value, element ) {
  1067. return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );
  1068. },
  1069. // http://jqueryvalidation.org/dateISO-method/
  1070. dateISO: function( value, element ) {
  1071. return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );
  1072. },
  1073. // http://jqueryvalidation.org/number-method/
  1074. number: function( value, element ) {
  1075. return this.optional( element ) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value );
  1076. },
  1077. // http://jqueryvalidation.org/digits-method/
  1078. digits: function( value, element ) {
  1079. return this.optional( element ) || /^\d+$/.test( value );
  1080. },
  1081. // http://jqueryvalidation.org/creditcard-method/
  1082. // based on http://en.wikipedia.org/wiki/Luhn_algorithm
  1083. creditcard: function( value, element ) {
  1084. if ( this.optional( element ) ) {
  1085. return "dependency-mismatch";
  1086. }
  1087. // accept only spaces, digits and dashes
  1088. if ( /[^0-9 \-]+/.test( value ) ) {
  1089. return false;
  1090. }
  1091. var nCheck = 0,
  1092. nDigit = 0,
  1093. bEven = false,
  1094. n, cDigit;
  1095. value = value.replace( /\D/g, "" );
  1096. // Basing min and max length on
  1097. // http://developer.ean.com/general_info/Valid_Credit_Card_Types
  1098. if ( value.length < 13 || value.length > 19 ) {
  1099. return false;
  1100. }
  1101. for ( n = value.length - 1; n >= 0; n--) {
  1102. cDigit = value.charAt( n );
  1103. nDigit = parseInt( cDigit, 10 );
  1104. if ( bEven ) {
  1105. if ( ( nDigit *= 2 ) > 9 ) {
  1106. nDigit -= 9;
  1107. }
  1108. }
  1109. nCheck += nDigit;
  1110. bEven = !bEven;
  1111. }
  1112. return ( nCheck % 10 ) === 0;
  1113. },
  1114. // http://jqueryvalidation.org/minlength-method/
  1115. minlength: function( value, element, param ) {
  1116. var length = $.isArray( value ) ? value.length : this.getLength( value, element );
  1117. return this.optional( element ) || length >= param;
  1118. },
  1119. // http://jqueryvalidation.org/maxlength-method/
  1120. maxlength: function( value, element, param ) {
  1121. var length = $.isArray( value ) ? value.length : this.getLength( value, element );
  1122. return this.optional( element ) || length <= param;
  1123. },
  1124. // http://jqueryvalidation.org/rangelength-method/
  1125. rangelength: function( value, element, param ) {
  1126. var length = $.isArray( value ) ? value.length : this.getLength( value, element );
  1127. return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );
  1128. },
  1129. // http://jqueryvalidation.org/min-method/
  1130. min: function( value, element, param ) {
  1131. return this.optional( element ) || value >= param;
  1132. },
  1133. // http://jqueryvalidation.org/max-method/
  1134. max: function( value, element, param ) {
  1135. return this.optional( element ) || value <= param;
  1136. },
  1137. // http://jqueryvalidation.org/range-method/
  1138. range: function( value, element, param ) {
  1139. return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
  1140. },
  1141. // http://jqueryvalidation.org/equalTo-method/
  1142. equalTo: function( value, element, param ) {
  1143. // bind to the blur event of the target in order to revalidate whenever the target field is updated
  1144. // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
  1145. var target = $( param );
  1146. if ( this.settings.onfocusout ) {
  1147. target.off( ".validate-equalTo" ).on( "blur.validate-equalTo", function() {
  1148. $( element ).valid();
  1149. });
  1150. }
  1151. return value === target.val();
  1152. },
  1153. // http://jqueryvalidation.org/remote-method/
  1154. remote: function( value, element, param ) {
  1155. if ( this.optional( element ) ) {
  1156. return "dependency-mismatch";
  1157. }
  1158. var previous = this.previousValue( element ),
  1159. validator, data;
  1160. if (!this.settings.messages[ element.name ] ) {
  1161. this.settings.messages[ element.name ] = {};
  1162. }
  1163. previous.originalMessage = this.settings.messages[ element.name ].remote;
  1164. this.settings.messages[ element.name ].remote = previous.message;
  1165. param = typeof param === "string" && { url: param } || param;
  1166. if ( previous.old === value ) {
  1167. return previous.valid;
  1168. }
  1169. previous.old = value;
  1170. validator = this;
  1171. this.startRequest( element );
  1172. data = {};
  1173. data[ element.name ] = value;
  1174. $.ajax( $.extend( true, {
  1175. mode: "abort",
  1176. port: "validate" + element.name,
  1177. dataType: "json",
  1178. data: data,
  1179. context: validator.currentForm,
  1180. success: function( response ) {
  1181. var valid = response === true || response === "true",
  1182. errors, message, submitted;
  1183. validator.settings.messages[ element.name ].remote = previous.originalMessage;
  1184. if ( valid ) {
  1185. submitted = validator.formSubmitted;
  1186. validator.prepareElement( element );
  1187. validator.formSubmitted = submitted;
  1188. validator.successList.push( element );
  1189. delete validator.invalid[ element.name ];
  1190. validator.showErrors();
  1191. } else {
  1192. errors = {};
  1193. message = response || validator.defaultMessage( element, "remote" );
  1194. errors[ element.name ] = previous.message = $.isFunction( message ) ? message( value ) : message;
  1195. validator.invalid[ element.name ] = true;
  1196. validator.showErrors( errors );
  1197. }
  1198. previous.valid = valid;
  1199. validator.stopRequest( element, valid );
  1200. }
  1201. }, param ) );
  1202. return "pending";
  1203. }
  1204. }
  1205. });
  1206. // ajax mode: abort
  1207. // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
  1208. // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
  1209. var pendingRequests = {},
  1210. ajax;
  1211. // Use a prefilter if available (1.5+)
  1212. if ( $.ajaxPrefilter ) {
  1213. $.ajaxPrefilter(function( settings, _, xhr ) {
  1214. var port = settings.port;
  1215. if ( settings.mode === "abort" ) {
  1216. if ( pendingRequests[port] ) {
  1217. pendingRequests[port].abort();
  1218. }
  1219. pendingRequests[port] = xhr;
  1220. }
  1221. });
  1222. } else {
  1223. // Proxy ajax
  1224. ajax = $.ajax;
  1225. $.ajax = function( settings ) {
  1226. var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
  1227. port = ( "port" in settings ? settings : $.ajaxSettings ).port;
  1228. if ( mode === "abort" ) {
  1229. if ( pendingRequests[port] ) {
  1230. pendingRequests[port].abort();
  1231. }
  1232. pendingRequests[port] = ajax.apply(this, arguments);
  1233. return pendingRequests[port];
  1234. }
  1235. return ajax.apply(this, arguments);
  1236. };
  1237. }
  1238. }));

自定义规则

  1. /*!
  2. * jQuery Validation Plugin v1.14.0
  3. *
  4. * http://jqueryvalidation.org/
  5. *
  6. * Copyright (c) 2015 Jörn Zaefferer
  7. * Released under the MIT license
  8. * by zzh add
  9. * shenfenzheng
  10. */
  11. // 字符验证
  12. jQuery.validator.addMethod("checkUseTags", function() {
  13. return $("#use_tags").val()!="" || $("#other_tags").val()!="";
  14. }, "请选择或填写赎回用途!");
  15. jQuery.validator.addMethod("stringCheck", function(value, element) {
  16. return this.optional(element) || /^[\u0391-\uFFE5\w]+$/.test(value);
  17. }, "只能包括中文字、英文字母、数字和下划线");
  18. // 中文字两个字节
  19. jQuery.validator.addMethod("byteRangeLength", function(value, element, param) {
  20. var length = value.length;
  21. for(var i = 0; i < value.length; i++){
  22. if(value.charCodeAt(i) > 127){
  23. length++;
  24. }
  25. }
  26. return this.optional(element) || ( length >= param[0] && length <= param[1] );
  27. }, "请确保输入的值在3-15个字节之间(一个中文字算2个字节)");
  28. // 身份证号码验证
  29. jQuery.validator.addMethod("isIdCardNo", function(value, element) {
  30. return this.optional(element) || idCardNoUtil.checkIdCardNo(value);
  31. }, "请正确输入您的身份证号码");
  32. //护照编号验证
  33. jQuery.validator.addMethod("passport", function(value, element) {
  34. return this.optional(element) || checknumber(value);
  35. }, "请正确输入您的护照编号");
  36. // 手机号码验证
  37. jQuery.validator.addMethod("isMobile", function(value, element) {
  38. var length = value.length;
  39. var mobile = /^(13[0-9]|14[0-9]|15[0-9]|18[0-9]|17[0-9])\d{8}$/;
  40. return this.optional(element) || (length == 11 && mobile.test(value));
  41. }, "请正确填写您的手机号码");
  42. // 电话号码验证
  43. jQuery.validator.addMethod("isTel", function(value, element) {
  44. var tel = /^\d{3,4}-?\d{7,9}$/; //电话号码格式010-12345678
  45. return this.optional(element) || (tel.test(value));
  46. }, "请正确填写您的电话号码");
  47. // 联系电话(手机/电话皆可)验证
  48. jQuery.validator.addMethod("isPhone", function(value,element) {
  49. var length = value.length;
  50. var mobile = /^(((13[0-9]{1})|(15[0-9]{1}))+\d{8})$/;
  51. var tel = /^\d{3,4}-?\d{7,9}$/;
  52. return this.optional(element) || (tel.test(value) || mobile.test(value));
  53. }, "请正确填写您的联系电话");
  54. // 邮政编码验证
  55. jQuery.validator.addMethod("isZipCode", function(value, element) {
  56. var tel = /^[0-9]{6}$/;
  57. return this.optional(element) || (tel.test(value));
  58. }, "请正确填写您的邮政编码");
  59. // 验证值小数位数不能超过两位
  60. jQuery.validator.addMethod("decimal", function(value, element) {
  61. var decimal = /^-?\d+(\.\d{1,2})?$/;
  62. return this.optional(element) || (decimal.test(value));
  63. }, "小数位数不能超过两位!");
  64. // 验证值必须大于特定值(不能等于)
  65. jQuery.validator.addMethod("gt", function(value, element, param) {
  66. return value > param;
  67. },"输入值必须大于{0}!");
  68. // 验证日期大于等于特定值
  69. jQuery.validator.addMethod("gtDate", function(value, element, param) {
  70. return Date.parse(value) >= Date.parse(param);
  71. },"输入值必须大于{0}!");
  72. // 验证两次输入值是否不相同
  73. jQuery.validator.addMethod("notEqualTo", function(value, element, param) {
  74. return value != $(param).val();
  75. }, "两次输入不能相同!");
  76. // 验证值不允许与特定值等于
  77. jQuery.validator.addMethod("notEqual", function(value, element, param) {
  78. return value != param;
  79. },"输入值不允许为{0}!");
  80. var idCardNoUtil = {
  81. provinceAndCitys: {11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江",
  82. 31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南",42:"湖北",43:"湖南",44:"广东",
  83. 45:"广西",46:"海南",50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏",61:"陕西",62:"甘肃",63:"青海",64:"宁夏",
  84. 65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外"},
  85. powers: ["7","9","10","5","8","4","2","1","6","3","7","9","10","5","8","4","2"],
  86. parityBit: ["1","0","X","9","8","7","6","5","4","3","2"],
  87. genders: {male:"男",female:"女"},
  88. checkAddressCode: function(addressCode){
  89. var check = /^[1-9]\d{5}$/.test(addressCode);
  90. if(!check) return false;
  91. if(idCardNoUtil.provinceAndCitys[parseInt(addressCode.substring(0,2))]){
  92. return true;
  93. }else{
  94. return false;
  95. }
  96. },
  97. checkBirthDayCode: function(birDayCode){
  98. var check = /^[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))$/.test(birDayCode);
  99. if(!check) return false;
  100. var yyyy = parseInt(birDayCode.substring(0,4),10);
  101. var mm = parseInt(birDayCode.substring(4,6),10);
  102. var dd = parseInt(birDayCode.substring(6),10);
  103. var xdata = new Date(yyyy,mm-1,dd);
  104. if(xdata > new Date()){
  105. return false;//生日不能大于当前日期
  106. }else if ( ( xdata.getFullYear() == yyyy ) && ( xdata.getMonth () == mm - 1 ) && ( xdata.getDate() == dd ) ){
  107. return true;
  108. }else{
  109. return false;
  110. }
  111. },
  112. getParityBit: function(idCardNo){
  113. var id17 = idCardNo.substring(0,17);
  114. var power = 0;
  115. for(var i=0;i<17;i++){
  116. power += parseInt(id17.charAt(i),10) * parseInt(idCardNoUtil.powers[i]);
  117. }
  118. var mod = power % 11;
  119. return idCardNoUtil.parityBit[mod];
  120. },
  121. checkParityBit: function(idCardNo){
  122. var parityBit = idCardNo.charAt(17).toUpperCase();
  123. if(idCardNoUtil.getParityBit(idCardNo) == parityBit){
  124. return true;
  125. }else{
  126. return false;
  127. }
  128. },
  129. checkIdCardNo: function(idCardNo){
  130. //15位和18位身份证号码的基本校验
  131. var check = /^\d{15}|(\d{17}(\d|x|X))$/.test(idCardNo);
  132. if(!check) return false;
  133. //判断长度为15位或18位
  134. if(idCardNo.length==15){
  135. return idCardNoUtil.check15IdCardNo(idCardNo);
  136. }else if(idCardNo.length==18){
  137. return idCardNoUtil.check18IdCardNo(idCardNo);
  138. }else{
  139. return false;
  140. }
  141. },
  142. //校验15位的身份证号码
  143. check15IdCardNo: function(idCardNo){
  144. //15位身份证号码的基本校验
  145. var check = /^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(idCardNo);
  146. if(!check) return false;
  147. //校验地址码
  148. var addressCode = idCardNo.substring(0,6);
  149. check = idCardNoUtil.checkAddressCode(addressCode);
  150. if(!check) return false;
  151. var birDayCode = '19' + idCardNo.substring(6,12);
  152. //校验日期码
  153. return idCardNoUtil.checkBirthDayCode(birDayCode);
  154. },
  155. //校验18位的身份证号码
  156. check18IdCardNo: function(idCardNo){
  157. //18位身份证号码的基本格式校验
  158. var check = /^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(idCardNo);
  159. if(!check) return false;
  160. //校验地址码
  161. var addressCode = idCardNo.substring(0,6);
  162. check = idCardNoUtil.checkAddressCode(addressCode);
  163. if(!check) return false;
  164. //校验日期码
  165. var birDayCode = idCardNo.substring(6,14);
  166. check = idCardNoUtil.checkBirthDayCode(birDayCode);
  167. if(!check) return false;
  168. //验证校检码
  169. return idCardNoUtil.checkParityBit(idCardNo);
  170. },
  171. formateDateCN: function(day){
  172. var yyyy =day.substring(0,4);
  173. var mm = day.substring(4,6);
  174. var dd = day.substring(6);
  175. return yyyy + '-' + mm +'-' + dd;
  176. },
  177. //获取信息
  178. getIdCardInfo: function(idCardNo){
  179. var idCardInfo = {
  180. gender:"", //性别
  181. birthday:"" // 出生日期(yyyy-mm-dd)
  182. };
  183. if(idCardNo.length==15){
  184. var aday = '19' + idCardNo.substring(6,12);
  185. idCardInfo.birthday=idCardNoUtil.formateDateCN(aday);
  186. if(parseInt(idCardNo.charAt(14))%2==0){
  187. idCardInfo.gender=idCardNoUtil.genders.female;
  188. }else{
  189. idCardInfo.gender=idCardNoUtil.genders.male;
  190. }
  191. }else if(idCardNo.length==18){
  192. var aday = idCardNo.substring(6,14);
  193. idCardInfo.birthday=idCardNoUtil.formateDateCN(aday);
  194. if(parseInt(idCardNo.charAt(16))%2==0){
  195. idCardInfo.gender=idCardNoUtil.genders.female;
  196. }else{
  197. idCardInfo.gender=idCardNoUtil.genders.male;
  198. }
  199. }
  200. return idCardInfo;
  201. },
  202. getId15:function(idCardNo){
  203. if(idCardNo.length==15){
  204. return idCardNo;
  205. }else if(idCardNo.length==18){
  206. return idCardNo.substring(0,6) + idCardNo.substring(8,17);
  207. }else{
  208. return null;
  209. }
  210. },
  211. getId18: function(idCardNo){
  212. if(idCardNo.length==15){
  213. var id17 = idCardNo.substring(0,6) + '19' + idCardNo.substring(6);
  214. var parityBit = idCardNoUtil.getParityBit(id17);
  215. return id17 + parityBit;
  216. }else if(idCardNo.length==18){
  217. return idCardNo;
  218. }else{
  219. return null;
  220. }
  221. }
  222. };
  223. //验证护照是否正确
  224. function checknumber(number){
  225. var str=number;
  226. //在JavaScript中,正则表达式只能使用"/"开头和结束,不能使用双引号
  227. var Expression=/(P\d{7})|(G\d{8})/;
  228. var objExp=new RegExp(Expression);
  229. if(objExp.test(str)==true){
  230. return true;
  231. }else{
  232. return false;
  233. }
  234. };

发表评论

表情:
评论列表 (有 0 条评论,716人围观)

还没有评论,来说两句吧...

相关阅读