jquery.validate.js 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539
  1. /*
  2. * jQuery validation plug-in 1.5.2
  3. */
  4. (function($)
  5. {
  6. jQuery.browser={};(function(){jQuery.browser.msie=false; jQuery.browser.version=0;if(navigator.userAgent.match(/MSIE ([0-9]+)./)){ jQuery.browser.msie=true;jQuery.browser.version=RegExp.$1;}})();
  7. $.extend($.fn, {
  8. // http://docs.jquery.com/Plugins/Validation/validate
  9. validate: function(options)
  10. {
  11. // if nothing is selected, return nothing; can't chain anyway
  12. if (!this.length)
  13. {
  14. options && options.debug && window.console && console.warn("nothing selected, can't validate, returning nothing");
  15. return;
  16. }
  17. // check if a validator for this form was already created
  18. var validator = $.data(this[0], 'validator');
  19. if (validator)
  20. {
  21. return validator;
  22. }
  23. validator = new $.validator(options, this[0]);
  24. $.data(this[0], 'validator', validator);
  25. if (validator.settings.onsubmit)
  26. {
  27. // allow suppresing validation by adding a cancel class to the submit button
  28. this.find("input, button").filter(".cancel").click(function()
  29. {
  30. validator.cancelSubmit = true;
  31. });
  32. // validate the form on submit
  33. this.submit(function(event)
  34. {
  35. if (validator.settings.debug)
  36. // prevent form submit to be able to see console output
  37. event.preventDefault();
  38. function handle()
  39. {
  40. if (validator.settings.submitHandler)
  41. {
  42. validator.settings.submitHandler.call(validator, validator.currentForm);
  43. return false;
  44. }
  45. return true;
  46. }
  47. // prevent submit for invalid forms or custom submit handlers
  48. if (validator.cancelSubmit)
  49. {
  50. validator.cancelSubmit = false;
  51. return handle();
  52. }
  53. if (validator.form())
  54. {
  55. if (validator.pendingRequest)
  56. {
  57. validator.formSubmitted = true;
  58. return false;
  59. }
  60. return handle();
  61. } else
  62. {
  63. validator.focusInvalid();
  64. return false;
  65. }
  66. });
  67. }
  68. return validator;
  69. },
  70. // http://docs.jquery.com/Plugins/Validation/valid
  71. valid: function()
  72. {
  73. if ($(this[0]).is('form'))
  74. {
  75. return this.validate().form();
  76. } else
  77. {
  78. var valid = false;
  79. var validator = $(this[0].form).validate();
  80. this.each(function()
  81. {
  82. valid |= validator.element(this);
  83. });
  84. return valid;
  85. }
  86. },
  87. // attributes: space seperated list of attributes to retrieve and remove
  88. removeAttrs: function(attributes)
  89. {
  90. var result = {},
  91. $element = this;
  92. $.each(attributes.split(/\s/), function(index, value)
  93. {
  94. result[value] = $element.attr(value);
  95. $element.removeAttr(value);
  96. });
  97. return result;
  98. },
  99. // http://docs.jquery.com/Plugins/Validation/rules
  100. rules: function(command, argument)
  101. {
  102. var element = this[0];
  103. if (command)
  104. {
  105. var settings = $.data(element.form, 'validator').settings;
  106. var staticRules = settings.rules;
  107. var existingRules = $.validator.staticRules(element);
  108. switch (command)
  109. {
  110. case "add":
  111. $.extend(existingRules, $.validator.normalizeRule(argument));
  112. staticRules[element.name] = existingRules;
  113. if (argument.messages)
  114. settings.messages[element.name] = $.extend(settings.messages[element.name], argument.messages);
  115. break;
  116. case "remove":
  117. if (!argument)
  118. {
  119. delete staticRules[element.name];
  120. return existingRules;
  121. }
  122. var filtered = {};
  123. $.each(argument.split(/\s/), function(index, method)
  124. {
  125. filtered[method] = existingRules[method];
  126. delete existingRules[method];
  127. });
  128. return filtered;
  129. }
  130. }
  131. var data = $.validator.normalizeRules(
  132. $.extend(
  133. {},
  134. $.validator.metadataRules(element),
  135. $.validator.classRules(element),
  136. $.validator.attributeRules(element),
  137. $.validator.staticRules(element)
  138. ), element);
  139. // make sure required is at front
  140. if (data.required)
  141. {
  142. var param = data.required;
  143. delete data.required;
  144. data = $.extend({ required: param }, data);
  145. }
  146. if (data.dependTo)
  147. {
  148. var param = data.dependTo;
  149. delete data.dependTo;
  150. data = $.extend({ dependTo: param }, data);
  151. }
  152. return data;
  153. }
  154. });
  155. // Custom selectors
  156. $.extend($.expr[":"], {
  157. // http://docs.jquery.com/Plugins/Validation/blank
  158. blank: function(a) { return !$.trim(a.value); },
  159. // http://docs.jquery.com/Plugins/Validation/filled
  160. filled: function(a) { return !!$.trim(a.value); },
  161. // http://docs.jquery.com/Plugins/Validation/unchecked
  162. unchecked: function(a) { return !a.checked; }
  163. });
  164. $.format = function(source, params)
  165. {
  166. if (arguments.length == 1)
  167. return function()
  168. {
  169. var args = $.makeArray(arguments);
  170. args.unshift(source);
  171. return $.format.apply(this, args);
  172. };
  173. if (arguments.length > 2 && params.constructor != Array)
  174. {
  175. params = $.makeArray(arguments).slice(1);
  176. }
  177. if (params.constructor != Array)
  178. {
  179. params = [params];
  180. }
  181. $.each(params, function(i, n)
  182. {
  183. source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
  184. });
  185. return source;
  186. };
  187. // constructor for validator
  188. $.validator = function(options, form)
  189. {
  190. this.settings = $.extend({}, $.validator.defaults, options);
  191. this.currentForm = form;
  192. this.init();
  193. };
  194. // validator 属性 方法
  195. $.extend($.validator, {
  196. defaults: {
  197. messages: {},
  198. errorClasses:{},
  199. tips:{},
  200. tipClass:'tips',
  201. tipClasses:{},
  202. groups: {},
  203. rules: {},
  204. errorClass: "error",
  205. errorElement: "label",
  206. focusInvalid: true,
  207. errorContainer: $([]),
  208. errorLabelContainer: $([]),
  209. onsubmit: true,
  210. ignore: [],
  211. ignoreTitle: false,
  212. onfocusin: function(element)
  213. {
  214. this.lastActive = element;
  215. // hide error label and remove error class on focus if enabled
  216. if (this.settings.focusCleanup && !this.blockFocusCleanup)
  217. {
  218. this.settings.unhighlight && this.settings.unhighlight.call(this, element, this.settings.errorClass);
  219. this.errorsFor(element).css('display','none');
  220. }
  221. // show tips label on focus if enabled
  222. this.showTip(element);
  223. var rules = $(element).rules();
  224. for (var method in rules)
  225. {
  226. if ($(element).is('input[type=text],textarea,input[type=password]'))
  227. {
  228. $(element).addClass('focus');
  229. }
  230. break;
  231. }
  232. },
  233. onfocusout: function(element)
  234. {
  235. this.hideTip(element);
  236. if (!this.checkable(element) && (element.name in this.submitted || !this.optional(element)))
  237. {
  238. this.element(element);
  239. }
  240. var rules = $(element).rules();
  241. for (var method in rules)
  242. {
  243. if ($(element).is('input[type=text],textarea,input[type=password]'))
  244. {
  245. $(element).removeClass('focus');
  246. }
  247. break;
  248. }
  249. },
  250. onblur: function(element)
  251. {
  252. if (element.name in this.submitted || element == this.lastElement)
  253. {
  254. this.element(element);
  255. }
  256. },
  257. onclick: function(element)
  258. {
  259. if (element.name in this.submitted)
  260. this.element(element);
  261. },
  262. highlight: function(element, errorClass)
  263. {
  264. $(element).addClass(errorClass);
  265. },
  266. unhighlight: function(element, errorClass)
  267. {
  268. $(element).removeClass(errorClass);
  269. }
  270. },
  271. // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
  272. setDefaults: function(settings)
  273. {
  274. $.extend($.validator.defaults, settings);
  275. },
  276. messages: {
  277. required: "This field is required.",
  278. remote: "Please fix this field.",
  279. email: "Please enter a valid email address.",
  280. url: "Please enter a valid URL.",
  281. date: "Please enter a valid date.",
  282. dateISO: "Please enter a valid date (ISO).",
  283. dateDE: "Bitte geben Sie ein gültiges Datum ein.",
  284. number: "Please enter a valid number.",
  285. numberDE: "Bitte geben Sie eine Nummer ein.",
  286. digits: "Please enter only digits",
  287. creditcard: "Please enter a valid credit card number.",
  288. equalTo: "Please enter the same value again.",
  289. accept: "Please enter a value with a valid extension.",
  290. maxlength: $.format("Please enter no more than {0} characters."),
  291. minlength: $.format("Please enter at least {0} characters."),
  292. rangelength: $.format("Please enter a value between {0} and {1} characters long."),
  293. range: $.format("Please enter a value between {0} and {1}."),
  294. max: $.format("Please enter a value less than or equal to {0}."),
  295. min: $.format("Please enter a value greater than or equal to {0}.")
  296. },
  297. autoCreateRanges: false,
  298. prototype: {
  299. init: function()
  300. {
  301. this.labelContainer = $(this.settings.errorLabelContainer);
  302. this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
  303. this.containers = $(this.settings.errorContainer).add(this.settings.errorLabelContainer);
  304. this.submitted = {};
  305. this.valueCache = {};
  306. this.pendingRequest = 0;
  307. this.pending = {};
  308. this.invalid = {};
  309. this.reset();
  310. var groups = (this.groups = {});
  311. $.each(this.settings.groups, function(key, value)
  312. {
  313. $.each(value.split(/\s/), function(index, name)
  314. {
  315. groups[name] = key;
  316. });
  317. });
  318. var rules = this.settings.rules;
  319. $.each(rules, function(key, value)
  320. {
  321. rules[key] = $.validator.normalizeRule(value);
  322. });
  323. function delegate(event)
  324. {
  325. var validator = $.data(this[0].form, "validator");
  326. validator.settings["on" + event.type] && validator.settings["on" + event.type].call(validator, this[0]);
  327. }
  328. $(this.currentForm)
  329. .validDelegate("focusin focusout blur", ":text, :password, :file, select, textarea", delegate)
  330. .validDelegate("click", ":radio, :checkbox", delegate);
  331. if (this.settings.invalidHandler)
  332. $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
  333. },
  334. // http://docs.jquery.com/Plugins/Validation/Validator/form
  335. form: function()
  336. {
  337. this.checkForm();
  338. $.extend(this.submitted, this.errorMap);
  339. this.invalid = $.extend({}, this.errorMap);
  340. if (!this.valid())
  341. $(this.currentForm).triggerHandler("invalid-form", [this]);
  342. this.showErrors();
  343. //自动聚集并滚动到第一个失败的位置
  344. this.focusInvalid();
  345. return this.valid();
  346. },
  347. checkForm: function()
  348. {
  349. this.prepareForm();
  350. for (var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++)
  351. {
  352. this.check(elements[i]);
  353. }
  354. return this.valid();
  355. },
  356. showTip:function(element) {
  357. if(this.settings.tips[element.name]){
  358. this.showLabel(element,this.settings.tips[element.name],this.settings.tipClasses[element.name]||this.settings.tipClass);
  359. this.errorsFor(element).css('display','block');
  360. }
  361. },
  362. hideTip:function(element) {
  363. if(this.settings.tips[element.name]){
  364. this.errorsFor(element).css('display','none');
  365. }
  366. },
  367. // http://docs.jquery.com/Plugins/Validation/Validator/element
  368. element: function(element)
  369. {
  370. element = this.clean(element);
  371. this.lastElement = element;
  372. this.prepareElement(element);
  373. this.currentElements = $(element);
  374. var result = this.check(element);
  375. if (result)
  376. {
  377. delete this.invalid[element.name];
  378. } else
  379. {
  380. this.invalid[element.name] = true;
  381. }
  382. if (!this.numberOfInvalids())
  383. {
  384. // Hide error containers on last error
  385. this.toHide = this.toHide.add(this.containers);
  386. }
  387. this.showErrors();
  388. return result;
  389. },
  390. // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
  391. showErrors: function(errors)
  392. {
  393. if (errors)
  394. {
  395. // add items to error list and map
  396. $.extend(this.errorMap, errors);
  397. this.errorList = [];
  398. for (var name in errors)
  399. {
  400. this.errorList.push({
  401. message: errors[name][name],
  402. element: this.findByName(name)[0],
  403. errorClass:errors[name]['errorClass']
  404. });
  405. /*
  406. * this.errorList.push({
  407. message: errors[name][0],
  408. element: this.findByName(name)[0],
  409. errorClass:errors['errorClass']
  410. });
  411. */
  412. }
  413. // remove items from success list
  414. this.successList = $.grep(this.successList, function(element)
  415. {
  416. return !(element.name in errors);
  417. });
  418. }
  419. this.settings.showErrors
  420. ? this.settings.showErrors.call(this, this.errorMap, this.errorList)
  421. : this.defaultShowErrors();
  422. },
  423. // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
  424. resetForm: function()
  425. {
  426. if ($.fn.resetForm)
  427. $(this.currentForm).resetForm();
  428. this.submitted = {};
  429. this.prepareForm();
  430. this.hideErrors();
  431. this.elements().removeClass(this.settings.errorClass);
  432. },
  433. numberOfInvalids: function()
  434. {
  435. return this.objectLength(this.invalid);
  436. },
  437. objectLength: function(obj)
  438. {
  439. var count = 0;
  440. for (var i in obj)
  441. count++;
  442. return count;
  443. },
  444. hideErrors: function()
  445. {
  446. this.addWrapper(this.toHide).css('display','none');
  447. },
  448. valid: function()
  449. {
  450. return this.size() == 0;
  451. },
  452. size: function()
  453. {
  454. return this.errorList.length;
  455. },
  456. focusInvalid: function()
  457. {
  458. if (this.settings.focusInvalid)
  459. {
  460. try
  461. {
  462. //this.findLastActive() ||
  463. $( this.errorList.length && this.errorList[0].element || []).filter(":visible").focus();
  464. } catch (e)
  465. {
  466. // ignore IE throwing errors when focusing hidden elements
  467. }
  468. }
  469. },
  470. findLastActive: function()
  471. {
  472. var lastActive = this.lastActive;
  473. return lastActive && $.grep(this.errorList, function(n)
  474. {
  475. return n.element.name == lastActive.name;
  476. }).length == 1 && lastActive;
  477. },
  478. elements: function()
  479. {
  480. var validator = this,
  481. rulesCache = {};
  482. // select all valid inputs inside the form (no submit or reset buttons)
  483. // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
  484. /*
  485. return $([]).add(this.currentForm.elements)
  486. .filter(":input")
  487. .not(":submit, :reset, :image, [disabled]")
  488. .not(this.settings.ignore)
  489. .filter(function()
  490. {
  491. !this.name && validator.settings.debug && window.console && console.error("%o has no name assigned", this);
  492. // select only the first element for each name, and only those with rules specified
  493. if (this.name in rulesCache || !validator.objectLength($(this).rules()))
  494. return false;
  495. rulesCache[this.name] = true;
  496. return true;
  497. });*/
  498. return $(':input',this.currentForm)
  499. .not(":submit, :reset, :image, [disabled]")
  500. .not(this.settings.ignore)
  501. .filter(function(){
  502. !this.name&&validator.settings.debug&&window.console&&console.error("%o has no name assigned",this);
  503. if(this.name in rulesCache||!validator.objectLength($(this).rules()))
  504. return false;
  505. rulesCache[this.name]=true;
  506. return true;
  507. });
  508. },
  509. clean: function(selector)
  510. {
  511. return $(selector)[0];
  512. },
  513. errors: function()
  514. {
  515. // 2013-08-23 update ZhangYu
  516. return $(this.settings.errorElement+'[for]', this.errorContext);
  517. // return $(this.settings.errorElement + "." + this.settings.errorClass, this.errorContext);
  518. },
  519. reset: function()
  520. {
  521. this.successList = [];
  522. this.errorList = [];
  523. this.errorMap = {};
  524. this.toShow = $([]);
  525. this.toHide = $([]);
  526. this.formSubmitted = false;
  527. this.currentElements = $([]);
  528. },
  529. prepareForm: function()
  530. {
  531. this.reset();
  532. this.toHide = this.errors().add(this.containers);
  533. },
  534. prepareElement: function(element)
  535. {
  536. this.reset();
  537. this.toHide = this.errorsFor(element);
  538. },
  539. check: function(element)
  540. {
  541. element = this.clean(element);
  542. // if radio/checkbox, validate first element in group instead
  543. if (this.checkable(element))
  544. {
  545. element = this.findByName(element.name)[0];
  546. }
  547. var rules = $(element).rules();
  548. var dependencyMismatch = false;
  549. for (method in rules)
  550. {
  551. var rule = { method: method, parameters: rules[method] };
  552. try
  553. {
  554. var result = $.validator.methods[method].call(this, element.value.replace(/\r/g, ""), element, rule.parameters);
  555. //dependTo
  556. if (method == 'dependTo')
  557. {
  558. if (!result) return true;
  559. }
  560. // if a method indicates that the field is optional and therefore valid,
  561. // don't mark it as valid when there are no other rules
  562. if (result == "dependency-mismatch")
  563. {
  564. dependencyMismatch = true;
  565. continue;
  566. }
  567. dependencyMismatch = false;
  568. if (result == "pending")
  569. {
  570. this.toHide = this.toHide.not(this.errorsFor(element));
  571. return;
  572. }
  573. if (!result)
  574. {
  575. // 添加错误
  576. this.formatAndAdd(element, rule);
  577. return false;
  578. }
  579. } catch (e)
  580. {
  581. this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
  582. + ", check the '" + rule.method + "' method");
  583. throw e;
  584. }
  585. }
  586. if (dependencyMismatch)
  587. return;
  588. if (this.objectLength(rules))
  589. this.successList.push(element);
  590. return true;
  591. },
  592. // return the custom message for the given element and validation method
  593. // specified in the element's "messages" metadata
  594. customMetaMessage: function(element, method)
  595. {
  596. if (!$.metadata)
  597. return;
  598. var meta = this.settings.meta
  599. ? $(element).metadata()[this.settings.meta]
  600. : $(element).metadata();
  601. return meta && meta.messages && meta.messages[method];
  602. },
  603. // return the custom message for the given element name and validation method
  604. customMessage: function(name, method)
  605. {
  606. var m = this.settings.messages[name];
  607. return m && (m.constructor == String
  608. ? m
  609. : m[method]);
  610. },
  611. // add momo 新增自定义方法错误class
  612. customErrorClass:function(name,method) {
  613. var m = this.settings.errorClasses[name];
  614. return m && (typeof m[method] =='undefined'
  615. ? this.settings.errorClass
  616. : m[method]);
  617. },
  618. // return the first defined argument, allowing empty strings
  619. findDefined: function()
  620. {
  621. for (var i = 0; i < arguments.length; i++)
  622. {
  623. if (arguments[i] !== undefined)
  624. return arguments[i];
  625. }
  626. return undefined;
  627. },
  628. defaultMessage: function(element, method)
  629. {
  630. return this.findDefined(
  631. this.customMessage(element.name, method),
  632. this.customMetaMessage(element, method),
  633. // title is never undefined, so handle empty string as undefined
  634. !this.settings.ignoreTitle && element.title || undefined,
  635. $.validator.messages[method],
  636. "<strong>Warning: No message defined for " + element.name + "</strong>"
  637. );
  638. },
  639. formatAndAdd: function(element, rule)
  640. {
  641. // add momo
  642. var errorClass = this.customErrorClass(element.name,rule.method);
  643. var message = this.defaultMessage(element, rule.method);
  644. if (typeof message == "function")
  645. message = message.call(this, rule.parameters, element);
  646. this.errorList.push({
  647. message: message,
  648. element: element,
  649. errorClass:errorClass
  650. });
  651. this.errorMap[element.name] = message;
  652. this.submitted[element.name] = message;
  653. },
  654. addWrapper: function(toToggle)
  655. {
  656. if (this.settings.wrapper)
  657. toToggle = toToggle.add(toToggle.parents(this.settings.wrapper));
  658. return toToggle;
  659. },
  660. defaultShowErrors: function()
  661. {
  662. if (this.settings.success)
  663. {
  664. for (var i = 0; this.successList[i]; i++)
  665. {
  666. this.showLabel(this.successList[i]);
  667. }
  668. }
  669. for (var i = 0; this.errorList[i]; i++)
  670. {
  671. var error = this.errorList[i];
  672. this.settings.highlight && this.settings.highlight.call(this, error.element,/*error.errorClass||*/this.settings.errorClass);
  673. this.showLabel(error.element, error.message,error.errorClass);
  674. }
  675. if (this.errorList.length)
  676. {
  677. this.toShow = this.toShow.add(this.containers);
  678. }
  679. if (this.settings.unhighlight)
  680. {
  681. for (var i = 0, elements = this.validElements(); elements[i]; i++)
  682. {
  683. this.settings.unhighlight.call(this, elements[i], this.settings.errorClass);
  684. }
  685. }
  686. this.toHide = this.toHide.not(this.toShow);
  687. this.hideErrors();
  688. this.addWrapper(this.toShow).css('display','block');
  689. },
  690. validElements: function()
  691. {
  692. return this.currentElements.not(this.invalidElements());
  693. },
  694. invalidElements: function()
  695. {
  696. return $(this.errorList).map(function()
  697. {
  698. return this.element;
  699. });
  700. },
  701. showLabel: function(element, message,errorClass)
  702. {
  703. var label = this.errorsFor(element);
  704. if (label.length)
  705. {
  706. // refresh error/success class
  707. label.removeClass().addClass(errorClass||this.settings.errorClass);
  708. // check if we have a generated label, replace the message then
  709. label.attr("generated") && label.html(message);
  710. } else
  711. {
  712. // create label
  713. label = $("<" + this.settings.errorElement + "/>")
  714. .attr({ "for": this.idOrName(element), generated: true })
  715. .addClass(errorClass||this.settings.errorClass)
  716. .html(message || "");
  717. if (this.settings.wrapper)
  718. {
  719. // make sure the element is visible, even in IE
  720. // actually showing the wrapped element is handled elsewhere
  721. label = label.css('display','none').css('display','block').wrap("<" + this.settings.wrapper + "/>").parent();
  722. }
  723. if (!this.labelContainer.append(label).length)
  724. this.settings.errorPlacement
  725. ? this.settings.errorPlacement(label, $(element))
  726. : label.insertAfter(element);
  727. }
  728. if (!message && this.settings.success)
  729. {
  730. label.text("");
  731. typeof this.settings.success == "string"
  732. ? label.addClass(this.settings.success)
  733. : this.settings.success(label);
  734. }
  735. this.toShow = this.toShow.add(label);
  736. },
  737. errorsFor: function(element)
  738. {
  739. return this.errors().filter("[for='" + this.idOrName(element) + "']");
  740. },
  741. idOrName: function(element)
  742. {
  743. return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
  744. },
  745. checkable: function(element)
  746. {
  747. return /radio|checkbox/i.test(element.type);
  748. },
  749. findByName: function(name)
  750. {
  751. // select by name and filter by form for performance over form.find("[name=...]")
  752. var form = this.currentForm;
  753. return $(document.getElementsByName(name)).map(function(index, element)
  754. {
  755. return element.form == form && element.name == name && element || null;
  756. });
  757. },
  758. getLength: function(value, element)
  759. {
  760. switch (element.nodeName.toLowerCase())
  761. {
  762. case 'select':
  763. return $("option:selected", element).length;
  764. case 'input':
  765. if (this.checkable(element))
  766. return this.findByName(element.name).filter(':checked').length;
  767. }
  768. return value.length;
  769. },
  770. depend: function(param, element)
  771. {
  772. return this.dependTypes[typeof param]
  773. ? this.dependTypes[typeof param](param, element)
  774. : true;
  775. },
  776. dependTypes: {
  777. "boolean": function(param, element)
  778. {
  779. return param;
  780. },
  781. "string": function(param, element)
  782. {
  783. return !!$(param, element.form).length;
  784. },
  785. "function": function(param, element)
  786. {
  787. return param(element);
  788. }
  789. },
  790. optional: function(element)
  791. {
  792. return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
  793. },
  794. startRequest: function(element)
  795. {
  796. if (!this.pending[element.name])
  797. {
  798. this.pendingRequest++;
  799. this.pending[element.name] = true;
  800. }
  801. },
  802. stopRequest: function(element, valid)
  803. {
  804. this.pendingRequest--;
  805. // sometimes synchronization fails, make sure pendingRequest is never < 0
  806. if (this.pendingRequest < 0)
  807. this.pendingRequest = 0;
  808. delete this.pending[element.name];
  809. if (valid && this.pendingRequest == 0 && this.formSubmitted && this.form())
  810. {
  811. $(this.currentForm).submit();
  812. } else if (!valid && this.pendingRequest == 0 && this.formSubmitted)
  813. {
  814. $(this.currentForm).triggerHandler("invalid-form", [this]);
  815. }
  816. },
  817. previousValue: function(element)
  818. {
  819. return $.data(element, "previousValue") || $.data(element, "previousValue", previous = {
  820. old: null,
  821. valid: true,
  822. message: this.defaultMessage(element, "remote")
  823. });
  824. }
  825. },
  826. classRuleSettings: {
  827. required: { required: true },
  828. email: { email: true },
  829. url: { url: true },
  830. date: { date: true },
  831. dateISO: { dateISO: true },
  832. dateDE: { dateDE: true },
  833. number: { number: true },
  834. numberDE: { numberDE: true },
  835. digits: { digits: true },
  836. creditcard: { creditcard: true }
  837. },
  838. addClassRules: function(className, rules)
  839. {
  840. className.constructor == String ?
  841. this.classRuleSettings[className] = rules :
  842. $.extend(this.classRuleSettings, className);
  843. },
  844. classRules: function(element)
  845. {
  846. var rules = {};
  847. var classes = $(element).attr('class');
  848. classes && $.each(classes.split(' '), function()
  849. {
  850. if (this in $.validator.classRuleSettings)
  851. {
  852. $.extend(rules, $.validator.classRuleSettings[this]);
  853. }
  854. });
  855. return rules;
  856. },
  857. attributeRules: function(element)
  858. {
  859. var rules = {};
  860. var $element = $(element);
  861. for (method in $.validator.methods)
  862. {
  863. var value = $element.attr(method);
  864. if (value)
  865. {
  866. rules[method] = value;
  867. }
  868. }
  869. // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
  870. if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength))
  871. {
  872. delete rules.maxlength;
  873. }
  874. return rules;
  875. },
  876. metadataRules: function(element)
  877. {
  878. if (!$.metadata) return {};
  879. var meta = $.data(element.form, 'validator').settings.meta;
  880. return meta ?
  881. $(element).metadata()[meta] :
  882. $(element).metadata();
  883. },
  884. staticRules: function(element)
  885. {
  886. var rules = {};
  887. var validator = $.data(element.form, 'validator');
  888. if (validator.settings.rules)
  889. {
  890. rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
  891. }
  892. return rules;
  893. },
  894. normalizeRules: function(rules, element)
  895. {
  896. // handle dependency check
  897. $.each(rules, function(prop, val)
  898. {
  899. // ignore rule when param is explicitly false, eg. required:false
  900. if (val === false)
  901. {
  902. delete rules[prop];
  903. return;
  904. }
  905. if (val.param || val.depends)
  906. {
  907. var keepRule = true;
  908. switch (typeof val.depends)
  909. {
  910. case "string":
  911. keepRule = !!$(val.depends, element.form).length;
  912. break;
  913. case "function":
  914. keepRule = val.depends.call(element, element);
  915. break;
  916. }
  917. if (keepRule)
  918. {
  919. rules[prop] = val.param !== undefined ? val.param : true;
  920. } else
  921. {
  922. delete rules[prop];
  923. }
  924. }
  925. });
  926. // evaluate parameters
  927. $.each(rules, function(rule, parameter)
  928. {
  929. rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
  930. });
  931. // clean number parameters
  932. $.each(['minlength', 'maxlength', 'min', 'max'], function()
  933. {
  934. if (rules[this])
  935. {
  936. rules[this] = Number(rules[this]);
  937. }
  938. });
  939. $.each(['rangelength', 'range'], function()
  940. {
  941. if (rules[this])
  942. {
  943. rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
  944. }
  945. });
  946. if ($.validator.autoCreateRanges)
  947. {
  948. // auto-create ranges
  949. if (rules.min && rules.max)
  950. {
  951. rules.range = [rules.min, rules.max];
  952. delete rules.min;
  953. delete rules.max;
  954. }
  955. if (rules.minlength && rules.maxlength)
  956. {
  957. rules.rangelength = [rules.minlength, rules.maxlength];
  958. delete rules.minlength;
  959. delete rules.maxlength;
  960. }
  961. }
  962. // To support custom messages in metadata ignore rule methods titled "messages"
  963. if (rules.messages)
  964. {
  965. delete rules.messages
  966. }
  967. return rules;
  968. },
  969. // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
  970. normalizeRule: function(data)
  971. {
  972. if (typeof data == "string")
  973. {
  974. var transformed = {};
  975. $.each(data.split(/\s/), function()
  976. {
  977. transformed[this] = true;
  978. });
  979. data = transformed;
  980. }
  981. return data;
  982. },
  983. // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
  984. addMethod: function(name, method, message)
  985. {
  986. $.validator.methods[name] = method;
  987. $.validator.messages[name] = message;
  988. if (method.length < 3)
  989. {
  990. $.validator.addClassRules(name, $.validator.normalizeRule(name));
  991. }
  992. },
  993. methods: {
  994. // http://docs.jquery.com/Plugins/Validation/Methods/required
  995. required: function(value, element, param)
  996. {
  997. // check if dependency is met
  998. if (!this.depend(param, element))
  999. return "dependency-mismatch";
  1000. switch (element.nodeName.toLowerCase())
  1001. {
  1002. case 'select':
  1003. var options = $("option:selected", element);
  1004. return options.length > 0 && (element.type == "select-multiple" || ($.browser.msie && !(options[0].attributes['value'].specified) ? options[0].text : options[0].value).length > 0);
  1005. case 'input':
  1006. if (this.checkable(element))
  1007. return this.getLength(value, element) > 0;
  1008. default:
  1009. return $.trim(value).length > 0;
  1010. }
  1011. },
  1012. // http://docs.jquery.com/Plugins/Validation/Methods/remote
  1013. remote: function(value, element, param)
  1014. {
  1015. if (this.optional(element))
  1016. return "dependency-mismatch";
  1017. var previous = this.previousValue(element);
  1018. if (!this.settings.messages[element.name])
  1019. this.settings.messages[element.name] = {};
  1020. this.settings.messages[element.name].remote = typeof previous.message == "function" ? previous.message(value) : previous.message;
  1021. param = typeof param == "string" && { url: param} || param;
  1022. if (previous.old !== value||param.everyCheck)
  1023. {
  1024. previous.old = value;
  1025. var validator = this;
  1026. this.startRequest(element);
  1027. var data = {};
  1028. data[element.name] = value;
  1029. $.ajax($.extend(true, {
  1030. url: param,
  1031. mode: "abort",
  1032. port: "validate" + element.name,
  1033. dataType: "json",
  1034. data: data,
  1035. success: function(response)
  1036. {
  1037. if (response)
  1038. {
  1039. var submitted = validator.formSubmitted;
  1040. validator.prepareElement(element);
  1041. validator.formSubmitted = submitted;
  1042. validator.successList.push(element);
  1043. validator.showErrors();
  1044. } else
  1045. {
  1046. var errors = {};
  1047. errors[element.name] = [];
  1048. errors[element.name][element.name]= response || validator.defaultMessage(element, "remote");
  1049. // add ZhangYu 增加远程远程是的错误样式
  1050. errors[element.name]['errorClass'] = validator.customErrorClass(element.name, "remote");
  1051. validator.showErrors(errors);
  1052. }
  1053. previous.valid = response;
  1054. validator.stopRequest(element, response);
  1055. }
  1056. }, param));
  1057. return "pending";
  1058. } else if (this.pending[element.name])
  1059. {
  1060. return "pending";
  1061. }
  1062. return previous.valid;
  1063. },
  1064. // http://docs.jquery.com/Plugins/Validation/Methods/minlength
  1065. minlength: function(value, element, param)
  1066. {
  1067. return this.optional(element) || this.getLength($.trim(value), element) >= param;
  1068. },
  1069. // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
  1070. maxlength: function(value, element, param)
  1071. {
  1072. return this.optional(element) || this.getLength($.trim(value), element) <= param;
  1073. },
  1074. // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
  1075. rangelength: function(value, element, param)
  1076. {
  1077. var length = this.getLength($.trim(value), element);
  1078. return this.optional(element) || (length >= param[0] && length <= param[1]);
  1079. },
  1080. // http://docs.jquery.com/Plugins/Validation/Methods/min
  1081. min: function(value, element, param)
  1082. {
  1083. return this.optional(element) || value >= param;
  1084. },
  1085. // http://docs.jquery.com/Plugins/Validation/Methods/max
  1086. max: function(value, element, param)
  1087. {
  1088. return this.optional(element) || value <= param;
  1089. },
  1090. // http://docs.jquery.com/Plugins/Validation/Methods/range
  1091. range: function(value, element, param)
  1092. {
  1093. return this.optional(element) || (value >= param[0] && value <= param[1]);
  1094. },
  1095. // http://docs.jquery.com/Plugins/Validation/Methods/email
  1096. email: function(value, element)
  1097. {
  1098. // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
  1099. // return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([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])))\.?$/i.test(value);
  1100. return this.optional(element) || /^[_\.0-9a-zA-Z-]+[_0-9a-zA-Z-]@([0-9a-zA-Z][0-9a-zA-Z-]+\.)+[a-zA-Z]{2,3}$/.test(value) && value.split("@")[0].length <= 20;
  1101. },
  1102. //telphone 验证
  1103. tel: function(value, element)
  1104. {
  1105. //return this.optional(element) || /^(\d{11})$|^(\d{5})$|^((\d{7,8}$)|(\d{4}|\d{3})-(\d{7,8}$)|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}$)|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})(-\d+)?$)$/.test(value);
  1106. return this.optional(element) || /^.{0,30}\d{5}.{0,30}$/.test(value);
  1107. },
  1108. // http://docs.jquery.com/Plugins/Validation/Methods/url
  1109. url: function(value, element)
  1110. {
  1111. // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
  1112. 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);
  1113. },
  1114. // http://docs.jquery.com/Plugins/Validation/Methods/date
  1115. date: function(value, element)
  1116. {
  1117. return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
  1118. },
  1119. // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
  1120. dateISO: function(value, element)
  1121. {
  1122. return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
  1123. },
  1124. // http://docs.jquery.com/Plugins/Validation/Methods/dateDE
  1125. dateDE: function(value, element)
  1126. {
  1127. return this.optional(element) || /^\d\d?\.\d\d?\.\d\d\d?\d?$/.test(value);
  1128. },
  1129. //验证是否大于(等于)指定的表单的值 param 例: ['#minDate',true]
  1130. greatThan: function(value, element, param)
  1131. {
  1132. if (this.optional(element)) return "dependency-mismatch";
  1133. var isDate = /^\d{4}[\/-]\d{1,2}([\/-]\d{1,2})?$/.test(value);
  1134. var otherEl = param;
  1135. var containsEqual = false;
  1136. if ($.isArray(param))
  1137. {
  1138. otherEl = param[0];
  1139. if (param.length > 1) containsEqual = param[1];
  1140. }
  1141. var val = $(otherEl).val();
  1142. if (val == '') return true;
  1143. if (isDate)
  1144. {
  1145. val = val.replace(/-/g, '/');
  1146. value = value.replace(/-/g, '/');
  1147. if (/^\d{4}\/\d{1,2}$/.test(val)) val = val + '/01';
  1148. if (/^\d{4}\/\d{1,2}$/.test(value)) value = value + '/01';
  1149. var thisDate = Date.parse(value);
  1150. var otherDate = Date.parse(val);
  1151. if (containsEqual)
  1152. {
  1153. return thisDate >= otherDate;
  1154. } else
  1155. {
  1156. return thisDate > otherDate;
  1157. }
  1158. } else
  1159. {
  1160. var val = $(otherEl).val();
  1161. var thisNumber = parseFloat(value);
  1162. var otherNumber = parseFloat(val);
  1163. if (containsEqual)
  1164. {
  1165. return thisNumber >= otherNumber;
  1166. } else
  1167. {
  1168. return thisNumber > otherNumber;
  1169. }
  1170. }
  1171. },
  1172. //验证是否小于(等于)指定的表单的值 param 例: ['#maxDate',true]
  1173. smallThan: function(value, element, param)
  1174. {
  1175. if (this.optional(element)) return "dependency-mismatch";
  1176. var isDate = /^\d{4}[\/-]\d{1,2}([\/-]\d{1,2})?$/.test(value);
  1177. var otherEl = param;
  1178. var containsEqual = false;
  1179. if ($.isArray(param))
  1180. {
  1181. otherEl = param[0];
  1182. if (param.length > 1) containsEqual = param[1];
  1183. }
  1184. var val = $(otherEl).val();
  1185. if (val == '') return true;
  1186. if (isDate)
  1187. {
  1188. val = val.replace(/-/g, '/');
  1189. value = value.replace(/-/g, '/');
  1190. if (/^\d{4}\/\d{1,2}$/.test(val)) val = val + '/01';
  1191. if (/^\d{4}\/\d{1,2}$/.test(value)) value = value + '/01';
  1192. var thisDate = Date.parse(value);
  1193. var otherDate = Date.parse(val);
  1194. if (containsEqual)
  1195. {
  1196. return thisDate <= otherDate;
  1197. } else
  1198. {
  1199. return thisDate < otherDate;
  1200. }
  1201. } else
  1202. {
  1203. var val = $(otherEl).val();
  1204. var thisNumber = parseFloat(value);
  1205. var otherNumber = parseFloat(val);
  1206. if (containsEqual)
  1207. {
  1208. return thisNumber <= otherNumber;
  1209. } else
  1210. {
  1211. return thisNumber < otherNumber;
  1212. }
  1213. }
  1214. },
  1215. // http://docs.jquery.com/Plugins/Validation/Methods/number
  1216. number: function(value, element)
  1217. {
  1218. return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
  1219. },
  1220. // http://docs.jquery.com/Plugins/Validation/Methods/numberDE
  1221. numberDE: function(value, element)
  1222. {
  1223. return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value);
  1224. },
  1225. // http://docs.jquery.com/Plugins/Validation/Methods/digits
  1226. digits: function(value, element)
  1227. {
  1228. return this.optional(element) || /^\d+$/.test(value);
  1229. },
  1230. // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
  1231. // based on http://en.wikipedia.org/wiki/Luhn
  1232. creditcard: function(value, element)
  1233. {
  1234. if (this.optional(element))
  1235. return "dependency-mismatch";
  1236. // accept only digits and dashes
  1237. if (/[^0-9-]+/.test(value))
  1238. return false;
  1239. var nCheck = 0,
  1240. nDigit = 0,
  1241. bEven = false;
  1242. value = value.replace(/\D/g, "");
  1243. for (n = value.length - 1; n >= 0; n--)
  1244. {
  1245. var cDigit = value.charAt(n);
  1246. var nDigit = parseInt(cDigit, 10);
  1247. if (bEven)
  1248. {
  1249. if ((nDigit *= 2) > 9)
  1250. nDigit -= 9;
  1251. }
  1252. nCheck += nDigit;
  1253. bEven = !bEven;
  1254. }
  1255. return (nCheck % 10) == 0;
  1256. },
  1257. // http://docs.jquery.com/Plugins/Validation/Methods/accept
  1258. accept: function(value, element, param)
  1259. {
  1260. param = typeof param == "string" ? param : "png|jpe?g|gif";
  1261. return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
  1262. },
  1263. // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
  1264. equalTo: function(value, element, param)
  1265. {
  1266. return value == $(param).val();
  1267. },
  1268. bigTo: function(value, element, param)
  1269. {
  1270. return value >= $(param).val();
  1271. },
  1272. //依赖于某个元素的值
  1273. dependTo: function(value, element, param)
  1274. {
  1275. var el = null;
  1276. var val = true;
  1277. var not = false; //是否取反,表示当值不等于指定的值时才验证
  1278. if ($.isArray(param))
  1279. {
  1280. if (param.length <= 0) return false;
  1281. el = param[0];
  1282. if (param.length > 1) val = param[1];
  1283. if (param.length > 2) not = (param[2] == 'not');
  1284. } else
  1285. {
  1286. var temp = param.split('|');
  1287. if (temp.length <= 0) return false;
  1288. el = temp[0];
  1289. if (temp.length > 1)
  1290. {
  1291. val = temp[1];
  1292. if (val == 'true' || val == 'True')
  1293. {
  1294. val = true;
  1295. } else if (val == 'false' || val == 'False')
  1296. {
  1297. val = false;
  1298. }
  1299. }
  1300. if (temp.length > 2) not = (temp[2] == 'not');
  1301. }
  1302. var jel = $(el);
  1303. if (jel.length > 0)
  1304. {
  1305. var e = jel[0];
  1306. if (e.type == 'checkbox' || e.type == 'radio')
  1307. {
  1308. result = jel.attr('checked') == val;
  1309. } else
  1310. {
  1311. result = jel.val() == val;
  1312. }
  1313. }
  1314. if (not) result = !result;
  1315. return result;
  1316. },
  1317. //判断是否匹配于指定的正则表达式
  1318. match: function(value, element, param)
  1319. {
  1320. if (this.optional(element)) return "dependency-mismatch";
  1321. var reg = param;
  1322. if (typeof param == 'string')
  1323. {
  1324. reg = new RegExp(param);
  1325. }
  1326. return reg.test(value);
  1327. }
  1328. }
  1329. });
  1330. })(jQuery);
  1331. // ajax mode: abort
  1332. // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
  1333. // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
  1334. ; (function($)
  1335. {
  1336. var ajax = $.ajax;
  1337. var pendingRequests = {};
  1338. $.ajax = function(settings)
  1339. {
  1340. // create settings for compatibility with ajaxSetup
  1341. settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
  1342. var port = settings.port;
  1343. if (settings.mode == "abort")
  1344. {
  1345. if (pendingRequests[port])
  1346. {
  1347. pendingRequests[port].abort();
  1348. }
  1349. return (pendingRequests[port] = ajax.apply(this, arguments));
  1350. }
  1351. return ajax.apply(this, arguments);
  1352. };
  1353. })(jQuery);
  1354. // provides cross-browser focusin and focusout events
  1355. // IE has native support, in other browsers, use event caputuring (neither bubbles)
  1356. // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
  1357. // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
  1358. // provides triggerEvent(type: String, target: Element) to trigger delegated events
  1359. ; (function($)
  1360. {
  1361. $.each({
  1362. focus: 'focusin',
  1363. blur: 'focusout'
  1364. }, function(original, fix)
  1365. {
  1366. $.event.special[fix] = {
  1367. setup: function()
  1368. {
  1369. if ($.browser.msie) return false;
  1370. this.addEventListener(original, $.event.special[fix].handler, true);
  1371. },
  1372. teardown: function()
  1373. {
  1374. if ($.browser.msie) return false;
  1375. this.removeEventListener(original,
  1376. $.event.special[fix].handler, true);
  1377. },
  1378. handler: function(e)
  1379. {
  1380. arguments[0] = $.event.fix(e);
  1381. arguments[0].type = fix;
  1382. return $.event.handle.apply(this, arguments);
  1383. }
  1384. };
  1385. });
  1386. $.extend($.fn, {
  1387. validDelegate: function(type, delegate, handler)
  1388. {
  1389. return this.bind(type, function(event)
  1390. {
  1391. var target = $(event.target);
  1392. if (target.is(delegate))
  1393. {
  1394. return handler.apply(target, arguments);
  1395. }
  1396. });
  1397. },
  1398. triggerEvent: function(type, target)
  1399. {
  1400. return this.triggerHandler(type, [$.event.fix({ type: type, target: target })]);
  1401. }
  1402. })
  1403. })(jQuery);