PageRenderTime 60ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/packages/jQuery.Validation.1.8.0/Content/Scripts/jquery.validate-vsdoc.js

#
JavaScript | 1299 lines | 917 code | 147 blank | 235 comment | 207 complexity | 020aba8d7e860542b68f0234b145bce5 MD5 | raw file
  1. /*
  2. * This file has been commented to support Visual Studio Intellisense.
  3. * You should not use this file at runtime inside the browser--it is only
  4. * intended to be used only for design-time IntelliSense. Please use the
  5. * standard jQuery library for all production use.
  6. *
  7. * Comment version: 1.8
  8. */
  9. /*
  10. * Note: While Microsoft is not the author of this file, Microsoft is
  11. * offering you a license subject to the terms of the Microsoft Software
  12. * License Terms for Microsoft ASP.NET Model View Controller 3.
  13. * Microsoft reserves all other rights. The notices below are provided
  14. * for informational purposes only and are not the license terms under
  15. * which Microsoft distributed this file.
  16. *
  17. * jQuery validation plugin 1.8.0
  18. *
  19. * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
  20. * http://docs.jquery.com/Plugins/Validation
  21. *
  22. * Copyright (c) 2006 - 2011 J??rn Zaefferer
  23. *
  24. */
  25. (function($) {
  26. $.extend($.fn, {
  27. // http://docs.jquery.com/Plugins/Validation/validate
  28. validate: function( options ) {
  29. /// <summary>
  30. /// Validates the selected form. This method sets up event handlers for submit, focus,
  31. /// keyup, blur and click to trigger validation of the entire form or individual
  32. /// elements. Each one can be disabled, see the onxxx options (onsubmit, onfocusout,
  33. /// onkeyup, onclick). focusInvalid focuses elements when submitting a invalid form.
  34. /// </summary>
  35. /// <param name="options" type="Options">
  36. /// A set of key/value pairs that configure the validate. All options are optional.
  37. /// </param>
  38. /// <returns type="Validator" />
  39. // if nothing is selected, return nothing; can't chain anyway
  40. if (!this.length) {
  41. options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
  42. return;
  43. }
  44. // check if a validator for this form was already created
  45. var validator = $.data(this[0], 'validator');
  46. if ( validator ) {
  47. return validator;
  48. }
  49. validator = new $.validator( options, this[0] );
  50. $.data(this[0], 'validator', validator);
  51. if ( validator.settings.onsubmit ) {
  52. // allow suppresing validation by adding a cancel class to the submit button
  53. this.find("input, button").filter(".cancel").click(function() {
  54. validator.cancelSubmit = true;
  55. });
  56. // when a submitHandler is used, capture the submitting button
  57. if (validator.settings.submitHandler) {
  58. this.find("input, button").filter(":submit").click(function() {
  59. validator.submitButton = this;
  60. });
  61. }
  62. // validate the form on submit
  63. this.submit( function( event ) {
  64. if ( validator.settings.debug )
  65. // prevent form submit to be able to see console output
  66. event.preventDefault();
  67. function handle() {
  68. if ( validator.settings.submitHandler ) {
  69. if (validator.submitButton) {
  70. // insert a hidden input as a replacement for the missing submit button
  71. var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
  72. }
  73. validator.settings.submitHandler.call( validator, validator.currentForm );
  74. if (validator.submitButton) {
  75. // and clean up afterwards; thanks to no-block-scope, hidden can be referenced
  76. hidden.remove();
  77. }
  78. return false;
  79. }
  80. return true;
  81. }
  82. // prevent submit for invalid forms or custom submit handlers
  83. if ( validator.cancelSubmit ) {
  84. validator.cancelSubmit = false;
  85. return handle();
  86. }
  87. if ( validator.form() ) {
  88. if ( validator.pendingRequest ) {
  89. validator.formSubmitted = true;
  90. return false;
  91. }
  92. return handle();
  93. } else {
  94. validator.focusInvalid();
  95. return false;
  96. }
  97. });
  98. }
  99. return validator;
  100. },
  101. // http://docs.jquery.com/Plugins/Validation/valid
  102. valid: function() {
  103. /// <summary>
  104. /// Checks if the selected form is valid or if all selected elements are valid.
  105. /// validate() needs to be called on the form before checking it using this method.
  106. /// </summary>
  107. /// <returns type="Boolean" />
  108. if ( $(this[0]).is('form')) {
  109. return this.validate().form();
  110. } else {
  111. var valid = true;
  112. var validator = $(this[0].form).validate();
  113. this.each(function() {
  114. valid &= validator.element(this);
  115. });
  116. return valid;
  117. }
  118. },
  119. // attributes: space seperated list of attributes to retrieve and remove
  120. removeAttrs: function(attributes) {
  121. /// <summary>
  122. /// Remove the specified attributes from the first matched element and return them.
  123. /// </summary>
  124. /// <param name="attributes" type="String">
  125. /// A space-seperated list of attribute names to remove.
  126. /// </param>
  127. /// <returns type="" />
  128. var result = {},
  129. $element = this;
  130. $.each(attributes.split(/\s/), function(index, value) {
  131. result[value] = $element.attr(value);
  132. $element.removeAttr(value);
  133. });
  134. return result;
  135. },
  136. // http://docs.jquery.com/Plugins/Validation/rules
  137. rules: function(command, argument) {
  138. /// <summary>
  139. /// Return the validations rules for the first selected element.
  140. /// </summary>
  141. /// <param name="command" type="String">
  142. /// Can be either "add" or "remove".
  143. /// </param>
  144. /// <param name="argument" type="">
  145. /// A list of rules to add or remove.
  146. /// </param>
  147. /// <returns type="" />
  148. var element = this[0];
  149. if (command) {
  150. var settings = $.data(element.form, 'validator').settings;
  151. var staticRules = settings.rules;
  152. var existingRules = $.validator.staticRules(element);
  153. switch(command) {
  154. case "add":
  155. $.extend(existingRules, $.validator.normalizeRule(argument));
  156. staticRules[element.name] = existingRules;
  157. if (argument.messages)
  158. settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
  159. break;
  160. case "remove":
  161. if (!argument) {
  162. delete staticRules[element.name];
  163. return existingRules;
  164. }
  165. var filtered = {};
  166. $.each(argument.split(/\s/), function(index, method) {
  167. filtered[method] = existingRules[method];
  168. delete existingRules[method];
  169. });
  170. return filtered;
  171. }
  172. }
  173. var data = $.validator.normalizeRules(
  174. $.extend(
  175. {},
  176. $.validator.metadataRules(element),
  177. $.validator.classRules(element),
  178. $.validator.attributeRules(element),
  179. $.validator.staticRules(element)
  180. ), element);
  181. // make sure required is at front
  182. if (data.required) {
  183. var param = data.required;
  184. delete data.required;
  185. data = $.extend({required: param}, data);
  186. }
  187. return data;
  188. }
  189. });
  190. // Custom selectors
  191. $.extend($.expr[":"], {
  192. // http://docs.jquery.com/Plugins/Validation/blank
  193. blank: function(a) {return !$.trim("" + a.value);},
  194. // http://docs.jquery.com/Plugins/Validation/filled
  195. filled: function(a) {return !!$.trim("" + a.value);},
  196. // http://docs.jquery.com/Plugins/Validation/unchecked
  197. unchecked: function(a) {return !a.checked;}
  198. });
  199. // constructor for validator
  200. $.validator = function( options, form ) {
  201. this.settings = $.extend( true, {}, $.validator.defaults, options );
  202. this.currentForm = form;
  203. this.init();
  204. };
  205. $.validator.format = function(source, params) {
  206. /// <summary>
  207. /// Replaces {n} placeholders with arguments.
  208. /// One or more arguments can be passed, in addition to the string template itself, to insert
  209. /// into the string.
  210. /// </summary>
  211. /// <param name="source" type="String">
  212. /// The string to format.
  213. /// </param>
  214. /// <param name="params" type="String">
  215. /// The first argument to insert, or an array of Strings to insert
  216. /// </param>
  217. /// <returns type="String" />
  218. if ( arguments.length == 1 )
  219. return function() {
  220. var args = $.makeArray(arguments);
  221. args.unshift(source);
  222. return $.validator.format.apply( this, args );
  223. };
  224. if ( arguments.length > 2 && params.constructor != Array ) {
  225. params = $.makeArray(arguments).slice(1);
  226. }
  227. if ( params.constructor != Array ) {
  228. params = [ params ];
  229. }
  230. $.each(params, function(i, n) {
  231. source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
  232. });
  233. return source;
  234. };
  235. $.extend($.validator, {
  236. defaults: {
  237. messages: {},
  238. groups: {},
  239. rules: {},
  240. errorClass: "error",
  241. validClass: "valid",
  242. errorElement: "label",
  243. focusInvalid: true,
  244. errorContainer: $( [] ),
  245. errorLabelContainer: $( [] ),
  246. onsubmit: true,
  247. ignore: [],
  248. ignoreTitle: false,
  249. onfocusin: function(element) {
  250. this.lastActive = element;
  251. // hide error label and remove error class on focus if enabled
  252. if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
  253. this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
  254. this.addWrapper(this.errorsFor(element)).hide();
  255. }
  256. },
  257. onfocusout: function(element) {
  258. if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
  259. this.element(element);
  260. }
  261. },
  262. onkeyup: function(element) {
  263. if ( element.name in this.submitted || element == this.lastElement ) {
  264. this.element(element);
  265. }
  266. },
  267. onclick: function(element) {
  268. // click on selects, radiobuttons and checkboxes
  269. if ( element.name in this.submitted )
  270. this.element(element);
  271. // or option elements, check parent select in that case
  272. else if (element.parentNode.name in this.submitted)
  273. this.element(element.parentNode);
  274. },
  275. highlight: function( element, errorClass, validClass ) {
  276. $(element).addClass(errorClass).removeClass(validClass);
  277. },
  278. unhighlight: function( element, errorClass, validClass ) {
  279. $(element).removeClass(errorClass).addClass(validClass);
  280. }
  281. },
  282. // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
  283. setDefaults: function(settings) {
  284. /// <summary>
  285. /// Modify default settings for validation.
  286. /// Accepts everything that Plugins/Validation/validate accepts.
  287. /// </summary>
  288. /// <param name="settings" type="Options">
  289. /// Options to set as default.
  290. /// </param>
  291. /// <returns type="undefined" />
  292. $.extend( $.validator.defaults, settings );
  293. },
  294. messages: {
  295. required: "This field is required.",
  296. remote: "Please fix this field.",
  297. email: "Please enter a valid email address.",
  298. url: "Please enter a valid URL.",
  299. date: "Please enter a valid date.",
  300. dateISO: "Please enter a valid date (ISO).",
  301. number: "Please enter a valid number.",
  302. digits: "Please enter only digits.",
  303. creditcard: "Please enter a valid credit card number.",
  304. equalTo: "Please enter the same value again.",
  305. accept: "Please enter a value with a valid extension.",
  306. maxlength: $.validator.format("Please enter no more than {0} characters."),
  307. minlength: $.validator.format("Please enter at least {0} characters."),
  308. rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
  309. range: $.validator.format("Please enter a value between {0} and {1}."),
  310. max: $.validator.format("Please enter a value less than or equal to {0}."),
  311. min: $.validator.format("Please enter a value greater than or equal to {0}.")
  312. },
  313. autoCreateRanges: false,
  314. prototype: {
  315. init: function() {
  316. this.labelContainer = $(this.settings.errorLabelContainer);
  317. this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
  318. this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
  319. this.submitted = {};
  320. this.valueCache = {};
  321. this.pendingRequest = 0;
  322. this.pending = {};
  323. this.invalid = {};
  324. this.reset();
  325. var groups = (this.groups = {});
  326. $.each(this.settings.groups, function(key, value) {
  327. $.each(value.split(/\s/), function(index, name) {
  328. groups[name] = key;
  329. });
  330. });
  331. var rules = this.settings.rules;
  332. $.each(rules, function(key, value) {
  333. rules[key] = $.validator.normalizeRule(value);
  334. });
  335. function delegate(event) {
  336. var validator = $.data(this[0].form, "validator"),
  337. eventType = "on" + event.type.replace(/^validate/, "");
  338. validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
  339. }
  340. $(this.currentForm)
  341. .validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
  342. .validateDelegate(":radio, :checkbox, select, option", "click", delegate);
  343. if (this.settings.invalidHandler)
  344. $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
  345. },
  346. // http://docs.jquery.com/Plugins/Validation/Validator/form
  347. form: function() {
  348. /// <summary>
  349. /// Validates the form, returns true if it is valid, false otherwise.
  350. /// This behaves as a normal submit event, but returns the result.
  351. /// </summary>
  352. /// <returns type="Boolean" />
  353. this.checkForm();
  354. $.extend(this.submitted, this.errorMap);
  355. this.invalid = $.extend({}, this.errorMap);
  356. if (!this.valid())
  357. $(this.currentForm).triggerHandler("invalid-form", [this]);
  358. this.showErrors();
  359. return this.valid();
  360. },
  361. checkForm: function() {
  362. this.prepareForm();
  363. for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
  364. this.check( elements[i] );
  365. }
  366. return this.valid();
  367. },
  368. // http://docs.jquery.com/Plugins/Validation/Validator/element
  369. element: function( element ) {
  370. /// <summary>
  371. /// Validates a single element, returns true if it is valid, false otherwise.
  372. /// This behaves as validation on blur or keyup, but returns the result.
  373. /// </summary>
  374. /// <param name="element" type="Selector">
  375. /// An element to validate, must be inside the validated form.
  376. /// </param>
  377. /// <returns type="Boolean" />
  378. element = this.clean( element );
  379. this.lastElement = element;
  380. this.prepareElement( element );
  381. this.currentElements = $(element);
  382. var result = this.check( element );
  383. if ( result ) {
  384. delete this.invalid[element.name];
  385. } else {
  386. this.invalid[element.name] = true;
  387. }
  388. if ( !this.numberOfInvalids() ) {
  389. // Hide error containers on last error
  390. this.toHide = this.toHide.add( this.containers );
  391. }
  392. this.showErrors();
  393. return result;
  394. },
  395. // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
  396. showErrors: function(errors) {
  397. /// <summary>
  398. /// Show the specified messages.
  399. /// Keys have to refer to the names of elements, values are displayed for those elements, using the configured error placement.
  400. /// </summary>
  401. /// <param name="errors" type="Object">
  402. /// One or more key/value pairs of input names and messages.
  403. /// </param>
  404. /// <returns type="undefined" />
  405. if(errors) {
  406. // add items to error list and map
  407. $.extend( this.errorMap, errors );
  408. this.errorList = [];
  409. for ( var name in errors ) {
  410. this.errorList.push({
  411. message: errors[name],
  412. element: this.findByName(name)[0]
  413. });
  414. }
  415. // remove items from success list
  416. this.successList = $.grep( this.successList, function(element) {
  417. return !(element.name in errors);
  418. });
  419. }
  420. this.settings.showErrors
  421. ? this.settings.showErrors.call( this, this.errorMap, this.errorList )
  422. : this.defaultShowErrors();
  423. },
  424. // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
  425. resetForm: function() {
  426. /// <summary>
  427. /// Resets the controlled form.
  428. /// Resets input fields to their original value (requires form plugin), removes classes
  429. /// indicating invalid elements and hides error messages.
  430. /// </summary>
  431. /// <returns type="undefined" />
  432. if ( $.fn.resetForm )
  433. $( this.currentForm ).resetForm();
  434. this.submitted = {};
  435. this.prepareForm();
  436. this.hideErrors();
  437. this.elements().removeClass( this.settings.errorClass );
  438. },
  439. numberOfInvalids: function() {
  440. /// <summary>
  441. /// Returns the number of invalid fields.
  442. /// This depends on the internal validator state. It covers all fields only after
  443. /// validating the complete form (on submit or via $("form").valid()). After validating
  444. /// a single element, only that element is counted. Most useful in combination with the
  445. /// invalidHandler-option.
  446. /// </summary>
  447. /// <returns type="Number" />
  448. return this.objectLength(this.invalid);
  449. },
  450. objectLength: function( obj ) {
  451. var count = 0;
  452. for ( var i in obj )
  453. count++;
  454. return count;
  455. },
  456. hideErrors: function() {
  457. this.addWrapper( this.toHide ).hide();
  458. },
  459. valid: function() {
  460. return this.size() == 0;
  461. },
  462. size: function() {
  463. return this.errorList.length;
  464. },
  465. focusInvalid: function() {
  466. if( this.settings.focusInvalid ) {
  467. try {
  468. $(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
  469. .filter(":visible")
  470. .focus()
  471. // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
  472. .trigger("focusin");
  473. } catch(e) {
  474. // ignore IE throwing errors when focusing hidden elements
  475. }
  476. }
  477. },
  478. findLastActive: function() {
  479. var lastActive = this.lastActive;
  480. return lastActive && $.grep(this.errorList, function(n) {
  481. return n.element.name == lastActive.name;
  482. }).length == 1 && lastActive;
  483. },
  484. elements: function() {
  485. var validator = this,
  486. rulesCache = {};
  487. // select all valid inputs inside the form (no submit or reset buttons)
  488. // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
  489. return $([]).add(this.currentForm.elements)
  490. .filter(":input")
  491. .not(":submit, :reset, :image, [disabled]")
  492. .not( this.settings.ignore )
  493. .filter(function() {
  494. !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
  495. // select only the first element for each name, and only those with rules specified
  496. if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
  497. return false;
  498. rulesCache[this.name] = true;
  499. return true;
  500. });
  501. },
  502. clean: function( selector ) {
  503. return $( selector )[0];
  504. },
  505. errors: function() {
  506. return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
  507. },
  508. reset: function() {
  509. this.successList = [];
  510. this.errorList = [];
  511. this.errorMap = {};
  512. this.toShow = $([]);
  513. this.toHide = $([]);
  514. this.currentElements = $([]);
  515. },
  516. prepareForm: function() {
  517. this.reset();
  518. this.toHide = this.errors().add( this.containers );
  519. },
  520. prepareElement: function( element ) {
  521. this.reset();
  522. this.toHide = this.errorsFor(element);
  523. },
  524. check: function( element ) {
  525. element = this.clean( element );
  526. // if radio/checkbox, validate first element in group instead
  527. if (this.checkable(element)) {
  528. element = this.findByName(element.name).not(this.settings.ignore)[0];
  529. }
  530. var rules = $(element).rules();
  531. var dependencyMismatch = false;
  532. for (var method in rules) {
  533. var rule = { method: method, parameters: rules[method] };
  534. try {
  535. var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
  536. // if a method indicates that the field is optional and therefore valid,
  537. // don't mark it as valid when there are no other rules
  538. if ( result == "dependency-mismatch" ) {
  539. dependencyMismatch = true;
  540. continue;
  541. }
  542. dependencyMismatch = false;
  543. if ( result == "pending" ) {
  544. this.toHide = this.toHide.not( this.errorsFor(element) );
  545. return;
  546. }
  547. if( !result ) {
  548. this.formatAndAdd( element, rule );
  549. return false;
  550. }
  551. } catch(e) {
  552. this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
  553. + ", check the '" + rule.method + "' method", e);
  554. throw e;
  555. }
  556. }
  557. if (dependencyMismatch)
  558. return;
  559. if ( this.objectLength(rules) )
  560. this.successList.push(element);
  561. return true;
  562. },
  563. // return the custom message for the given element and validation method
  564. // specified in the element's "messages" metadata
  565. customMetaMessage: function(element, method) {
  566. if (!$.metadata)
  567. return;
  568. var meta = this.settings.meta
  569. ? $(element).metadata()[this.settings.meta]
  570. : $(element).metadata();
  571. return meta && meta.messages && meta.messages[method];
  572. },
  573. // return the custom message for the given element name and validation method
  574. customMessage: function( name, method ) {
  575. var m = this.settings.messages[name];
  576. return m && (m.constructor == String
  577. ? m
  578. : m[method]);
  579. },
  580. // return the first defined argument, allowing empty strings
  581. findDefined: function() {
  582. for(var i = 0; i < arguments.length; i++) {
  583. if (arguments[i] !== undefined)
  584. return arguments[i];
  585. }
  586. return undefined;
  587. },
  588. defaultMessage: function( element, method) {
  589. return this.findDefined(
  590. this.customMessage( element.name, method ),
  591. this.customMetaMessage( element, method ),
  592. // title is never undefined, so handle empty string as undefined
  593. !this.settings.ignoreTitle && element.title || undefined,
  594. $.validator.messages[method],
  595. "<strong>Warning: No message defined for " + element.name + "</strong>"
  596. );
  597. },
  598. formatAndAdd: function( element, rule ) {
  599. var message = this.defaultMessage( element, rule.method ),
  600. theregex = /\$?\{(\d+)\}/g;
  601. if ( typeof message == "function" ) {
  602. message = message.call(this, rule.parameters, element);
  603. } else if (theregex.test(message)) {
  604. message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
  605. }
  606. this.errorList.push({
  607. message: message,
  608. element: element
  609. });
  610. this.errorMap[element.name] = message;
  611. this.submitted[element.name] = message;
  612. },
  613. addWrapper: function(toToggle) {
  614. if ( this.settings.wrapper )
  615. toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
  616. return toToggle;
  617. },
  618. defaultShowErrors: function() {
  619. for ( var i = 0; this.errorList[i]; i++ ) {
  620. var error = this.errorList[i];
  621. this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
  622. this.showLabel( error.element, error.message );
  623. }
  624. if( this.errorList.length ) {
  625. this.toShow = this.toShow.add( this.containers );
  626. }
  627. if (this.settings.success) {
  628. for ( var i = 0; this.successList[i]; i++ ) {
  629. this.showLabel( this.successList[i] );
  630. }
  631. }
  632. if (this.settings.unhighlight) {
  633. for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
  634. this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
  635. }
  636. }
  637. this.toHide = this.toHide.not( this.toShow );
  638. this.hideErrors();
  639. this.addWrapper( this.toShow ).show();
  640. },
  641. validElements: function() {
  642. return this.currentElements.not(this.invalidElements());
  643. },
  644. invalidElements: function() {
  645. return $(this.errorList).map(function() {
  646. return this.element;
  647. });
  648. },
  649. showLabel: function(element, message) {
  650. var label = this.errorsFor( element );
  651. if ( label.length ) {
  652. // refresh error/success class
  653. label.removeClass().addClass( this.settings.errorClass );
  654. // check if we have a generated label, replace the message then
  655. label.attr("generated") && label.html(message);
  656. } else {
  657. // create label
  658. label = $("<" + this.settings.errorElement + "/>")
  659. .attr({"for": this.idOrName(element), generated: true})
  660. .addClass(this.settings.errorClass)
  661. .html(message || "");
  662. if ( this.settings.wrapper ) {
  663. // make sure the element is visible, even in IE
  664. // actually showing the wrapped element is handled elsewhere
  665. label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
  666. }
  667. if ( !this.labelContainer.append(label).length )
  668. this.settings.errorPlacement
  669. ? this.settings.errorPlacement(label, $(element) )
  670. : label.insertAfter(element);
  671. }
  672. if ( !message && this.settings.success ) {
  673. label.text("");
  674. typeof this.settings.success == "string"
  675. ? label.addClass( this.settings.success )
  676. : this.settings.success( label );
  677. }
  678. this.toShow = this.toShow.add(label);
  679. },
  680. errorsFor: function(element) {
  681. var name = this.idOrName(element);
  682. return this.errors().filter(function() {
  683. return $(this).attr('for') == name;
  684. });
  685. },
  686. idOrName: function(element) {
  687. return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
  688. },
  689. checkable: function( element ) {
  690. return /radio|checkbox/i.test(element.type);
  691. },
  692. findByName: function( name ) {
  693. // select by name and filter by form for performance over form.find("[name=...]")
  694. var form = this.currentForm;
  695. return $(document.getElementsByName(name)).map(function(index, element) {
  696. return element.form == form && element.name == name && element || null;
  697. });
  698. },
  699. getLength: function(value, element) {
  700. switch( element.nodeName.toLowerCase() ) {
  701. case 'select':
  702. return $("option:selected", element).length;
  703. case 'input':
  704. if( this.checkable( element) )
  705. return this.findByName(element.name).filter(':checked').length;
  706. }
  707. return value.length;
  708. },
  709. depend: function(param, element) {
  710. return this.dependTypes[typeof param]
  711. ? this.dependTypes[typeof param](param, element)
  712. : true;
  713. },
  714. dependTypes: {
  715. "boolean": function(param, element) {
  716. return param;
  717. },
  718. "string": function(param, element) {
  719. return !!$(param, element.form).length;
  720. },
  721. "function": function(param, element) {
  722. return param(element);
  723. }
  724. },
  725. optional: function(element) {
  726. return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
  727. },
  728. startRequest: function(element) {
  729. if (!this.pending[element.name]) {
  730. this.pendingRequest++;
  731. this.pending[element.name] = true;
  732. }
  733. },
  734. stopRequest: function(element, valid) {
  735. this.pendingRequest--;
  736. // sometimes synchronization fails, make sure pendingRequest is never < 0
  737. if (this.pendingRequest < 0)
  738. this.pendingRequest = 0;
  739. delete this.pending[element.name];
  740. if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
  741. $(this.currentForm).submit();
  742. this.formSubmitted = false;
  743. } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
  744. $(this.currentForm).triggerHandler("invalid-form", [this]);
  745. this.formSubmitted = false;
  746. }
  747. },
  748. previousValue: function(element) {
  749. return $.data(element, "previousValue") || $.data(element, "previousValue", {
  750. old: null,
  751. valid: true,
  752. message: this.defaultMessage( element, "remote" )
  753. });
  754. }
  755. },
  756. classRuleSettings: {
  757. required: {required: true},
  758. email: {email: true},
  759. url: {url: true},
  760. date: {date: true},
  761. dateISO: {dateISO: true},
  762. dateDE: {dateDE: true},
  763. number: {number: true},
  764. numberDE: {numberDE: true},
  765. digits: {digits: true},
  766. creditcard: {creditcard: true}
  767. },
  768. addClassRules: function(className, rules) {
  769. /// <summary>
  770. /// Add a compound class method - useful to refactor common combinations of rules into a single
  771. /// class.
  772. /// </summary>
  773. /// <param name="name" type="String">
  774. /// The name of the class rule to add
  775. /// </param>
  776. /// <param name="rules" type="Options">
  777. /// The compound rules
  778. /// </param>
  779. /// <returns type="undefined" />
  780. className.constructor == String ?
  781. this.classRuleSettings[className] = rules :
  782. $.extend(this.classRuleSettings, className);
  783. },
  784. classRules: function(element) {
  785. var rules = {};
  786. var classes = $(element).attr('class');
  787. classes && $.each(classes.split(' '), function() {
  788. if (this in $.validator.classRuleSettings) {
  789. $.extend(rules, $.validator.classRuleSettings[this]);
  790. }
  791. });
  792. return rules;
  793. },
  794. attributeRules: function(element) {
  795. var rules = {};
  796. var $element = $(element);
  797. for (var method in $.validator.methods) {
  798. var value = $element.attr(method);
  799. if (value) {
  800. rules[method] = value;
  801. }
  802. }
  803. // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
  804. if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
  805. delete rules.maxlength;
  806. }
  807. return rules;
  808. },
  809. metadataRules: function(element) {
  810. if (!$.metadata) return {};
  811. var meta = $.data(element.form, 'validator').settings.meta;
  812. return meta ?
  813. $(element).metadata()[meta] :
  814. $(element).metadata();
  815. },
  816. staticRules: function(element) {
  817. var rules = {};
  818. var validator = $.data(element.form, 'validator');
  819. if (validator.settings.rules) {
  820. rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
  821. }
  822. return rules;
  823. },
  824. normalizeRules: function(rules, element) {
  825. // handle dependency check
  826. $.each(rules, function(prop, val) {
  827. // ignore rule when param is explicitly false, eg. required:false
  828. if (val === false) {
  829. delete rules[prop];
  830. return;
  831. }
  832. if (val.param || val.depends) {
  833. var keepRule = true;
  834. switch (typeof val.depends) {
  835. case "string":
  836. keepRule = !!$(val.depends, element.form).length;
  837. break;
  838. case "function":
  839. keepRule = val.depends.call(element, element);
  840. break;
  841. }
  842. if (keepRule) {
  843. rules[prop] = val.param !== undefined ? val.param : true;
  844. } else {
  845. delete rules[prop];
  846. }
  847. }
  848. });
  849. // evaluate parameters
  850. $.each(rules, function(rule, parameter) {
  851. rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
  852. });
  853. // clean number parameters
  854. $.each(['minlength', 'maxlength', 'min', 'max'], function() {
  855. if (rules[this]) {
  856. rules[this] = Number(rules[this]);
  857. }
  858. });
  859. $.each(['rangelength', 'range'], function() {
  860. if (rules[this]) {
  861. rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
  862. }
  863. });
  864. if ($.validator.autoCreateRanges) {
  865. // auto-create ranges
  866. if (rules.min && rules.max) {
  867. rules.range = [rules.min, rules.max];
  868. delete rules.min;
  869. delete rules.max;
  870. }
  871. if (rules.minlength && rules.maxlength) {
  872. rules.rangelength = [rules.minlength, rules.maxlength];
  873. delete rules.minlength;
  874. delete rules.maxlength;
  875. }
  876. }
  877. // To support custom messages in metadata ignore rule methods titled "messages"
  878. if (rules.messages) {
  879. delete rules.messages;
  880. }
  881. return rules;
  882. },
  883. // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
  884. normalizeRule: function(data) {
  885. if( typeof data == "string" ) {
  886. var transformed = {};
  887. $.each(data.split(/\s/), function() {
  888. transformed[this] = true;
  889. });
  890. data = transformed;
  891. }
  892. return data;
  893. },
  894. // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
  895. addMethod: function(name, method, message) {
  896. /// <summary>
  897. /// Add a custom validation method. It must consist of a name (must be a legal javascript
  898. /// identifier), a javascript based function and a default string message.
  899. /// </summary>
  900. /// <param name="name" type="String">
  901. /// The name of the method, used to identify and referencing it, must be a valid javascript
  902. /// identifier
  903. /// </param>
  904. /// <param name="method" type="Function">
  905. /// The actual method implementation, returning true if an element is valid
  906. /// </param>
  907. /// <param name="message" type="String" optional="true">
  908. /// (Optional) The default message to display for this method. Can be a function created by
  909. /// jQuery.validator.format(value). When undefined, an already existing message is used
  910. /// (handy for localization), otherwise the field-specific messages have to be defined.
  911. /// </param>
  912. /// <returns type="undefined" />
  913. $.validator.methods[name] = method;
  914. $.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
  915. if (method.length < 3) {
  916. $.validator.addClassRules(name, $.validator.normalizeRule(name));
  917. }
  918. },
  919. methods: {
  920. // http://docs.jquery.com/Plugins/Validation/Methods/required
  921. required: function(value, element, param) {
  922. // check if dependency is met
  923. if ( !this.depend(param, element) )
  924. return "dependency-mismatch";
  925. switch( element.nodeName.toLowerCase() ) {
  926. case 'select':
  927. // could be an array for select-multiple or a string, both are fine this way
  928. var val = $(element).val();
  929. return val && val.length > 0;
  930. case 'input':
  931. if ( this.checkable(element) )
  932. return this.getLength(value, element) > 0;
  933. default:
  934. return $.trim(value).length > 0;
  935. }
  936. },
  937. // http://docs.jquery.com/Plugins/Validation/Methods/remote
  938. remote: function(value, element, param) {
  939. if ( this.optional(element) )
  940. return "dependency-mismatch";
  941. var previous = this.previousValue(element);
  942. if (!this.settings.messages[element.name] )
  943. this.settings.messages[element.name] = {};
  944. previous.originalMessage = this.settings.messages[element.name].remote;
  945. this.settings.messages[element.name].remote = previous.message;
  946. param = typeof param == "string" && {url:param} || param;
  947. if ( this.pending[element.name] ) {
  948. return "pending";
  949. }
  950. if ( previous.old === value ) {
  951. return previous.valid;
  952. }
  953. previous.old = value;
  954. var validator = this;
  955. this.startRequest(element);
  956. var data = {};
  957. data[element.name] = value;
  958. $.ajax($.extend(true, {
  959. url: param,
  960. mode: "abort",
  961. port: "validate" + element.name,
  962. dataType: "json",
  963. data: data,
  964. success: function(response) {
  965. validator.settings.messages[element.name].remote = previous.originalMessage;
  966. var valid = response === true;
  967. if ( valid ) {
  968. var submitted = validator.formSubmitted;
  969. validator.prepareElement(element);
  970. validator.formSubmitted = submitted;
  971. validator.successList.push(element);
  972. validator.showErrors();
  973. } else {
  974. var errors = {};
  975. var message = response || validator.defaultMessage(element, "remote");
  976. errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
  977. validator.showErrors(errors);
  978. }
  979. previous.valid = valid;
  980. validator.stopRequest(element, valid);
  981. }
  982. }, param));
  983. return "pending";
  984. },
  985. // http://docs.jquery.com/Plugins/Validation/Methods/minlength
  986. minlength: function(value, element, param) {
  987. return this.optional(element) || this.getLength($.trim(value), element) >= param;
  988. },
  989. // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
  990. maxlength: function(value, element, param) {
  991. return this.optional(element) || this.getLength($.trim(value), element) <= param;
  992. },
  993. // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
  994. rangelength: function(value, element, param) {
  995. var length = this.getLength($.trim(value), element);
  996. return this.optional(element) || ( length >= param[0] && length <= param[1] );
  997. },
  998. // http://docs.jquery.com/Plugins/Validation/Methods/min
  999. min: function( value, element, param ) {
  1000. return this.optional(element) || value >= param;
  1001. },
  1002. // http://docs.jquery.com/Plugins/Validation/Methods/max
  1003. max: function( value, element, param ) {
  1004. return this.optional(element) || value <= param;
  1005. },
  1006. // http://docs.jquery.com/Plugins/Validation/Methods/range
  1007. range: function( value, element, param ) {
  1008. return this.optional(element) || ( value >= param[0] && value <= param[1] );
  1009. },
  1010. // http://docs.jquery.com/Plugins/Validation/Methods/email
  1011. email: function(value, element) {
  1012. // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
  1013. 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);
  1014. },
  1015. // http://docs.jquery.com/Plugins/Validation/Methods/url
  1016. url: function(value, element) {
  1017. // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
  1018. 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);
  1019. },
  1020. // http://docs.jquery.com/Plugins/Validation/Methods/date
  1021. date: function(value, element) {
  1022. return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
  1023. },
  1024. // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
  1025. dateISO: function(value, element) {
  1026. return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
  1027. },
  1028. // http://docs.jquery.com/Plugins/Validation/Methods/number
  1029. number: function(value, element) {
  1030. return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
  1031. },
  1032. // http://docs.jquery.com/Plugins/Validation/Methods/digits
  1033. digits: function(value, element) {
  1034. return this.optional(element) || /^\d+$/.test(value);
  1035. },
  1036. // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
  1037. // based on http://en.wikipedia.org/wiki/Luhn
  1038. creditcard: function(value, element) {
  1039. if ( this.optional(element) )
  1040. return "dependency-mismatch";
  1041. // accept only digits and dashes
  1042. if (/[^0-9-]+/.test(value))
  1043. return false;
  1044. var nCheck = 0,
  1045. nDigit = 0,
  1046. bEven = false;
  1047. value = value.replace(/\D/g, "");
  1048. for (var n = value.length - 1; n >= 0; n--) {
  1049. var cDigit = value.charAt(n);
  1050. var nDigit = parseInt(cDigit, 10);
  1051. if (bEven) {
  1052. if ((nDigit *= 2) > 9)
  1053. nDigit -= 9;
  1054. }
  1055. nCheck += nDigit;
  1056. bEven = !bEven;
  1057. }
  1058. return (nCheck % 10) == 0;
  1059. },
  1060. // http://docs.jquery.com/Plugins/Validation/Methods/accept
  1061. accept: function(value, element, param) {
  1062. param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
  1063. return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
  1064. },
  1065. // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
  1066. equalTo: function(value, element, param) {
  1067. // bind to the blur event of the target in order to revalidate whenever the target field is updated
  1068. // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
  1069. var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
  1070. $(element).valid();
  1071. });
  1072. return value == target.val();
  1073. }
  1074. }
  1075. });
  1076. // deprecated, use $.validator.format instead
  1077. $.format = $.validator.format;
  1078. })(jQuery);
  1079. // ajax mode: abort
  1080. // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
  1081. // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
  1082. ;(function($) {
  1083. var pendingRequests = {};
  1084. // Use a prefilter if available (1.5+)
  1085. if ( $.ajaxPrefilter ) {
  1086. $.ajaxPrefilter(function(settings, _, xhr) {
  1087. var port = settings.port;
  1088. if (settings.mode == "abort") {
  1089. if ( pendingRequests[port] ) {
  1090. pendingRequests[port].abort();
  1091. } pendingRequests[port] = xhr;
  1092. }
  1093. });
  1094. } else {
  1095. // Proxy ajax
  1096. var ajax = $.ajax;
  1097. $.ajax = function(settings) {
  1098. var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
  1099. port = ( "port" in settings ? settings : $.ajaxSettings ).port;
  1100. if (mode == "abort") {
  1101. if ( pendingRequests[port] ) {
  1102. pendingRequests[port].abort();
  1103. }
  1104. return (pendingRequests[port] = ajax.apply(this, arguments));
  1105. }
  1106. return ajax.apply(this, arguments);
  1107. };
  1108. }
  1109. })(jQuery);
  1110. // provides cross-browser focusin and focusout events
  1111. // IE has native support, in other browsers, use event caputuring (neither bubbles)
  1112. // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
  1113. // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
  1114. ;(function($) {
  1115. // only implement if not provided by jQuery core (since 1.4)
  1116. // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
  1117. if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
  1118. $.each({
  1119. focus: 'focusin',
  1120. blur: 'focusout'
  1121. }, function( original, fix ){
  1122. $.event.special[fix] = {
  1123. setup:function() {
  1124. this.addEventListener( original, handler, true );
  1125. },
  1126. teardown:function() {
  1127. this.removeEventListener( original, handler, true );
  1128. },
  1129. handler: function(e) {
  1130. arguments[0] = $.event.fix(e);
  1131. arguments[0].type = fix;
  1132. return $.event.handle.apply(this, arguments);
  1133. }
  1134. };
  1135. function handler(e) {
  1136. e = $.event.fix(e);
  1137. e.type = fix;
  1138. return $.event.handle.call(this, e);
  1139. }
  1140. });
  1141. };
  1142. $.extend($.fn, {
  1143. validateDelegate: function(delegate, type, handler) {
  1144. return this.bind(type, function(event) {
  1145. var target = $(event.target);
  1146. if (target.is(delegate)) {
  1147. return handler.apply(target, arguments);
  1148. }
  1149. });
  1150. }
  1151. });
  1152. })(jQuery);