PageRenderTime 55ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/files/parsleyjs/2.3.0/parsley.js

https://gitlab.com/Mirros/jsdelivr
JavaScript | 1337 lines | 879 code | 253 blank | 205 comment | 200 complexity | 9e1fd656ed99c6713e0561953d2aa64c MD5 | raw file
  1. /*!
  2. * Parsley.js
  3. * Version 2.3.0 - built Tue, Feb 9th 2016, 8:49 pm
  4. * http://parsleyjs.org
  5. * Guillaume Potier - <guillaume@wisembly.com>
  6. * Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
  7. * MIT Licensed
  8. */
  9. // The source code below is generated by babel as
  10. // Parsley is written in ECMAScript 6
  11. //
  12. var _slice = Array.prototype.slice;
  13. function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }
  14. (function (global, factory) {
  15. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) : typeof define === 'function' && define.amd ? define(['jquery'], factory) : global.parsley = factory(global.jQuery);
  16. })(this, function ($) {
  17. 'use strict';
  18. var globalID = 1;
  19. var pastWarnings = {};
  20. var ParsleyUtils__ParsleyUtils = {
  21. // Parsley DOM-API
  22. // returns object from dom attributes and values
  23. attr: function attr($element, namespace, obj) {
  24. var i;
  25. var attribute;
  26. var attributes;
  27. var regex = new RegExp('^' + namespace, 'i');
  28. if ('undefined' === typeof obj) obj = {};else {
  29. // Clear all own properties. This won't affect prototype's values
  30. for (i in obj) {
  31. if (obj.hasOwnProperty(i)) delete obj[i];
  32. }
  33. }
  34. if ('undefined' === typeof $element || 'undefined' === typeof $element[0]) return obj;
  35. attributes = $element[0].attributes;
  36. for (i = attributes.length; i--;) {
  37. attribute = attributes[i];
  38. if (attribute && attribute.specified && regex.test(attribute.name)) {
  39. obj[this.camelize(attribute.name.slice(namespace.length))] = this.deserializeValue(attribute.value);
  40. }
  41. }
  42. return obj;
  43. },
  44. checkAttr: function checkAttr($element, namespace, _checkAttr) {
  45. return $element.is('[' + namespace + _checkAttr + ']');
  46. },
  47. setAttr: function setAttr($element, namespace, attr, value) {
  48. $element[0].setAttribute(this.dasherize(namespace + attr), String(value));
  49. },
  50. generateID: function generateID() {
  51. return '' + globalID++;
  52. },
  53. /** Third party functions **/
  54. // Zepto deserialize function
  55. deserializeValue: function deserializeValue(value) {
  56. var num;
  57. try {
  58. return value ? value == "true" || (value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? $.parseJSON(value) : value) : value;
  59. } catch (e) {
  60. return value;
  61. }
  62. },
  63. // Zepto camelize function
  64. camelize: function camelize(str) {
  65. return str.replace(/-+(.)?/g, function (match, chr) {
  66. return chr ? chr.toUpperCase() : '';
  67. });
  68. },
  69. // Zepto dasherize function
  70. dasherize: function dasherize(str) {
  71. return str.replace(/::/g, '/').replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2').replace(/([a-z\d])([A-Z])/g, '$1_$2').replace(/_/g, '-').toLowerCase();
  72. },
  73. warn: function warn() {
  74. var _window$console;
  75. if (window.console && 'function' === typeof window.console.warn) (_window$console = window.console).warn.apply(_window$console, arguments);
  76. },
  77. warnOnce: function warnOnce(msg) {
  78. if (!pastWarnings[msg]) {
  79. pastWarnings[msg] = true;
  80. this.warn.apply(this, arguments);
  81. }
  82. },
  83. _resetWarnings: function _resetWarnings() {
  84. pastWarnings = {};
  85. },
  86. trimString: function trimString(string) {
  87. return string.replace(/^\s+|\s+$/g, '');
  88. },
  89. // Object.create polyfill, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Polyfill
  90. objectCreate: Object.create || (function () {
  91. var Object = function Object() {};
  92. return function (prototype) {
  93. if (arguments.length > 1) {
  94. throw Error('Second argument not supported');
  95. }
  96. if (typeof prototype != 'object') {
  97. throw TypeError('Argument must be an object');
  98. }
  99. Object.prototype = prototype;
  100. var result = new Object();
  101. Object.prototype = null;
  102. return result;
  103. };
  104. })()
  105. };
  106. var ParsleyUtils__default = ParsleyUtils__ParsleyUtils;
  107. // All these options could be overriden and specified directly in DOM using
  108. // `data-parsley-` default DOM-API
  109. // eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"`
  110. // eg: `data-parsley-stop-on-first-failing-constraint="false"`
  111. var ParsleyDefaults = {
  112. // ### General
  113. // Default data-namespace for DOM API
  114. namespace: 'data-parsley-',
  115. // Supported inputs by default
  116. inputs: 'input, textarea, select',
  117. // Excluded inputs by default
  118. excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden]',
  119. // Stop validating field on highest priority failing constraint
  120. priorityEnabled: true,
  121. // ### Field only
  122. // identifier used to group together inputs (e.g. radio buttons...)
  123. multiple: null,
  124. // identifier (or array of identifiers) used to validate only a select group of inputs
  125. group: null,
  126. // ### UI
  127. // Enable\Disable error messages
  128. uiEnabled: true,
  129. // Key events threshold before validation
  130. validationThreshold: 3,
  131. // Focused field on form validation error. 'first'|'last'|'none'
  132. focus: 'first',
  133. // `$.Event()` that will trigger validation. eg: `keyup`, `change`...
  134. trigger: false,
  135. // Class that would be added on every failing validation Parsley field
  136. errorClass: 'parsley-error',
  137. // Same for success validation
  138. successClass: 'parsley-success',
  139. // Return the `$element` that will receive these above success or error classes
  140. // Could also be (and given directly from DOM) a valid selector like `'#div'`
  141. classHandler: function classHandler(ParsleyField) {},
  142. // Return the `$element` where errors will be appended
  143. // Could also be (and given directly from DOM) a valid selector like `'#div'`
  144. errorsContainer: function errorsContainer(ParsleyField) {},
  145. // ul elem that would receive errors' list
  146. errorsWrapper: '<ul class="parsley-errors-list"></ul>',
  147. // li elem that would receive error message
  148. errorTemplate: '<li></li>'
  149. };
  150. var ParsleyAbstract = function ParsleyAbstract() {};
  151. ParsleyAbstract.prototype = {
  152. asyncSupport: true, // Deprecated
  153. actualizeOptions: function actualizeOptions() {
  154. ParsleyUtils__default.attr(this.$element, this.options.namespace, this.domOptions);
  155. if (this.parent && this.parent.actualizeOptions) this.parent.actualizeOptions();
  156. return this;
  157. },
  158. _resetOptions: function _resetOptions(initOptions) {
  159. this.domOptions = ParsleyUtils__default.objectCreate(this.parent.options);
  160. this.options = ParsleyUtils__default.objectCreate(this.domOptions);
  161. // Shallow copy of ownProperties of initOptions:
  162. for (var i in initOptions) {
  163. if (initOptions.hasOwnProperty(i)) this.options[i] = initOptions[i];
  164. }
  165. this.actualizeOptions();
  166. },
  167. _listeners: null,
  168. // Register a callback for the given event name
  169. // Callback is called with context as the first argument and the `this`
  170. // The context is the current parsley instance, or window.Parsley if global
  171. // A return value of `false` will interrupt the calls
  172. on: function on(name, fn) {
  173. this._listeners = this._listeners || {};
  174. var queue = this._listeners[name] = this._listeners[name] || [];
  175. queue.push(fn);
  176. return this;
  177. },
  178. // Deprecated. Use `on` instead
  179. subscribe: function subscribe(name, fn) {
  180. $.listenTo(this, name.toLowerCase(), fn);
  181. },
  182. // Unregister a callback (or all if none is given) for the given event name
  183. off: function off(name, fn) {
  184. var queue = this._listeners && this._listeners[name];
  185. if (queue) {
  186. if (!fn) {
  187. delete this._listeners[name];
  188. } else {
  189. for (var i = queue.length; i--;) if (queue[i] === fn) queue.splice(i, 1);
  190. }
  191. }
  192. return this;
  193. },
  194. // Deprecated. Use `off`
  195. unsubscribe: function unsubscribe(name, fn) {
  196. $.unsubscribeTo(this, name.toLowerCase());
  197. },
  198. // Trigger an event of the given name
  199. // A return value of `false` interrupts the callback chain
  200. // Returns false if execution was interrupted
  201. trigger: function trigger(name, target, extraArg) {
  202. target = target || this;
  203. var queue = this._listeners && this._listeners[name];
  204. var result;
  205. var parentResult;
  206. if (queue) {
  207. for (var i = queue.length; i--;) {
  208. result = queue[i].call(target, target, extraArg);
  209. if (result === false) return result;
  210. }
  211. }
  212. if (this.parent) {
  213. return this.parent.trigger(name, target, extraArg);
  214. }
  215. return true;
  216. },
  217. // Reset UI
  218. reset: function reset() {
  219. // Field case: just emit a reset event for UI
  220. if ('ParsleyForm' !== this.__class__) {
  221. this._resetUI();
  222. return this._trigger('reset');
  223. }
  224. // Form case: emit a reset event for each field
  225. for (var i = 0; i < this.fields.length; i++) this.fields[i].reset();
  226. this._trigger('reset');
  227. },
  228. // Destroy Parsley instance (+ UI)
  229. destroy: function destroy() {
  230. // Field case: emit destroy event to clean UI and then destroy stored instance
  231. this._destroyUI();
  232. if ('ParsleyForm' !== this.__class__) {
  233. this.$element.removeData('Parsley');
  234. this.$element.removeData('ParsleyFieldMultiple');
  235. this._trigger('destroy');
  236. return;
  237. }
  238. // Form case: destroy all its fields and then destroy stored instance
  239. for (var i = 0; i < this.fields.length; i++) this.fields[i].destroy();
  240. this.$element.removeData('Parsley');
  241. this._trigger('destroy');
  242. },
  243. asyncIsValid: function asyncIsValid(group, force) {
  244. ParsleyUtils__default.warnOnce("asyncIsValid is deprecated; please use whenValid instead");
  245. return this.whenValid({ group: group, force: force });
  246. },
  247. _findRelated: function _findRelated() {
  248. return this.options.multiple ? this.parent.$element.find('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]') : this.$element;
  249. }
  250. };
  251. var requirementConverters = {
  252. string: function string(_string) {
  253. return _string;
  254. },
  255. integer: function integer(string) {
  256. if (isNaN(string)) throw 'Requirement is not an integer: "' + string + '"';
  257. return parseInt(string, 10);
  258. },
  259. number: function number(string) {
  260. if (isNaN(string)) throw 'Requirement is not a number: "' + string + '"';
  261. return parseFloat(string);
  262. },
  263. reference: function reference(string) {
  264. // Unused for now
  265. var result = $(string);
  266. if (result.length === 0) throw 'No such reference: "' + string + '"';
  267. return result;
  268. },
  269. boolean: function boolean(string) {
  270. return string !== 'false';
  271. },
  272. object: function object(string) {
  273. return ParsleyUtils__default.deserializeValue(string);
  274. },
  275. regexp: function regexp(_regexp) {
  276. var flags = '';
  277. // Test if RegExp is literal, if not, nothing to be done, otherwise, we need to isolate flags and pattern
  278. if (/^\/.*\/(?:[gimy]*)$/.test(_regexp)) {
  279. // Replace the regexp literal string with the first match group: ([gimy]*)
  280. // If no flag is present, this will be a blank string
  281. flags = _regexp.replace(/.*\/([gimy]*)$/, '$1');
  282. // Again, replace the regexp literal string with the first match group:
  283. // everything excluding the opening and closing slashes and the flags
  284. _regexp = _regexp.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
  285. } else {
  286. // Anchor regexp:
  287. _regexp = '^' + _regexp + '$';
  288. }
  289. return new RegExp(_regexp, flags);
  290. }
  291. };
  292. var convertArrayRequirement = function convertArrayRequirement(string, length) {
  293. var m = string.match(/^\s*\[(.*)\]\s*$/);
  294. if (!m) throw 'Requirement is not an array: "' + string + '"';
  295. var values = m[1].split(',').map(ParsleyUtils__default.trimString);
  296. if (values.length !== length) throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed';
  297. return values;
  298. };
  299. var convertRequirement = function convertRequirement(requirementType, string) {
  300. var converter = requirementConverters[requirementType || 'string'];
  301. if (!converter) throw 'Unknown requirement specification: "' + requirementType + '"';
  302. return converter(string);
  303. };
  304. var convertExtraOptionRequirement = function convertExtraOptionRequirement(requirementSpec, string, extraOptionReader) {
  305. var main = null;
  306. var extra = {};
  307. for (var key in requirementSpec) {
  308. if (key) {
  309. var value = extraOptionReader(key);
  310. if ('string' === typeof value) value = convertRequirement(requirementSpec[key], value);
  311. extra[key] = value;
  312. } else {
  313. main = convertRequirement(requirementSpec[key], string);
  314. }
  315. }
  316. return [main, extra];
  317. };
  318. // A Validator needs to implement the methods `validate` and `parseRequirements`
  319. var ParsleyValidator = function ParsleyValidator(spec) {
  320. $.extend(true, this, spec);
  321. };
  322. ParsleyValidator.prototype = {
  323. // Returns `true` iff the given `value` is valid according the given requirements.
  324. validate: function validate(value, requirementFirstArg) {
  325. if (this.fn) {
  326. // Legacy style validator
  327. if (arguments.length > 3) // If more args then value, requirement, instance...
  328. requirementFirstArg = [].slice.call(arguments, 1, -1); // Skip first arg (value) and last (instance), combining the rest
  329. return this.fn.call(this, value, requirementFirstArg);
  330. }
  331. if ($.isArray(value)) {
  332. if (!this.validateMultiple) throw 'Validator `' + this.name + '` does not handle multiple values';
  333. return this.validateMultiple.apply(this, arguments);
  334. } else {
  335. if (this.validateNumber) {
  336. if (isNaN(value)) return false;
  337. arguments[0] = parseFloat(arguments[0]);
  338. return this.validateNumber.apply(this, arguments);
  339. }
  340. if (this.validateString) {
  341. return this.validateString.apply(this, arguments);
  342. }
  343. throw 'Validator `' + this.name + '` only handles multiple values';
  344. }
  345. },
  346. // Parses `requirements` into an array of arguments,
  347. // according to `this.requirementType`
  348. parseRequirements: function parseRequirements(requirements, extraOptionReader) {
  349. if ('string' !== typeof requirements) {
  350. // Assume requirement already parsed
  351. // but make sure we return an array
  352. return $.isArray(requirements) ? requirements : [requirements];
  353. }
  354. var type = this.requirementType;
  355. if ($.isArray(type)) {
  356. var values = convertArrayRequirement(requirements, type.length);
  357. for (var i = 0; i < values.length; i++) values[i] = convertRequirement(type[i], values[i]);
  358. return values;
  359. } else if ($.isPlainObject(type)) {
  360. return convertExtraOptionRequirement(type, requirements, extraOptionReader);
  361. } else {
  362. return [convertRequirement(type, requirements)];
  363. }
  364. },
  365. // Defaults:
  366. requirementType: 'string',
  367. priority: 2
  368. };
  369. var ParsleyValidatorRegistry = function ParsleyValidatorRegistry(validators, catalog) {
  370. this.__class__ = 'ParsleyValidatorRegistry';
  371. // Default Parsley locale is en
  372. this.locale = 'en';
  373. this.init(validators || {}, catalog || {});
  374. };
  375. var typeRegexes = {
  376. email: /^((([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,
  377. // Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
  378. number: /^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,
  379. integer: /^-?\d+$/,
  380. digits: /^\d+$/,
  381. alphanum: /^\w+$/i,
  382. url: new RegExp("^" +
  383. // protocol identifier
  384. "(?:(?:https?|ftp)://)?" + // ** mod: make scheme optional
  385. // user:pass authentication
  386. "(?:\\S+(?::\\S*)?@)?" + "(?:" +
  387. // IP address exclusion
  388. // private & local networks
  389. // "(?!(?:10|127)(?:\\.\\d{1,3}){3})" + // ** mod: allow local networks
  390. // "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" + // ** mod: allow local networks
  391. // "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + // ** mod: allow local networks
  392. // IP address dotted notation octets
  393. // excludes loopback network 0.0.0.0
  394. // excludes reserved space >= 224.0.0.0
  395. // excludes network & broacast addresses
  396. // (first & last IP address of each class)
  397. "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + "|" +
  398. // host name
  399. '(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)' +
  400. // domain name
  401. '(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*' +
  402. // TLD identifier
  403. '(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))' + ")" +
  404. // port number
  405. "(?::\\d{2,5})?" +
  406. // resource path
  407. "(?:/\\S*)?" + "$", 'i')
  408. };
  409. typeRegexes.range = typeRegexes.number;
  410. // See http://stackoverflow.com/a/10454560/8279
  411. var decimalPlaces = function decimalPlaces(num) {
  412. var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
  413. if (!match) {
  414. return 0;
  415. }
  416. return Math.max(0,
  417. // Number of digits right of decimal point.
  418. (match[1] ? match[1].length : 0) - (
  419. // Adjust for scientific notation.
  420. match[2] ? +match[2] : 0));
  421. };
  422. ParsleyValidatorRegistry.prototype = {
  423. init: function init(validators, catalog) {
  424. this.catalog = catalog;
  425. // Copy prototype's validators:
  426. this.validators = $.extend({}, this.validators);
  427. for (var name in validators) this.addValidator(name, validators[name].fn, validators[name].priority);
  428. window.Parsley.trigger('parsley:validator:init');
  429. },
  430. // Set new messages locale if we have dictionary loaded in ParsleyConfig.i18n
  431. setLocale: function setLocale(locale) {
  432. if ('undefined' === typeof this.catalog[locale]) throw new Error(locale + ' is not available in the catalog');
  433. this.locale = locale;
  434. return this;
  435. },
  436. // Add a new messages catalog for a given locale. Set locale for this catalog if set === `true`
  437. addCatalog: function addCatalog(locale, messages, set) {
  438. if ('object' === typeof messages) this.catalog[locale] = messages;
  439. if (true === set) return this.setLocale(locale);
  440. return this;
  441. },
  442. // Add a specific message for a given constraint in a given locale
  443. addMessage: function addMessage(locale, name, message) {
  444. if ('undefined' === typeof this.catalog[locale]) this.catalog[locale] = {};
  445. this.catalog[locale][name] = message;
  446. return this;
  447. },
  448. // Add messages for a given locale
  449. addMessages: function addMessages(locale, nameMessageObject) {
  450. for (var name in nameMessageObject) this.addMessage(locale, name, nameMessageObject[name]);
  451. return this;
  452. },
  453. // Add a new validator
  454. //
  455. // addValidator('custom', {
  456. // requirementType: ['integer', 'integer'],
  457. // validateString: function(value, from, to) {},
  458. // priority: 22,
  459. // messages: {
  460. // en: "Hey, that's no good",
  461. // fr: "Aye aye, pas bon du tout",
  462. // }
  463. // })
  464. //
  465. // Old API was addValidator(name, function, priority)
  466. //
  467. addValidator: function addValidator(name, arg1, arg2) {
  468. if (this.validators[name]) ParsleyUtils__default.warn('Validator "' + name + '" is already defined.');else if (ParsleyDefaults.hasOwnProperty(name)) {
  469. ParsleyUtils__default.warn('"' + name + '" is a restricted keyword and is not a valid validator name.');
  470. return;
  471. }
  472. return this._setValidator.apply(this, arguments);
  473. },
  474. updateValidator: function updateValidator(name, arg1, arg2) {
  475. if (!this.validators[name]) {
  476. ParsleyUtils__default.warn('Validator "' + name + '" is not already defined.');
  477. return this.addValidator.apply(this, arguments);
  478. }
  479. return this._setValidator(this, arguments);
  480. },
  481. removeValidator: function removeValidator(name) {
  482. if (!this.validators[name]) ParsleyUtils__default.warn('Validator "' + name + '" is not defined.');
  483. delete this.validators[name];
  484. return this;
  485. },
  486. _setValidator: function _setValidator(name, validator, priority) {
  487. if ('object' !== typeof validator) {
  488. // Old style validator, with `fn` and `priority`
  489. validator = {
  490. fn: validator,
  491. priority: priority
  492. };
  493. }
  494. if (!validator.validate) {
  495. validator = new ParsleyValidator(validator);
  496. }
  497. this.validators[name] = validator;
  498. for (var locale in validator.messages || {}) this.addMessage(locale, name, validator.messages[locale]);
  499. return this;
  500. },
  501. getErrorMessage: function getErrorMessage(constraint) {
  502. var message;
  503. // Type constraints are a bit different, we have to match their requirements too to find right error message
  504. if ('type' === constraint.name) {
  505. var typeMessages = this.catalog[this.locale][constraint.name] || {};
  506. message = typeMessages[constraint.requirements];
  507. } else message = this.formatMessage(this.catalog[this.locale][constraint.name], constraint.requirements);
  508. return message || this.catalog[this.locale].defaultMessage || this.catalog.en.defaultMessage;
  509. },
  510. // Kind of light `sprintf()` implementation
  511. formatMessage: function formatMessage(string, parameters) {
  512. if ('object' === typeof parameters) {
  513. for (var i in parameters) string = this.formatMessage(string, parameters[i]);
  514. return string;
  515. }
  516. return 'string' === typeof string ? string.replace(/%s/i, parameters) : '';
  517. },
  518. // Here is the Parsley default validators list.
  519. // A validator is an object with the following key values:
  520. // - priority: an integer
  521. // - requirement: 'string' (default), 'integer', 'number', 'regexp' or an Array of these
  522. // - validateString, validateMultiple, validateNumber: functions returning `true`, `false` or a promise
  523. // Alternatively, a validator can be a function that returns such an object
  524. //
  525. validators: {
  526. notblank: {
  527. validateString: function validateString(value) {
  528. return (/\S/.test(value)
  529. );
  530. },
  531. priority: 2
  532. },
  533. required: {
  534. validateMultiple: function validateMultiple(values) {
  535. return values.length > 0;
  536. },
  537. validateString: function validateString(value) {
  538. return (/\S/.test(value)
  539. );
  540. },
  541. priority: 512
  542. },
  543. type: {
  544. validateString: function validateString(value, type) {
  545. var _ref = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
  546. var _ref$step = _ref.step;
  547. var step = _ref$step === undefined ? '1' : _ref$step;
  548. var _ref$base = _ref.base;
  549. var base = _ref$base === undefined ? 0 : _ref$base;
  550. var regex = typeRegexes[type];
  551. if (!regex) {
  552. throw new Error('validator type `' + type + '` is not supported');
  553. }
  554. if (!regex.test(value)) return false;
  555. if ('number' === type) {
  556. if (!/^any$/i.test(step || '')) {
  557. var nb = Number(value);
  558. var decimals = Math.max(decimalPlaces(step), decimalPlaces(base));
  559. if (decimalPlaces(nb) > decimals) // Value can't have too many decimals
  560. return false;
  561. // Be careful of rounding errors by using integers.
  562. var toInt = function toInt(f) {
  563. return Math.round(f * Math.pow(10, decimals));
  564. };
  565. if ((toInt(nb) - toInt(base)) % toInt(step) != 0) return false;
  566. }
  567. }
  568. return true;
  569. },
  570. requirementType: {
  571. '': 'string',
  572. step: 'string',
  573. base: 'number'
  574. },
  575. priority: 256
  576. },
  577. pattern: {
  578. validateString: function validateString(value, regexp) {
  579. return regexp.test(value);
  580. },
  581. requirementType: 'regexp',
  582. priority: 64
  583. },
  584. minlength: {
  585. validateString: function validateString(value, requirement) {
  586. return value.length >= requirement;
  587. },
  588. requirementType: 'integer',
  589. priority: 30
  590. },
  591. maxlength: {
  592. validateString: function validateString(value, requirement) {
  593. return value.length <= requirement;
  594. },
  595. requirementType: 'integer',
  596. priority: 30
  597. },
  598. length: {
  599. validateString: function validateString(value, min, max) {
  600. return value.length >= min && value.length <= max;
  601. },
  602. requirementType: ['integer', 'integer'],
  603. priority: 30
  604. },
  605. mincheck: {
  606. validateMultiple: function validateMultiple(values, requirement) {
  607. return values.length >= requirement;
  608. },
  609. requirementType: 'integer',
  610. priority: 30
  611. },
  612. maxcheck: {
  613. validateMultiple: function validateMultiple(values, requirement) {
  614. return values.length <= requirement;
  615. },
  616. requirementType: 'integer',
  617. priority: 30
  618. },
  619. check: {
  620. validateMultiple: function validateMultiple(values, min, max) {
  621. return values.length >= min && values.length <= max;
  622. },
  623. requirementType: ['integer', 'integer'],
  624. priority: 30
  625. },
  626. min: {
  627. validateNumber: function validateNumber(value, requirement) {
  628. return value >= requirement;
  629. },
  630. requirementType: 'number',
  631. priority: 30
  632. },
  633. max: {
  634. validateNumber: function validateNumber(value, requirement) {
  635. return value <= requirement;
  636. },
  637. requirementType: 'number',
  638. priority: 30
  639. },
  640. range: {
  641. validateNumber: function validateNumber(value, min, max) {
  642. return value >= min && value <= max;
  643. },
  644. requirementType: ['number', 'number'],
  645. priority: 30
  646. },
  647. equalto: {
  648. validateString: function validateString(value, refOrValue) {
  649. var $reference = $(refOrValue);
  650. if ($reference.length) return value === $reference.val();else return value === refOrValue;
  651. },
  652. priority: 256
  653. }
  654. }
  655. };
  656. var ParsleyUI = {};
  657. var diffResults = function diffResults(newResult, oldResult, deep) {
  658. var added = [];
  659. var kept = [];
  660. for (var i = 0; i < newResult.length; i++) {
  661. var found = false;
  662. for (var j = 0; j < oldResult.length; j++) if (newResult[i].assert.name === oldResult[j].assert.name) {
  663. found = true;
  664. break;
  665. }
  666. if (found) kept.push(newResult[i]);else added.push(newResult[i]);
  667. }
  668. return {
  669. kept: kept,
  670. added: added,
  671. removed: !deep ? diffResults(oldResult, newResult, true).added : []
  672. };
  673. };
  674. ParsleyUI.Form = {
  675. _actualizeTriggers: function _actualizeTriggers() {
  676. var _this = this;
  677. this.$element.on('submit.Parsley', function (evt) {
  678. _this.onSubmitValidate(evt);
  679. });
  680. this.$element.on('click.Parsley', 'input[type="submit"], button[type="submit"]', function (evt) {
  681. _this.onSubmitButton(evt);
  682. });
  683. // UI could be disabled
  684. if (false === this.options.uiEnabled) return;
  685. this.$element.attr('novalidate', '');
  686. },
  687. focus: function focus() {
  688. this._focusedField = null;
  689. if (true === this.validationResult || 'none' === this.options.focus) return null;
  690. for (var i = 0; i < this.fields.length; i++) {
  691. var field = this.fields[i];
  692. if (true !== field.validationResult && field.validationResult.length > 0 && 'undefined' === typeof field.options.noFocus) {
  693. this._focusedField = field.$element;
  694. if ('first' === this.options.focus) break;
  695. }
  696. }
  697. if (null === this._focusedField) return null;
  698. return this._focusedField.focus();
  699. },
  700. _destroyUI: function _destroyUI() {
  701. // Reset all event listeners
  702. this.$element.off('.Parsley');
  703. }
  704. };
  705. ParsleyUI.Field = {
  706. _reflowUI: function _reflowUI() {
  707. this._buildUI();
  708. // If this field doesn't have an active UI don't bother doing something
  709. if (!this._ui) return;
  710. // Diff between two validation results
  711. var diff = diffResults(this.validationResult, this._ui.lastValidationResult);
  712. // Then store current validation result for next reflow
  713. this._ui.lastValidationResult = this.validationResult;
  714. // Handle valid / invalid / none field class
  715. this._manageStatusClass();
  716. // Add, remove, updated errors messages
  717. this._manageErrorsMessages(diff);
  718. // Triggers impl
  719. this._actualizeTriggers();
  720. // If field is not valid for the first time, bind keyup trigger to ease UX and quickly inform user
  721. if ((diff.kept.length || diff.added.length) && true !== this._failedOnce) this._manageFailingFieldTrigger();
  722. },
  723. // Returns an array of field's error message(s)
  724. getErrorsMessages: function getErrorsMessages() {
  725. // No error message, field is valid
  726. if (true === this.validationResult) return [];
  727. var messages = [];
  728. for (var i = 0; i < this.validationResult.length; i++) messages.push(this.validationResult[i].errorMessage || this._getErrorMessage(this.validationResult[i].assert));
  729. return messages;
  730. },
  731. _manageStatusClass: function _manageStatusClass() {
  732. if (this.hasConstraints() && this.needsValidation() && true === this.validationResult) this._successClass();else if (this.validationResult.length > 0) this._errorClass();else this._resetClass();
  733. },
  734. _manageErrorsMessages: function _manageErrorsMessages(diff) {
  735. if ('undefined' !== typeof this.options.errorsMessagesDisabled) return;
  736. // Case where we have errorMessage option that configure an unique field error message, regardless failing validators
  737. if ('undefined' !== typeof this.options.errorMessage) {
  738. if (diff.added.length || diff.kept.length) {
  739. this._insertErrorWrapper();
  740. if (0 === this._ui.$errorsWrapper.find('.parsley-custom-error-message').length) this._ui.$errorsWrapper.append($(this.options.errorTemplate).addClass('parsley-custom-error-message'));
  741. return this._ui.$errorsWrapper.addClass('filled').find('.parsley-custom-error-message').html(this.options.errorMessage);
  742. }
  743. return this._ui.$errorsWrapper.removeClass('filled').find('.parsley-custom-error-message').remove();
  744. }
  745. // Show, hide, update failing constraints messages
  746. for (var i = 0; i < diff.removed.length; i++) this.removeError(diff.removed[i].assert.name, { updateClass: false });
  747. for (i = 0; i < diff.added.length; i++) this.addError(diff.added[i].assert.name, { message: diff.added[i].errorMessage, assert: diff.added[i].assert, updateClass: false });
  748. for (i = 0; i < diff.kept.length; i++) this.updateError(diff.kept[i].assert.name, { message: diff.kept[i].errorMessage, assert: diff.kept[i].assert, updateClass: false });
  749. },
  750. // TODO: strange API here, intuitive for manual usage with addError(pslyInstance, 'foo', 'bar')
  751. // but a little bit complex for above internal usage, with forced undefined parameter...
  752. addError: function addError(name) {
  753. var _ref2 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  754. var message = _ref2.message;
  755. var assert = _ref2.assert;
  756. var _ref2$updateClass = _ref2.updateClass;
  757. var updateClass = _ref2$updateClass === undefined ? true : _ref2$updateClass;
  758. this._insertErrorWrapper();
  759. this._ui.$errorsWrapper.addClass('filled').append($(this.options.errorTemplate).addClass('parsley-' + name).html(message || this._getErrorMessage(assert)));
  760. if (updateClass) this._errorClass();
  761. },
  762. // Same as above
  763. updateError: function updateError(name) {
  764. var _ref3 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  765. var message = _ref3.message;
  766. var assert = _ref3.assert;
  767. var _ref3$updateClass = _ref3.updateClass;
  768. var updateClass = _ref3$updateClass === undefined ? true : _ref3$updateClass;
  769. this._ui.$errorsWrapper.addClass('filled').find('.parsley-' + name).html(message || this._getErrorMessage(assert));
  770. if (updateClass) this._errorClass();
  771. },
  772. // Same as above twice
  773. removeError: function removeError(name) {
  774. var _ref4 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  775. var _ref4$updateClass = _ref4.updateClass;
  776. var updateClass = _ref4$updateClass === undefined ? true : _ref4$updateClass;
  777. this._ui.$errorsWrapper.removeClass('filled').find('.parsley-' + name).remove();
  778. // edge case possible here: remove a standard Parsley error that is still failing in this.validationResult
  779. // but highly improbable cuz' manually removing a well Parsley handled error makes no sense.
  780. if (updateClass) this._manageStatusClass();
  781. },
  782. _getErrorMessage: function _getErrorMessage(constraint) {
  783. var customConstraintErrorMessage = constraint.name + 'Message';
  784. if ('undefined' !== typeof this.options[customConstraintErrorMessage]) return window.Parsley.formatMessage(this.options[customConstraintErrorMessage], constraint.requirements);
  785. return window.Parsley.getErrorMessage(constraint);
  786. },
  787. _buildUI: function _buildUI() {
  788. // UI could be already built or disabled
  789. if (this._ui || false === this.options.uiEnabled) return;
  790. var _ui = {};
  791. // Give field its Parsley id in DOM
  792. this.$element.attr(this.options.namespace + 'id', this.__id__);
  793. /** Generate important UI elements and store them in this **/
  794. // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes
  795. _ui.$errorClassHandler = this._manageClassHandler();
  796. // $errorsWrapper is a div that would contain the various field errors, it will be appended into $errorsContainer
  797. _ui.errorsWrapperId = 'parsley-id-' + (this.options.multiple ? 'multiple-' + this.options.multiple : this.__id__);
  798. _ui.$errorsWrapper = $(this.options.errorsWrapper).attr('id', _ui.errorsWrapperId);
  799. // ValidationResult UI storage to detect what have changed bwt two validations, and update DOM accordingly
  800. _ui.lastValidationResult = [];
  801. _ui.validationInformationVisible = false;
  802. // Store it in this for later
  803. this._ui = _ui;
  804. },
  805. // Determine which element will have `parsley-error` and `parsley-success` classes
  806. _manageClassHandler: function _manageClassHandler() {
  807. // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
  808. if ('string' === typeof this.options.classHandler && $(this.options.classHandler).length) return $(this.options.classHandler);
  809. // Class handled could also be determined by function given in Parsley options
  810. var $handler = this.options.classHandler();
  811. // If this function returned a valid existing DOM element, go for it
  812. if ('undefined' !== typeof $handler && $handler.length) return $handler;
  813. // Otherwise, if simple element (input, texatrea, select...) it will perfectly host the classes
  814. if (!this.options.multiple || this.$element.is('select')) return this.$element;
  815. // But if multiple element (radio, checkbox), that would be their parent
  816. return this.$element.parent();
  817. },
  818. _insertErrorWrapper: function _insertErrorWrapper() {
  819. var $errorsContainer;
  820. // Nothing to do if already inserted
  821. if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
  822. if ('string' === typeof this.options.errorsContainer) {
  823. if ($(this.options.errorsContainer).length) return $(this.options.errorsContainer).append(this._ui.$errorsWrapper);else ParsleyUtils__default.warn('The errors container `' + this.options.errorsContainer + '` does not exist in DOM');
  824. } else if ('function' === typeof this.options.errorsContainer) $errorsContainer = this.options.errorsContainer();
  825. if ('undefined' !== typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
  826. var $from = this.$element;
  827. if (this.options.multiple) $from = $from.parent();
  828. return $from.after(this._ui.$errorsWrapper);
  829. },
  830. _actualizeTriggers: function _actualizeTriggers() {
  831. var _this2 = this;
  832. var $toBind = this._findRelated();
  833. // Remove Parsley events already bound on this field
  834. $toBind.off('.Parsley');
  835. if (this._failedOnce) $toBind.on('input.ParsleyFailedOnce', function () {
  836. _this2.validate();
  837. });else {
  838. $toBind.off('.ParsleyFailedOnce');
  839. var triggers = this.options.trigger && this.options.trigger.replace(/^\s+/g, '').replace(/\s+$/g, '');
  840. // If no trigger is set, all good
  841. if (!triggers) return;
  842. $toBind.on(triggers.split(' ').join('.Parsley ') + '.Parsley', function (event) {
  843. _this2._eventValidate(event);
  844. });
  845. }
  846. },
  847. _eventValidate: function _eventValidate(event) {
  848. // For keyup, keypress, keydown... events that could be a little bit obstrusive
  849. // do not validate if val length < min threshold on first validation. Once field have been validated once and info
  850. // about success or failure have been displayed, always validate with this trigger to reflect every yalidation change.
  851. if (/key/.test(event.type)) if (!(this._ui && field._ui.validationInformationVisible) && this.getValue().length <= this.options.validationThreshold) return;
  852. this.validate();
  853. },
  854. _manageFailingFieldTrigger: function _manageFailingFieldTrigger() {
  855. var _this3 = this;
  856. this._failedOnce = true;
  857. this._actualizeTriggers();
  858. this._findRelated().on('input.ParsleyFailedOnce', function () {
  859. _this3.validate();
  860. });
  861. },
  862. _resetUI: function _resetUI() {
  863. // Reset all event listeners
  864. this._failedOnce = false;
  865. this._actualizeTriggers();
  866. // Nothing to do if UI never initialized for this field
  867. if ('undefined' === typeof this._ui) return;
  868. // Reset all errors' li
  869. this._ui.$errorsWrapper.removeClass('filled').children().remove();
  870. // Reset validation class
  871. this._resetClass();
  872. // Reset validation flags and last validation result
  873. this._ui.lastValidationResult = [];
  874. this._ui.validationInformationVisible = false;
  875. },
  876. _destroyUI: function _destroyUI() {
  877. this._resetUI();
  878. if ('undefined' !== typeof this._ui) this._ui.$errorsWrapper.remove();
  879. delete this._ui;
  880. },
  881. _successClass: function _successClass() {
  882. this._ui.validationInformationVisible = true;
  883. this._ui.$errorClassHandler.removeClass(this.options.errorClass).addClass(this.options.successClass);
  884. },
  885. _errorClass: function _errorClass() {
  886. this._ui.validationInformationVisible = true;
  887. this._ui.$errorClassHandler.removeClass(this.options.successClass).addClass(this.options.errorClass);
  888. },
  889. _resetClass: function _resetClass() {
  890. this._ui.$errorClassHandler.removeClass(this.options.successClass).removeClass(this.options.errorClass);
  891. }
  892. };
  893. var ParsleyForm = function ParsleyForm(element, domOptions, options) {
  894. this.__class__ = 'ParsleyForm';
  895. this.__id__ = ParsleyUtils__default.generateID();
  896. this.$element = $(element);
  897. this.domOptions = domOptions;
  898. this.options = options;
  899. this.parent = window.Parsley;
  900. this.fields = [];
  901. this.validationResult = null;
  902. };
  903. var ParsleyForm__statusMapping = { pending: null, resolved: true, rejected: false };
  904. ParsleyForm.prototype = {
  905. onSubmitValidate: function onSubmitValidate(event) {
  906. var _this4 = this;
  907. // This is a Parsley generated submit event, do not validate, do not prevent, simply exit and keep normal behavior
  908. if (true === event.parsley) return;
  909. // If we didn't come here through a submit button, use the first one in the form
  910. var $submitSource = this._$submitSource || this.$element.find('input[type="submit"], button[type="submit"]').first();
  911. this._$submitSource = null;
  912. this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true);
  913. if ($submitSource.is('[formnovalidate]')) return;
  914. var promise = this.whenValidate({ event: event });
  915. if ('resolved' === promise.state() && false !== this._trigger('submit')) {
  916. // All good, let event go through. We make this distinction because browsers
  917. // differ in their handling of `submit` being called from inside a submit event [#1047]
  918. } else {
  919. // Rejected or pending: cancel this submit
  920. event.stopImmediatePropagation();
  921. event.preventDefault();
  922. if ('pending' === promise.state()) promise.done(function () {
  923. _this4._submit($submitSource);
  924. });
  925. }
  926. },
  927. onSubmitButton: function onSubmitButton(event) {
  928. this._$submitSource = $(event.target);
  929. },
  930. // internal
  931. // _submit submits the form, this time without going through the validations.
  932. // Care must be taken to "fake" the actual submit button being clicked.
  933. _submit: function _submit($submitSource) {
  934. if (false === this._trigger('submit')) return;
  935. // Add submit button's data
  936. if ($submitSource) {
  937. var $synthetic = this.$element.find('.parsley-synthetic-submit-button').prop('disabled', false);
  938. if (0 === $synthetic.length) $synthetic = $('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element);
  939. $synthetic.attr({
  940. name: $submitSource.attr('name'),
  941. value: $submitSource.attr('value')
  942. });
  943. }
  944. this.$element.trigger($.extend($.Event('submit'), { parsley: true }));
  945. },
  946. // Performs validation on fields while triggering events.
  947. // @returns `true` if all validations succeeds, `false`
  948. // if a failure is immediately detected, or `null`
  949. // if dependant on a promise.
  950. // Consider using `whenValidate` instead.
  951. validate: function validate(options) {
  952. if (arguments.length >= 1 && !$.isPlainObject(options)) {
  953. ParsleyUtils__default.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.');
  954. var _arguments = _slice.call(arguments);
  955. var group = _arguments[0];
  956. var force = _arguments[1];
  957. var event = _arguments[2];
  958. options = { group: group, force: force, event: event };
  959. }
  960. return ParsleyForm__statusMapping[this.whenValidate(options).state()];
  961. },
  962. whenValidate: function whenValidate() {
  963. var _this5 = this;
  964. var _ref5 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  965. var group = _ref5.group;
  966. var force = _ref5.force;
  967. var event = _ref5.event;
  968. this.submitEvent = event;
  969. if (event) {
  970. this.submitEvent = $.extend({}, event, { preventDefault: function preventDefault() {
  971. ParsleyUtils__default.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`");
  972. _this5.validationResult = false;
  973. } });
  974. }
  975. this.validationResult = true;
  976. // fire validate event to eventually modify things before very validation
  977. this._trigger('validate');
  978. // Refresh form DOM options and form's fields that could have changed
  979. this._refreshFields();
  980. var promises = this._withoutReactualizingFormOptions(function () {
  981. return $.map(_this5.fields, function (field) {
  982. return field.whenValidate({ force: force, group: group });
  983. });
  984. });
  985. var promiseBasedOnValidationResult = function promiseBasedOnValidationResult() {
  986. var r = $.Deferred();
  987. if (false === _this5.validationResult) r.reject();
  988. return r.resolve().promise();
  989. };
  990. return $.when.apply($, _toConsumableArray(promises)).done(function () {
  991. _this5._trigger('success');
  992. }).fail(function () {
  993. _this5.validationResult = false;
  994. _this5.focus();
  995. _this5._trigger('error');
  996. }).always(function () {
  997. _this5._trigger('validated');
  998. }).pipe(promiseBasedOnValidationResult, promiseBasedOnValidationResult);
  999. },
  1000. // Iterate over refreshed fields, and stop on first failure.
  1001. // Returns `true` if all fields are valid, `false` if a failure is detected
  1002. // or `null` if the result depends on an unresolved promise.
  1003. // Prefer using `whenValid` instead.
  1004. isValid: function isValid(options) {
  1005. if (arguments.length >= 1 && !$.isPlainObject(options)) {
  1006. ParsleyUtils__default.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.');
  1007. var _arguments2 = _slice.call(arguments);
  1008. var group = _arguments2[0];
  1009. var force = _arguments2[1];
  1010. options = { group: group, force: force };
  1011. }
  1012. return ParsleyForm__statusMapping[this.whenValid(options).state()];
  1013. },
  1014. // Iterate over refreshed fields and validate them.
  1015. // Returns a promise.
  1016. // A validation that immediately fails will interrupt the validations.
  1017. whenValid: function whenValid() {
  1018. var _this6 = this;
  1019. var _ref6 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  1020. var group = _ref6.group;
  1021. var force = _ref6.force;
  1022. this._refreshFields();
  1023. var promises = this._withoutReactualizingFormOptions(function () {
  1024. return $.map(_this6.fields, function (field) {
  1025. return field.whenValid({ group: group, force: force });
  1026. });
  1027. });
  1028. return $.when.apply($, _toConsumableArray(promises));
  1029. },
  1030. _refreshFields: function _refreshFields() {
  1031. return this.actualizeOptions()._bindFields();
  1032. },
  1033. _bindFields: function _bindFields() {
  1034. var _this7 = this;
  1035. var oldFields = this.fields;
  1036. this.fields = [];
  1037. this.fieldsMappedById = {};
  1038. this._withoutReactualizingFormOptions(function () {
  1039. _this7.$element.find(_this7.options.inputs).not(_this7.options.excluded).each(function (_, element) {
  1040. var fieldInstance = new window.Parsley.Factory(element, {}, _this7);
  1041. // Only add valid and not excluded `ParsleyField` and `ParsleyFieldMultiple` children
  1042. if (('ParsleyField' === fieldInstance.__class__ || 'ParsleyFieldMultiple' === fieldInstance.__class__) && true !== fieldInstance.options.excluded) if ('undefined' === typeof _this7.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__]) {
  1043. _this7.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__] = fieldInstance;
  1044. _this7.fields.push(fieldInstance);
  1045. }
  1046. });
  1047. $(oldFields).not(_this7.fields).each(function (_, field) {
  1048. field._trigger('reset');
  1049. });
  1050. });
  1051. return this;
  1052. },
  1053. // Internal only.
  1054. // Looping on a form's fields to do validation or similar
  1055. // will trigger reactualizing options on all of them, which
  1056. // in turn will reactualize the form's options.
  1057. // To avoid calling actualizeOptions so many times on the form
  1058. // for nothing, _withoutReactualizingFormOptions temporarily disables
  1059. // the method actualizeOptions on this form while `fn` is called.
  1060. _withoutReactualizingFormOptions: function _withoutReactualizingFormOptions(fn) {
  1061. var oldActualizeOptions = this.actualizeOptions;
  1062. this.actualizeOptions = function () {
  1063. return this;
  1064. };
  1065. var result = fn();
  1066. this.actualizeOptions = oldActualizeOptions;
  1067. return result;
  1068. },
  1069. // Internal only.
  1070. // Shortcut to trigger an event
  1071. // Returns true iff event is not interrupted and default not prevented.
  1072. _trigger: function _trigger(eventName) {
  1073. return this.trigger('form:' + eventName);
  1074. }
  1075. };
  1076. var ConstraintFactory = function ConstraintFactory(parsleyField, name, requirements, priority, isDomConstraint) {
  1077. if (!/ParsleyField/.test(parsleyField.__class__)) throw new Error('ParsleyField or ParsleyFieldMultiple instance expected');
  1078. var validatorSpec = window.Parsley._validatorRegistry.validators[name];
  1079. var validator = new ParsleyValidator(validatorSpec);
  1080. $.extend(this, {
  1081. validator: validator,
  1082. name: name,
  1083. requirements: requirements,
  1084. prio