parsley-rails 2.0.7.0 → 2.4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -5
  3. data/lib/parsley-rails/version.rb +1 -1
  4. data/parsley-rails.gemspec +2 -2
  5. data/update.sh +3 -4
  6. data/vendor/assets/javascripts/parsley.i18n.al.js +29 -0
  7. data/vendor/assets/javascripts/parsley.i18n.ar.js +4 -8
  8. data/vendor/assets/javascripts/parsley.i18n.bg.js +4 -8
  9. data/vendor/assets/javascripts/parsley.i18n.ca.js +29 -0
  10. data/vendor/assets/javascripts/parsley.i18n.cs.extra.js +3 -3
  11. data/vendor/assets/javascripts/parsley.i18n.cs.js +6 -10
  12. data/vendor/assets/javascripts/parsley.i18n.da.js +4 -9
  13. data/vendor/assets/javascripts/parsley.i18n.de.extra.js +3 -3
  14. data/vendor/assets/javascripts/parsley.i18n.de.js +7 -8
  15. data/vendor/assets/javascripts/parsley.i18n.el.extra.js +14 -0
  16. data/vendor/assets/javascripts/parsley.i18n.el.js +29 -0
  17. data/vendor/assets/javascripts/parsley.i18n.en.extra.js +5 -4
  18. data/vendor/assets/javascripts/parsley.i18n.en.js +5 -8
  19. data/vendor/assets/javascripts/parsley.i18n.es.js +4 -6
  20. data/vendor/assets/javascripts/parsley.i18n.eu.js +29 -0
  21. data/vendor/assets/javascripts/parsley.i18n.fa.js +9 -13
  22. data/vendor/assets/javascripts/parsley.i18n.fi.extra.js +3 -3
  23. data/vendor/assets/javascripts/parsley.i18n.fi.js +5 -9
  24. data/vendor/assets/javascripts/parsley.i18n.fr.extra.js +5 -4
  25. data/vendor/assets/javascripts/parsley.i18n.fr.js +4 -8
  26. data/vendor/assets/javascripts/parsley.i18n.he.extra.js +3 -3
  27. data/vendor/assets/javascripts/parsley.i18n.he.js +4 -8
  28. data/vendor/assets/javascripts/parsley.i18n.hr.extra.js +14 -0
  29. data/vendor/assets/javascripts/parsley.i18n.hr.js +29 -0
  30. data/vendor/assets/javascripts/parsley.i18n.hu.extra.js +14 -0
  31. data/vendor/assets/javascripts/parsley.i18n.hu.js +30 -0
  32. data/vendor/assets/javascripts/parsley.i18n.id.extra.js +3 -3
  33. data/vendor/assets/javascripts/parsley.i18n.id.js +4 -8
  34. data/vendor/assets/javascripts/parsley.i18n.it.extra.js +3 -3
  35. data/vendor/assets/javascripts/parsley.i18n.it.js +4 -8
  36. data/vendor/assets/javascripts/parsley.i18n.ja.js +4 -8
  37. data/vendor/assets/javascripts/parsley.i18n.ko.js +5 -9
  38. data/vendor/assets/javascripts/parsley.i18n.lt.js +29 -0
  39. data/vendor/assets/javascripts/parsley.i18n.lv.extra.js +14 -0
  40. data/vendor/assets/javascripts/parsley.i18n.lv.js +29 -0
  41. data/vendor/assets/javascripts/{parsley.i18n.ms_MY.extra.js → parsley.i18n.ms.extra.js} +4 -4
  42. data/vendor/assets/javascripts/{parsley.i18n.ms_MY.js → parsley.i18n.ms.js} +4 -8
  43. data/vendor/assets/javascripts/parsley.i18n.nl.extra.js +3 -3
  44. data/vendor/assets/javascripts/parsley.i18n.nl.js +4 -8
  45. data/vendor/assets/javascripts/parsley.i18n.no.js +29 -0
  46. data/vendor/assets/javascripts/parsley.i18n.pl.js +19 -23
  47. data/vendor/assets/javascripts/parsley.i18n.pt-br.js +4 -8
  48. data/vendor/assets/javascripts/parsley.i18n.pt-pt.js +29 -0
  49. data/vendor/assets/javascripts/parsley.i18n.ro.extra.js +14 -0
  50. data/vendor/assets/javascripts/parsley.i18n.ro.js +29 -0
  51. data/vendor/assets/javascripts/parsley.i18n.ru.extra.js +3 -3
  52. data/vendor/assets/javascripts/parsley.i18n.ru.js +4 -13
  53. data/vendor/assets/javascripts/parsley.i18n.sl.extra.js +14 -0
  54. data/vendor/assets/javascripts/parsley.i18n.sl.js +30 -0
  55. data/vendor/assets/javascripts/parsley.i18n.sq.js +29 -0
  56. data/vendor/assets/javascripts/parsley.i18n.sv.extra.js +3 -3
  57. data/vendor/assets/javascripts/parsley.i18n.sv.js +4 -8
  58. data/vendor/assets/javascripts/parsley.i18n.th.js +4 -8
  59. data/vendor/assets/javascripts/parsley.i18n.tr.js +22 -26
  60. data/vendor/assets/javascripts/parsley.i18n.uk.extra.js +9 -0
  61. data/vendor/assets/javascripts/parsley.i18n.uk.js +29 -0
  62. data/vendor/assets/javascripts/parsley.i18n.zh_cn.extra.js +3 -3
  63. data/vendor/assets/javascripts/parsley.i18n.zh_cn.js +4 -8
  64. data/vendor/assets/javascripts/parsley.i18n.zh_tw.js +16 -20
  65. data/vendor/assets/javascripts/parsley.js +1970 -1673
  66. data/vendor/assets/javascripts/parsley.min.js +18 -0
  67. metadata +27 -6
  68. data/vendor/assets/javascripts/parsley.remote.js +0 -2347
@@ -1,6 +1,6 @@
1
- window.ParsleyConfig = window.ParsleyConfig || {};
2
- window.ParsleyConfig.i18n = window.ParsleyConfig.i18n || {};
1
+ // Validation errors messages for Parsley
2
+ // Load this after Parsley
3
3
 
4
- window.ParsleyConfig.i18n.zh_cn = $.extend(window.ParsleyConfig.i18n.zh_cn || {}, {
4
+ Parsley.addMessages('zh-cn', {
5
5
  dateiso: "请输入正确格式的日期 (YYYY-MM-DD)."
6
6
  });
@@ -1,9 +1,7 @@
1
- // ParsleyConfig definition if not already set
2
- window.ParsleyConfig = window.ParsleyConfig || {};
3
- window.ParsleyConfig.i18n = window.ParsleyConfig.i18n || {};
1
+ // Validation errors messages for Parsley
2
+ // Load this after Parsley
4
3
 
5
- // Define then the messages
6
- window.ParsleyConfig.i18n.zh_cn = $.extend(window.ParsleyConfig.i18n.zh_cn || {}, {
4
+ Parsley.addMessages('zh-cn', {
7
5
  defaultMessage: "不正确的值",
8
6
  type: {
9
7
  email: "请输入一个有效的电子邮箱地址",
@@ -28,6 +26,4 @@ window.ParsleyConfig.i18n.zh_cn = $.extend(window.ParsleyConfig.i18n.zh_cn || {}
28
26
  equalto: "输入值不同"
29
27
  });
30
28
 
31
- // If file is loaded after Parsley main file, auto-load locale
32
- if ('undefined' !== typeof window.ParsleyValidator)
33
- window.ParsleyValidator.addCatalog('zh_cn', window.ParsleyConfig.i18n.zh_cn, true);
29
+ Parsley.setLocale('zh-cn');
@@ -1,33 +1,29 @@
1
- // ParsleyConfig definition if not already set
2
- window.ParsleyConfig = window.ParsleyConfig || {};
3
- window.ParsleyConfig.i18n = window.ParsleyConfig.i18n || {};
1
+ // Validation errors messages for Parsley
2
+ // Load this after Parsley
4
3
 
5
- // Define then the messages
6
- window.ParsleyConfig.i18n.zh_tw = $.extend(window.ParsleyConfig.i18n.zh_tw || {}, {
4
+ Parsley.addMessages('zh-tw', {
7
5
  defaultMessage: "這個值似乎是無效的。",
8
6
  type: {
9
- email: "請輸入一個有效的email。",
7
+ email: "請輸入一個正確的電子郵件地址。",
10
8
  url: "請輸入一個有效的網址。",
11
- number: "這個值應該是一個數字。",
12
- integer: "這個值應該是一個整數數字。",
13
- digits: "這個值應該是一個號碼。",
14
- alphanum: "這個值應該是字母或數字。"
9
+ number: "請輸入一個數字。",
10
+ integer: "請輸入一個整數。",
11
+ digits: "這個欄位只接受數字。",
12
+ alphanum: "這個欄位只接受英文字母或是數字。"
15
13
  },
16
- notblank: "這個值不應該為空值。",
17
- required: "這個空格必須填寫。",
14
+ notblank: "這個欄位不能為空白。",
15
+ required: "這個欄位必須填寫。",
18
16
  pattern: "這個值似乎是無效的。",
19
17
  min: "輸入的值應該大於或等於 %s",
20
18
  max: "輸入的值應該小於或等於 %s",
21
- range: "這個值應該在 %s 和 %s 之間。",
22
- minlength: "這個值至少要 %s 字元。",
23
- maxlength: "這個值最多要 %s 字元。",
24
- length: "字元長度應該在 %s 和 %s",
19
+ range: "輸入的值應該在 %s 和 %s 之間。",
20
+ minlength: "輸入的值至少要有 %s 個字元。",
21
+ maxlength: "輸入的值最多可以有 %s 個字元。",
22
+ length: "字元長度應該在 %s 和 %s 之間。",
25
23
  mincheck: "你至少要選擇 %s 個項目。",
26
24
  maxcheck: "你最多可選擇 %s 個項目。",
27
25
  check: "你必須選擇 %s 到 %s 個項目。",
28
- equalto: "輸入值不同"
26
+ equalto: "輸入值不同。"
29
27
  });
30
28
 
31
- // If file is loaded after Parsley main file, auto-load locale
32
- if ('undefined' !== typeof window.ParsleyValidator)
33
- window.ParsleyValidator.addCatalog('zh_tw', window.ParsleyConfig.i18n.zh_tw, true);
29
+ Parsley.setLocale('zh-tw');
@@ -1,2083 +1,2380 @@
1
1
  /*!
2
- * Parsleyjs
2
+ * Parsley.js
3
+ * Version 2.4.4 - built Thu, Aug 4th 2016, 9:54 pm
4
+ * http://parsleyjs.org
3
5
  * Guillaume Potier - <guillaume@wisembly.com>
4
- * Version 2.0.6 - built Sat Jan 24 2015 14:44:37
6
+ * Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
5
7
  * MIT Licensed
6
- *
7
8
  */
8
- !(function (factory) {
9
- if (typeof define === 'function' && define.amd) {
10
- // AMD. Register as an anonymous module depending on jQuery.
11
- define(['jquery'], factory);
12
- } else {
13
- // No AMD. Register plugin with global jQuery object.
14
- factory(jQuery);
15
- }
16
- }(function ($) {
17
- // small hack for requirejs if jquery is loaded through map and not path
18
- // see http://requirejs.org/docs/jquery.html
19
- if ('undefined' === typeof $ && 'undefined' !== typeof window.jQuery)
20
- $ = window.jQuery;
21
- var ParsleyUtils = {
9
+
10
+ // The source code below is generated by babel as
11
+ // Parsley is written in ECMAScript 6
12
+ //
13
+ var _slice = Array.prototype.slice;
14
+
15
+ 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); } }
16
+
17
+ (function (global, factory) {
18
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) : typeof define === 'function' && define.amd ? define(['jquery'], factory) : global.parsley = factory(global.jQuery);
19
+ })(this, function ($) {
20
+ 'use strict';
21
+
22
+ var globalID = 1;
23
+ var pastWarnings = {};
24
+
25
+ var ParsleyUtils__ParsleyUtils = {
22
26
  // Parsley DOM-API
23
27
  // returns object from dom attributes and values
24
- // if attr is given, returns bool if attr present in DOM or not
25
- attr: function ($element, namespace, checkAttr) {
26
- var
27
- attribute,
28
- obj = {},
29
- msie = this.msieversion(),
30
- regex = new RegExp('^' + namespace, 'i');
31
- if ('undefined' === typeof $element || 'undefined' === typeof $element[0])
32
- return {};
33
- for (var i in $element[0].attributes) {
34
- attribute = $element[0].attributes[i];
35
- if ('undefined' !== typeof attribute && null !== attribute && (!msie || msie >= 8 || attribute.specified) && regex.test(attribute.name)) {
36
- if ('undefined' !== typeof checkAttr && new RegExp(checkAttr + '$', 'i').test(attribute.name))
37
- return true;
38
- obj[this.camelize(attribute.name.replace(namespace, ''))] = this.deserializeValue(attribute.value);
28
+ attr: function attr($element, namespace, obj) {
29
+ var i;
30
+ var attribute;
31
+ var attributes;
32
+ var regex = new RegExp('^' + namespace, 'i');
33
+
34
+ if ('undefined' === typeof obj) obj = {};else {
35
+ // Clear all own properties. This won't affect prototype's values
36
+ for (i in obj) {
37
+ if (obj.hasOwnProperty(i)) delete obj[i];
39
38
  }
40
39
  }
41
- return 'undefined' === typeof checkAttr ? obj : false;
42
- },
43
- setAttr: function ($element, namespace, attr, value) {
44
- $element[0].setAttribute(this.dasherize(namespace + attr), String(value));
45
- },
46
- // Recursive object / array getter
47
- get: function (obj, path) {
48
- var
49
- i = 0,
50
- paths = (path || '').split('.');
51
- while (this.isObject(obj) || this.isArray(obj)) {
52
- obj = obj[paths[i++]];
53
- if (i === paths.length)
54
- return obj;
40
+
41
+ if ('undefined' === typeof $element || 'undefined' === typeof $element[0]) return obj;
42
+
43
+ attributes = $element[0].attributes;
44
+ for (i = attributes.length; i--;) {
45
+ attribute = attributes[i];
46
+
47
+ if (attribute && attribute.specified && regex.test(attribute.name)) {
48
+ obj[this.camelize(attribute.name.slice(namespace.length))] = this.deserializeValue(attribute.value);
49
+ }
55
50
  }
56
- return undefined;
51
+
52
+ return obj;
57
53
  },
58
- hash: function (length) {
59
- return String(Math.random()).substring(2, length ? length + 2 : 9);
54
+
55
+ checkAttr: function checkAttr($element, namespace, _checkAttr) {
56
+ return $element.is('[' + namespace + _checkAttr + ']');
60
57
  },
61
- /** Third party functions **/
62
- // Underscore isArray
63
- isArray: function (mixed) {
64
- return Object.prototype.toString.call(mixed) === '[object Array]';
58
+
59
+ setAttr: function setAttr($element, namespace, attr, value) {
60
+ $element[0].setAttribute(this.dasherize(namespace + attr), String(value));
65
61
  },
66
- // Underscore isObject
67
- isObject: function (mixed) {
68
- return mixed === Object(mixed);
62
+
63
+ generateID: function generateID() {
64
+ return '' + globalID++;
69
65
  },
66
+
67
+ /** Third party functions **/
70
68
  // Zepto deserialize function
71
- deserializeValue: function (value) {
69
+ deserializeValue: function deserializeValue(value) {
72
70
  var num;
71
+
73
72
  try {
74
- return value ?
75
- value == "true" ||
76
- (value == "false" ? false :
77
- value == "null" ? null :
78
- !isNaN(num = Number(value)) ? num :
79
- /^[\[\{]/.test(value) ? $.parseJSON(value) :
80
- value)
81
- : value;
82
- } catch (e) { return value; }
73
+ return value ? value == "true" || (value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? $.parseJSON(value) : value) : value;
74
+ } catch (e) {
75
+ return value;
76
+ }
83
77
  },
78
+
84
79
  // Zepto camelize function
85
- camelize: function (str) {
86
- return str.replace(/-+(.)?/g, function(match, chr) {
80
+ camelize: function camelize(str) {
81
+ return str.replace(/-+(.)?/g, function (match, chr) {
87
82
  return chr ? chr.toUpperCase() : '';
88
83
  });
89
84
  },
85
+
90
86
  // Zepto dasherize function
91
- dasherize: function (str) {
92
- return str.replace(/::/g, '/')
93
- .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
94
- .replace(/([a-z\d])([A-Z])/g, '$1_$2')
95
- .replace(/_/g, '-')
96
- .toLowerCase();
97
- },
98
- // http://support.microsoft.com/kb/167820
99
- // http://stackoverflow.com/questions/19999388/jquery-check-if-user-is-using-ie
100
- msieversion: function () {
101
- var
102
- ua = window.navigator.userAgent,
103
- msie = ua.indexOf('MSIE ');
104
- if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))
105
- return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
106
- return 0;
107
- }
87
+ dasherize: function dasherize(str) {
88
+ 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();
89
+ },
90
+
91
+ warn: function warn() {
92
+ var _window$console;
93
+
94
+ if (window.console && 'function' === typeof window.console.warn) (_window$console = window.console).warn.apply(_window$console, arguments);
95
+ },
96
+
97
+ warnOnce: function warnOnce(msg) {
98
+ if (!pastWarnings[msg]) {
99
+ pastWarnings[msg] = true;
100
+ this.warn.apply(this, arguments);
101
+ }
102
+ },
103
+
104
+ _resetWarnings: function _resetWarnings() {
105
+ pastWarnings = {};
106
+ },
107
+
108
+ trimString: function trimString(string) {
109
+ return string.replace(/^\s+|\s+$/g, '');
110
+ },
111
+
112
+ namespaceEvents: function namespaceEvents(events, namespace) {
113
+ events = this.trimString(events || '').split(/\s+/);
114
+ if (!events[0]) return '';
115
+ return $.map(events, function (evt) {
116
+ return evt + '.' + namespace;
117
+ }).join(' ');
118
+ },
119
+
120
+ difference: function difference(array, remove) {
121
+ // This is O(N^2), should be optimized
122
+ var result = [];
123
+ $.each(array, function (_, elem) {
124
+ if (remove.indexOf(elem) == -1) result.push(elem);
125
+ });
126
+ return result;
127
+ },
128
+
129
+ // Alter-ego to native Promise.all, but for jQuery
130
+ all: function all(promises) {
131
+ // jQuery treats $.when() and $.when(singlePromise) differently; let's avoid that and add spurious elements
132
+ return $.when.apply($, _toConsumableArray(promises).concat([42, 42]));
133
+ },
134
+
135
+ // Object.create polyfill, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Polyfill
136
+ objectCreate: Object.create || (function () {
137
+ var Object = function Object() {};
138
+ return function (prototype) {
139
+ if (arguments.length > 1) {
140
+ throw Error('Second argument not supported');
141
+ }
142
+ if (typeof prototype != 'object') {
143
+ throw TypeError('Argument must be an object');
144
+ }
145
+ Object.prototype = prototype;
146
+ var result = new Object();
147
+ Object.prototype = null;
148
+ return result;
149
+ };
150
+ })(),
151
+
152
+ _SubmitSelector: 'input[type="submit"], button:submit'
108
153
  };
109
- // All these options could be overriden and specified directly in DOM using
110
- // `data-parsley-` default DOM-API
111
- // eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"`
112
- // eg: `data-parsley-stop-on-first-failing-constraint="false"`
154
+
155
+ var ParsleyUtils__default = ParsleyUtils__ParsleyUtils;
156
+
157
+ // All these options could be overriden and specified directly in DOM using
158
+ // `data-parsley-` default DOM-API
159
+ // eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"`
160
+ // eg: `data-parsley-stop-on-first-failing-constraint="false"`
161
+
113
162
  var ParsleyDefaults = {
114
163
  // ### General
164
+
115
165
  // Default data-namespace for DOM API
116
166
  namespace: 'data-parsley-',
167
+
117
168
  // Supported inputs by default
118
169
  inputs: 'input, textarea, select',
170
+
119
171
  // Excluded inputs by default
120
172
  excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden]',
173
+
121
174
  // Stop validating field on highest priority failing constraint
122
175
  priorityEnabled: true,
176
+
177
+ // ### Field only
178
+
179
+ // identifier used to group together inputs (e.g. radio buttons...)
180
+ multiple: null,
181
+
182
+ // identifier (or array of identifiers) used to validate only a select group of inputs
183
+ group: null,
184
+
123
185
  // ### UI
124
186
  // Enable\Disable error messages
125
187
  uiEnabled: true,
188
+
126
189
  // Key events threshold before validation
127
190
  validationThreshold: 3,
128
- // Focused field on form validation error. 'fist'|'last'|'none'
191
+
192
+ // Focused field on form validation error. 'first'|'last'|'none'
129
193
  focus: 'first',
130
- // `$.Event()` that will trigger validation. eg: `keyup`, `change`...
194
+
195
+ // event(s) that will trigger validation before first failure. eg: `input`...
131
196
  trigger: false,
197
+
198
+ // event(s) that will trigger validation after first failure.
199
+ triggerAfterFailure: 'input',
200
+
132
201
  // Class that would be added on every failing validation Parsley field
133
202
  errorClass: 'parsley-error',
203
+
134
204
  // Same for success validation
135
205
  successClass: 'parsley-success',
206
+
136
207
  // Return the `$element` that will receive these above success or error classes
137
208
  // Could also be (and given directly from DOM) a valid selector like `'#div'`
138
- classHandler: function (ParsleyField) {},
209
+ classHandler: function classHandler(ParsleyField) {},
210
+
139
211
  // Return the `$element` where errors will be appended
140
212
  // Could also be (and given directly from DOM) a valid selector like `'#div'`
141
- errorsContainer: function (ParsleyField) {},
213
+ errorsContainer: function errorsContainer(ParsleyField) {},
214
+
142
215
  // ul elem that would receive errors' list
143
216
  errorsWrapper: '<ul class="parsley-errors-list"></ul>',
217
+
144
218
  // li elem that would receive error message
145
219
  errorTemplate: '<li></li>'
146
220
  };
147
221
 
148
- var ParsleyAbstract = function() {};
222
+ var ParsleyAbstract = function ParsleyAbstract() {
223
+ this.__id__ = ParsleyUtils__default.generateID();
224
+ };
225
+
149
226
  ParsleyAbstract.prototype = {
150
- asyncSupport: false,
151
- actualizeOptions: function () {
152
- this.options = this.OptionsFactory.get(this);
227
+ asyncSupport: true, // Deprecated
228
+
229
+ _pipeAccordingToValidationResult: function _pipeAccordingToValidationResult() {
230
+ var _this = this;
231
+
232
+ var pipe = function pipe() {
233
+ var r = $.Deferred();
234
+ if (true !== _this.validationResult) r.reject();
235
+ return r.resolve().promise();
236
+ };
237
+ return [pipe, pipe];
238
+ },
239
+
240
+ actualizeOptions: function actualizeOptions() {
241
+ ParsleyUtils__default.attr(this.$element, this.options.namespace, this.domOptions);
242
+ if (this.parent && this.parent.actualizeOptions) this.parent.actualizeOptions();
153
243
  return this;
154
244
  },
155
- // ParsleyValidator validate proxy function . Could be replaced by third party scripts
156
- validateThroughValidator: function (value, constraints, priority) {
157
- return window.ParsleyValidator.validate(value, constraints, priority);
245
+
246
+ _resetOptions: function _resetOptions(initOptions) {
247
+ this.domOptions = ParsleyUtils__default.objectCreate(this.parent.options);
248
+ this.options = ParsleyUtils__default.objectCreate(this.domOptions);
249
+ // Shallow copy of ownProperties of initOptions:
250
+ for (var i in initOptions) {
251
+ if (initOptions.hasOwnProperty(i)) this.options[i] = initOptions[i];
252
+ }
253
+ this.actualizeOptions();
254
+ },
255
+
256
+ _listeners: null,
257
+
258
+ // Register a callback for the given event name
259
+ // Callback is called with context as the first argument and the `this`
260
+ // The context is the current parsley instance, or window.Parsley if global
261
+ // A return value of `false` will interrupt the calls
262
+ on: function on(name, fn) {
263
+ this._listeners = this._listeners || {};
264
+ var queue = this._listeners[name] = this._listeners[name] || [];
265
+ queue.push(fn);
266
+
267
+ return this;
158
268
  },
159
- // Subscribe an event and a handler for a specific field or a specific form
160
- // If on a ParsleyForm instance, it will be attached to form instance and also
161
- // To every field instance for this form
162
- subscribe: function (name, fn) {
269
+
270
+ // Deprecated. Use `on` instead
271
+ subscribe: function subscribe(name, fn) {
163
272
  $.listenTo(this, name.toLowerCase(), fn);
273
+ },
274
+
275
+ // Unregister a callback (or all if none is given) for the given event name
276
+ off: function off(name, fn) {
277
+ var queue = this._listeners && this._listeners[name];
278
+ if (queue) {
279
+ if (!fn) {
280
+ delete this._listeners[name];
281
+ } else {
282
+ for (var i = queue.length; i--;) if (queue[i] === fn) queue.splice(i, 1);
283
+ }
284
+ }
164
285
  return this;
165
286
  },
166
- // Same as subscribe above. Unsubscribe an event for field, or form + its fields
167
- unsubscribe: function (name) {
287
+
288
+ // Deprecated. Use `off`
289
+ unsubscribe: function unsubscribe(name, fn) {
168
290
  $.unsubscribeTo(this, name.toLowerCase());
169
- return this;
170
291
  },
292
+
293
+ // Trigger an event of the given name
294
+ // A return value of `false` interrupts the callback chain
295
+ // Returns false if execution was interrupted
296
+ trigger: function trigger(name, target, extraArg) {
297
+ target = target || this;
298
+ var queue = this._listeners && this._listeners[name];
299
+ var result;
300
+ var parentResult;
301
+ if (queue) {
302
+ for (var i = queue.length; i--;) {
303
+ result = queue[i].call(target, target, extraArg);
304
+ if (result === false) return result;
305
+ }
306
+ }
307
+ if (this.parent) {
308
+ return this.parent.trigger(name, target, extraArg);
309
+ }
310
+ return true;
311
+ },
312
+
171
313
  // Reset UI
172
- reset: function () {
314
+ reset: function reset() {
173
315
  // Field case: just emit a reset event for UI
174
- if ('ParsleyForm' !== this.__class__)
175
- return $.emit('parsley:field:reset', this);
316
+ if ('ParsleyForm' !== this.__class__) {
317
+ this._resetUI();
318
+ return this._trigger('reset');
319
+ }
320
+
176
321
  // Form case: emit a reset event for each field
177
- for (var i = 0; i < this.fields.length; i++)
178
- $.emit('parsley:field:reset', this.fields[i]);
179
- $.emit('parsley:form:reset', this);
322
+ for (var i = 0; i < this.fields.length; i++) this.fields[i].reset();
323
+
324
+ this._trigger('reset');
180
325
  },
326
+
181
327
  // Destroy Parsley instance (+ UI)
182
- destroy: function () {
328
+ destroy: function destroy() {
183
329
  // Field case: emit destroy event to clean UI and then destroy stored instance
330
+ this._destroyUI();
184
331
  if ('ParsleyForm' !== this.__class__) {
185
332
  this.$element.removeData('Parsley');
186
333
  this.$element.removeData('ParsleyFieldMultiple');
187
- $.emit('parsley:field:destroy', this);
334
+ this._trigger('destroy');
335
+
188
336
  return;
189
337
  }
338
+
190
339
  // Form case: destroy all its fields and then destroy stored instance
191
- for (var i = 0; i < this.fields.length; i++)
192
- this.fields[i].destroy();
340
+ for (var i = 0; i < this.fields.length; i++) this.fields[i].destroy();
341
+
193
342
  this.$element.removeData('Parsley');
194
- $.emit('parsley:form:destroy', this);
343
+ this._trigger('destroy');
344
+ },
345
+
346
+ asyncIsValid: function asyncIsValid(group, force) {
347
+ ParsleyUtils__default.warnOnce("asyncIsValid is deprecated; please use whenValid instead");
348
+ return this.whenValid({ group: group, force: force });
349
+ },
350
+
351
+ _findRelated: function _findRelated() {
352
+ return this.options.multiple ? this.parent.$element.find('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]') : this.$element;
195
353
  }
196
354
  };
197
- /*!
198
- * validator.js
199
- * Guillaume Potier - <guillaume@wisembly.com>
200
- * Version 1.0.1 - built Mon Aug 25 2014 16:10:10
201
- * MIT Licensed
202
- *
203
- */
204
- var Validator = ( function ( ) {
205
- var exports = {};
206
- /**
207
- * Validator
208
- */
209
- var Validator = function ( options ) {
210
- this.__class__ = 'Validator';
211
- this.__version__ = '1.0.1';
212
- this.options = options || {};
213
- this.bindingKey = this.options.bindingKey || '_validatorjsConstraint';
214
- };
215
- Validator.prototype = {
216
- constructor: Validator,
217
- /*
218
- * Validate string: validate( string, Assert, string ) || validate( string, [ Assert, Assert ], [ string, string ] )
219
- * Validate object: validate( object, Constraint, string ) || validate( object, Constraint, [ string, string ] )
220
- * Validate binded object: validate( object, string ) || validate( object, [ string, string ] )
221
- */
222
- validate: function ( objectOrString, AssertsOrConstraintOrGroup, group ) {
223
- if ( 'string' !== typeof objectOrString && 'object' !== typeof objectOrString )
224
- throw new Error( 'You must validate an object or a string' );
225
- // string / array validation
226
- if ( 'string' === typeof objectOrString || _isArray(objectOrString) )
227
- return this._validateString( objectOrString, AssertsOrConstraintOrGroup, group );
228
- // binded object validation
229
- if ( this.isBinded( objectOrString ) )
230
- return this._validateBindedObject( objectOrString, AssertsOrConstraintOrGroup );
231
- // regular object validation
232
- return this._validateObject( objectOrString, AssertsOrConstraintOrGroup, group );
233
- },
234
- bind: function ( object, constraint ) {
235
- if ( 'object' !== typeof object )
236
- throw new Error( 'Must bind a Constraint to an object' );
237
- object[ this.bindingKey ] = new Constraint( constraint );
238
- return this;
355
+
356
+ var requirementConverters = {
357
+ string: function string(_string) {
358
+ return _string;
239
359
  },
240
- unbind: function ( object ) {
241
- if ( 'undefined' === typeof object._validatorjsConstraint )
242
- return this;
243
- delete object[ this.bindingKey ];
244
- return this;
360
+ integer: function integer(string) {
361
+ if (isNaN(string)) throw 'Requirement is not an integer: "' + string + '"';
362
+ return parseInt(string, 10);
245
363
  },
246
- isBinded: function ( object ) {
247
- return 'undefined' !== typeof object[ this.bindingKey ];
248
- },
249
- getBinded: function ( object ) {
250
- return this.isBinded( object ) ? object[ this.bindingKey ] : null;
251
- },
252
- _validateString: function ( string, assert, group ) {
253
- var result, failures = [];
254
- if ( !_isArray( assert ) )
255
- assert = [ assert ];
256
- for ( var i = 0; i < assert.length; i++ ) {
257
- if ( ! ( assert[ i ] instanceof Assert) )
258
- throw new Error( 'You must give an Assert or an Asserts array to validate a string' );
259
- result = assert[ i ].check( string, group );
260
- if ( result instanceof Violation )
261
- failures.push( result );
262
- }
263
- return failures.length ? failures : true;
364
+ number: function number(string) {
365
+ if (isNaN(string)) throw 'Requirement is not a number: "' + string + '"';
366
+ return parseFloat(string);
367
+ },
368
+ reference: function reference(string) {
369
+ // Unused for now
370
+ var result = $(string);
371
+ if (result.length === 0) throw 'No such reference: "' + string + '"';
372
+ return result;
264
373
  },
265
- _validateObject: function ( object, constraint, group ) {
266
- if ( 'object' !== typeof constraint )
267
- throw new Error( 'You must give a constraint to validate an object' );
268
- if ( constraint instanceof Constraint )
269
- return constraint.check( object, group );
270
- return new Constraint( constraint ).check( object, group );
374
+ boolean: function boolean(string) {
375
+ return string !== 'false';
271
376
  },
272
- _validateBindedObject: function ( object, group ) {
273
- return object[ this.bindingKey ].check( object, group );
377
+ object: function object(string) {
378
+ return ParsleyUtils__default.deserializeValue(string);
379
+ },
380
+ regexp: function regexp(_regexp) {
381
+ var flags = '';
382
+
383
+ // Test if RegExp is literal, if not, nothing to be done, otherwise, we need to isolate flags and pattern
384
+ if (/^\/.*\/(?:[gimy]*)$/.test(_regexp)) {
385
+ // Replace the regexp literal string with the first match group: ([gimy]*)
386
+ // If no flag is present, this will be a blank string
387
+ flags = _regexp.replace(/.*\/([gimy]*)$/, '$1');
388
+ // Again, replace the regexp literal string with the first match group:
389
+ // everything excluding the opening and closing slashes and the flags
390
+ _regexp = _regexp.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
391
+ } else {
392
+ // Anchor regexp:
393
+ _regexp = '^' + _regexp + '$';
394
+ }
395
+ return new RegExp(_regexp, flags);
274
396
  }
275
397
  };
276
- Validator.errorCode = {
277
- must_be_a_string: 'must_be_a_string',
278
- must_be_an_array: 'must_be_an_array',
279
- must_be_a_number: 'must_be_a_number',
280
- must_be_a_string_or_array: 'must_be_a_string_or_array'
398
+
399
+ var convertArrayRequirement = function convertArrayRequirement(string, length) {
400
+ var m = string.match(/^\s*\[(.*)\]\s*$/);
401
+ if (!m) throw 'Requirement is not an array: "' + string + '"';
402
+ var values = m[1].split(',').map(ParsleyUtils__default.trimString);
403
+ if (values.length !== length) throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed';
404
+ return values;
281
405
  };
282
- /**
283
- * Constraint
284
- */
285
- var Constraint = function ( data, options ) {
286
- this.__class__ = 'Constraint';
287
- this.options = options || {};
288
- this.nodes = {};
289
- if ( data ) {
290
- try {
291
- this._bootstrap( data );
292
- } catch ( err ) {
293
- throw new Error( 'Should give a valid mapping object to Constraint', err, data );
406
+
407
+ var convertRequirement = function convertRequirement(requirementType, string) {
408
+ var converter = requirementConverters[requirementType || 'string'];
409
+ if (!converter) throw 'Unknown requirement specification: "' + requirementType + '"';
410
+ return converter(string);
411
+ };
412
+
413
+ var convertExtraOptionRequirement = function convertExtraOptionRequirement(requirementSpec, string, extraOptionReader) {
414
+ var main = null;
415
+ var extra = {};
416
+ for (var key in requirementSpec) {
417
+ if (key) {
418
+ var value = extraOptionReader(key);
419
+ if ('string' === typeof value) value = convertRequirement(requirementSpec[key], value);
420
+ extra[key] = value;
421
+ } else {
422
+ main = convertRequirement(requirementSpec[key], string);
294
423
  }
295
424
  }
425
+ return [main, extra];
296
426
  };
297
- Constraint.prototype = {
298
- constructor: Constraint,
299
- check: function ( object, group ) {
300
- var result, failures = {};
301
- // check all constraint nodes.
302
- for ( var property in this.nodes ) {
303
- var isRequired = false;
304
- var constraint = this.get(property);
305
- var constraints = _isArray( constraint ) ? constraint : [constraint];
306
- for (var i = constraints.length - 1; i >= 0; i--) {
307
- if ( 'Required' === constraints[i].__class__ ) {
308
- isRequired = constraints[i].requiresValidation( group );
309
- continue;
310
- }
311
- }
312
- if ( ! this.has( property, object ) && ! this.options.strict && ! isRequired ) {
313
- continue;
427
+
428
+ // A Validator needs to implement the methods `validate` and `parseRequirements`
429
+
430
+ var ParsleyValidator = function ParsleyValidator(spec) {
431
+ $.extend(true, this, spec);
432
+ };
433
+
434
+ ParsleyValidator.prototype = {
435
+ // Returns `true` iff the given `value` is valid according the given requirements.
436
+ validate: function validate(value, requirementFirstArg) {
437
+ if (this.fn) {
438
+ // Legacy style validator
439
+
440
+ if (arguments.length > 3) // If more args then value, requirement, instance...
441
+ requirementFirstArg = [].slice.call(arguments, 1, -1); // Skip first arg (value) and last (instance), combining the rest
442
+ return this.fn.call(this, value, requirementFirstArg);
443
+ }
444
+
445
+ if ($.isArray(value)) {
446
+ if (!this.validateMultiple) throw 'Validator `' + this.name + '` does not handle multiple values';
447
+ return this.validateMultiple.apply(this, arguments);
448
+ } else {
449
+ if (this.validateNumber) {
450
+ if (isNaN(value)) return false;
451
+ arguments[0] = parseFloat(arguments[0]);
452
+ return this.validateNumber.apply(this, arguments);
314
453
  }
315
- try {
316
- if (! this.has( property, this.options.strict || isRequired ? object : undefined ) ) {
317
- // we trigger here a HaveProperty Assert violation to have uniform Violation object in the end
318
- new Assert().HaveProperty( property ).validate( object );
319
- }
320
- result = this._check( property, object[ property ], group );
321
- // check returned an array of Violations or an object mapping Violations
322
- if ( ( _isArray( result ) && result.length > 0 ) || ( !_isArray( result ) && !_isEmptyObject( result ) ) ) {
323
- failures[ property ] = result;
324
- }
325
- } catch ( violation ) {
326
- failures[ property ] = violation;
454
+ if (this.validateString) {
455
+ return this.validateString.apply(this, arguments);
327
456
  }
457
+ throw 'Validator `' + this.name + '` only handles multiple values';
328
458
  }
329
- return _isEmptyObject(failures) ? true : failures;
330
459
  },
331
- add: function ( node, object ) {
332
- if ( object instanceof Assert || ( _isArray( object ) && object[ 0 ] instanceof Assert ) ) {
333
- this.nodes[ node ] = object;
334
- return this;
460
+
461
+ // Parses `requirements` into an array of arguments,
462
+ // according to `this.requirementType`
463
+ parseRequirements: function parseRequirements(requirements, extraOptionReader) {
464
+ if ('string' !== typeof requirements) {
465
+ // Assume requirement already parsed
466
+ // but make sure we return an array
467
+ return $.isArray(requirements) ? requirements : [requirements];
335
468
  }
336
- if ( 'object' === typeof object && !_isArray( object ) ) {
337
- this.nodes[ node ] = object instanceof Constraint ? object : new Constraint( object );
338
- return this;
469
+ var type = this.requirementType;
470
+ if ($.isArray(type)) {
471
+ var values = convertArrayRequirement(requirements, type.length);
472
+ for (var i = 0; i < values.length; i++) values[i] = convertRequirement(type[i], values[i]);
473
+ return values;
474
+ } else if ($.isPlainObject(type)) {
475
+ return convertExtraOptionRequirement(type, requirements, extraOptionReader);
476
+ } else {
477
+ return [convertRequirement(type, requirements)];
339
478
  }
340
- throw new Error( 'Should give an Assert, an Asserts array, a Constraint', object );
341
- },
342
- has: function ( node, nodes ) {
343
- nodes = 'undefined' !== typeof nodes ? nodes : this.nodes;
344
- return 'undefined' !== typeof nodes[ node ];
345
479
  },
346
- get: function ( node, placeholder ) {
347
- return this.has( node ) ? this.nodes[ node ] : placeholder || null;
348
- },
349
- remove: function ( node ) {
350
- var _nodes = [];
351
- for ( var i in this.nodes )
352
- if ( i !== node )
353
- _nodes[ i ] = this.nodes[ i ];
354
- this.nodes = _nodes;
355
- return this;
356
- },
357
- _bootstrap: function ( data ) {
358
- if ( data instanceof Constraint )
359
- return this.nodes = data.nodes;
360
- for ( var node in data )
361
- this.add( node, data[ node ] );
362
- },
363
- _check: function ( node, value, group ) {
364
- // Assert
365
- if ( this.nodes[ node ] instanceof Assert )
366
- return this._checkAsserts( value, [ this.nodes[ node ] ], group );
367
- // Asserts
368
- if ( _isArray( this.nodes[ node ] ) )
369
- return this._checkAsserts( value, this.nodes[ node ], group );
370
- // Constraint -> check api
371
- if ( this.nodes[ node ] instanceof Constraint )
372
- return this.nodes[ node ].check( value, group );
373
- throw new Error( 'Invalid node', this.nodes[ node ] );
374
- },
375
- _checkAsserts: function ( value, asserts, group ) {
376
- var result, failures = [];
377
- for ( var i = 0; i < asserts.length; i++ ) {
378
- result = asserts[ i ].check( value, group );
379
- if ( 'undefined' !== typeof result && true !== result )
380
- failures.push( result );
381
- // Some asserts (Collection for example) could return an object
382
- // if ( result && ! ( result instanceof Violation ) )
383
- // return result;
384
- //
385
- // // Vast assert majority return Violation
386
- // if ( result instanceof Violation )
387
- // failures.push( result );
388
- }
389
- return failures;
390
- }
480
+ // Defaults:
481
+ requirementType: 'string',
482
+
483
+ priority: 2
484
+
391
485
  };
392
- /**
393
- * Violation
394
- */
395
- var Violation = function ( assert, value, violation ) {
396
- this.__class__ = 'Violation';
397
- if ( ! ( assert instanceof Assert ) )
398
- throw new Error( 'Should give an assertion implementing the Assert interface' );
399
- this.assert = assert;
400
- this.value = value;
401
- if ( 'undefined' !== typeof violation )
402
- this.violation = violation;
486
+
487
+ var ParsleyValidatorRegistry = function ParsleyValidatorRegistry(validators, catalog) {
488
+ this.__class__ = 'ParsleyValidatorRegistry';
489
+
490
+ // Default Parsley locale is en
491
+ this.locale = 'en';
492
+
493
+ this.init(validators || {}, catalog || {});
403
494
  };
404
- Violation.prototype = {
405
- show: function () {
406
- var show = {
407
- assert: this.assert.__class__,
408
- value: this.value
409
- };
410
- if ( this.violation )
411
- show.violation = this.violation;
412
- return show;
413
- },
414
- __toString: function () {
415
- if ( 'undefined' !== typeof this.violation )
416
- this.violation = '", ' + this.getViolation().constraint + ' expected was ' + this.getViolation().expected;
417
- return this.assert.__class__ + ' assert failed for "' + this.value + this.violation || '';
418
- },
419
- getViolation: function () {
420
- var constraint, expected;
421
- for ( constraint in this.violation )
422
- expected = this.violation[ constraint ];
423
- return { constraint: constraint, expected: expected };
424
- }
495
+
496
+ var typeRegexes = {
497
+ 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,
498
+
499
+ // Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
500
+ number: /^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,
501
+
502
+ integer: /^-?\d+$/,
503
+
504
+ digits: /^\d+$/,
505
+
506
+ alphanum: /^\w+$/i,
507
+
508
+ url: new RegExp("^" +
509
+ // protocol identifier
510
+ "(?:(?:https?|ftp)://)?" + // ** mod: make scheme optional
511
+ // user:pass authentication
512
+ "(?:\\S+(?::\\S*)?@)?" + "(?:" +
513
+ // IP address exclusion
514
+ // private & local networks
515
+ // "(?!(?:10|127)(?:\\.\\d{1,3}){3})" + // ** mod: allow local networks
516
+ // "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" + // ** mod: allow local networks
517
+ // "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + // ** mod: allow local networks
518
+ // IP address dotted notation octets
519
+ // excludes loopback network 0.0.0.0
520
+ // excludes reserved space >= 224.0.0.0
521
+ // excludes network & broacast addresses
522
+ // (first & last IP address of each class)
523
+ "(?:[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]))" + "|" +
524
+ // host name
525
+ '(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)' +
526
+ // domain name
527
+ '(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*' +
528
+ // TLD identifier
529
+ '(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))' + ")" +
530
+ // port number
531
+ "(?::\\d{2,5})?" +
532
+ // resource path
533
+ "(?:/\\S*)?" + "$", 'i')
425
534
  };
426
- /**
427
- * Assert
428
- */
429
- var Assert = function ( group ) {
430
- this.__class__ = 'Assert';
431
- this.__parentClass__ = this.__class__;
432
- this.groups = [];
433
- if ( 'undefined' !== typeof group )
434
- this.addGroup( group );
535
+ typeRegexes.range = typeRegexes.number;
536
+
537
+ // See http://stackoverflow.com/a/10454560/8279
538
+ var decimalPlaces = function decimalPlaces(num) {
539
+ var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
540
+ if (!match) {
541
+ return 0;
542
+ }
543
+ return Math.max(0,
544
+ // Number of digits right of decimal point.
545
+ (match[1] ? match[1].length : 0) - (
546
+ // Adjust for scientific notation.
547
+ match[2] ? +match[2] : 0));
435
548
  };
436
- Assert.prototype = {
437
- construct: Assert,
438
- requiresValidation: function ( group ) {
439
- if ( group && !this.hasGroup( group ) )
440
- return false;
441
- if ( !group && this.hasGroups() )
442
- return false;
443
- return true;
444
- },
445
- check: function ( value, group ) {
446
- if ( !this.requiresValidation( group ) )
447
- return;
448
- try {
449
- return this.validate( value, group );
450
- } catch ( violation ) {
451
- return violation;
452
- }
453
- },
454
- hasGroup: function ( group ) {
455
- if ( _isArray( group ) )
456
- return this.hasOneOf( group );
457
- // All Asserts respond to "Any" group
458
- if ( 'Any' === group )
459
- return true;
460
- // Asserts with no group also respond to "Default" group. Else return false
461
- if ( !this.hasGroups() )
462
- return 'Default' === group;
463
- return -1 !== this.groups.indexOf( group );
464
- },
465
- hasOneOf: function ( groups ) {
466
- for ( var i = 0; i < groups.length; i++ )
467
- if ( this.hasGroup( groups[ i ] ) )
468
- return true;
469
- return false;
470
- },
471
- hasGroups: function () {
472
- return this.groups.length > 0;
473
- },
474
- addGroup: function ( group ) {
475
- if ( _isArray( group ) )
476
- return this.addGroups( group );
477
- if ( !this.hasGroup( group ) )
478
- this.groups.push( group );
479
- return this;
549
+
550
+ ParsleyValidatorRegistry.prototype = {
551
+ init: function init(validators, catalog) {
552
+ this.catalog = catalog;
553
+ // Copy prototype's validators:
554
+ this.validators = $.extend({}, this.validators);
555
+
556
+ for (var name in validators) this.addValidator(name, validators[name].fn, validators[name].priority);
557
+
558
+ window.Parsley.trigger('parsley:validator:init');
480
559
  },
481
- removeGroup: function ( group ) {
482
- var _groups = [];
483
- for ( var i = 0; i < this.groups.length; i++ )
484
- if ( group !== this.groups[ i ] )
485
- _groups.push( this.groups[ i ] );
486
- this.groups = _groups;
560
+
561
+ // Set new messages locale if we have dictionary loaded in ParsleyConfig.i18n
562
+ setLocale: function setLocale(locale) {
563
+ if ('undefined' === typeof this.catalog[locale]) throw new Error(locale + ' is not available in the catalog');
564
+
565
+ this.locale = locale;
566
+
487
567
  return this;
488
568
  },
489
- addGroups: function ( groups ) {
490
- for ( var i = 0; i < groups.length; i++ )
491
- this.addGroup( groups[ i ] );
569
+
570
+ // Add a new messages catalog for a given locale. Set locale for this catalog if set === `true`
571
+ addCatalog: function addCatalog(locale, messages, set) {
572
+ if ('object' === typeof messages) this.catalog[locale] = messages;
573
+
574
+ if (true === set) return this.setLocale(locale);
575
+
492
576
  return this;
493
577
  },
494
- /**
495
- * Asserts definitions
496
- */
497
- HaveProperty: function ( node ) {
498
- this.__class__ = 'HaveProperty';
499
- this.node = node;
500
- this.validate = function ( object ) {
501
- if ( 'undefined' === typeof object[ this.node ] )
502
- throw new Violation( this, object, { value: this.node } );
503
- return true;
504
- };
578
+
579
+ // Add a specific message for a given constraint in a given locale
580
+ addMessage: function addMessage(locale, name, message) {
581
+ if ('undefined' === typeof this.catalog[locale]) this.catalog[locale] = {};
582
+
583
+ this.catalog[locale][name] = message;
584
+
505
585
  return this;
506
586
  },
507
- Blank: function () {
508
- this.__class__ = 'Blank';
509
- this.validate = function ( value ) {
510
- if ( 'string' !== typeof value )
511
- throw new Violation( this, value, { value: Validator.errorCode.must_be_a_string } );
512
- if ( '' !== value.replace( /^\s+/g, '' ).replace( /\s+$/g, '' ) )
513
- throw new Violation( this, value );
514
- return true;
515
- };
587
+
588
+ // Add messages for a given locale
589
+ addMessages: function addMessages(locale, nameMessageObject) {
590
+ for (var name in nameMessageObject) this.addMessage(locale, name, nameMessageObject[name]);
591
+
516
592
  return this;
517
593
  },
518
- Callback: function ( fn ) {
519
- this.__class__ = 'Callback';
520
- this.arguments = Array.prototype.slice.call( arguments );
521
- if ( 1 === this.arguments.length )
522
- this.arguments = [];
523
- else
524
- this.arguments.splice( 0, 1 );
525
- if ( 'function' !== typeof fn )
526
- throw new Error( 'Callback must be instanciated with a function' );
527
- this.fn = fn;
528
- this.validate = function ( value ) {
529
- var result = this.fn.apply( this, [ value ].concat( this.arguments ) );
530
- if ( true !== result )
531
- throw new Violation( this, value, { result: result } );
532
- return true;
533
- };
534
- return this;
594
+
595
+ // Add a new validator
596
+ //
597
+ // addValidator('custom', {
598
+ // requirementType: ['integer', 'integer'],
599
+ // validateString: function(value, from, to) {},
600
+ // priority: 22,
601
+ // messages: {
602
+ // en: "Hey, that's no good",
603
+ // fr: "Aye aye, pas bon du tout",
604
+ // }
605
+ // })
606
+ //
607
+ // Old API was addValidator(name, function, priority)
608
+ //
609
+ addValidator: function addValidator(name, arg1, arg2) {
610
+ if (this.validators[name]) ParsleyUtils__default.warn('Validator "' + name + '" is already defined.');else if (ParsleyDefaults.hasOwnProperty(name)) {
611
+ ParsleyUtils__default.warn('"' + name + '" is a restricted keyword and is not a valid validator name.');
612
+ return;
613
+ }
614
+ return this._setValidator.apply(this, arguments);
535
615
  },
536
- Choice: function ( list ) {
537
- this.__class__ = 'Choice';
538
- if ( !_isArray( list ) && 'function' !== typeof list )
539
- throw new Error( 'Choice must be instanciated with an array or a function' );
540
- this.list = list;
541
- this.validate = function ( value ) {
542
- var list = 'function' === typeof this.list ? this.list() : this.list;
543
- for ( var i = 0; i < list.length; i++ )
544
- if ( value === list[ i ] )
545
- return true;
546
- throw new Violation( this, value, { choices: list } );
547
- };
548
- return this;
616
+
617
+ updateValidator: function updateValidator(name, arg1, arg2) {
618
+ if (!this.validators[name]) {
619
+ ParsleyUtils__default.warn('Validator "' + name + '" is not already defined.');
620
+ return this.addValidator.apply(this, arguments);
621
+ }
622
+ return this._setValidator.apply(this, arguments);
549
623
  },
550
- Collection: function ( assertOrConstraint ) {
551
- this.__class__ = 'Collection';
552
- this.constraint = 'undefined' !== typeof assertOrConstraint ? (assertOrConstraint instanceof Assert ? assertOrConstraint : new Constraint( assertOrConstraint )) : false;
553
- this.validate = function ( collection, group ) {
554
- var result, validator = new Validator(), count = 0, failures = {}, groups = this.groups.length ? this.groups : group;
555
- if ( !_isArray( collection ) )
556
- throw new Violation( this, collection, { value: Validator.errorCode.must_be_an_array } );
557
- for ( var i = 0; i < collection.length; i++ ) {
558
- result = this.constraint ?
559
- validator.validate( collection[ i ], this.constraint, groups ) :
560
- validator.validate( collection[ i ], groups );
561
- if ( !_isEmptyObject( result ) )
562
- failures[ count ] = result;
563
- count++;
564
- }
565
- return !_isEmptyObject( failures ) ? failures : true;
566
- };
624
+
625
+ removeValidator: function removeValidator(name) {
626
+ if (!this.validators[name]) ParsleyUtils__default.warn('Validator "' + name + '" is not defined.');
627
+
628
+ delete this.validators[name];
629
+
567
630
  return this;
568
631
  },
569
- Count: function ( count ) {
570
- this.__class__ = 'Count';
571
- this.count = count;
572
- this.validate = function ( array ) {
573
- if ( !_isArray( array ) )
574
- throw new Violation( this, array, { value: Validator.errorCode.must_be_an_array } );
575
- var count = 'function' === typeof this.count ? this.count( array ) : this.count;
576
- if ( isNaN( Number( count ) ) )
577
- throw new Error( 'Count must be a valid interger', count );
578
- if ( count !== array.length )
579
- throw new Violation( this, array, { count: count } );
580
- return true;
581
- };
632
+
633
+ _setValidator: function _setValidator(name, validator, priority) {
634
+ if ('object' !== typeof validator) {
635
+ // Old style validator, with `fn` and `priority`
636
+ validator = {
637
+ fn: validator,
638
+ priority: priority
639
+ };
640
+ }
641
+ if (!validator.validate) {
642
+ validator = new ParsleyValidator(validator);
643
+ }
644
+ this.validators[name] = validator;
645
+
646
+ for (var locale in validator.messages || {}) this.addMessage(locale, name, validator.messages[locale]);
647
+
582
648
  return this;
583
649
  },
584
- Email: function () {
585
- this.__class__ = 'Email';
586
- this.validate = function ( value ) {
587
- var regExp = /^((([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;
588
- if ( 'string' !== typeof value )
589
- throw new Violation( this, value, { value: Validator.errorCode.must_be_a_string } );
590
- if ( !regExp.test( value ) )
591
- throw new Violation( this, value );
592
- return true;
593
- };
594
- return this;
650
+
651
+ getErrorMessage: function getErrorMessage(constraint) {
652
+ var message;
653
+
654
+ // Type constraints are a bit different, we have to match their requirements too to find right error message
655
+ if ('type' === constraint.name) {
656
+ var typeMessages = this.catalog[this.locale][constraint.name] || {};
657
+ message = typeMessages[constraint.requirements];
658
+ } else message = this.formatMessage(this.catalog[this.locale][constraint.name], constraint.requirements);
659
+
660
+ return message || this.catalog[this.locale].defaultMessage || this.catalog.en.defaultMessage;
595
661
  },
596
- EqualTo: function ( reference ) {
597
- this.__class__ = 'EqualTo';
598
- if ( 'undefined' === typeof reference )
599
- throw new Error( 'EqualTo must be instanciated with a value or a function' );
600
- this.reference = reference;
601
- this.validate = function ( value ) {
602
- var reference = 'function' === typeof this.reference ? this.reference( value ) : this.reference;
603
- if ( reference !== value )
604
- throw new Violation( this, value, { value: reference } );
605
- return true;
606
- };
607
- return this;
662
+
663
+ // Kind of light `sprintf()` implementation
664
+ formatMessage: function formatMessage(string, parameters) {
665
+ if ('object' === typeof parameters) {
666
+ for (var i in parameters) string = this.formatMessage(string, parameters[i]);
667
+
668
+ return string;
669
+ }
670
+
671
+ return 'string' === typeof string ? string.replace(/%s/i, parameters) : '';
608
672
  },
609
- GreaterThan: function ( threshold ) {
610
- this.__class__ = 'GreaterThan';
611
- if ( 'undefined' === typeof threshold )
612
- throw new Error( 'Should give a threshold value' );
613
- this.threshold = threshold;
614
- this.validate = function ( value ) {
615
- if ( '' === value || isNaN( Number( value ) ) )
616
- throw new Violation( this, value, { value: Validator.errorCode.must_be_a_number } );
617
- if ( this.threshold >= value )
618
- throw new Violation( this, value, { threshold: this.threshold } );
619
- return true;
620
- };
621
- return this;
622
- },
623
- GreaterThanOrEqual: function ( threshold ) {
624
- this.__class__ = 'GreaterThanOrEqual';
625
- if ( 'undefined' === typeof threshold )
626
- throw new Error( 'Should give a threshold value' );
627
- this.threshold = threshold;
628
- this.validate = function ( value ) {
629
- if ( '' === value || isNaN( Number( value ) ) )
630
- throw new Violation( this, value, { value: Validator.errorCode.must_be_a_number } );
631
- if ( this.threshold > value )
632
- throw new Violation( this, value, { threshold: this.threshold } );
633
- return true;
634
- };
635
- return this;
636
- },
637
- InstanceOf: function ( classRef ) {
638
- this.__class__ = 'InstanceOf';
639
- if ( 'undefined' === typeof classRef )
640
- throw new Error( 'InstanceOf must be instanciated with a value' );
641
- this.classRef = classRef;
642
- this.validate = function ( value ) {
643
- if ( true !== (value instanceof this.classRef) )
644
- throw new Violation( this, value, { classRef: this.classRef } );
645
- return true;
646
- };
647
- return this;
648
- },
649
- Length: function ( boundaries ) {
650
- this.__class__ = 'Length';
651
- if ( !boundaries.min && !boundaries.max )
652
- throw new Error( 'Lenth assert must be instanciated with a { min: x, max: y } object' );
653
- this.min = boundaries.min;
654
- this.max = boundaries.max;
655
- this.validate = function ( value ) {
656
- if ( 'string' !== typeof value && !_isArray( value ) )
657
- throw new Violation( this, value, { value: Validator.errorCode.must_be_a_string_or_array } );
658
- if ( 'undefined' !== typeof this.min && this.min === this.max && value.length !== this.min )
659
- throw new Violation( this, value, { min: this.min, max: this.max } );
660
- if ( 'undefined' !== typeof this.max && value.length > this.max )
661
- throw new Violation( this, value, { max: this.max } );
662
- if ( 'undefined' !== typeof this.min && value.length < this.min )
663
- throw new Violation( this, value, { min: this.min } );
664
- return true;
665
- };
666
- return this;
667
- },
668
- LessThan: function ( threshold ) {
669
- this.__class__ = 'LessThan';
670
- if ( 'undefined' === typeof threshold )
671
- throw new Error( 'Should give a threshold value' );
672
- this.threshold = threshold;
673
- this.validate = function ( value ) {
674
- if ( '' === value || isNaN( Number( value ) ) )
675
- throw new Violation( this, value, { value: Validator.errorCode.must_be_a_number } );
676
- if ( this.threshold <= value )
677
- throw new Violation( this, value, { threshold: this.threshold } );
678
- return true;
679
- };
680
- return this;
681
- },
682
- LessThanOrEqual: function ( threshold ) {
683
- this.__class__ = 'LessThanOrEqual';
684
- if ( 'undefined' === typeof threshold )
685
- throw new Error( 'Should give a threshold value' );
686
- this.threshold = threshold;
687
- this.validate = function ( value ) {
688
- if ( '' === value || isNaN( Number( value ) ) )
689
- throw new Violation( this, value, { value: Validator.errorCode.must_be_a_number } );
690
- if ( this.threshold < value )
691
- throw new Violation( this, value, { threshold: this.threshold } );
692
- return true;
693
- };
694
- return this;
695
- },
696
- NotNull: function () {
697
- this.__class__ = 'NotNull';
698
- this.validate = function ( value ) {
699
- if ( null === value || 'undefined' === typeof value )
700
- throw new Violation( this, value );
701
- return true;
702
- };
703
- return this;
704
- },
705
- NotBlank: function () {
706
- this.__class__ = 'NotBlank';
707
- this.validate = function ( value ) {
708
- if ( 'string' !== typeof value )
709
- throw new Violation( this, value, { value: Validator.errorCode.must_be_a_string } );
710
- if ( '' === value.replace( /^\s+/g, '' ).replace( /\s+$/g, '' ) )
711
- throw new Violation( this, value );
712
- return true;
713
- };
714
- return this;
715
- },
716
- Null: function () {
717
- this.__class__ = 'Null';
718
- this.validate = function ( value ) {
719
- if ( null !== value )
720
- throw new Violation( this, value );
721
- return true;
722
- };
723
- return this;
724
- },
725
- Range: function ( min, max ) {
726
- this.__class__ = 'Range';
727
- if ( 'undefined' === typeof min || 'undefined' === typeof max )
728
- throw new Error( 'Range assert expects min and max values' );
729
- this.min = min;
730
- this.max = max;
731
- this.validate = function ( value ) {
732
- try {
733
- // validate strings and objects with their Length
734
- if ( ( 'string' === typeof value && isNaN( Number( value ) ) ) || _isArray( value ) )
735
- new Assert().Length( { min: this.min, max: this.max } ).validate( value );
736
- // validate numbers with their value
737
- else
738
- new Assert().GreaterThanOrEqual( this.min ).validate( value ) && new Assert().LessThanOrEqual( this.max ).validate( value );
739
- return true;
740
- } catch ( violation ) {
741
- throw new Violation( this, value, violation.violation );
742
- }
743
- return true;
744
- };
745
- return this;
746
- },
747
- Regexp: function ( regexp, flag ) {
748
- this.__class__ = 'Regexp';
749
- if ( 'undefined' === typeof regexp )
750
- throw new Error( 'You must give a regexp' );
751
- this.regexp = regexp;
752
- this.flag = flag || '';
753
- this.validate = function ( value ) {
754
- if ( 'string' !== typeof value )
755
- throw new Violation( this, value, { value: Validator.errorCode.must_be_a_string } );
756
- if ( !new RegExp( this.regexp, this.flag ).test( value ) )
757
- throw new Violation( this, value, { regexp: this.regexp, flag: this.flag } );
758
- return true;
759
- };
760
- return this;
761
- },
762
- Required: function () {
763
- this.__class__ = 'Required';
764
- this.validate = function ( value ) {
765
- if ( 'undefined' === typeof value )
766
- throw new Violation( this, value );
767
- try {
768
- if ( 'string' === typeof value )
769
- new Assert().NotNull().validate( value ) && new Assert().NotBlank().validate( value );
770
- else if ( true === _isArray( value ) )
771
- new Assert().Length( { min: 1 } ).validate( value );
772
- } catch ( violation ) {
773
- throw new Violation( this, value );
774
- }
775
- return true;
776
- };
777
- return this;
778
- },
779
- // Unique() or Unique ( { key: foo } )
780
- Unique: function ( object ) {
781
- this.__class__ = 'Unique';
782
- if ( 'object' === typeof object )
783
- this.key = object.key;
784
- this.validate = function ( array ) {
785
- var value, store = [];
786
- if ( !_isArray( array ) )
787
- throw new Violation( this, array, { value: Validator.errorCode.must_be_an_array } );
788
- for ( var i = 0; i < array.length; i++ ) {
789
- value = 'object' === typeof array[ i ] ? array[ i ][ this.key ] : array[ i ];
790
- if ( 'undefined' === typeof value )
791
- continue;
792
- if ( -1 !== store.indexOf( value ) )
793
- throw new Violation( this, array, { value: value } );
794
- store.push( value );
795
- }
796
- return true;
797
- };
798
- return this;
799
- }
800
- };
801
- // expose to the world these awesome classes
802
- exports.Assert = Assert;
803
- exports.Validator = Validator;
804
- exports.Violation = Violation;
805
- exports.Constraint = Constraint;
806
- /**
807
- * Some useful object prototypes / functions here
808
- */
809
- // IE8<= compatibility
810
- // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
811
- if (!Array.prototype.indexOf)
812
- Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
813
-
814
- if (this === null) {
815
- throw new TypeError();
816
- }
817
- var t = Object(this);
818
- var len = t.length >>> 0;
819
- if (len === 0) {
820
- return -1;
821
- }
822
- var n = 0;
823
- if (arguments.length > 1) {
824
- n = Number(arguments[1]);
825
- if (n != n) { // shortcut for verifying if it's NaN
826
- n = 0;
827
- } else if (n !== 0 && n != Infinity && n != -Infinity) {
828
- n = (n > 0 || -1) * Math.floor(Math.abs(n));
829
- }
830
- }
831
- if (n >= len) {
832
- return -1;
833
- }
834
- var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
835
- for (; k < len; k++) {
836
- if (k in t && t[k] === searchElement) {
837
- return k;
838
- }
839
- }
840
- return -1;
841
- };
842
- // Test if object is empty, useful for Constraint violations check
843
- var _isEmptyObject = function ( obj ) {
844
- for ( var property in obj )
845
- return false;
846
- return true;
847
- };
848
- var _isArray = function ( obj ) {
849
- return Object.prototype.toString.call( obj ) === '[object Array]';
850
- };
851
- // AMD export
852
- if ( typeof define === 'function' && define.amd ) {
853
- define( 'vendors/validator.js/dist/validator',[],function() {
854
- return exports;
855
- } );
856
- // commonjs export
857
- } else if ( typeof module !== 'undefined' && module.exports ) {
858
- module.exports = exports;
859
- // browser
860
- } else {
861
- window[ 'undefined' !== typeof validatorjs_ns ? validatorjs_ns : 'Validator' ] = exports;
862
- }
863
673
 
864
- return exports;
865
- } )( );
866
-
867
- // This is needed for Browserify usage that requires Validator.js through module.exports
868
- Validator = 'undefined' !== typeof Validator ? Validator : ('undefined' !== typeof module ? module.exports : null);
869
- var ParsleyValidator = function (validators, catalog) {
870
- this.__class__ = 'ParsleyValidator';
871
- this.Validator = Validator;
872
- // Default Parsley locale is en
873
- this.locale = 'en';
874
- this.init(validators || {}, catalog || {});
875
- };
876
- ParsleyValidator.prototype = {
877
- init: function (validators, catalog) {
878
- this.catalog = catalog;
879
- for (var name in validators)
880
- this.addValidator(name, validators[name].fn, validators[name].priority, validators[name].requirementsTransformer);
881
- $.emit('parsley:validator:init');
882
- },
883
- // Set new messages locale if we have dictionary loaded in ParsleyConfig.i18n
884
- setLocale: function (locale) {
885
- if ('undefined' === typeof this.catalog[locale])
886
- throw new Error(locale + ' is not available in the catalog');
887
- this.locale = locale;
888
- return this;
889
- },
890
- // Add a new messages catalog for a given locale. Set locale for this catalog if set === `true`
891
- addCatalog: function (locale, messages, set) {
892
- if ('object' === typeof messages)
893
- this.catalog[locale] = messages;
894
- if (true === set)
895
- return this.setLocale(locale);
896
- return this;
897
- },
898
- // Add a specific message for a given constraint in a given locale
899
- addMessage: function (locale, name, message) {
900
- if ('undefined' === typeof this.catalog[locale])
901
- this.catalog[locale] = {};
902
- this.catalog[locale][name.toLowerCase()] = message;
903
- return this;
904
- },
905
- validate: function (value, constraints, priority) {
906
- return new this.Validator.Validator().validate.apply(new Validator.Validator(), arguments);
907
- },
908
- // Add a new validator
909
- addValidator: function (name, fn, priority, requirementsTransformer) {
910
- this.validators[name.toLowerCase()] = function (requirements) {
911
- return $.extend(new Validator.Assert().Callback(fn, requirements), {
912
- priority: priority,
913
- requirementsTransformer: requirementsTransformer
914
- });
915
- };
916
- return this;
917
- },
918
- updateValidator: function (name, fn, priority, requirementsTransformer) {
919
- return this.addValidator(name, fn, priority, requirementsTransformer);
920
- },
921
- removeValidator: function (name) {
922
- delete this.validators[name];
923
- return this;
924
- },
925
- getErrorMessage: function (constraint) {
926
- var message;
927
- // Type constraints are a bit different, we have to match their requirements too to find right error message
928
- if ('type' === constraint.name)
929
- message = this.catalog[this.locale][constraint.name][constraint.requirements];
930
- else
931
- message = this.formatMessage(this.catalog[this.locale][constraint.name], constraint.requirements);
932
- return '' !== message ? message : this.catalog[this.locale].defaultMessage;
933
- },
934
- // Kind of light `sprintf()` implementation
935
- formatMessage: function (string, parameters) {
936
- if ('object' === typeof parameters) {
937
- for (var i in parameters)
938
- string = this.formatMessage(string, parameters[i]);
939
- return string;
940
- }
941
- return 'string' === typeof string ? string.replace(new RegExp('%s', 'i'), parameters) : '';
942
- },
943
674
  // Here is the Parsley default validators list.
944
- // This is basically Validatorjs validators, with different API for some of them
945
- // and a Parsley priority set
675
+ // A validator is an object with the following key values:
676
+ // - priority: an integer
677
+ // - requirement: 'string' (default), 'integer', 'number', 'regexp' or an Array of these
678
+ // - validateString, validateMultiple, validateNumber: functions returning `true`, `false` or a promise
679
+ // Alternatively, a validator can be a function that returns such an object
680
+ //
946
681
  validators: {
947
- notblank: function () {
948
- return $.extend(new Validator.Assert().NotBlank(), { priority: 2 });
682
+ notblank: {
683
+ validateString: function validateString(value) {
684
+ return (/\S/.test(value)
685
+ );
686
+ },
687
+ priority: 2
949
688
  },
950
- required: function () {
951
- return $.extend(new Validator.Assert().Required(), { priority: 512 });
689
+ required: {
690
+ validateMultiple: function validateMultiple(values) {
691
+ return values.length > 0;
692
+ },
693
+ validateString: function validateString(value) {
694
+ return (/\S/.test(value)
695
+ );
696
+ },
697
+ priority: 512
952
698
  },
953
- type: function (type) {
954
- var assert;
955
- switch (type) {
956
- case 'email':
957
- assert = new Validator.Assert().Email();
958
- break;
959
- // range type just ensure we have a number here
960
- case 'range':
961
- case 'number':
962
- assert = new Validator.Assert().Regexp('^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)?(?:\\.\\d+)?$');
963
- break;
964
- case 'integer':
965
- assert = new Validator.Assert().Regexp('^-?\\d+$');
966
- break;
967
- case 'digits':
968
- assert = new Validator.Assert().Regexp('^\\d+$');
969
- break;
970
- case 'alphanum':
971
- assert = new Validator.Assert().Regexp('^\\w+$', 'i');
972
- break;
973
- case 'url':
974
- assert = new Validator.Assert().Regexp('(https?:\\/\\/)?(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,24}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)', 'i');
975
- break;
976
- default:
699
+ type: {
700
+ validateString: function validateString(value, type) {
701
+ var _ref = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
702
+
703
+ var _ref$step = _ref.step;
704
+ var step = _ref$step === undefined ? '1' : _ref$step;
705
+ var _ref$base = _ref.base;
706
+ var base = _ref$base === undefined ? 0 : _ref$base;
707
+
708
+ var regex = typeRegexes[type];
709
+ if (!regex) {
977
710
  throw new Error('validator type `' + type + '` is not supported');
978
- }
979
- return $.extend(assert, { priority: 256 });
711
+ }
712
+ if (!regex.test(value)) return false;
713
+ if ('number' === type) {
714
+ if (!/^any$/i.test(step || '')) {
715
+ var nb = Number(value);
716
+ var decimals = Math.max(decimalPlaces(step), decimalPlaces(base));
717
+ if (decimalPlaces(nb) > decimals) // Value can't have too many decimals
718
+ return false;
719
+ // Be careful of rounding errors by using integers.
720
+ var toInt = function toInt(f) {
721
+ return Math.round(f * Math.pow(10, decimals));
722
+ };
723
+ if ((toInt(nb) - toInt(base)) % toInt(step) != 0) return false;
724
+ }
725
+ }
726
+ return true;
727
+ },
728
+ requirementType: {
729
+ '': 'string',
730
+ step: 'string',
731
+ base: 'number'
732
+ },
733
+ priority: 256
980
734
  },
981
- pattern: function (regexp) {
982
- var flags = '';
983
- // Test if RegExp is literal, if not, nothing to be done, otherwise, we need to isolate flags and pattern
984
- if (!!(/^\/.*\/(?:[gimy]*)$/.test(regexp))) {
985
- // Replace the regexp literal string with the first match group: ([gimy]*)
986
- // If no flag is present, this will be a blank string
987
- flags = regexp.replace(/.*\/([gimy]*)$/, '$1');
988
- // Again, replace the regexp literal string with the first match group:
989
- // everything excluding the opening and closing slashes and the flags
990
- regexp = regexp.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
991
- }
992
- return $.extend(new Validator.Assert().Regexp(regexp, flags), { priority: 64 });
735
+ pattern: {
736
+ validateString: function validateString(value, regexp) {
737
+ return regexp.test(value);
738
+ },
739
+ requirementType: 'regexp',
740
+ priority: 64
993
741
  },
994
- minlength: function (value) {
995
- return $.extend(new Validator.Assert().Length({ min: value }), {
996
- priority: 30,
997
- requirementsTransformer: function () {
998
- return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value;
999
- }
1000
- });
742
+ minlength: {
743
+ validateString: function validateString(value, requirement) {
744
+ return value.length >= requirement;
745
+ },
746
+ requirementType: 'integer',
747
+ priority: 30
1001
748
  },
1002
- maxlength: function (value) {
1003
- return $.extend(new Validator.Assert().Length({ max: value }), {
1004
- priority: 30,
1005
- requirementsTransformer: function () {
1006
- return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value;
1007
- }
1008
- });
749
+ maxlength: {
750
+ validateString: function validateString(value, requirement) {
751
+ return value.length <= requirement;
752
+ },
753
+ requirementType: 'integer',
754
+ priority: 30
1009
755
  },
1010
- length: function (array) {
1011
- return $.extend(new Validator.Assert().Length({ min: array[0], max: array[1] }), { priority: 32 });
756
+ length: {
757
+ validateString: function validateString(value, min, max) {
758
+ return value.length >= min && value.length <= max;
759
+ },
760
+ requirementType: ['integer', 'integer'],
761
+ priority: 30
1012
762
  },
1013
- mincheck: function (length) {
1014
- return this.minlength(length);
763
+ mincheck: {
764
+ validateMultiple: function validateMultiple(values, requirement) {
765
+ return values.length >= requirement;
766
+ },
767
+ requirementType: 'integer',
768
+ priority: 30
1015
769
  },
1016
- maxcheck: function (length) {
1017
- return this.maxlength(length);
770
+ maxcheck: {
771
+ validateMultiple: function validateMultiple(values, requirement) {
772
+ return values.length <= requirement;
773
+ },
774
+ requirementType: 'integer',
775
+ priority: 30
1018
776
  },
1019
- check: function (array) {
1020
- return this.length(array);
777
+ check: {
778
+ validateMultiple: function validateMultiple(values, min, max) {
779
+ return values.length >= min && values.length <= max;
780
+ },
781
+ requirementType: ['integer', 'integer'],
782
+ priority: 30
1021
783
  },
1022
- min: function (value) {
1023
- return $.extend(new Validator.Assert().GreaterThanOrEqual(value), {
1024
- priority: 30,
1025
- requirementsTransformer: function () {
1026
- return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value;
1027
- }
1028
- });
784
+ min: {
785
+ validateNumber: function validateNumber(value, requirement) {
786
+ return value >= requirement;
787
+ },
788
+ requirementType: 'number',
789
+ priority: 30
1029
790
  },
1030
- max: function (value) {
1031
- return $.extend(new Validator.Assert().LessThanOrEqual(value), {
1032
- priority: 30,
1033
- requirementsTransformer: function () {
1034
- return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value;
1035
- }
1036
- });
791
+ max: {
792
+ validateNumber: function validateNumber(value, requirement) {
793
+ return value <= requirement;
794
+ },
795
+ requirementType: 'number',
796
+ priority: 30
1037
797
  },
1038
- range: function (array) {
1039
- return $.extend(new Validator.Assert().Range(array[0], array[1]), {
1040
- priority: 32,
1041
- requirementsTransformer: function () {
1042
- for (var i = 0; i < array.length; i++)
1043
- array[i] = 'string' === typeof array[i] && !isNaN(array[i]) ? parseInt(array[i], 10) : array[i];
1044
- return array;
1045
- }
1046
- });
798
+ range: {
799
+ validateNumber: function validateNumber(value, min, max) {
800
+ return value >= min && value <= max;
801
+ },
802
+ requirementType: ['number', 'number'],
803
+ priority: 30
1047
804
  },
1048
- equalto: function (value) {
1049
- return $.extend(new Validator.Assert().EqualTo(value), {
1050
- priority: 256,
1051
- requirementsTransformer: function () {
1052
- return $(value).length ? $(value).val() : value;
1053
- }
1054
- });
805
+ equalto: {
806
+ validateString: function validateString(value, refOrValue) {
807
+ var $reference = $(refOrValue);
808
+ if ($reference.length) return value === $reference.val();else return value === refOrValue;
809
+ },
810
+ priority: 256
1055
811
  }
1056
812
  }
1057
813
  };
1058
814
 
1059
- var ParsleyUI = function (options) {
1060
- this.__class__ = 'ParsleyUI';
815
+ var ParsleyUI = {};
816
+
817
+ var diffResults = function diffResults(newResult, oldResult, deep) {
818
+ var added = [];
819
+ var kept = [];
820
+
821
+ for (var i = 0; i < newResult.length; i++) {
822
+ var found = false;
823
+
824
+ for (var j = 0; j < oldResult.length; j++) if (newResult[i].assert.name === oldResult[j].assert.name) {
825
+ found = true;
826
+ break;
827
+ }
828
+
829
+ if (found) kept.push(newResult[i]);else added.push(newResult[i]);
830
+ }
831
+
832
+ return {
833
+ kept: kept,
834
+ added: added,
835
+ removed: !deep ? diffResults(oldResult, newResult, true).added : []
836
+ };
1061
837
  };
1062
- ParsleyUI.prototype = {
1063
- listen: function () {
1064
- $.listen('parsley:form:init', this, this.setupForm);
1065
- $.listen('parsley:field:init', this, this.setupField);
1066
- $.listen('parsley:field:validated', this, this.reflow);
1067
- $.listen('parsley:form:validated', this, this.focus);
1068
- $.listen('parsley:field:reset', this, this.reset);
1069
- $.listen('parsley:form:destroy', this, this.destroy);
1070
- $.listen('parsley:field:destroy', this, this.destroy);
1071
- return this;
838
+
839
+ ParsleyUI.Form = {
840
+
841
+ _actualizeTriggers: function _actualizeTriggers() {
842
+ var _this2 = this;
843
+
844
+ this.$element.on('submit.Parsley', function (evt) {
845
+ _this2.onSubmitValidate(evt);
846
+ });
847
+ this.$element.on('click.Parsley', ParsleyUtils__default._SubmitSelector, function (evt) {
848
+ _this2.onSubmitButton(evt);
849
+ });
850
+
851
+ // UI could be disabled
852
+ if (false === this.options.uiEnabled) return;
853
+
854
+ this.$element.attr('novalidate', '');
1072
855
  },
1073
- reflow: function (fieldInstance) {
1074
- // If this field has not an active UI (case for multiples) don't bother doing something
1075
- if ('undefined' === typeof fieldInstance._ui || false === fieldInstance._ui.active)
1076
- return;
856
+
857
+ focus: function focus() {
858
+ this._focusedField = null;
859
+
860
+ if (true === this.validationResult || 'none' === this.options.focus) return null;
861
+
862
+ for (var i = 0; i < this.fields.length; i++) {
863
+ var field = this.fields[i];
864
+ if (true !== field.validationResult && field.validationResult.length > 0 && 'undefined' === typeof field.options.noFocus) {
865
+ this._focusedField = field.$element;
866
+ if ('first' === this.options.focus) break;
867
+ }
868
+ }
869
+
870
+ if (null === this._focusedField) return null;
871
+
872
+ return this._focusedField.focus();
873
+ },
874
+
875
+ _destroyUI: function _destroyUI() {
876
+ // Reset all event listeners
877
+ this.$element.off('.Parsley');
878
+ }
879
+
880
+ };
881
+
882
+ ParsleyUI.Field = {
883
+
884
+ _reflowUI: function _reflowUI() {
885
+ this._buildUI();
886
+
887
+ // If this field doesn't have an active UI don't bother doing something
888
+ if (!this._ui) return;
889
+
1077
890
  // Diff between two validation results
1078
- var diff = this._diff(fieldInstance.validationResult, fieldInstance._ui.lastValidationResult);
891
+ var diff = diffResults(this.validationResult, this._ui.lastValidationResult);
892
+
1079
893
  // Then store current validation result for next reflow
1080
- fieldInstance._ui.lastValidationResult = fieldInstance.validationResult;
1081
- // Field have been validated at least once if here. Useful for binded key events...
1082
- fieldInstance._ui.validatedOnce = true;
894
+ this._ui.lastValidationResult = this.validationResult;
895
+
1083
896
  // Handle valid / invalid / none field class
1084
- this.manageStatusClass(fieldInstance);
897
+ this._manageStatusClass();
898
+
1085
899
  // Add, remove, updated errors messages
1086
- this.manageErrorsMessages(fieldInstance, diff);
900
+ this._manageErrorsMessages(diff);
901
+
1087
902
  // Triggers impl
1088
- this.actualizeTriggers(fieldInstance);
903
+ this._actualizeTriggers();
904
+
1089
905
  // If field is not valid for the first time, bind keyup trigger to ease UX and quickly inform user
1090
- if ((diff.kept.length || diff.added.length) && 'undefined' === typeof fieldInstance._ui.failedOnce)
1091
- this.manageFailingFieldTrigger(fieldInstance);
906
+ if ((diff.kept.length || diff.added.length) && !this._failedOnce) {
907
+ this._failedOnce = true;
908
+ this._actualizeTriggers();
909
+ }
1092
910
  },
911
+
1093
912
  // Returns an array of field's error message(s)
1094
- getErrorsMessages: function (fieldInstance) {
913
+ getErrorsMessages: function getErrorsMessages() {
1095
914
  // No error message, field is valid
1096
- if (true === fieldInstance.validationResult)
1097
- return [];
915
+ if (true === this.validationResult) return [];
916
+
1098
917
  var messages = [];
1099
- for (var i = 0; i < fieldInstance.validationResult.length; i++)
1100
- messages.push(this._getErrorMessage(fieldInstance, fieldInstance.validationResult[i].assert));
918
+
919
+ for (var i = 0; i < this.validationResult.length; i++) messages.push(this.validationResult[i].errorMessage || this._getErrorMessage(this.validationResult[i].assert));
920
+
1101
921
  return messages;
1102
922
  },
1103
- manageStatusClass: function (fieldInstance) {
1104
- if (true === fieldInstance.validationResult)
1105
- this._successClass(fieldInstance);
1106
- else if (fieldInstance.validationResult.length > 0)
1107
- this._errorClass(fieldInstance);
1108
- else
1109
- this._resetClass(fieldInstance);
923
+
924
+ // It's a goal of Parsley that this method is no longer required [#1073]
925
+ addError: function addError(name) {
926
+ var _ref2 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
927
+
928
+ var message = _ref2.message;
929
+ var assert = _ref2.assert;
930
+ var _ref2$updateClass = _ref2.updateClass;
931
+ var updateClass = _ref2$updateClass === undefined ? true : _ref2$updateClass;
932
+
933
+ this._buildUI();
934
+ this._addError(name, { message: message, assert: assert });
935
+
936
+ if (updateClass) this._errorClass();
1110
937
  },
1111
- manageErrorsMessages: function (fieldInstance, diff) {
1112
- if ('undefined' !== typeof fieldInstance.options.errorsMessagesDisabled)
1113
- return;
938
+
939
+ // It's a goal of Parsley that this method is no longer required [#1073]
940
+ updateError: function updateError(name) {
941
+ var _ref3 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
942
+
943
+ var message = _ref3.message;
944
+ var assert = _ref3.assert;
945
+ var _ref3$updateClass = _ref3.updateClass;
946
+ var updateClass = _ref3$updateClass === undefined ? true : _ref3$updateClass;
947
+
948
+ this._buildUI();
949
+ this._updateError(name, { message: message, assert: assert });
950
+
951
+ if (updateClass) this._errorClass();
952
+ },
953
+
954
+ // It's a goal of Parsley that this method is no longer required [#1073]
955
+ removeError: function removeError(name) {
956
+ var _ref4 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
957
+
958
+ var _ref4$updateClass = _ref4.updateClass;
959
+ var updateClass = _ref4$updateClass === undefined ? true : _ref4$updateClass;
960
+
961
+ this._buildUI();
962
+ this._removeError(name);
963
+
964
+ // edge case possible here: remove a standard Parsley error that is still failing in this.validationResult
965
+ // but highly improbable cuz' manually removing a well Parsley handled error makes no sense.
966
+ if (updateClass) this._manageStatusClass();
967
+ },
968
+
969
+ _manageStatusClass: function _manageStatusClass() {
970
+ if (this.hasConstraints() && this.needsValidation() && true === this.validationResult) this._successClass();else if (this.validationResult.length > 0) this._errorClass();else this._resetClass();
971
+ },
972
+
973
+ _manageErrorsMessages: function _manageErrorsMessages(diff) {
974
+ if ('undefined' !== typeof this.options.errorsMessagesDisabled) return;
975
+
1114
976
  // Case where we have errorMessage option that configure an unique field error message, regardless failing validators
1115
- if ('undefined' !== typeof fieldInstance.options.errorMessage) {
1116
- if ((diff.added.length || diff.kept.length)) {
1117
- if (0 === fieldInstance._ui.$errorsWrapper.find('.parsley-custom-error-message').length)
1118
- fieldInstance._ui.$errorsWrapper
1119
- .append(
1120
- $(fieldInstance.options.errorTemplate)
1121
- .addClass('parsley-custom-error-message')
1122
- );
1123
- return fieldInstance._ui.$errorsWrapper
1124
- .addClass('filled')
1125
- .find('.parsley-custom-error-message')
1126
- .html(fieldInstance.options.errorMessage);
977
+ if ('undefined' !== typeof this.options.errorMessage) {
978
+ if (diff.added.length || diff.kept.length) {
979
+ this._insertErrorWrapper();
980
+
981
+ if (0 === this._ui.$errorsWrapper.find('.parsley-custom-error-message').length) this._ui.$errorsWrapper.append($(this.options.errorTemplate).addClass('parsley-custom-error-message'));
982
+
983
+ return this._ui.$errorsWrapper.addClass('filled').find('.parsley-custom-error-message').html(this.options.errorMessage);
1127
984
  }
1128
- return fieldInstance._ui.$errorsWrapper
1129
- .removeClass('filled')
1130
- .find('.parsley-custom-error-message')
1131
- .remove();
985
+
986
+ return this._ui.$errorsWrapper.removeClass('filled').find('.parsley-custom-error-message').remove();
1132
987
  }
988
+
1133
989
  // Show, hide, update failing constraints messages
1134
- for (var i = 0; i < diff.removed.length; i++)
1135
- this.removeError(fieldInstance, diff.removed[i].assert.name, true);
1136
- for (i = 0; i < diff.added.length; i++)
1137
- this.addError(fieldInstance, diff.added[i].assert.name, undefined, diff.added[i].assert, true);
1138
- for (i = 0; i < diff.kept.length; i++)
1139
- this.updateError(fieldInstance, diff.kept[i].assert.name, undefined, diff.kept[i].assert, true);
1140
- },
1141
- // TODO: strange API here, intuitive for manual usage with addError(pslyInstance, 'foo', 'bar')
1142
- // but a little bit complex for above internal usage, with forced undefined parameter...
1143
- addError: function (fieldInstance, name, message, assert, doNotUpdateClass) {
1144
- fieldInstance._ui.$errorsWrapper
1145
- .addClass('filled')
1146
- .append(
1147
- $(fieldInstance.options.errorTemplate)
1148
- .addClass('parsley-' + name)
1149
- .html(message || this._getErrorMessage(fieldInstance, assert))
1150
- );
1151
- if (true !== doNotUpdateClass)
1152
- this._errorClass(fieldInstance);
1153
- },
1154
- // Same as above
1155
- updateError: function (fieldInstance, name, message, assert, doNotUpdateClass) {
1156
- fieldInstance._ui.$errorsWrapper
1157
- .addClass('filled')
1158
- .find('.parsley-' + name)
1159
- .html(message || this._getErrorMessage(fieldInstance, assert));
1160
- if (true !== doNotUpdateClass)
1161
- this._errorClass(fieldInstance);
1162
- },
1163
- // Same as above twice
1164
- removeError: function (fieldInstance, name, doNotUpdateClass) {
1165
- fieldInstance._ui.$errorsWrapper
1166
- .removeClass('filled')
1167
- .find('.parsley-' + name)
1168
- .remove();
1169
- // edge case possible here: remove a standard Parsley error that is still failing in fieldInstance.validationResult
1170
- // but highly improbable cuz' manually removing a well Parsley handled error makes no sense.
1171
- if (true !== doNotUpdateClass)
1172
- this.manageStatusClass(fieldInstance);
1173
- },
1174
- focus: function (formInstance) {
1175
- if (true === formInstance.validationResult || 'none' === formInstance.options.focus)
1176
- return formInstance._focusedField = null;
1177
- formInstance._focusedField = null;
1178
- for (var i = 0; i < formInstance.fields.length; i++)
1179
- if (true !== formInstance.fields[i].validationResult && formInstance.fields[i].validationResult.length > 0 && 'undefined' === typeof formInstance.fields[i].options.noFocus) {
1180
- if ('first' === formInstance.options.focus) {
1181
- formInstance._focusedField = formInstance.fields[i].$element;
1182
- return formInstance._focusedField.focus();
1183
- }
1184
- formInstance._focusedField = formInstance.fields[i].$element;
1185
- }
1186
- if (null === formInstance._focusedField)
1187
- return null;
1188
- return formInstance._focusedField.focus();
990
+ for (var i = 0; i < diff.removed.length; i++) this._removeError(diff.removed[i].assert.name);
991
+
992
+ 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 });
993
+
994
+ 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 });
1189
995
  },
1190
- _getErrorMessage: function (fieldInstance, constraint) {
1191
- var customConstraintErrorMessage = constraint.name + 'Message';
1192
- if ('undefined' !== typeof fieldInstance.options[customConstraintErrorMessage])
1193
- return window.ParsleyValidator.formatMessage(fieldInstance.options[customConstraintErrorMessage], constraint.requirements);
1194
- return window.ParsleyValidator.getErrorMessage(constraint);
1195
- },
1196
- _diff: function (newResult, oldResult, deep) {
1197
- var
1198
- added = [],
1199
- kept = [];
1200
- for (var i = 0; i < newResult.length; i++) {
1201
- var found = false;
1202
- for (var j = 0; j < oldResult.length; j++)
1203
- if (newResult[i].assert.name === oldResult[j].assert.name) {
1204
- found = true;
1205
- break;
1206
- }
1207
- if (found)
1208
- kept.push(newResult[i]);
1209
- else
1210
- added.push(newResult[i]);
1211
- }
1212
- return {
1213
- kept: kept,
1214
- added: added,
1215
- removed: !deep ? this._diff(oldResult, newResult, true).added : []
1216
- };
996
+
997
+ _addError: function _addError(name, _ref5) {
998
+ var message = _ref5.message;
999
+ var assert = _ref5.assert;
1000
+
1001
+ this._insertErrorWrapper();
1002
+ this._ui.$errorsWrapper.addClass('filled').append($(this.options.errorTemplate).addClass('parsley-' + name).html(message || this._getErrorMessage(assert)));
1217
1003
  },
1218
- setupForm: function (formInstance) {
1219
- formInstance.$element.on('submit.Parsley', false, $.proxy(formInstance.onSubmitValidate, formInstance));
1220
- // UI could be disabled
1221
- if (false === formInstance.options.uiEnabled)
1222
- return;
1223
- formInstance.$element.attr('novalidate', '');
1004
+
1005
+ _updateError: function _updateError(name, _ref6) {
1006
+ var message = _ref6.message;
1007
+ var assert = _ref6.assert;
1008
+
1009
+ this._ui.$errorsWrapper.addClass('filled').find('.parsley-' + name).html(message || this._getErrorMessage(assert));
1224
1010
  },
1225
- setupField: function (fieldInstance) {
1226
- var _ui = { active: false };
1227
- // UI could be disabled
1228
- if (false === fieldInstance.options.uiEnabled)
1229
- return;
1230
- _ui.active = true;
1011
+
1012
+ _removeError: function _removeError(name) {
1013
+ this._ui.$errorsWrapper.removeClass('filled').find('.parsley-' + name).remove();
1014
+ },
1015
+
1016
+ _getErrorMessage: function _getErrorMessage(constraint) {
1017
+ var customConstraintErrorMessage = constraint.name + 'Message';
1018
+
1019
+ if ('undefined' !== typeof this.options[customConstraintErrorMessage]) return window.Parsley.formatMessage(this.options[customConstraintErrorMessage], constraint.requirements);
1020
+
1021
+ return window.Parsley.getErrorMessage(constraint);
1022
+ },
1023
+
1024
+ _buildUI: function _buildUI() {
1025
+ // UI could be already built or disabled
1026
+ if (this._ui || false === this.options.uiEnabled) return;
1027
+
1028
+ var _ui = {};
1029
+
1231
1030
  // Give field its Parsley id in DOM
1232
- fieldInstance.$element.attr(fieldInstance.options.namespace + 'id', fieldInstance.__id__);
1233
- /** Generate important UI elements and store them in fieldInstance **/
1031
+ this.$element.attr(this.options.namespace + 'id', this.__id__);
1032
+
1033
+ /** Generate important UI elements and store them in this **/
1234
1034
  // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes
1235
- _ui.$errorClassHandler = this._manageClassHandler(fieldInstance);
1035
+ _ui.$errorClassHandler = this._manageClassHandler();
1036
+
1236
1037
  // $errorsWrapper is a div that would contain the various field errors, it will be appended into $errorsContainer
1237
- _ui.errorsWrapperId = 'parsley-id-' + ('undefined' !== typeof fieldInstance.options.multiple ? 'multiple-' + fieldInstance.options.multiple : fieldInstance.__id__);
1238
- _ui.$errorsWrapper = $(fieldInstance.options.errorsWrapper).attr('id', _ui.errorsWrapperId);
1038
+ _ui.errorsWrapperId = 'parsley-id-' + (this.options.multiple ? 'multiple-' + this.options.multiple : this.__id__);
1039
+ _ui.$errorsWrapper = $(this.options.errorsWrapper).attr('id', _ui.errorsWrapperId);
1040
+
1239
1041
  // ValidationResult UI storage to detect what have changed bwt two validations, and update DOM accordingly
1240
1042
  _ui.lastValidationResult = [];
1241
- _ui.validatedOnce = false;
1242
1043
  _ui.validationInformationVisible = false;
1243
- // Store it in fieldInstance for later
1244
- fieldInstance._ui = _ui;
1245
- // Stops excluded inputs from getting errorContainer added
1246
- if( !fieldInstance.$element.is(fieldInstance.options.excluded) ) {
1247
- /** Mess with DOM now **/
1248
- this._insertErrorWrapper(fieldInstance);
1249
- }
1250
- // Bind triggers first time
1251
- this.actualizeTriggers(fieldInstance);
1044
+
1045
+ // Store it in this for later
1046
+ this._ui = _ui;
1252
1047
  },
1048
+
1253
1049
  // Determine which element will have `parsley-error` and `parsley-success` classes
1254
- _manageClassHandler: function (fieldInstance) {
1050
+ _manageClassHandler: function _manageClassHandler() {
1255
1051
  // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
1256
- if ('string' === typeof fieldInstance.options.classHandler && $(fieldInstance.options.classHandler).length)
1257
- return $(fieldInstance.options.classHandler);
1052
+ if ('string' === typeof this.options.classHandler && $(this.options.classHandler).length) return $(this.options.classHandler);
1053
+
1258
1054
  // Class handled could also be determined by function given in Parsley options
1259
- var $handler = fieldInstance.options.classHandler(fieldInstance);
1055
+ var $handler = this.options.classHandler.call(this, this);
1056
+
1260
1057
  // If this function returned a valid existing DOM element, go for it
1261
- if ('undefined' !== typeof $handler && $handler.length)
1262
- return $handler;
1263
- // Otherwise, if simple element (input, texatrea, select...) it will perfectly host the classes
1264
- if ('undefined' === typeof fieldInstance.options.multiple || fieldInstance.$element.is('select'))
1265
- return fieldInstance.$element;
1058
+ if ('undefined' !== typeof $handler && $handler.length) return $handler;
1059
+
1060
+ return this._inputHolder();
1061
+ },
1062
+
1063
+ _inputHolder: function _inputHolder() {
1064
+ // if simple element (input, texatrea, select...) it will perfectly host the classes and precede the error container
1065
+ if (!this.options.multiple || this.$element.is('select')) return this.$element;
1066
+
1266
1067
  // But if multiple element (radio, checkbox), that would be their parent
1267
- return fieldInstance.$element.parent();
1068
+ return this.$element.parent();
1268
1069
  },
1269
- _insertErrorWrapper: function (fieldInstance) {
1070
+
1071
+ _insertErrorWrapper: function _insertErrorWrapper() {
1270
1072
  var $errorsContainer;
1271
- if ('string' === typeof fieldInstance.options.errorsContainer) {
1272
- if ($(fieldInstance.options.errorsContainer).length)
1273
- return $(fieldInstance.options.errorsContainer).append(fieldInstance._ui.$errorsWrapper);
1274
- else if (window.console && window.console.warn)
1275
- window.console.warn('The errors container `' + fieldInstance.options.errorsContainer + '` does not exist in DOM');
1276
- }
1277
- else if ('function' === typeof fieldInstance.options.errorsContainer)
1278
- $errorsContainer = fieldInstance.options.errorsContainer(fieldInstance);
1279
- if ('undefined' !== typeof $errorsContainer && $errorsContainer.length)
1280
- return $errorsContainer.append(fieldInstance._ui.$errorsWrapper);
1281
- return 'undefined' === typeof fieldInstance.options.multiple ? fieldInstance.$element.after(fieldInstance._ui.$errorsWrapper) : fieldInstance.$element.parent().after(fieldInstance._ui.$errorsWrapper);
1282
- },
1283
- actualizeTriggers: function (fieldInstance) {
1284
- var $toBind = fieldInstance.$element;
1285
- if (fieldInstance.options.multiple)
1286
- $toBind = $('[' + fieldInstance.options.namespace + 'multiple="' + fieldInstance.options.multiple + '"]')
1287
- // Remove Parsley events already binded on this field
1073
+
1074
+ // Nothing to do if already inserted
1075
+ if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
1076
+
1077
+ if ('string' === typeof this.options.errorsContainer) {
1078
+ 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');
1079
+ } else if ('function' === typeof this.options.errorsContainer) $errorsContainer = this.options.errorsContainer.call(this, this);
1080
+
1081
+ if ('undefined' !== typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
1082
+
1083
+ return this._inputHolder().after(this._ui.$errorsWrapper);
1084
+ },
1085
+
1086
+ _actualizeTriggers: function _actualizeTriggers() {
1087
+ var _this3 = this;
1088
+
1089
+ var $toBind = this._findRelated();
1090
+ var trigger;
1091
+
1092
+ // Remove Parsley events already bound on this field
1288
1093
  $toBind.off('.Parsley');
1289
- // If no trigger is set, all good
1290
- if (false === fieldInstance.options.trigger)
1291
- return;
1292
- var triggers = fieldInstance.options.trigger.replace(/^\s+/g , '').replace(/\s+$/g , '');
1293
- if ('' === triggers)
1294
- return;
1295
- // Bind fieldInstance.eventValidate if exists (for parsley.ajax for example), ParsleyUI.eventValidate otherwise
1296
- $toBind.on(
1297
- triggers.split(' ').join('.Parsley ') + '.Parsley',
1298
- $.proxy('function' === typeof fieldInstance.eventValidate ? fieldInstance.eventValidate : this.eventValidate, fieldInstance));
1299
- },
1300
- // Called through $.proxy with fieldInstance. `this` context is ParsleyField
1301
- eventValidate: function(event) {
1302
- // For keyup, keypress, keydown... events that could be a little bit obstrusive
1094
+ if (this._failedOnce) $toBind.on(ParsleyUtils__default.namespaceEvents(this.options.triggerAfterFailure, 'Parsley'), function () {
1095
+ _this3.validate();
1096
+ });else if (trigger = ParsleyUtils__default.namespaceEvents(this.options.trigger, 'Parsley')) {
1097
+ $toBind.on(trigger, function (event) {
1098
+ _this3._eventValidate(event);
1099
+ });
1100
+ }
1101
+ },
1102
+
1103
+ _eventValidate: function _eventValidate(event) {
1104
+ // For keyup, keypress, keydown, input... events that could be a little bit obstrusive
1303
1105
  // do not validate if val length < min threshold on first validation. Once field have been validated once and info
1304
1106
  // about success or failure have been displayed, always validate with this trigger to reflect every yalidation change.
1305
- if (new RegExp('key').test(event.type))
1306
- if (!this._ui.validationInformationVisible && this.getValue().length <= this.options.validationThreshold)
1307
- return;
1308
- this._ui.validatedOnce = true;
1107
+ if (/key|input/.test(event.type)) if (!(this._ui && this._ui.validationInformationVisible) && this.getValue().length <= this.options.validationThreshold) return;
1108
+
1309
1109
  this.validate();
1310
1110
  },
1311
- manageFailingFieldTrigger: function (fieldInstance) {
1312
- fieldInstance._ui.failedOnce = true;
1313
- // Radio and checkboxes fields must bind every field multiple
1314
- if (fieldInstance.options.multiple)
1315
- $('[' + fieldInstance.options.namespace + 'multiple="' + fieldInstance.options.multiple + '"]').each(function () {
1316
- if (!new RegExp('change', 'i').test($(this).parsley().options.trigger || ''))
1317
- return $(this).on('change.ParsleyFailedOnce', false, $.proxy(fieldInstance.validate, fieldInstance));
1318
- });
1319
- // Select case
1320
- if (fieldInstance.$element.is('select'))
1321
- if (!new RegExp('change', 'i').test(fieldInstance.options.trigger || ''))
1322
- return fieldInstance.$element.on('change.ParsleyFailedOnce', false, $.proxy(fieldInstance.validate, fieldInstance));
1323
- // All other inputs fields
1324
- if (!new RegExp('keyup', 'i').test(fieldInstance.options.trigger || ''))
1325
- return fieldInstance.$element.on('keyup.ParsleyFailedOnce', false, $.proxy(fieldInstance.validate, fieldInstance));
1326
- },
1327
- reset: function (parsleyInstance) {
1111
+
1112
+ _resetUI: function _resetUI() {
1328
1113
  // Reset all event listeners
1329
- parsleyInstance.$element.off('.Parsley');
1330
- parsleyInstance.$element.off('.ParsleyFailedOnce');
1114
+ this._failedOnce = false;
1115
+ this._actualizeTriggers();
1116
+
1331
1117
  // Nothing to do if UI never initialized for this field
1332
- if ('undefined' === typeof parsleyInstance._ui)
1333
- return;
1334
- if ('ParsleyForm' === parsleyInstance.__class__)
1335
- return;
1118
+ if ('undefined' === typeof this._ui) return;
1119
+
1336
1120
  // Reset all errors' li
1337
- parsleyInstance._ui.$errorsWrapper
1338
- .removeClass('filled')
1339
- .children()
1340
- .remove();
1121
+ this._ui.$errorsWrapper.removeClass('filled').children().remove();
1122
+
1341
1123
  // Reset validation class
1342
- this._resetClass(parsleyInstance);
1124
+ this._resetClass();
1125
+
1343
1126
  // Reset validation flags and last validation result
1344
- parsleyInstance._ui.validatedOnce = false;
1345
- parsleyInstance._ui.lastValidationResult = [];
1346
- parsleyInstance._ui.validationInformationVisible = false;
1127
+ this._ui.lastValidationResult = [];
1128
+ this._ui.validationInformationVisible = false;
1347
1129
  },
1348
- destroy: function (parsleyInstance) {
1349
- this.reset(parsleyInstance);
1350
- if ('ParsleyForm' === parsleyInstance.__class__)
1351
- return;
1352
- if ('undefined' !== typeof parsleyInstance._ui)
1353
- parsleyInstance._ui.$errorsWrapper.remove();
1354
- delete parsleyInstance._ui;
1355
- },
1356
- _successClass: function (fieldInstance) {
1357
- fieldInstance._ui.validationInformationVisible = true;
1358
- fieldInstance._ui.$errorClassHandler.removeClass(fieldInstance.options.errorClass).addClass(fieldInstance.options.successClass);
1359
- },
1360
- _errorClass: function (fieldInstance) {
1361
- fieldInstance._ui.validationInformationVisible = true;
1362
- fieldInstance._ui.$errorClassHandler.removeClass(fieldInstance.options.successClass).addClass(fieldInstance.options.errorClass);
1130
+
1131
+ _destroyUI: function _destroyUI() {
1132
+ this._resetUI();
1133
+
1134
+ if ('undefined' !== typeof this._ui) this._ui.$errorsWrapper.remove();
1135
+
1136
+ delete this._ui;
1363
1137
  },
1364
- _resetClass: function (fieldInstance) {
1365
- fieldInstance._ui.$errorClassHandler.removeClass(fieldInstance.options.successClass).removeClass(fieldInstance.options.errorClass);
1366
- }
1367
- };
1368
1138
 
1369
- var ParsleyOptionsFactory = function (defaultOptions, globalOptions, userOptions, namespace) {
1370
- this.__class__ = 'OptionsFactory';
1371
- this.__id__ = ParsleyUtils.hash(4);
1372
- this.formOptions = null;
1373
- this.fieldOptions = null;
1374
- this.staticOptions = $.extend(true, {}, defaultOptions, globalOptions, userOptions, { namespace: namespace });
1375
- };
1376
- ParsleyOptionsFactory.prototype = {
1377
- get: function (parsleyInstance) {
1378
- if ('undefined' === typeof parsleyInstance.__class__)
1379
- throw new Error('Parsley Instance expected');
1380
- switch (parsleyInstance.__class__) {
1381
- case 'Parsley':
1382
- return this.staticOptions;
1383
- case 'ParsleyForm':
1384
- return this.getFormOptions(parsleyInstance);
1385
- case 'ParsleyField':
1386
- case 'ParsleyFieldMultiple':
1387
- return this.getFieldOptions(parsleyInstance);
1388
- default:
1389
- throw new Error('Instance ' + parsleyInstance.__class__ + ' is not supported');
1390
- }
1139
+ _successClass: function _successClass() {
1140
+ this._ui.validationInformationVisible = true;
1141
+ this._ui.$errorClassHandler.removeClass(this.options.errorClass).addClass(this.options.successClass);
1142
+ },
1143
+ _errorClass: function _errorClass() {
1144
+ this._ui.validationInformationVisible = true;
1145
+ this._ui.$errorClassHandler.removeClass(this.options.successClass).addClass(this.options.errorClass);
1391
1146
  },
1392
- getFormOptions: function (formInstance) {
1393
- this.formOptions = ParsleyUtils.attr(formInstance.$element, this.staticOptions.namespace);
1394
- // not deep extend, since formOptions is a 1 level deep object
1395
- return $.extend({}, this.staticOptions, this.formOptions);
1396
- },
1397
- getFieldOptions: function (fieldInstance) {
1398
- this.fieldOptions = ParsleyUtils.attr(fieldInstance.$element, this.staticOptions.namespace);
1399
- if (null === this.formOptions && 'undefined' !== typeof fieldInstance.parent)
1400
- this.formOptions = this.getFormOptions(fieldInstance.parent);
1401
- // not deep extend, since formOptions and fieldOptions is a 1 level deep object
1402
- return $.extend({}, this.staticOptions, this.formOptions, this.fieldOptions);
1147
+ _resetClass: function _resetClass() {
1148
+ this._ui.$errorClassHandler.removeClass(this.options.successClass).removeClass(this.options.errorClass);
1403
1149
  }
1404
1150
  };
1405
1151
 
1406
- var ParsleyForm = function (element, OptionsFactory) {
1152
+ var ParsleyForm = function ParsleyForm(element, domOptions, options) {
1407
1153
  this.__class__ = 'ParsleyForm';
1408
- this.__id__ = ParsleyUtils.hash(4);
1409
- if ('OptionsFactory' !== ParsleyUtils.get(OptionsFactory, '__class__'))
1410
- throw new Error('You must give an OptionsFactory instance');
1411
- this.OptionsFactory = OptionsFactory;
1154
+
1412
1155
  this.$element = $(element);
1156
+ this.domOptions = domOptions;
1157
+ this.options = options;
1158
+ this.parent = window.Parsley;
1159
+
1160
+ this.fields = [];
1413
1161
  this.validationResult = null;
1414
- this.options = this.OptionsFactory.get(this);
1415
1162
  };
1163
+
1164
+ var ParsleyForm__statusMapping = { pending: null, resolved: true, rejected: false };
1165
+
1416
1166
  ParsleyForm.prototype = {
1417
- onSubmitValidate: function (event) {
1418
- this.validate(undefined, undefined, event);
1419
- // prevent form submission if validation fails
1420
- if (false === this.validationResult && event instanceof $.Event) {
1421
- event.stopImmediatePropagation();
1422
- event.preventDefault();
1167
+ onSubmitValidate: function onSubmitValidate(event) {
1168
+ var _this4 = this;
1169
+
1170
+ // This is a Parsley generated submit event, do not validate, do not prevent, simply exit and keep normal behavior
1171
+ if (true === event.parsley) return;
1172
+
1173
+ // If we didn't come here through a submit button, use the first one in the form
1174
+ var $submitSource = this._$submitSource || this.$element.find(ParsleyUtils__default._SubmitSelector).first();
1175
+ this._$submitSource = null;
1176
+ this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true);
1177
+ if ($submitSource.is('[formnovalidate]')) return;
1178
+
1179
+ var promise = this.whenValidate({ event: event });
1180
+
1181
+ if ('resolved' === promise.state() && false !== this._trigger('submit')) {
1182
+ // All good, let event go through. We make this distinction because browsers
1183
+ // differ in their handling of `submit` being called from inside a submit event [#1047]
1184
+ } else {
1185
+ // Rejected or pending: cancel this submit
1186
+ event.stopImmediatePropagation();
1187
+ event.preventDefault();
1188
+ if ('pending' === promise.state()) promise.done(function () {
1189
+ _this4._submit($submitSource);
1190
+ });
1191
+ }
1192
+ },
1193
+
1194
+ onSubmitButton: function onSubmitButton(event) {
1195
+ this._$submitSource = $(event.currentTarget);
1196
+ },
1197
+ // internal
1198
+ // _submit submits the form, this time without going through the validations.
1199
+ // Care must be taken to "fake" the actual submit button being clicked.
1200
+ _submit: function _submit($submitSource) {
1201
+ if (false === this._trigger('submit')) return;
1202
+ // Add submit button's data
1203
+ if ($submitSource) {
1204
+ var $synthetic = this.$element.find('.parsley-synthetic-submit-button').prop('disabled', false);
1205
+ if (0 === $synthetic.length) $synthetic = $('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element);
1206
+ $synthetic.attr({
1207
+ name: $submitSource.attr('name'),
1208
+ value: $submitSource.attr('value')
1209
+ });
1423
1210
  }
1424
- return this;
1211
+
1212
+ this.$element.trigger($.extend($.Event('submit'), { parsley: true }));
1425
1213
  },
1426
- // @returns boolean
1427
- validate: function (group, force, event) {
1214
+
1215
+ // Performs validation on fields while triggering events.
1216
+ // @returns `true` if all validations succeeds, `false`
1217
+ // if a failure is immediately detected, or `null`
1218
+ // if dependant on a promise.
1219
+ // Consider using `whenValidate` instead.
1220
+ validate: function validate(options) {
1221
+ if (arguments.length >= 1 && !$.isPlainObject(options)) {
1222
+ ParsleyUtils__default.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.');
1223
+
1224
+ var _arguments = _slice.call(arguments);
1225
+
1226
+ var group = _arguments[0];
1227
+ var force = _arguments[1];
1228
+ var event = _arguments[2];
1229
+
1230
+ options = { group: group, force: force, event: event };
1231
+ }
1232
+ return ParsleyForm__statusMapping[this.whenValidate(options).state()];
1233
+ },
1234
+
1235
+ whenValidate: function whenValidate() {
1236
+ var _ParsleyUtils__default$all$done$fail$always,
1237
+ _this5 = this;
1238
+
1239
+ var _ref7 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
1240
+
1241
+ var group = _ref7.group;
1242
+ var force = _ref7.force;
1243
+ var event = _ref7.event;
1244
+
1428
1245
  this.submitEvent = event;
1246
+ if (event) {
1247
+ this.submitEvent = $.extend({}, event, { preventDefault: function preventDefault() {
1248
+ ParsleyUtils__default.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`");
1249
+ _this5.validationResult = false;
1250
+ } });
1251
+ }
1429
1252
  this.validationResult = true;
1430
- var fieldValidationResult = [];
1431
- $.emit('parsley:form:validate', this);
1253
+
1254
+ // fire validate event to eventually modify things before every validation
1255
+ this._trigger('validate');
1256
+
1432
1257
  // Refresh form DOM options and form's fields that could have changed
1433
1258
  this._refreshFields();
1434
- // loop through fields to validate them one by one
1435
- for (var i = 0; i < this.fields.length; i++) {
1436
- // do not validate a field if not the same as given validation group
1437
- if (group && !this._isFieldInGroup(this.fields[i], group))
1438
- continue;
1439
- fieldValidationResult = this.fields[i].validate(force);
1440
- if (true !== fieldValidationResult && fieldValidationResult.length > 0 && this.validationResult)
1441
- this.validationResult = false;
1442
- }
1443
- $.emit('parsley:form:' + (this.validationResult ? 'success' : 'error'), this);
1444
- $.emit('parsley:form:validated', this);
1445
- return this.validationResult;
1259
+
1260
+ var promises = this._withoutReactualizingFormOptions(function () {
1261
+ return $.map(_this5.fields, function (field) {
1262
+ return field.whenValidate({ force: force, group: group });
1263
+ });
1264
+ });
1265
+
1266
+ return (_ParsleyUtils__default$all$done$fail$always = ParsleyUtils__default.all(promises).done(function () {
1267
+ _this5._trigger('success');
1268
+ }).fail(function () {
1269
+ _this5.validationResult = false;
1270
+ _this5.focus();
1271
+ _this5._trigger('error');
1272
+ }).always(function () {
1273
+ _this5._trigger('validated');
1274
+ })).pipe.apply(_ParsleyUtils__default$all$done$fail$always, _toConsumableArray(this._pipeAccordingToValidationResult()));
1446
1275
  },
1447
- // Iterate over refreshed fields, and stop on first failure
1448
- isValid: function (group, force) {
1449
- this._refreshFields();
1450
- for (var i = 0; i < this.fields.length; i++) {
1451
- // do not validate a field if not the same as given validation group
1452
- if (group && !this._isFieldInGroup(this.fields[i], group))
1453
- continue;
1454
- if (false === this.fields[i].isValid(force))
1455
- return false;
1276
+
1277
+ // Iterate over refreshed fields, and stop on first failure.
1278
+ // Returns `true` if all fields are valid, `false` if a failure is detected
1279
+ // or `null` if the result depends on an unresolved promise.
1280
+ // Prefer using `whenValid` instead.
1281
+ isValid: function isValid(options) {
1282
+ if (arguments.length >= 1 && !$.isPlainObject(options)) {
1283
+ ParsleyUtils__default.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.');
1284
+
1285
+ var _arguments2 = _slice.call(arguments);
1286
+
1287
+ var group = _arguments2[0];
1288
+ var force = _arguments2[1];
1289
+
1290
+ options = { group: group, force: force };
1456
1291
  }
1457
- return true;
1292
+ return ParsleyForm__statusMapping[this.whenValid(options).state()];
1458
1293
  },
1459
- _isFieldInGroup: function (field, group) {
1460
- if(ParsleyUtils.isArray(field.options.group))
1461
- return -1 !== $.inArray(group, field.options.group);
1462
- return field.options.group === group;
1294
+
1295
+ // Iterate over refreshed fields and validate them.
1296
+ // Returns a promise.
1297
+ // A validation that immediately fails will interrupt the validations.
1298
+ whenValid: function whenValid() {
1299
+ var _this6 = this;
1300
+
1301
+ var _ref8 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
1302
+
1303
+ var group = _ref8.group;
1304
+ var force = _ref8.force;
1305
+
1306
+ this._refreshFields();
1307
+
1308
+ var promises = this._withoutReactualizingFormOptions(function () {
1309
+ return $.map(_this6.fields, function (field) {
1310
+ return field.whenValid({ group: group, force: force });
1311
+ });
1312
+ });
1313
+ return ParsleyUtils__default.all(promises);
1463
1314
  },
1464
- _refreshFields: function () {
1315
+
1316
+ _refreshFields: function _refreshFields() {
1465
1317
  return this.actualizeOptions()._bindFields();
1466
1318
  },
1467
- _bindFields: function () {
1468
- var self = this;
1319
+
1320
+ _bindFields: function _bindFields() {
1321
+ var _this7 = this;
1322
+
1323
+ var oldFields = this.fields;
1324
+
1469
1325
  this.fields = [];
1470
1326
  this.fieldsMappedById = {};
1471
- this.$element.find(this.options.inputs).each(function () {
1472
- var fieldInstance = new window.Parsley(this, {}, self);
1473
- // Only add valid and not excluded `ParsleyField` and `ParsleyFieldMultiple` children
1474
- if (('ParsleyField' === fieldInstance.__class__ || 'ParsleyFieldMultiple' === fieldInstance.__class__) && !fieldInstance.$element.is(fieldInstance.options.excluded))
1475
- if ('undefined' === typeof self.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__]) {
1476
- self.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__] = fieldInstance;
1477
- self.fields.push(fieldInstance);
1327
+
1328
+ this._withoutReactualizingFormOptions(function () {
1329
+ _this7.$element.find(_this7.options.inputs).not(_this7.options.excluded).each(function (_, element) {
1330
+ var fieldInstance = new window.Parsley.Factory(element, {}, _this7);
1331
+
1332
+ // Only add valid and not excluded `ParsleyField` and `ParsleyFieldMultiple` children
1333
+ if (('ParsleyField' === fieldInstance.__class__ || 'ParsleyFieldMultiple' === fieldInstance.__class__) && true !== fieldInstance.options.excluded) if ('undefined' === typeof _this7.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__]) {
1334
+ _this7.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__] = fieldInstance;
1335
+ _this7.fields.push(fieldInstance);
1478
1336
  }
1337
+ });
1338
+
1339
+ $.each(ParsleyUtils__default.difference(oldFields, _this7.fields), function (_, field) {
1340
+ field._trigger('reset');
1341
+ });
1479
1342
  });
1480
1343
  return this;
1344
+ },
1345
+
1346
+ // Internal only.
1347
+ // Looping on a form's fields to do validation or similar
1348
+ // will trigger reactualizing options on all of them, which
1349
+ // in turn will reactualize the form's options.
1350
+ // To avoid calling actualizeOptions so many times on the form
1351
+ // for nothing, _withoutReactualizingFormOptions temporarily disables
1352
+ // the method actualizeOptions on this form while `fn` is called.
1353
+ _withoutReactualizingFormOptions: function _withoutReactualizingFormOptions(fn) {
1354
+ var oldActualizeOptions = this.actualizeOptions;
1355
+ this.actualizeOptions = function () {
1356
+ return this;
1357
+ };
1358
+ var result = fn();
1359
+ this.actualizeOptions = oldActualizeOptions;
1360
+ return result;
1361
+ },
1362
+
1363
+ // Internal only.
1364
+ // Shortcut to trigger an event
1365
+ // Returns true iff event is not interrupted and default not prevented.
1366
+ _trigger: function _trigger(eventName) {
1367
+ return this.trigger('form:' + eventName);
1481
1368
  }
1369
+
1482
1370
  };
1483
1371
 
1484
- var ConstraintFactory = function (parsleyField, name, requirements, priority, isDomConstraint) {
1485
- var assert = {};
1486
- if (!new RegExp('ParsleyField').test(ParsleyUtils.get(parsleyField, '__class__')))
1487
- throw new Error('ParsleyField or ParsleyFieldMultiple instance expected');
1488
- if ('function' === typeof window.ParsleyValidator.validators[name])
1489
- assert = window.ParsleyValidator.validators[name](requirements);
1490
- if ('Assert' !== assert.__parentClass__)
1491
- throw new Error('Valid validator expected');
1492
- var getPriority = function () {
1493
- if ('undefined' !== typeof parsleyField.options[name + 'Priority'])
1494
- return parsleyField.options[name + 'Priority'];
1495
- return ParsleyUtils.get(assert, 'priority') || 2;
1496
- };
1497
- priority = priority || getPriority();
1498
- // If validator have a requirementsTransformer, execute it
1499
- if ('function' === typeof assert.requirementsTransformer) {
1500
- requirements = assert.requirementsTransformer();
1501
- // rebuild assert with new requirements
1502
- assert = window.ParsleyValidator.validators[name](requirements);
1503
- }
1504
- return $.extend(assert, {
1372
+ var ConstraintFactory = function ConstraintFactory(parsleyField, name, requirements, priority, isDomConstraint) {
1373
+ if (!/ParsleyField/.test(parsleyField.__class__)) throw new Error('ParsleyField or ParsleyFieldMultiple instance expected');
1374
+
1375
+ var validatorSpec = window.Parsley._validatorRegistry.validators[name];
1376
+ var validator = new ParsleyValidator(validatorSpec);
1377
+
1378
+ $.extend(this, {
1379
+ validator: validator,
1505
1380
  name: name,
1506
1381
  requirements: requirements,
1507
- priority: priority,
1508
- groups: [priority],
1509
- isDomConstraint: isDomConstraint || ParsleyUtils.attr(parsleyField.$element, parsleyField.options.namespace, name)
1382
+ priority: priority || parsleyField.options[name + 'Priority'] || validator.priority,
1383
+ isDomConstraint: true === isDomConstraint
1510
1384
  });
1385
+ this._parseRequirements(parsleyField.options);
1386
+ };
1387
+
1388
+ var capitalize = function capitalize(str) {
1389
+ var cap = str[0].toUpperCase();
1390
+ return cap + str.slice(1);
1391
+ };
1392
+
1393
+ ConstraintFactory.prototype = {
1394
+ validate: function validate(value, instance) {
1395
+ var _validator;
1396
+
1397
+ return (_validator = this.validator).validate.apply(_validator, [value].concat(_toConsumableArray(this.requirementList), [instance]));
1398
+ },
1399
+
1400
+ _parseRequirements: function _parseRequirements(options) {
1401
+ var _this8 = this;
1402
+
1403
+ this.requirementList = this.validator.parseRequirements(this.requirements, function (key) {
1404
+ return options[_this8.name + capitalize(key)];
1405
+ });
1406
+ }
1511
1407
  };
1512
1408
 
1513
- var ParsleyField = function (field, OptionsFactory, parsleyFormInstance) {
1409
+ var ParsleyField = function ParsleyField(field, domOptions, options, parsleyFormInstance) {
1514
1410
  this.__class__ = 'ParsleyField';
1515
- this.__id__ = ParsleyUtils.hash(4);
1411
+
1516
1412
  this.$element = $(field);
1517
- // If we have a parent `ParsleyForm` instance given, use its `OptionsFactory`, and save parent
1413
+
1414
+ // Set parent if we have one
1518
1415
  if ('undefined' !== typeof parsleyFormInstance) {
1519
1416
  this.parent = parsleyFormInstance;
1520
- this.OptionsFactory = this.parent.OptionsFactory;
1521
- this.options = this.OptionsFactory.get(this);
1522
- // Else, take the `Parsley` one
1523
- } else {
1524
- this.OptionsFactory = OptionsFactory;
1525
- this.options = this.OptionsFactory.get(this);
1526
1417
  }
1418
+
1419
+ this.options = options;
1420
+ this.domOptions = domOptions;
1421
+
1527
1422
  // Initialize some properties
1528
1423
  this.constraints = [];
1529
1424
  this.constraintsByName = {};
1530
- this.validationResult = [];
1425
+ this.validationResult = true;
1426
+
1531
1427
  // Bind constraints
1532
1428
  this._bindConstraints();
1533
1429
  };
1430
+
1431
+ var parsley_field__statusMapping = { pending: null, resolved: true, rejected: false };
1432
+
1534
1433
  ParsleyField.prototype = {
1535
1434
  // # Public API
1536
- // Validate field and $.emit some events for mainly `ParsleyUI`
1537
- // @returns validationResult:
1538
- // - `true` if all constraints pass
1539
- // - `[]` if not required field and empty (not validated)
1540
- // - `[Violation, [Violation...]]` if there were validation errors
1541
- validate: function (force) {
1435
+ // Validate field and trigger some events for mainly `ParsleyUI`
1436
+ // @returns `true`, an array of the validators that failed, or
1437
+ // `null` if validation is not finished. Prefer using whenValidate
1438
+ validate: function validate(options) {
1439
+ if (arguments.length >= 1 && !$.isPlainObject(options)) {
1440
+ ParsleyUtils__default.warnOnce('Calling validate on a parsley field without passing arguments as an object is deprecated.');
1441
+ options = { options: options };
1442
+ }
1443
+ var promise = this.whenValidate(options);
1444
+ if (!promise) // If excluded with `group` option
1445
+ return true;
1446
+ switch (promise.state()) {
1447
+ case 'pending':
1448
+ return null;
1449
+ case 'resolved':
1450
+ return true;
1451
+ case 'rejected':
1452
+ return this.validationResult;
1453
+ }
1454
+ },
1455
+
1456
+ // Validate field and trigger some events for mainly `ParsleyUI`
1457
+ // @returns a promise that succeeds only when all validations do
1458
+ // or `undefined` if field is not in the given `group`.
1459
+ whenValidate: function whenValidate() {
1460
+ var _whenValid$always$done$fail$always,
1461
+ _this9 = this;
1462
+
1463
+ var _ref9 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
1464
+
1465
+ var force = _ref9.force;
1466
+ var group = _ref9.group;
1467
+
1468
+ // do not validate a field if not the same as given validation group
1469
+ this.refreshConstraints();
1470
+ if (group && !this._isInGroup(group)) return;
1471
+
1542
1472
  this.value = this.getValue();
1473
+
1543
1474
  // Field Validate event. `this.value` could be altered for custom needs
1544
- $.emit('parsley:field:validate', this);
1545
- $.emit('parsley:field:' + (this.isValid(force, this.value) ? 'success' : 'error'), this);
1546
- // Field validated event. `this.validationResult` could be altered for custom needs too
1547
- $.emit('parsley:field:validated', this);
1548
- return this.validationResult;
1549
- },
1550
- // Just validate field. Do not trigger any event
1551
- // Same @return as `validate()`
1552
- isValid: function (force, value) {
1553
- // Recompute options and rebind constraints to have latest changes
1554
- this.refreshConstraints();
1555
- // Sort priorities to validate more important first
1556
- var priorities = this._getConstraintsSortedPriorities();
1557
- if (0 === priorities.length)
1558
- return this.validationResult = [];
1559
- // Value could be passed as argument, needed to add more power to 'parsley:field:validate'
1560
- if ('undefined' === typeof value || null === value)
1561
- value = this.getValue();
1562
- // If a field is empty and not required, leave it alone, it's just fine
1475
+ this._trigger('validate');
1476
+
1477
+ return (_whenValid$always$done$fail$always = this.whenValid({ force: force, value: this.value, _refreshed: true }).always(function () {
1478
+ _this9._reflowUI();
1479
+ }).done(function () {
1480
+ _this9._trigger('success');
1481
+ }).fail(function () {
1482
+ _this9._trigger('error');
1483
+ }).always(function () {
1484
+ _this9._trigger('validated');
1485
+ })).pipe.apply(_whenValid$always$done$fail$always, _toConsumableArray(this._pipeAccordingToValidationResult()));
1486
+ },
1487
+
1488
+ hasConstraints: function hasConstraints() {
1489
+ return 0 !== this.constraints.length;
1490
+ },
1491
+
1492
+ // An empty optional field does not need validation
1493
+ needsValidation: function needsValidation(value) {
1494
+ if ('undefined' === typeof value) value = this.getValue();
1495
+
1496
+ // If a field is empty and not required, it is valid
1563
1497
  // Except if `data-parsley-validate-if-empty` explicitely added, useful for some custom validators
1564
- if (!value.length && !this._isRequired() && 'undefined' === typeof this.options.validateIfEmpty && true !== force)
1565
- return this.validationResult = [];
1566
- // If we want to validate field against all constraints, just call Validator and let it do the job
1567
- if (false === this.options.priorityEnabled)
1568
- return true === (this.validationResult = this.validateThroughValidator(value, this.constraints, 'Any'));
1569
- // Else, iterate over priorities one by one, and validate related asserts one by one
1570
- for (var i = 0; i < priorities.length; i++)
1571
- if (true !== (this.validationResult = this.validateThroughValidator(value, this.constraints, priorities[i])))
1572
- return false;
1498
+ if (!value.length && !this._isRequired() && 'undefined' === typeof this.options.validateIfEmpty) return false;
1499
+
1573
1500
  return true;
1574
1501
  },
1502
+
1503
+ _isInGroup: function _isInGroup(group) {
1504
+ if ($.isArray(this.options.group)) return -1 !== $.inArray(group, this.options.group);
1505
+ return this.options.group === group;
1506
+ },
1507
+
1508
+ // Just validate field. Do not trigger any event.
1509
+ // Returns `true` iff all constraints pass, `false` if there are failures,
1510
+ // or `null` if the result can not be determined yet (depends on a promise)
1511
+ // See also `whenValid`.
1512
+ isValid: function isValid(options) {
1513
+ if (arguments.length >= 1 && !$.isPlainObject(options)) {
1514
+ ParsleyUtils__default.warnOnce('Calling isValid on a parsley field without passing arguments as an object is deprecated.');
1515
+
1516
+ var _arguments3 = _slice.call(arguments);
1517
+
1518
+ var force = _arguments3[0];
1519
+ var value = _arguments3[1];
1520
+
1521
+ options = { force: force, value: value };
1522
+ }
1523
+ var promise = this.whenValid(options);
1524
+ if (!promise) // Excluded via `group`
1525
+ return true;
1526
+ return parsley_field__statusMapping[promise.state()];
1527
+ },
1528
+
1529
+ // Just validate field. Do not trigger any event.
1530
+ // @returns a promise that succeeds only when all validations do
1531
+ // or `undefined` if the field is not in the given `group`.
1532
+ // The argument `force` will force validation of empty fields.
1533
+ // If a `value` is given, it will be validated instead of the value of the input.
1534
+ whenValid: function whenValid() {
1535
+ var _this10 = this;
1536
+
1537
+ var _ref10 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
1538
+
1539
+ var _ref10$force = _ref10.force;
1540
+ var force = _ref10$force === undefined ? false : _ref10$force;
1541
+ var value = _ref10.value;
1542
+ var group = _ref10.group;
1543
+ var _refreshed = _ref10._refreshed;
1544
+
1545
+ // Recompute options and rebind constraints to have latest changes
1546
+ if (!_refreshed) this.refreshConstraints();
1547
+ // do not validate a field if not the same as given validation group
1548
+ if (group && !this._isInGroup(group)) return;
1549
+
1550
+ this.validationResult = true;
1551
+
1552
+ // A field without constraint is valid
1553
+ if (!this.hasConstraints()) return $.when();
1554
+
1555
+ // Value could be passed as argument, needed to add more power to 'field:validate'
1556
+ if ('undefined' === typeof value || null === value) value = this.getValue();
1557
+
1558
+ if (!this.needsValidation(value) && true !== force) return $.when();
1559
+
1560
+ var groupedConstraints = this._getGroupedConstraints();
1561
+ var promises = [];
1562
+ $.each(groupedConstraints, function (_, constraints) {
1563
+ // Process one group of constraints at a time, we validate the constraints
1564
+ // and combine the promises together.
1565
+ var promise = ParsleyUtils__default.all($.map(constraints, function (constraint) {
1566
+ return _this10._validateConstraint(value, constraint);
1567
+ }));
1568
+ promises.push(promise);
1569
+ if (promise.state() === 'rejected') return false; // Interrupt processing if a group has already failed
1570
+ });
1571
+ return ParsleyUtils__default.all(promises);
1572
+ },
1573
+
1574
+ // @returns a promise
1575
+ _validateConstraint: function _validateConstraint(value, constraint) {
1576
+ var _this11 = this;
1577
+
1578
+ var result = constraint.validate(value, this);
1579
+ // Map false to a failed promise
1580
+ if (false === result) result = $.Deferred().reject();
1581
+ // Make sure we return a promise and that we record failures
1582
+ return ParsleyUtils__default.all([result]).fail(function (errorMessage) {
1583
+ if (!(_this11.validationResult instanceof Array)) _this11.validationResult = [];
1584
+ _this11.validationResult.push({
1585
+ assert: constraint,
1586
+ errorMessage: 'string' === typeof errorMessage && errorMessage
1587
+ });
1588
+ });
1589
+ },
1590
+
1575
1591
  // @returns Parsley field computed value that could be overrided or configured in DOM
1576
- getValue: function () {
1592
+ getValue: function getValue() {
1577
1593
  var value;
1578
- // Value could be overriden in DOM
1579
- if ('undefined' !== typeof this.options.value)
1580
- value = this.options.value;
1581
- else
1582
- value = this.$element.val();
1594
+
1595
+ // Value could be overriden in DOM or with explicit options
1596
+ if ('function' === typeof this.options.value) value = this.options.value(this);else if ('undefined' !== typeof this.options.value) value = this.options.value;else value = this.$element.val();
1597
+
1583
1598
  // Handle wrong DOM or configurations
1584
- if ('undefined' === typeof value || null === value)
1585
- return '';
1586
- // Use `data-parsley-trim-value="true"` to auto trim inputs entry
1587
- if (true === this.options.trimValue)
1588
- return value.replace(/^\s+|\s+$/g, '');
1589
- return value;
1599
+ if ('undefined' === typeof value || null === value) return '';
1600
+
1601
+ return this._handleWhitespace(value);
1590
1602
  },
1603
+
1591
1604
  // Actualize options that could have change since previous validation
1592
1605
  // Re-bind accordingly constraints (could be some new, removed or updated)
1593
- refreshConstraints: function () {
1606
+ refreshConstraints: function refreshConstraints() {
1594
1607
  return this.actualizeOptions()._bindConstraints();
1595
1608
  },
1609
+
1596
1610
  /**
1597
1611
  * Add a new constraint to a field
1598
1612
  *
1599
- * @method addConstraint
1600
1613
  * @param {String} name
1601
1614
  * @param {Mixed} requirements optional
1602
1615
  * @param {Number} priority optional
1603
1616
  * @param {Boolean} isDomConstraint optional
1604
1617
  */
1605
- addConstraint: function (name, requirements, priority, isDomConstraint) {
1606
- name = name.toLowerCase();
1607
- if ('function' === typeof window.ParsleyValidator.validators[name]) {
1618
+ addConstraint: function addConstraint(name, requirements, priority, isDomConstraint) {
1619
+
1620
+ if (window.Parsley._validatorRegistry.validators[name]) {
1608
1621
  var constraint = new ConstraintFactory(this, name, requirements, priority, isDomConstraint);
1622
+
1609
1623
  // if constraint already exist, delete it and push new version
1610
- if ('undefined' !== this.constraintsByName[constraint.name])
1611
- this.removeConstraint(constraint.name);
1624
+ if ('undefined' !== this.constraintsByName[constraint.name]) this.removeConstraint(constraint.name);
1625
+
1612
1626
  this.constraints.push(constraint);
1613
1627
  this.constraintsByName[constraint.name] = constraint;
1614
1628
  }
1629
+
1615
1630
  return this;
1616
1631
  },
1632
+
1617
1633
  // Remove a constraint
1618
- removeConstraint: function (name) {
1619
- for (var i = 0; i < this.constraints.length; i++)
1620
- if (name === this.constraints[i].name) {
1621
- this.constraints.splice(i, 1);
1622
- break;
1623
- }
1634
+ removeConstraint: function removeConstraint(name) {
1635
+ for (var i = 0; i < this.constraints.length; i++) if (name === this.constraints[i].name) {
1636
+ this.constraints.splice(i, 1);
1637
+ break;
1638
+ }
1624
1639
  delete this.constraintsByName[name];
1625
1640
  return this;
1626
1641
  },
1642
+
1627
1643
  // Update a constraint (Remove + re-add)
1628
- updateConstraint: function (name, parameters, priority) {
1629
- return this.removeConstraint(name)
1630
- .addConstraint(name, parameters, priority);
1644
+ updateConstraint: function updateConstraint(name, parameters, priority) {
1645
+ return this.removeConstraint(name).addConstraint(name, parameters, priority);
1631
1646
  },
1647
+
1632
1648
  // # Internals
1649
+
1633
1650
  // Internal only.
1634
1651
  // Bind constraints from config + options + DOM
1635
- _bindConstraints: function () {
1636
- var constraints = [], constraintsByName = {};
1652
+ _bindConstraints: function _bindConstraints() {
1653
+ var constraints = [];
1654
+ var constraintsByName = {};
1655
+
1637
1656
  // clean all existing DOM constraints to only keep javascript user constraints
1638
- for (var i = 0; i < this.constraints.length; i++)
1639
- if (false === this.constraints[i].isDomConstraint) {
1640
- constraints.push(this.constraints[i]);
1641
- constraintsByName[this.constraints[i].name] = this.constraints[i];
1642
- }
1657
+ for (var i = 0; i < this.constraints.length; i++) if (false === this.constraints[i].isDomConstraint) {
1658
+ constraints.push(this.constraints[i]);
1659
+ constraintsByName[this.constraints[i].name] = this.constraints[i];
1660
+ }
1661
+
1643
1662
  this.constraints = constraints;
1644
1663
  this.constraintsByName = constraintsByName;
1664
+
1645
1665
  // then re-add Parsley DOM-API constraints
1646
- for (var name in this.options)
1647
- this.addConstraint(name, this.options[name]);
1666
+ for (var name in this.options) this.addConstraint(name, this.options[name], undefined, true);
1667
+
1648
1668
  // finally, bind special HTML5 constraints
1649
1669
  return this._bindHtml5Constraints();
1650
1670
  },
1671
+
1651
1672
  // Internal only.
1652
1673
  // Bind specific HTML5 constraints to be HTML5 compliant
1653
- _bindHtml5Constraints: function () {
1674
+ _bindHtml5Constraints: function _bindHtml5Constraints() {
1654
1675
  // html5 required
1655
- if (this.$element.hasClass('required') || this.$element.attr('required'))
1656
- this.addConstraint('required', true, undefined, true);
1676
+ if (this.$element.hasClass('required') || this.$element.attr('required')) this.addConstraint('required', true, undefined, true);
1677
+
1657
1678
  // html5 pattern
1658
- if ('string' === typeof this.$element.attr('pattern'))
1659
- this.addConstraint('pattern', this.$element.attr('pattern'), undefined, true);
1679
+ if ('string' === typeof this.$element.attr('pattern')) this.addConstraint('pattern', this.$element.attr('pattern'), undefined, true);
1680
+
1660
1681
  // range
1661
- if ('undefined' !== typeof this.$element.attr('min') && 'undefined' !== typeof this.$element.attr('max'))
1662
- this.addConstraint('range', [this.$element.attr('min'), this.$element.attr('max')], undefined, true);
1682
+ if ('undefined' !== typeof this.$element.attr('min') && 'undefined' !== typeof this.$element.attr('max')) this.addConstraint('range', [this.$element.attr('min'), this.$element.attr('max')], undefined, true);
1683
+
1663
1684
  // HTML5 min
1664
- else if ('undefined' !== typeof this.$element.attr('min'))
1665
- this.addConstraint('min', this.$element.attr('min'), undefined, true);
1666
- // HTML5 max
1667
- else if ('undefined' !== typeof this.$element.attr('max'))
1668
- this.addConstraint('max', this.$element.attr('max'), undefined, true);
1669
-
1685
+ else if ('undefined' !== typeof this.$element.attr('min')) this.addConstraint('min', this.$element.attr('min'), undefined, true);
1686
+
1687
+ // HTML5 max
1688
+ else if ('undefined' !== typeof this.$element.attr('max')) this.addConstraint('max', this.$element.attr('max'), undefined, true);
1689
+
1670
1690
  // length
1671
- if ('undefined' !== typeof this.$element.attr('minlength') && 'undefined' !== typeof this.$element.attr('maxlength'))
1672
- this.addConstraint('length', [this.$element.attr('minlength'), this.$element.attr('maxlength')], undefined, true);
1691
+ if ('undefined' !== typeof this.$element.attr('minlength') && 'undefined' !== typeof this.$element.attr('maxlength')) this.addConstraint('length', [this.$element.attr('minlength'), this.$element.attr('maxlength')], undefined, true);
1692
+
1673
1693
  // HTML5 minlength
1674
- else if ('undefined' !== typeof this.$element.attr('minlength'))
1675
- this.addConstraint('minlength', this.$element.attr('minlength'), undefined, true);
1676
- // HTML5 maxlength
1677
- else if ('undefined' !== typeof this.$element.attr('maxlength'))
1678
- this.addConstraint('maxlength', this.$element.attr('maxlength'), undefined, true);
1694
+ else if ('undefined' !== typeof this.$element.attr('minlength')) this.addConstraint('minlength', this.$element.attr('minlength'), undefined, true);
1695
+
1696
+ // HTML5 maxlength
1697
+ else if ('undefined' !== typeof this.$element.attr('maxlength')) this.addConstraint('maxlength', this.$element.attr('maxlength'), undefined, true);
1679
1698
 
1680
1699
  // html5 types
1681
1700
  var type = this.$element.attr('type');
1682
- if ('undefined' === typeof type)
1683
- return this;
1701
+
1702
+ if ('undefined' === typeof type) return this;
1703
+
1684
1704
  // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
1685
1705
  if ('number' === type) {
1686
- if (('undefined' === typeof this.$element.attr('step')) || (0 === parseFloat(this.$element.attr('step')) % 1)) {
1687
- return this.addConstraint('type', 'integer', undefined, true);
1688
- } else {
1689
- return this.addConstraint('type', 'number', undefined, true);
1706
+ return this.addConstraint('type', ['number', {
1707
+ step: this.$element.attr('step'),
1708
+ base: this.$element.attr('min') || this.$element.attr('value')
1709
+ }], undefined, true);
1710
+ // Regular other HTML5 supported types
1711
+ } else if (/^(email|url|range)$/i.test(type)) {
1712
+ return this.addConstraint('type', type, undefined, true);
1690
1713
  }
1691
- // Regular other HTML5 supported types
1692
- } else if (new RegExp(type, 'i').test('email url range')) {
1693
- return this.addConstraint('type', type, undefined, true);
1694
- }
1695
1714
  return this;
1696
1715
  },
1716
+
1697
1717
  // Internal only.
1698
1718
  // Field is required if have required constraint without `false` value
1699
- _isRequired: function () {
1700
- if ('undefined' === typeof this.constraintsByName.required)
1701
- return false;
1719
+ _isRequired: function _isRequired() {
1720
+ if ('undefined' === typeof this.constraintsByName.required) return false;
1721
+
1702
1722
  return false !== this.constraintsByName.required.requirements;
1703
1723
  },
1724
+
1725
+ // Internal only.
1726
+ // Shortcut to trigger an event
1727
+ _trigger: function _trigger(eventName) {
1728
+ return this.trigger('field:' + eventName);
1729
+ },
1730
+
1731
+ // Internal only
1732
+ // Handles whitespace in a value
1733
+ // Use `data-parsley-whitespace="squish"` to auto squish input value
1734
+ // Use `data-parsley-whitespace="trim"` to auto trim input value
1735
+ _handleWhitespace: function _handleWhitespace(value) {
1736
+ if (true === this.options.trimValue) ParsleyUtils__default.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"');
1737
+
1738
+ if ('squish' === this.options.whitespace) value = value.replace(/\s{2,}/g, ' ');
1739
+
1740
+ if ('trim' === this.options.whitespace || 'squish' === this.options.whitespace || true === this.options.trimValue) value = ParsleyUtils__default.trimString(value);
1741
+
1742
+ return value;
1743
+ },
1744
+
1704
1745
  // Internal only.
1705
- // Sort constraints by priority DESC
1706
- _getConstraintsSortedPriorities: function () {
1707
- var priorities = [];
1746
+ // Returns the constraints, grouped by descending priority.
1747
+ // The result is thus an array of arrays of constraints.
1748
+ _getGroupedConstraints: function _getGroupedConstraints() {
1749
+ if (false === this.options.priorityEnabled) return [this.constraints];
1750
+
1751
+ var groupedConstraints = [];
1752
+ var index = {};
1753
+
1708
1754
  // Create array unique of priorities
1709
- for (var i = 0; i < this.constraints.length; i++)
1710
- if (-1 === priorities.indexOf(this.constraints[i].priority))
1711
- priorities.push(this.constraints[i].priority);
1755
+ for (var i = 0; i < this.constraints.length; i++) {
1756
+ var p = this.constraints[i].priority;
1757
+ if (!index[p]) groupedConstraints.push(index[p] = []);
1758
+ index[p].push(this.constraints[i]);
1759
+ }
1712
1760
  // Sort them by priority DESC
1713
- priorities.sort(function (a, b) { return b - a; });
1714
- return priorities;
1761
+ groupedConstraints.sort(function (a, b) {
1762
+ return b[0].priority - a[0].priority;
1763
+ });
1764
+
1765
+ return groupedConstraints;
1715
1766
  }
1767
+
1716
1768
  };
1717
1769
 
1718
- var ParsleyMultiple = function () {
1770
+ var parsley_field = ParsleyField;
1771
+
1772
+ var ParsleyMultiple = function ParsleyMultiple() {
1719
1773
  this.__class__ = 'ParsleyFieldMultiple';
1720
1774
  };
1775
+
1721
1776
  ParsleyMultiple.prototype = {
1722
1777
  // Add new `$element` sibling for multiple field
1723
- addElement: function ($element) {
1778
+ addElement: function addElement($element) {
1724
1779
  this.$elements.push($element);
1780
+
1725
1781
  return this;
1726
1782
  },
1783
+
1727
1784
  // See `ParsleyField.refreshConstraints()`
1728
- refreshConstraints: function () {
1785
+ refreshConstraints: function refreshConstraints() {
1729
1786
  var fieldConstraints;
1787
+
1730
1788
  this.constraints = [];
1789
+
1731
1790
  // Select multiple special treatment
1732
1791
  if (this.$element.is('select')) {
1733
1792
  this.actualizeOptions()._bindConstraints();
1793
+
1734
1794
  return this;
1735
1795
  }
1796
+
1736
1797
  // Gather all constraints for each input in the multiple group
1737
1798
  for (var i = 0; i < this.$elements.length; i++) {
1799
+
1738
1800
  // Check if element have not been dynamically removed since last binding
1739
1801
  if (!$('html').has(this.$elements[i]).length) {
1740
1802
  this.$elements.splice(i, 1);
1741
1803
  continue;
1742
1804
  }
1805
+
1743
1806
  fieldConstraints = this.$elements[i].data('ParsleyFieldMultiple').refreshConstraints().constraints;
1744
- for (var j = 0; j < fieldConstraints.length; j++)
1745
- this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);
1807
+
1808
+ for (var j = 0; j < fieldConstraints.length; j++) this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);
1746
1809
  }
1810
+
1747
1811
  return this;
1748
1812
  },
1813
+
1749
1814
  // See `ParsleyField.getValue()`
1750
- getValue: function () {
1815
+ getValue: function getValue() {
1751
1816
  // Value could be overriden in DOM
1752
- if ('undefined' !== typeof this.options.value)
1753
- return this.options.value;
1817
+ if ('function' === typeof this.options.value) return this.options.value(this);else if ('undefined' !== typeof this.options.value) return this.options.value;
1818
+
1754
1819
  // Radio input case
1755
- if (this.$element.is('input[type=radio]'))
1756
- return $('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]:checked').val() || '';
1820
+ if (this.$element.is('input[type=radio]')) return this._findRelated().filter(':checked').val() || '';
1821
+
1757
1822
  // checkbox input case
1758
1823
  if (this.$element.is('input[type=checkbox]')) {
1759
1824
  var values = [];
1760
- $('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]:checked').each(function () {
1825
+
1826
+ this._findRelated().filter(':checked').each(function () {
1761
1827
  values.push($(this).val());
1762
1828
  });
1763
- return values.length ? values : [];
1829
+
1830
+ return values;
1764
1831
  }
1832
+
1765
1833
  // Select multiple case
1766
- if (this.$element.is('select') && null === this.$element.val())
1767
- return [];
1834
+ if (this.$element.is('select') && null === this.$element.val()) return [];
1835
+
1768
1836
  // Default case that should never happen
1769
1837
  return this.$element.val();
1770
1838
  },
1771
- _init: function (multiple) {
1839
+
1840
+ _init: function _init() {
1772
1841
  this.$elements = [this.$element];
1773
- this.options.multiple = multiple;
1842
+
1774
1843
  return this;
1775
1844
  }
1776
1845
  };
1777
1846
 
1778
- var
1779
- o = $({}),
1780
- subscribed = {};
1781
- // $.listen(name, callback);
1782
- // $.listen(name, context, callback);
1783
- $.listen = function (name) {
1784
- if ('undefined' === typeof subscribed[name])
1785
- subscribed[name] = [];
1786
- if ('function' === typeof arguments[1])
1787
- return subscribed[name].push({ fn: arguments[1] });
1788
- if ('object' === typeof arguments[1] && 'function' === typeof arguments[2])
1789
- return subscribed[name].push({ fn: arguments[2], ctxt: arguments[1] });
1790
- throw new Error('Wrong parameters');
1791
- };
1792
- $.listenTo = function (instance, name, fn) {
1793
- if ('undefined' === typeof subscribed[name])
1794
- subscribed[name] = [];
1795
- if (!(instance instanceof ParsleyField) && !(instance instanceof ParsleyForm))
1796
- throw new Error('Must give Parsley instance');
1797
- if ('string' !== typeof name || 'function' !== typeof fn)
1798
- throw new Error('Wrong parameters');
1799
- subscribed[name].push({ instance: instance, fn: fn });
1800
- };
1801
- $.unsubscribe = function (name, fn) {
1802
- if ('undefined' === typeof subscribed[name])
1803
- return;
1804
- if ('string' !== typeof name || 'function' !== typeof fn)
1805
- throw new Error('Wrong arguments');
1806
- for (var i = 0; i < subscribed[name].length; i++)
1807
- if (subscribed[name][i].fn === fn)
1808
- return subscribed[name].splice(i, 1);
1809
- };
1810
- $.unsubscribeTo = function (instance, name) {
1811
- if ('undefined' === typeof subscribed[name])
1812
- return;
1813
- if (!(instance instanceof ParsleyField) && !(instance instanceof ParsleyForm))
1814
- throw new Error('Must give Parsley instance');
1815
- for (var i = 0; i < subscribed[name].length; i++)
1816
- if ('undefined' !== typeof subscribed[name][i].instance && subscribed[name][i].instance.__id__ === instance.__id__)
1817
- return subscribed[name].splice(i, 1);
1818
- };
1819
- $.unsubscribeAll = function (name) {
1820
- if ('undefined' === typeof subscribed[name])
1821
- return;
1822
- delete subscribed[name];
1823
- };
1824
- // $.emit(name [, arguments...]);
1825
- // $.emit(name, instance [, arguments...]);
1826
- $.emit = function (name, instance) {
1827
- if ('undefined' === typeof subscribed[name])
1828
- return;
1829
- // loop through registered callbacks for this event
1830
- for (var i = 0; i < subscribed[name].length; i++) {
1831
- // if instance is not registered, simple emit
1832
- if ('undefined' === typeof subscribed[name][i].instance) {
1833
- subscribed[name][i].fn.apply('undefined' !== typeof subscribed[name][i].ctxt ? subscribed[name][i].ctxt : o, Array.prototype.slice.call(arguments, 1));
1834
- continue;
1847
+ var ParsleyFactory = function ParsleyFactory(element, options, parsleyFormInstance) {
1848
+ this.$element = $(element);
1849
+
1850
+ // If the element has already been bound, returns its saved Parsley instance
1851
+ var savedparsleyFormInstance = this.$element.data('Parsley');
1852
+ if (savedparsleyFormInstance) {
1853
+
1854
+ // If the saved instance has been bound without a ParsleyForm parent and there is one given in this call, add it
1855
+ if ('undefined' !== typeof parsleyFormInstance && savedparsleyFormInstance.parent === window.Parsley) {
1856
+ savedparsleyFormInstance.parent = parsleyFormInstance;
1857
+ savedparsleyFormInstance._resetOptions(savedparsleyFormInstance.options);
1835
1858
  }
1836
- // if instance registered but no instance given for the emit, continue
1837
- if (!(instance instanceof ParsleyField) && !(instance instanceof ParsleyForm))
1838
- continue;
1839
- // if instance is registered and same id, emit
1840
- if (subscribed[name][i].instance.__id__ === instance.__id__) {
1841
- subscribed[name][i].fn.apply(o, Array.prototype.slice.call(arguments, 1));
1842
- continue;
1859
+
1860
+ if ('object' === typeof options) {
1861
+ $.extend(savedparsleyFormInstance.options, options);
1843
1862
  }
1844
- // if registered instance is a Form and fired one is a Field, loop over all its fields and emit if field found
1845
- if (subscribed[name][i].instance instanceof ParsleyForm && instance instanceof ParsleyField)
1846
- for (var j = 0; j < subscribed[name][i].instance.fields.length; j++)
1847
- if (subscribed[name][i].instance.fields[j].__id__ === instance.__id__) {
1848
- subscribed[name][i].fn.apply(o, Array.prototype.slice.call(arguments, 1));
1849
- continue;
1850
- }
1863
+
1864
+ return savedparsleyFormInstance;
1851
1865
  }
1852
- };
1853
- $.subscribed = function () { return subscribed; };
1854
-
1855
- // ParsleyConfig definition if not already set
1856
- window.ParsleyConfig = window.ParsleyConfig || {};
1857
- window.ParsleyConfig.i18n = window.ParsleyConfig.i18n || {};
1858
- // Define then the messages
1859
- window.ParsleyConfig.i18n.en = $.extend(window.ParsleyConfig.i18n.en || {}, {
1860
- defaultMessage: "This value seems to be invalid.",
1861
- type: {
1862
- email: "This value should be a valid email.",
1863
- url: "This value should be a valid url.",
1864
- number: "This value should be a valid number.",
1865
- integer: "This value should be a valid integer.",
1866
- digits: "This value should be digits.",
1867
- alphanum: "This value should be alphanumeric."
1868
- },
1869
- notblank: "This value should not be blank.",
1870
- required: "This value is required.",
1871
- pattern: "This value seems to be invalid.",
1872
- min: "This value should be greater than or equal to %s.",
1873
- max: "This value should be lower than or equal to %s.",
1874
- range: "This value should be between %s and %s.",
1875
- minlength: "This value is too short. It should have %s characters or more.",
1876
- maxlength: "This value is too long. It should have %s characters or fewer.",
1877
- length: "This value length is invalid. It should be between %s and %s characters long.",
1878
- mincheck: "You must select at least %s choices.",
1879
- maxcheck: "You must select %s choices or fewer.",
1880
- check: "You must select between %s and %s choices.",
1881
- equalto: "This value should be the same."
1882
- });
1883
- // If file is loaded after Parsley main file, auto-load locale
1884
- if ('undefined' !== typeof window.ParsleyValidator)
1885
- window.ParsleyValidator.addCatalog('en', window.ParsleyConfig.i18n.en, true);
1886
-
1887
- // Parsley.js 2.0.6
1888
- // http://parsleyjs.org
1889
- // (c) 20012-2014 Guillaume Potier, Wisembly
1890
- // Parsley may be freely distributed under the MIT license.
1891
-
1892
- // ### Parsley factory
1893
- var Parsley = function (element, options, parsleyFormInstance) {
1894
- this.__class__ = 'Parsley';
1895
- this.__version__ = '2.0.6';
1896
- this.__id__ = ParsleyUtils.hash(4);
1866
+
1897
1867
  // Parsley must be instantiated with a DOM element or jQuery $element
1898
- if ('undefined' === typeof element)
1899
- throw new Error('You must give an element');
1900
- if ('undefined' !== typeof parsleyFormInstance && 'ParsleyForm' !== parsleyFormInstance.__class__)
1901
- throw new Error('Parent instance must be a ParsleyForm instance');
1902
- return this.init($(element), options, parsleyFormInstance);
1868
+ if (!this.$element.length) throw new Error('You must bind Parsley on an existing element.');
1869
+
1870
+ if ('undefined' !== typeof parsleyFormInstance && 'ParsleyForm' !== parsleyFormInstance.__class__) throw new Error('Parent instance must be a ParsleyForm instance');
1871
+
1872
+ this.parent = parsleyFormInstance || window.Parsley;
1873
+ return this.init(options);
1903
1874
  };
1904
- Parsley.prototype = {
1905
- init: function ($element, options, parsleyFormInstance) {
1906
- if (!$element.length)
1907
- throw new Error('You must bind Parsley on an existing element.');
1908
- this.$element = $element;
1909
- // If element have already been binded, returns its saved Parsley instance
1910
- if (this.$element.data('Parsley')) {
1911
- var savedparsleyFormInstance = this.$element.data('Parsley');
1912
- // If saved instance have been binded without a ParsleyForm parent and there is one given in this call, add it
1913
- if ('undefined' !== typeof parsleyFormInstance)
1914
- savedparsleyFormInstance.parent = parsleyFormInstance;
1915
- return savedparsleyFormInstance;
1916
- }
1917
- // Handle 'static' options
1918
- this.OptionsFactory = new ParsleyOptionsFactory(ParsleyDefaults, ParsleyUtils.get(window, 'ParsleyConfig') || {}, options, this.getNamespace(options));
1919
- this.options = this.OptionsFactory.get(this);
1920
- // A ParsleyForm instance is obviously a `<form>` elem but also every node that is not an input and have `data-parsley-validate` attribute
1921
- if (this.$element.is('form') || (ParsleyUtils.attr(this.$element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)))
1922
- return this.bind('parsleyForm');
1923
- // Every other supported element and not excluded element is binded as a `ParsleyField` or `ParsleyFieldMultiple`
1924
- else if (this.$element.is(this.options.inputs) && !this.$element.is(this.options.excluded))
1925
- return this.isMultiple() ? this.handleMultiple(parsleyFormInstance) : this.bind('parsleyField', parsleyFormInstance);
1926
- return this;
1875
+
1876
+ ParsleyFactory.prototype = {
1877
+ init: function init(options) {
1878
+ this.__class__ = 'Parsley';
1879
+ this.__version__ = '2.4.4';
1880
+ this.__id__ = ParsleyUtils__default.generateID();
1881
+
1882
+ // Pre-compute options
1883
+ this._resetOptions(options);
1884
+
1885
+ // A ParsleyForm instance is obviously a `<form>` element but also every node that is not an input and has the `data-parsley-validate` attribute
1886
+ if (this.$element.is('form') || ParsleyUtils__default.checkAttr(this.$element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)) return this.bind('parsleyForm');
1887
+
1888
+ // Every other element is bound as a `ParsleyField` or `ParsleyFieldMultiple`
1889
+ return this.isMultiple() ? this.handleMultiple() : this.bind('parsleyField');
1927
1890
  },
1928
- isMultiple: function () {
1929
- return (this.$element.is('input[type=radio], input[type=checkbox]') && 'undefined' === typeof this.options.multiple) || (this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple'));
1891
+
1892
+ isMultiple: function isMultiple() {
1893
+ return this.$element.is('input[type=radio], input[type=checkbox]') || this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple');
1930
1894
  },
1895
+
1931
1896
  // Multiples fields are a real nightmare :(
1932
- // Maybe some refacto would be appreciated here...
1933
- handleMultiple: function (parsleyFormInstance) {
1934
- var
1935
- that = this,
1936
- name,
1937
- multiple,
1938
- parsleyMultipleInstance;
1939
- // Get parsleyFormInstance options if exist, mixed with element attributes
1940
- this.options = $.extend(this.options, parsleyFormInstance ? parsleyFormInstance.OptionsFactory.get(parsleyFormInstance) : {}, ParsleyUtils.attr(this.$element, this.options.namespace));
1897
+ // Maybe some refactoring would be appreciated here...
1898
+ handleMultiple: function handleMultiple() {
1899
+ var _this12 = this;
1900
+
1901
+ var name;
1902
+ var multiple;
1903
+ var parsleyMultipleInstance;
1904
+
1941
1905
  // Handle multiple name
1942
- if (this.options.multiple)
1943
- multiple = this.options.multiple;
1944
- else if ('undefined' !== typeof this.$element.attr('name') && this.$element.attr('name').length)
1945
- multiple = name = this.$element.attr('name');
1946
- else if ('undefined' !== typeof this.$element.attr('id') && this.$element.attr('id').length)
1947
- multiple = this.$element.attr('id');
1906
+ if (this.options.multiple) ; // We already have our 'multiple' identifier
1907
+ else if ('undefined' !== typeof this.$element.attr('name') && this.$element.attr('name').length) this.options.multiple = name = this.$element.attr('name');else if ('undefined' !== typeof this.$element.attr('id') && this.$element.attr('id').length) this.options.multiple = this.$element.attr('id');
1908
+
1948
1909
  // Special select multiple input
1949
1910
  if (this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple')) {
1950
- return this.bind('parsleyFieldMultiple', parsleyFormInstance, multiple || this.__id__);
1951
- // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it
1952
- } else if ('undefined' === typeof multiple) {
1953
- if (window.console && window.console.warn)
1954
- window.console.warn('To be binded by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.', this.$element);
1955
- return this;
1956
- }
1911
+ this.options.multiple = this.options.multiple || this.__id__;
1912
+ return this.bind('parsleyFieldMultiple');
1913
+
1914
+ // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it
1915
+ } else if (!this.options.multiple) {
1916
+ ParsleyUtils__default.warn('To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.', this.$element);
1917
+ return this;
1918
+ }
1919
+
1957
1920
  // Remove special chars
1958
- multiple = multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g, '');
1921
+ this.options.multiple = this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g, '');
1922
+
1959
1923
  // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
1960
1924
  if ('undefined' !== typeof name) {
1961
- $('input[name="' + name + '"]').each(function () {
1962
- if ($(this).is('input[type=radio], input[type=checkbox]'))
1963
- $(this).attr(that.options.namespace + 'multiple', multiple);
1925
+ $('input[name="' + name + '"]').each(function (i, input) {
1926
+ if ($(input).is('input[type=radio], input[type=checkbox]')) $(input).attr(_this12.options.namespace + 'multiple', _this12.options.multiple);
1964
1927
  });
1965
1928
  }
1929
+
1966
1930
  // Check here if we don't already have a related multiple instance saved
1967
- if ($('[' + this.options.namespace + 'multiple=' + multiple +']').length) {
1968
- for (var i = 0; i < $('[' + this.options.namespace + 'multiple=' + multiple +']').length; i++) {
1969
- if ('undefined' !== typeof $($('[' + this.options.namespace + 'multiple=' + multiple +']').get(i)).data('Parsley')) {
1970
- parsleyMultipleInstance = $($('[' + this.options.namespace + 'multiple=' + multiple +']').get(i)).data('Parsley');
1971
- if (!this.$element.data('ParsleyFieldMultiple')) {
1972
- parsleyMultipleInstance.addElement(this.$element);
1973
- this.$element.attr(this.options.namespace + 'id', parsleyMultipleInstance.__id__);
1974
- }
1975
- break;
1931
+ var $previouslyRelated = this._findRelated();
1932
+ for (var i = 0; i < $previouslyRelated.length; i++) {
1933
+ parsleyMultipleInstance = $($previouslyRelated.get(i)).data('Parsley');
1934
+ if ('undefined' !== typeof parsleyMultipleInstance) {
1935
+
1936
+ if (!this.$element.data('ParsleyFieldMultiple')) {
1937
+ parsleyMultipleInstance.addElement(this.$element);
1976
1938
  }
1939
+
1940
+ break;
1977
1941
  }
1978
1942
  }
1979
- // Create a secret ParsleyField instance for every multiple field. It would be stored in `data('ParsleyFieldMultiple')`
1980
- // And would be useful later to access classic `ParsleyField` stuff while being in a `ParsleyFieldMultiple` instance
1981
- this.bind('parsleyField', parsleyFormInstance, multiple, true);
1982
- return parsleyMultipleInstance || this.bind('parsleyFieldMultiple', parsleyFormInstance, multiple);
1983
- },
1984
- // Retrieve namespace used for DOM-API
1985
- getNamespace: function (options) {
1986
- // `data-parsley-namespace=<namespace>`
1987
- if ('undefined' !== typeof this.$element.data('parsleyNamespace'))
1988
- return this.$element.data('parsleyNamespace');
1989
- if ('undefined' !== typeof ParsleyUtils.get(options, 'namespace'))
1990
- return options.namespace;
1991
- if ('undefined' !== typeof ParsleyUtils.get(window, 'ParsleyConfig.namespace'))
1992
- return window.ParsleyConfig.namespace;
1993
- return ParsleyDefaults.namespace;
1943
+
1944
+ // Create a secret ParsleyField instance for every multiple field. It will be stored in `data('ParsleyFieldMultiple')`
1945
+ // And will be useful later to access classic `ParsleyField` stuff while being in a `ParsleyFieldMultiple` instance
1946
+ this.bind('parsleyField', true);
1947
+
1948
+ return parsleyMultipleInstance || this.bind('parsleyFieldMultiple');
1994
1949
  },
1950
+
1995
1951
  // Return proper `ParsleyForm`, `ParsleyField` or `ParsleyFieldMultiple`
1996
- bind: function (type, parentParsleyFormInstance, multiple, doNotStore) {
1952
+ bind: function bind(type, doNotStore) {
1997
1953
  var parsleyInstance;
1954
+
1998
1955
  switch (type) {
1999
1956
  case 'parsleyForm':
2000
- parsleyInstance = $.extend(
2001
- new ParsleyForm(this.$element, this.OptionsFactory),
2002
- new ParsleyAbstract(),
2003
- window.ParsleyExtend
2004
- )._bindFields();
1957
+ parsleyInstance = $.extend(new ParsleyForm(this.$element, this.domOptions, this.options), new ParsleyAbstract(), window.ParsleyExtend)._bindFields();
2005
1958
  break;
2006
1959
  case 'parsleyField':
2007
- parsleyInstance = $.extend(
2008
- new ParsleyField(this.$element, this.OptionsFactory, parentParsleyFormInstance),
2009
- new ParsleyAbstract(),
2010
- window.ParsleyExtend
2011
- );
1960
+ parsleyInstance = $.extend(new parsley_field(this.$element, this.domOptions, this.options, this.parent), new ParsleyAbstract(), window.ParsleyExtend);
2012
1961
  break;
2013
1962
  case 'parsleyFieldMultiple':
2014
- parsleyInstance = $.extend(
2015
- new ParsleyField(this.$element, this.OptionsFactory, parentParsleyFormInstance),
2016
- new ParsleyAbstract(),
2017
- new ParsleyMultiple(),
2018
- window.ParsleyExtend
2019
- )._init(multiple);
1963
+ parsleyInstance = $.extend(new parsley_field(this.$element, this.domOptions, this.options, this.parent), new ParsleyMultiple(), new ParsleyAbstract(), window.ParsleyExtend)._init();
2020
1964
  break;
2021
1965
  default:
2022
1966
  throw new Error(type + 'is not a supported Parsley type');
2023
1967
  }
2024
- if ('undefined' !== typeof multiple)
2025
- ParsleyUtils.setAttr(this.$element, this.options.namespace, 'multiple', multiple);
1968
+
1969
+ if (this.options.multiple) ParsleyUtils__default.setAttr(this.$element, this.options.namespace, 'multiple', this.options.multiple);
1970
+
2026
1971
  if ('undefined' !== typeof doNotStore) {
2027
1972
  this.$element.data('ParsleyFieldMultiple', parsleyInstance);
1973
+
2028
1974
  return parsleyInstance;
2029
1975
  }
2030
- // Store instance if `ParsleyForm`, `ParsleyField` or `ParsleyFieldMultiple`
2031
- if (new RegExp('ParsleyF', 'i').test(parsleyInstance.__class__)) {
2032
- // Store for later access the freshly binded instance in DOM element itself using jQuery `data()`
2033
- this.$element.data('Parsley', parsleyInstance);
2034
- // Tell the world we got a new ParsleyForm or ParsleyField instance!
2035
- $.emit('parsley:' + ('parsleyForm' === type ? 'form' : 'field') + ':init', parsleyInstance);
2036
- }
1976
+
1977
+ // Store the freshly bound instance in a DOM element for later access using jQuery `data()`
1978
+ this.$element.data('Parsley', parsleyInstance);
1979
+
1980
+ // Tell the world we have a new ParsleyForm or ParsleyField instance!
1981
+ parsleyInstance._actualizeTriggers();
1982
+ parsleyInstance._trigger('init');
1983
+
2037
1984
  return parsleyInstance;
2038
1985
  }
2039
1986
  };
1987
+
1988
+ var vernums = $.fn.jquery.split('.');
1989
+ if (parseInt(vernums[0]) <= 1 && parseInt(vernums[1]) < 8) {
1990
+ throw "The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.";
1991
+ }
1992
+ if (!vernums.forEach) {
1993
+ ParsleyUtils__default.warn('Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim');
1994
+ }
1995
+ // Inherit `on`, `off` & `trigger` to Parsley:
1996
+ var Parsley = $.extend(new ParsleyAbstract(), {
1997
+ $element: $(document),
1998
+ actualizeOptions: null,
1999
+ _resetOptions: null,
2000
+ Factory: ParsleyFactory,
2001
+ version: '2.4.4'
2002
+ });
2003
+
2004
+ // Supplement ParsleyField and Form with ParsleyAbstract
2005
+ // This way, the constructors will have access to those methods
2006
+ $.extend(parsley_field.prototype, ParsleyUI.Field, ParsleyAbstract.prototype);
2007
+ $.extend(ParsleyForm.prototype, ParsleyUI.Form, ParsleyAbstract.prototype);
2008
+ // Inherit actualizeOptions and _resetOptions:
2009
+ $.extend(ParsleyFactory.prototype, ParsleyAbstract.prototype);
2010
+
2040
2011
  // ### jQuery API
2041
2012
  // `$('.elem').parsley(options)` or `$('.elem').psly(options)`
2042
2013
  $.fn.parsley = $.fn.psly = function (options) {
2043
2014
  if (this.length > 1) {
2044
2015
  var instances = [];
2016
+
2045
2017
  this.each(function () {
2046
2018
  instances.push($(this).parsley(options));
2047
2019
  });
2020
+
2048
2021
  return instances;
2049
2022
  }
2023
+
2050
2024
  // Return undefined if applied to non existing DOM element
2051
2025
  if (!$(this).length) {
2052
- if (window.console && window.console.warn)
2053
- window.console.warn('You must bind Parsley on an existing element.');
2026
+ ParsleyUtils__default.warn('You must bind Parsley on an existing element.');
2027
+
2054
2028
  return;
2055
2029
  }
2056
- return new Parsley(this, options);
2030
+
2031
+ return new ParsleyFactory(this, options);
2057
2032
  };
2058
- // ### ParsleyUI
2059
- // UI is a class apart that only listen to some events and them modify DOM accordingly
2060
- // Could be overriden by defining a `window.ParsleyConfig.ParsleyUI` appropriate class (with `listen()` method basically)
2061
- window.ParsleyUI = 'function' === typeof ParsleyUtils.get(window, 'ParsleyConfig.ParsleyUI') ?
2062
- new window.ParsleyConfig.ParsleyUI().listen() : new ParsleyUI().listen();
2033
+
2063
2034
  // ### ParsleyField and ParsleyForm extension
2064
- // Ensure that defined if not already the case
2065
- if ('undefined' === typeof window.ParsleyExtend)
2066
- window.ParsleyExtend = {};
2067
- // ### ParsleyConfig
2068
- // Ensure that defined if not already the case
2069
- if ('undefined' === typeof window.ParsleyConfig)
2070
- window.ParsleyConfig = {};
2035
+ // Ensure the extension is now defined if it wasn't previously
2036
+ if ('undefined' === typeof window.ParsleyExtend) window.ParsleyExtend = {};
2037
+
2038
+ // ### Parsley config
2039
+ // Inherit from ParsleyDefault, and copy over any existing values
2040
+ Parsley.options = $.extend(ParsleyUtils__default.objectCreate(ParsleyDefaults), window.ParsleyConfig);
2041
+ window.ParsleyConfig = Parsley.options; // Old way of accessing global options
2042
+
2071
2043
  // ### Globals
2072
2044
  window.Parsley = window.psly = Parsley;
2073
- window.ParsleyUtils = ParsleyUtils;
2074
- window.ParsleyValidator = new ParsleyValidator(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
2045
+ window.ParsleyUtils = ParsleyUtils__default;
2046
+
2047
+ // ### Define methods that forward to the registry, and deprecate all access except through window.Parsley
2048
+ var registry = window.Parsley._validatorRegistry = new ParsleyValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
2049
+ window.ParsleyValidator = {};
2050
+ $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator'.split(' '), function (i, method) {
2051
+ window.Parsley[method] = $.proxy(registry, method);
2052
+ window.ParsleyValidator[method] = function () {
2053
+ var _window$Parsley;
2054
+
2055
+ ParsleyUtils__default.warnOnce('Accessing the method \'' + method + '\' through ParsleyValidator is deprecated. Simply call \'window.Parsley.' + method + '(...)\'');
2056
+ return (_window$Parsley = window.Parsley)[method].apply(_window$Parsley, arguments);
2057
+ };
2058
+ });
2059
+
2060
+ // ### ParsleyUI
2061
+ // Deprecated global object
2062
+ window.Parsley.UI = ParsleyUI;
2063
+ window.ParsleyUI = {
2064
+ removeError: function removeError(instance, name, doNotUpdateClass) {
2065
+ var updateClass = true !== doNotUpdateClass;
2066
+ ParsleyUtils__default.warnOnce('Accessing ParsleyUI is deprecated. Call \'removeError\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
2067
+ return instance.removeError(name, { updateClass: updateClass });
2068
+ },
2069
+ getErrorsMessages: function getErrorsMessages(instance) {
2070
+ ParsleyUtils__default.warnOnce('Accessing ParsleyUI is deprecated. Call \'getErrorsMessages\' on the instance directly.');
2071
+ return instance.getErrorsMessages();
2072
+ }
2073
+ };
2074
+ $.each('addError updateError'.split(' '), function (i, method) {
2075
+ window.ParsleyUI[method] = function (instance, name, message, assert, doNotUpdateClass) {
2076
+ var updateClass = true !== doNotUpdateClass;
2077
+ ParsleyUtils__default.warnOnce('Accessing ParsleyUI is deprecated. Call \'' + method + '\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
2078
+ return instance[method](name, { message: message, assert: assert, updateClass: updateClass });
2079
+ };
2080
+ });
2081
+
2075
2082
  // ### PARSLEY auto-binding
2076
2083
  // Prevent it by setting `ParsleyConfig.autoBind` to `false`
2077
- if (false !== ParsleyUtils.get(window, 'ParsleyConfig.autoBind'))
2084
+ if (false !== window.ParsleyConfig.autoBind) {
2078
2085
  $(function () {
2079
2086
  // Works only on `data-parsley-validate`.
2080
- if ($('[data-parsley-validate]').length)
2081
- $('[data-parsley-validate]').parsley();
2087
+ if ($('[data-parsley-validate]').length) $('[data-parsley-validate]').parsley();
2088
+ });
2089
+ }
2090
+
2091
+ var o = $({});
2092
+ var deprecated = function deprecated() {
2093
+ ParsleyUtils__default.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley");
2094
+ };
2095
+
2096
+ // Returns an event handler that calls `fn` with the arguments it expects
2097
+ function adapt(fn, context) {
2098
+ // Store to allow unbinding
2099
+ if (!fn.parsleyAdaptedCallback) {
2100
+ fn.parsleyAdaptedCallback = function () {
2101
+ var args = Array.prototype.slice.call(arguments, 0);
2102
+ args.unshift(this);
2103
+ fn.apply(context || o, args);
2104
+ };
2105
+ }
2106
+ return fn.parsleyAdaptedCallback;
2107
+ }
2108
+
2109
+ var eventPrefix = 'parsley:';
2110
+ // Converts 'parsley:form:validate' into 'form:validate'
2111
+ function eventName(name) {
2112
+ if (name.lastIndexOf(eventPrefix, 0) === 0) return name.substr(eventPrefix.length);
2113
+ return name;
2114
+ }
2115
+
2116
+ // $.listen is deprecated. Use Parsley.on instead.
2117
+ $.listen = function (name, callback) {
2118
+ var context;
2119
+ deprecated();
2120
+ if ('object' === typeof arguments[1] && 'function' === typeof arguments[2]) {
2121
+ context = arguments[1];
2122
+ callback = arguments[2];
2123
+ }
2124
+
2125
+ if ('function' !== typeof callback) throw new Error('Wrong parameters');
2126
+
2127
+ window.Parsley.on(eventName(name), adapt(callback, context));
2128
+ };
2129
+
2130
+ $.listenTo = function (instance, name, fn) {
2131
+ deprecated();
2132
+ if (!(instance instanceof parsley_field) && !(instance instanceof ParsleyForm)) throw new Error('Must give Parsley instance');
2133
+
2134
+ if ('string' !== typeof name || 'function' !== typeof fn) throw new Error('Wrong parameters');
2135
+
2136
+ instance.on(eventName(name), adapt(fn));
2137
+ };
2138
+
2139
+ $.unsubscribe = function (name, fn) {
2140
+ deprecated();
2141
+ if ('string' !== typeof name || 'function' !== typeof fn) throw new Error('Wrong arguments');
2142
+ window.Parsley.off(eventName(name), fn.parsleyAdaptedCallback);
2143
+ };
2144
+
2145
+ $.unsubscribeTo = function (instance, name) {
2146
+ deprecated();
2147
+ if (!(instance instanceof parsley_field) && !(instance instanceof ParsleyForm)) throw new Error('Must give Parsley instance');
2148
+ instance.off(eventName(name));
2149
+ };
2150
+
2151
+ $.unsubscribeAll = function (name) {
2152
+ deprecated();
2153
+ window.Parsley.off(eventName(name));
2154
+ $('form,input,textarea,select').each(function () {
2155
+ var instance = $(this).data('Parsley');
2156
+ if (instance) {
2157
+ instance.off(eventName(name));
2158
+ }
2159
+ });
2160
+ };
2161
+
2162
+ // $.emit is deprecated. Use jQuery events instead.
2163
+ $.emit = function (name, instance) {
2164
+ var _instance;
2165
+
2166
+ deprecated();
2167
+ var instanceGiven = instance instanceof parsley_field || instance instanceof ParsleyForm;
2168
+ var args = Array.prototype.slice.call(arguments, instanceGiven ? 2 : 1);
2169
+ args.unshift(eventName(name));
2170
+ if (!instanceGiven) {
2171
+ instance = window.Parsley;
2172
+ }
2173
+ (_instance = instance).trigger.apply(_instance, _toConsumableArray(args));
2174
+ };
2175
+
2176
+ var pubsub = {};
2177
+
2178
+ $.extend(true, Parsley, {
2179
+ asyncValidators: {
2180
+ 'default': {
2181
+ fn: function fn(xhr) {
2182
+ // By default, only status 2xx are deemed successful.
2183
+ // Note: we use status instead of state() because responses with status 200
2184
+ // but invalid messages (e.g. an empty body for content type set to JSON) will
2185
+ // result in state() === 'rejected'.
2186
+ return xhr.status >= 200 && xhr.status < 300;
2187
+ },
2188
+ url: false
2189
+ },
2190
+ reverse: {
2191
+ fn: function fn(xhr) {
2192
+ // If reverse option is set, a failing ajax request is considered successful
2193
+ return xhr.status < 200 || xhr.status >= 300;
2194
+ },
2195
+ url: false
2196
+ }
2197
+ },
2198
+
2199
+ addAsyncValidator: function addAsyncValidator(name, fn, url, options) {
2200
+ Parsley.asyncValidators[name] = {
2201
+ fn: fn,
2202
+ url: url || false,
2203
+ options: options || {}
2204
+ };
2205
+
2206
+ return this;
2207
+ }
2208
+
2209
+ });
2210
+
2211
+ Parsley.addValidator('remote', {
2212
+ requirementType: {
2213
+ '': 'string',
2214
+ 'validator': 'string',
2215
+ 'reverse': 'boolean',
2216
+ 'options': 'object'
2217
+ },
2218
+
2219
+ validateString: function validateString(value, url, options, instance) {
2220
+ var data = {};
2221
+ var ajaxOptions;
2222
+ var csr;
2223
+ var validator = options.validator || (true === options.reverse ? 'reverse' : 'default');
2224
+
2225
+ if ('undefined' === typeof Parsley.asyncValidators[validator]) throw new Error('Calling an undefined async validator: `' + validator + '`');
2226
+
2227
+ url = Parsley.asyncValidators[validator].url || url;
2228
+
2229
+ // Fill current value
2230
+ if (url.indexOf('{value}') > -1) {
2231
+ url = url.replace('{value}', encodeURIComponent(value));
2232
+ } else {
2233
+ data[instance.$element.attr('name') || instance.$element.attr('id')] = value;
2234
+ }
2235
+
2236
+ // Merge options passed in from the function with the ones in the attribute
2237
+ var remoteOptions = $.extend(true, options.options || {}, Parsley.asyncValidators[validator].options);
2238
+
2239
+ // All `$.ajax(options)` could be overridden or extended directly from DOM in `data-parsley-remote-options`
2240
+ ajaxOptions = $.extend(true, {}, {
2241
+ url: url,
2242
+ data: data,
2243
+ type: 'GET'
2244
+ }, remoteOptions);
2245
+
2246
+ // Generate store key based on ajax options
2247
+ instance.trigger('field:ajaxoptions', instance, ajaxOptions);
2248
+
2249
+ csr = $.param(ajaxOptions);
2250
+
2251
+ // Initialise querry cache
2252
+ if ('undefined' === typeof Parsley._remoteCache) Parsley._remoteCache = {};
2253
+
2254
+ // Try to retrieve stored xhr
2255
+ var xhr = Parsley._remoteCache[csr] = Parsley._remoteCache[csr] || $.ajax(ajaxOptions);
2256
+
2257
+ var handleXhr = function handleXhr() {
2258
+ var result = Parsley.asyncValidators[validator].fn.call(instance, xhr, url, options);
2259
+ if (!result) // Map falsy results to rejected promise
2260
+ result = $.Deferred().reject();
2261
+ return $.when(result);
2262
+ };
2263
+
2264
+ return xhr.then(handleXhr, handleXhr);
2265
+ },
2266
+
2267
+ priority: -1
2268
+ });
2269
+
2270
+ Parsley.on('form:submit', function () {
2271
+ Parsley._remoteCache = {};
2272
+ });
2273
+
2274
+ window.ParsleyExtend.addAsyncValidator = function () {
2275
+ ParsleyUtils.warnOnce('Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`');
2276
+ return Parsley.addAsyncValidator.apply(Parsley, arguments);
2277
+ };
2278
+
2279
+ // This is included with the Parsley library itself,
2280
+ // thus there is no use in adding it to your project.
2281
+ Parsley.addMessages('en', {
2282
+ defaultMessage: "This value seems to be invalid.",
2283
+ type: {
2284
+ email: "This value should be a valid email.",
2285
+ url: "This value should be a valid url.",
2286
+ number: "This value should be a valid number.",
2287
+ integer: "This value should be a valid integer.",
2288
+ digits: "This value should be digits.",
2289
+ alphanum: "This value should be alphanumeric."
2290
+ },
2291
+ notblank: "This value should not be blank.",
2292
+ required: "This value is required.",
2293
+ pattern: "This value seems to be invalid.",
2294
+ min: "This value should be greater than or equal to %s.",
2295
+ max: "This value should be lower than or equal to %s.",
2296
+ range: "This value should be between %s and %s.",
2297
+ minlength: "This value is too short. It should have %s characters or more.",
2298
+ maxlength: "This value is too long. It should have %s characters or fewer.",
2299
+ length: "This value length is invalid. It should be between %s and %s characters long.",
2300
+ mincheck: "You must select at least %s choices.",
2301
+ maxcheck: "You must select %s choices or fewer.",
2302
+ check: "You must select between %s and %s choices.",
2303
+ equalto: "This value should be the same."
2304
+ });
2305
+
2306
+ Parsley.setLocale('en');
2307
+
2308
+ /**
2309
+ * inputevent - Alleviate browser bugs for input events
2310
+ * https://github.com/marcandre/inputevent
2311
+ * @version v0.0.3 - (built Thu, Apr 14th 2016, 5:58 pm)
2312
+ * @author Marc-Andre Lafortune <github@marc-andre.ca>
2313
+ * @license MIT
2314
+ */
2315
+
2316
+ function InputEvent() {
2317
+ var _this13 = this;
2318
+
2319
+ var globals = window || global;
2320
+
2321
+ // Slightly odd way construct our object. This way methods are force bound.
2322
+ // Used to test for duplicate library.
2323
+ $.extend(this, {
2324
+
2325
+ // For browsers that do not support isTrusted, assumes event is native.
2326
+ isNativeEvent: function isNativeEvent(evt) {
2327
+ return evt.originalEvent && evt.originalEvent.isTrusted !== false;
2328
+ },
2329
+
2330
+ fakeInputEvent: function fakeInputEvent(evt) {
2331
+ if (_this13.isNativeEvent(evt)) {
2332
+ $(evt.target).trigger('input');
2333
+ }
2334
+ },
2335
+
2336
+ misbehaves: function misbehaves(evt) {
2337
+ if (_this13.isNativeEvent(evt)) {
2338
+ _this13.behavesOk(evt);
2339
+ $(document).on('change.inputevent', evt.data.selector, _this13.fakeInputEvent);
2340
+ _this13.fakeInputEvent(evt);
2341
+ }
2342
+ },
2343
+
2344
+ behavesOk: function behavesOk(evt) {
2345
+ if (_this13.isNativeEvent(evt)) {
2346
+ $(document) // Simply unbinds the testing handler
2347
+ .off('input.inputevent', evt.data.selector, _this13.behavesOk).off('change.inputevent', evt.data.selector, _this13.misbehaves);
2348
+ }
2349
+ },
2350
+
2351
+ // Bind the testing handlers
2352
+ install: function install() {
2353
+ if (globals.inputEventPatched) {
2354
+ return;
2355
+ }
2356
+ globals.inputEventPatched = '0.0.3';
2357
+ var _arr = ['select', 'input[type="checkbox"]', 'input[type="radio"]', 'input[type="file"]'];
2358
+ for (var _i = 0; _i < _arr.length; _i++) {
2359
+ var selector = _arr[_i];
2360
+ $(document).on('input.inputevent', selector, { selector: selector }, _this13.behavesOk).on('change.inputevent', selector, { selector: selector }, _this13.misbehaves);
2361
+ }
2362
+ },
2363
+
2364
+ uninstall: function uninstall() {
2365
+ delete globals.inputEventPatched;
2366
+ $(document).off('.inputevent');
2367
+ }
2368
+
2082
2369
  });
2083
- }));
2370
+ };
2371
+
2372
+ var inputevent = new InputEvent();
2373
+
2374
+ inputevent.install();
2375
+
2376
+ var parsley = Parsley;
2377
+
2378
+ return parsley;
2379
+ });
2380
+ //# sourceMappingURL=parsley.js.map