PageRenderTime 42ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/files/parsleyjs/2.3.5/parsley.js

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