parsley.js 87 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357
  1. /*!
  2. * Parsley.js
  3. * Version 2.3.13 - built Tue, May 31st 2016, 8:55 am
  4. * http://parsleyjs.org
  5. * Guillaume Potier - <guillaume@wisembly.com>
  6. * Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
  7. * MIT Licensed
  8. */
  9. // The source code below is generated by babel as
  10. // Parsley is written in ECMAScript 6
  11. //
  12. var _slice = Array.prototype.slice;
  13. function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }
  14. (function (global, factory) {
  15. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) : typeof define === 'function' && define.amd ? define(['jquery'], factory) : global.parsley = factory(global.jQuery);
  16. })(this, function ($) {
  17. 'use strict';
  18. var globalID = 1;
  19. var pastWarnings = {};
  20. var ParsleyUtils__ParsleyUtils = {
  21. // Parsley DOM-API
  22. // returns object from dom attributes and values
  23. attr: function attr($element, namespace, obj) {
  24. var i;
  25. var attribute;
  26. var attributes;
  27. var regex = new RegExp('^' + namespace, 'i');
  28. if ('undefined' === typeof obj) obj = {};else {
  29. // Clear all own properties. This won't affect prototype's values
  30. for (i in obj) {
  31. if (obj.hasOwnProperty(i)) delete obj[i];
  32. }
  33. }
  34. if ('undefined' === typeof $element || 'undefined' === typeof $element[0]) return obj;
  35. attributes = $element[0].attributes;
  36. for (i = attributes.length; i--;) {
  37. attribute = attributes[i];
  38. if (attribute && attribute.specified && regex.test(attribute.name)) {
  39. obj[this.camelize(attribute.name.slice(namespace.length))] = this.deserializeValue(attribute.value);
  40. }
  41. }
  42. return obj;
  43. },
  44. checkAttr: function checkAttr($element, namespace, _checkAttr) {
  45. return $element.is('[' + namespace + _checkAttr + ']');
  46. },
  47. setAttr: function setAttr($element, namespace, attr, value) {
  48. $element[0].setAttribute(this.dasherize(namespace + attr), String(value));
  49. },
  50. generateID: function generateID() {
  51. return '' + globalID++;
  52. },
  53. /** Third party functions **/
  54. // Zepto deserialize function
  55. deserializeValue: function deserializeValue(value) {
  56. var num;
  57. try {
  58. return value ? value == "true" || (value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? $.parseJSON(value) : value) : value;
  59. } catch (e) {
  60. return value;
  61. }
  62. },
  63. // Zepto camelize function
  64. camelize: function camelize(str) {
  65. return str.replace(/-+(.)?/g, function (match, chr) {
  66. return chr ? chr.toUpperCase() : '';
  67. });
  68. },
  69. // Zepto dasherize function
  70. dasherize: function dasherize(str) {
  71. return str.replace(/::/g, '/').replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2').replace(/([a-z\d])([A-Z])/g, '$1_$2').replace(/_/g, '-').toLowerCase();
  72. },
  73. warn: function warn() {
  74. var _window$console;
  75. if (window.console && 'function' === typeof window.console.warn) (_window$console = window.console).warn.apply(_window$console, arguments);
  76. },
  77. warnOnce: function warnOnce(msg) {
  78. if (!pastWarnings[msg]) {
  79. pastWarnings[msg] = true;
  80. this.warn.apply(this, arguments);
  81. }
  82. },
  83. _resetWarnings: function _resetWarnings() {
  84. pastWarnings = {};
  85. },
  86. trimString: function trimString(string) {
  87. return string.replace(/^\s+|\s+$/g, '');
  88. },
  89. namespaceEvents: function namespaceEvents(events, namespace) {
  90. events = this.trimString(events || '').split(/\s+/);
  91. if (!events[0]) return '';
  92. return $.map(events, function (evt) {
  93. return evt + '.' + namespace;
  94. }).join(' ');
  95. },
  96. // Object.create polyfill, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Polyfill
  97. objectCreate: Object.create || (function () {
  98. var Object = function Object() {};
  99. return function (prototype) {
  100. if (arguments.length > 1) {
  101. throw Error('Second argument not supported');
  102. }
  103. if (typeof prototype != 'object') {
  104. throw TypeError('Argument must be an object');
  105. }
  106. Object.prototype = prototype;
  107. var result = new Object();
  108. Object.prototype = null;
  109. return result;
  110. };
  111. })()
  112. };
  113. var ParsleyUtils__default = ParsleyUtils__ParsleyUtils;
  114. // All these options could be overriden and specified directly in DOM using
  115. // `data-parsley-` default DOM-API
  116. // eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"`
  117. // eg: `data-parsley-stop-on-first-failing-constraint="false"`
  118. var ParsleyDefaults = {
  119. // ### General
  120. // Default data-namespace for DOM API
  121. namespace: 'data-parsley-',
  122. // Supported inputs by default
  123. inputs: 'input, textarea, select',
  124. // Excluded inputs by default
  125. excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden]',
  126. // Stop validating field on highest priority failing constraint
  127. priorityEnabled: true,
  128. // ### Field only
  129. // identifier used to group together inputs (e.g. radio buttons...)
  130. multiple: null,
  131. // identifier (or array of identifiers) used to validate only a select group of inputs
  132. group: null,
  133. // ### UI
  134. // Enable\Disable error messages
  135. uiEnabled: true,
  136. // Key events threshold before validation
  137. validationThreshold: 3,
  138. // Focused field on form validation error. 'first'|'last'|'none'
  139. focus: 'first',
  140. // event(s) that will trigger validation before first failure. eg: `input`...
  141. trigger: false,
  142. // event(s) that will trigger validation after first failure.
  143. triggerAfterFailure: 'input',
  144. // Class that would be added on every failing validation Parsley field
  145. errorClass: 'parsley-error',
  146. // Same for success validation
  147. successClass: 'parsley-success',
  148. // Return the `$element` that will receive these above success or error classes
  149. // Could also be (and given directly from DOM) a valid selector like `'#div'`
  150. classHandler: function classHandler(ParsleyField) {},
  151. // Return the `$element` where errors will be appended
  152. // Could also be (and given directly from DOM) a valid selector like `'#div'`
  153. errorsContainer: function errorsContainer(ParsleyField) {},
  154. // ul elem that would receive errors' list
  155. errorsWrapper: '<ul class="parsley-errors-list"></ul>',
  156. // li elem that would receive error message
  157. errorTemplate: '<li></li>'
  158. };
  159. var ParsleyAbstract = function ParsleyAbstract() {
  160. this.__id__ = ParsleyUtils__default.generateID();
  161. };
  162. ParsleyAbstract.prototype = {
  163. asyncSupport: true, // Deprecated
  164. _pipeAccordingToValidationResult: function _pipeAccordingToValidationResult() {
  165. var _this = this;
  166. var pipe = function pipe() {
  167. var r = $.Deferred();
  168. if (true !== _this.validationResult) r.reject();
  169. return r.resolve().promise();
  170. };
  171. return [pipe, pipe];
  172. },
  173. actualizeOptions: function actualizeOptions() {
  174. ParsleyUtils__default.attr(this.$element, this.options.namespace, this.domOptions);
  175. if (this.parent && this.parent.actualizeOptions) this.parent.actualizeOptions();
  176. return this;
  177. },
  178. _resetOptions: function _resetOptions(initOptions) {
  179. this.domOptions = ParsleyUtils__default.objectCreate(this.parent.options);
  180. this.options = ParsleyUtils__default.objectCreate(this.domOptions);
  181. // Shallow copy of ownProperties of initOptions:
  182. for (var i in initOptions) {
  183. if (initOptions.hasOwnProperty(i)) this.options[i] = initOptions[i];
  184. }
  185. this.actualizeOptions();
  186. },
  187. _listeners: null,
  188. // Register a callback for the given event name
  189. // Callback is called with context as the first argument and the `this`
  190. // The context is the current parsley instance, or window.Parsley if global
  191. // A return value of `false` will interrupt the calls
  192. on: function on(name, fn) {
  193. this._listeners = this._listeners || {};
  194. var queue = this._listeners[name] = this._listeners[name] || [];
  195. queue.push(fn);
  196. return this;
  197. },
  198. // Deprecated. Use `on` instead
  199. subscribe: function subscribe(name, fn) {
  200. $.listenTo(this, name.toLowerCase(), fn);
  201. },
  202. // Unregister a callback (or all if none is given) for the given event name
  203. off: function off(name, fn) {
  204. var queue = this._listeners && this._listeners[name];
  205. if (queue) {
  206. if (!fn) {
  207. delete this._listeners[name];
  208. } else {
  209. for (var i = queue.length; i--;) if (queue[i] === fn) queue.splice(i, 1);
  210. }
  211. }
  212. return this;
  213. },
  214. // Deprecated. Use `off`
  215. unsubscribe: function unsubscribe(name, fn) {
  216. $.unsubscribeTo(this, name.toLowerCase());
  217. },
  218. // Trigger an event of the given name
  219. // A return value of `false` interrupts the callback chain
  220. // Returns false if execution was interrupted
  221. trigger: function trigger(name, target, extraArg) {
  222. target = target || this;
  223. var queue = this._listeners && this._listeners[name];
  224. var result;
  225. var parentResult;
  226. if (queue) {
  227. for (var i = queue.length; i--;) {
  228. result = queue[i].call(target, target, extraArg);
  229. if (result === false) return result;
  230. }
  231. }
  232. if (this.parent) {
  233. return this.parent.trigger(name, target, extraArg);
  234. }
  235. return true;
  236. },
  237. // Reset UI
  238. reset: function reset() {
  239. // Field case: just emit a reset event for UI
  240. if ('ParsleyForm' !== this.__class__) {
  241. this._resetUI();
  242. return this._trigger('reset');
  243. }
  244. // Form case: emit a reset event for each field
  245. for (var i = 0; i < this.fields.length; i++) this.fields[i].reset();
  246. this._trigger('reset');
  247. },
  248. // Destroy Parsley instance (+ UI)
  249. destroy: function destroy() {
  250. // Field case: emit destroy event to clean UI and then destroy stored instance
  251. this._destroyUI();
  252. if ('ParsleyForm' !== this.__class__) {
  253. this.$element.removeData('Parsley');
  254. this.$element.removeData('ParsleyFieldMultiple');
  255. this._trigger('destroy');
  256. return;
  257. }
  258. // Form case: destroy all its fields and then destroy stored instance
  259. for (var i = 0; i < this.fields.length; i++) this.fields[i].destroy();
  260. this.$element.removeData('Parsley');
  261. this._trigger('destroy');
  262. },
  263. asyncIsValid: function asyncIsValid(group, force) {
  264. ParsleyUtils__default.warnOnce("asyncIsValid is deprecated; please use whenValid instead");
  265. return this.whenValid({ group: group, force: force });
  266. },
  267. _findRelated: function _findRelated() {
  268. return this.options.multiple ? this.parent.$element.find('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]') : this.$element;
  269. }
  270. };
  271. var requirementConverters = {
  272. string: function string(_string) {
  273. return _string;
  274. },
  275. integer: function integer(string) {
  276. if (isNaN(string)) throw 'Requirement is not an integer: "' + string + '"';
  277. return parseInt(string, 10);
  278. },
  279. number: function number(string) {
  280. if (isNaN(string)) throw 'Requirement is not a number: "' + string + '"';
  281. return parseFloat(string);
  282. },
  283. reference: function reference(string) {
  284. // Unused for now
  285. var result = $(string);
  286. if (result.length === 0) throw 'No such reference: "' + string + '"';
  287. return result;
  288. },
  289. boolean: function boolean(string) {
  290. return string !== 'false';
  291. },
  292. object: function object(string) {
  293. return ParsleyUtils__default.deserializeValue(string);
  294. },
  295. regexp: function regexp(_regexp) {
  296. var flags = '';
  297. // Test if RegExp is literal, if not, nothing to be done, otherwise, we need to isolate flags and pattern
  298. if (/^\/.*\/(?:[gimy]*)$/.test(_regexp)) {
  299. // Replace the regexp literal string with the first match group: ([gimy]*)
  300. // If no flag is present, this will be a blank string
  301. flags = _regexp.replace(/.*\/([gimy]*)$/, '$1');
  302. // Again, replace the regexp literal string with the first match group:
  303. // everything excluding the opening and closing slashes and the flags
  304. _regexp = _regexp.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
  305. } else {
  306. // Anchor regexp:
  307. _regexp = '^' + _regexp + '$';
  308. }
  309. return new RegExp(_regexp, flags);
  310. }
  311. };
  312. var convertArrayRequirement = function convertArrayRequirement(string, length) {
  313. var m = string.match(/^\s*\[(.*)\]\s*$/);
  314. if (!m) throw 'Requirement is not an array: "' + string + '"';
  315. var values = m[1].split(',').map(ParsleyUtils__default.trimString);
  316. if (values.length !== length) throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed';
  317. return values;
  318. };
  319. var convertRequirement = function convertRequirement(requirementType, string) {
  320. var converter = requirementConverters[requirementType || 'string'];
  321. if (!converter) throw 'Unknown requirement specification: "' + requirementType + '"';
  322. return converter(string);
  323. };
  324. var convertExtraOptionRequirement = function convertExtraOptionRequirement(requirementSpec, string, extraOptionReader) {
  325. var main = null;
  326. var extra = {};
  327. for (var key in requirementSpec) {
  328. if (key) {
  329. var value = extraOptionReader(key);
  330. if ('string' === typeof value) value = convertRequirement(requirementSpec[key], value);
  331. extra[key] = value;
  332. } else {
  333. main = convertRequirement(requirementSpec[key], string);
  334. }
  335. }
  336. return [main, extra];
  337. };
  338. // A Validator needs to implement the methods `validate` and `parseRequirements`
  339. var ParsleyValidator = function ParsleyValidator(spec) {
  340. $.extend(true, this, spec);
  341. };
  342. ParsleyValidator.prototype = {
  343. // Returns `true` iff the given `value` is valid according the given requirements.
  344. validate: function validate(value, requirementFirstArg) {
  345. if (this.fn) {
  346. // Legacy style validator
  347. if (arguments.length > 3) // If more args then value, requirement, instance...
  348. requirementFirstArg = [].slice.call(arguments, 1, -1); // Skip first arg (value) and last (instance), combining the rest
  349. return this.fn.call(this, value, requirementFirstArg);
  350. }
  351. if ($.isArray(value)) {
  352. if (!this.validateMultiple) throw 'Validator `' + this.name + '` does not handle multiple values';
  353. return this.validateMultiple.apply(this, arguments);
  354. } else {
  355. if (this.validateNumber) {
  356. if (isNaN(value)) return false;
  357. arguments[0] = parseFloat(arguments[0]);
  358. return this.validateNumber.apply(this, arguments);
  359. }
  360. if (this.validateString) {
  361. return this.validateString.apply(this, arguments);
  362. }
  363. throw 'Validator `' + this.name + '` only handles multiple values';
  364. }
  365. },
  366. // Parses `requirements` into an array of arguments,
  367. // according to `this.requirementType`
  368. parseRequirements: function parseRequirements(requirements, extraOptionReader) {
  369. if ('string' !== typeof requirements) {
  370. // Assume requirement already parsed
  371. // but make sure we return an array
  372. return $.isArray(requirements) ? requirements : [requirements];
  373. }
  374. var type = this.requirementType;
  375. if ($.isArray(type)) {
  376. var values = convertArrayRequirement(requirements, type.length);
  377. for (var i = 0; i < values.length; i++) values[i] = convertRequirement(type[i], values[i]);
  378. return values;
  379. } else if ($.isPlainObject(type)) {
  380. return convertExtraOptionRequirement(type, requirements, extraOptionReader);
  381. } else {
  382. return [convertRequirement(type, requirements)];
  383. }
  384. },
  385. // Defaults:
  386. requirementType: 'string',
  387. priority: 2
  388. };
  389. var ParsleyValidatorRegistry = function ParsleyValidatorRegistry(validators, catalog) {
  390. this.__class__ = 'ParsleyValidatorRegistry';
  391. // Default Parsley locale is en
  392. this.locale = 'en';
  393. this.init(validators || {}, catalog || {});
  394. };
  395. var typeRegexes = {
  396. 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,
  397. // Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
  398. number: /^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,
  399. integer: /^-?\d+$/,
  400. digits: /^\d+$/,
  401. alphanum: /^\w+$/i,
  402. url: new RegExp("^" +
  403. // protocol identifier
  404. "(?:(?:https?|ftp)://)?" + // ** mod: make scheme optional
  405. // user:pass authentication
  406. "(?:\\S+(?::\\S*)?@)?" + "(?:" +
  407. // IP address exclusion
  408. // private & local networks
  409. // "(?!(?:10|127)(?:\\.\\d{1,3}){3})" + // ** mod: allow local networks
  410. // "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" + // ** mod: allow local networks
  411. // "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + // ** mod: allow local networks
  412. // IP address dotted notation octets
  413. // excludes loopback network 0.0.0.0
  414. // excludes reserved space >= 224.0.0.0
  415. // excludes network & broacast addresses
  416. // (first & last IP address of each class)
  417. "(?:[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]))" + "|" +
  418. // host name
  419. '(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)' +
  420. // domain name
  421. '(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*' +
  422. // TLD identifier
  423. '(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))' + ")" +
  424. // port number
  425. "(?::\\d{2,5})?" +
  426. // resource path
  427. "(?:/\\S*)?" + "$", 'i')
  428. };
  429. typeRegexes.range = typeRegexes.number;
  430. // See http://stackoverflow.com/a/10454560/8279
  431. var decimalPlaces = function decimalPlaces(num) {
  432. var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
  433. if (!match) {
  434. return 0;
  435. }
  436. return Math.max(0,
  437. // Number of digits right of decimal point.
  438. (match[1] ? match[1].length : 0) - (
  439. // Adjust for scientific notation.
  440. match[2] ? +match[2] : 0));
  441. };
  442. ParsleyValidatorRegistry.prototype = {
  443. init: function init(validators, catalog) {
  444. this.catalog = catalog;
  445. // Copy prototype's validators:
  446. this.validators = $.extend({}, this.validators);
  447. for (var name in validators) this.addValidator(name, validators[name].fn, validators[name].priority);
  448. window.Parsley.trigger('parsley:validator:init');
  449. },
  450. // Set new messages locale if we have dictionary loaded in ParsleyConfig.i18n
  451. setLocale: function setLocale(locale) {
  452. if ('undefined' === typeof this.catalog[locale]) throw new Error(locale + ' is not available in the catalog');
  453. this.locale = locale;
  454. return this;
  455. },
  456. // Add a new messages catalog for a given locale. Set locale for this catalog if set === `true`
  457. addCatalog: function addCatalog(locale, messages, set) {
  458. if ('object' === typeof messages) this.catalog[locale] = messages;
  459. if (true === set) return this.setLocale(locale);
  460. return this;
  461. },
  462. // Add a specific message for a given constraint in a given locale
  463. addMessage: function addMessage(locale, name, message) {
  464. if ('undefined' === typeof this.catalog[locale]) this.catalog[locale] = {};
  465. this.catalog[locale][name] = message;
  466. return this;
  467. },
  468. // Add messages for a given locale
  469. addMessages: function addMessages(locale, nameMessageObject) {
  470. for (var name in nameMessageObject) this.addMessage(locale, name, nameMessageObject[name]);
  471. return this;
  472. },
  473. // Add a new validator
  474. //
  475. // addValidator('custom', {
  476. // requirementType: ['integer', 'integer'],
  477. // validateString: function(value, from, to) {},
  478. // priority: 22,
  479. // messages: {
  480. // en: "Hey, that's no good",
  481. // fr: "Aye aye, pas bon du tout",
  482. // }
  483. // })
  484. //
  485. // Old API was addValidator(name, function, priority)
  486. //
  487. addValidator: function addValidator(name, arg1, arg2) {
  488. if (this.validators[name]) ParsleyUtils__default.warn('Validator "' + name + '" is already defined.');else if (ParsleyDefaults.hasOwnProperty(name)) {
  489. ParsleyUtils__default.warn('"' + name + '" is a restricted keyword and is not a valid validator name.');
  490. return;
  491. }
  492. return this._setValidator.apply(this, arguments);
  493. },
  494. updateValidator: function updateValidator(name, arg1, arg2) {
  495. if (!this.validators[name]) {
  496. ParsleyUtils__default.warn('Validator "' + name + '" is not already defined.');
  497. return this.addValidator.apply(this, arguments);
  498. }
  499. return this._setValidator.apply(this, arguments);
  500. },
  501. removeValidator: function removeValidator(name) {
  502. if (!this.validators[name]) ParsleyUtils__default.warn('Validator "' + name + '" is not defined.');
  503. delete this.validators[name];
  504. return this;
  505. },
  506. _setValidator: function _setValidator(name, validator, priority) {
  507. if ('object' !== typeof validator) {
  508. // Old style validator, with `fn` and `priority`
  509. validator = {
  510. fn: validator,
  511. priority: priority
  512. };
  513. }
  514. if (!validator.validate) {
  515. validator = new ParsleyValidator(validator);
  516. }
  517. this.validators[name] = validator;
  518. for (var locale in validator.messages || {}) this.addMessage(locale, name, validator.messages[locale]);
  519. return this;
  520. },
  521. getErrorMessage: function getErrorMessage(constraint) {
  522. var message;
  523. // Type constraints are a bit different, we have to match their requirements too to find right error message
  524. if ('type' === constraint.name) {
  525. var typeMessages = this.catalog[this.locale][constraint.name] || {};
  526. message = typeMessages[constraint.requirements];
  527. } else message = this.formatMessage(this.catalog[this.locale][constraint.name], constraint.requirements);
  528. return message || this.catalog[this.locale].defaultMessage || this.catalog.en.defaultMessage;
  529. },
  530. // Kind of light `sprintf()` implementation
  531. formatMessage: function formatMessage(string, parameters) {
  532. if ('object' === typeof parameters) {
  533. for (var i in parameters) string = this.formatMessage(string, parameters[i]);
  534. return string;
  535. }
  536. return 'string' === typeof string ? string.replace(/%s/i, parameters) : '';
  537. },
  538. // Here is the Parsley default validators list.
  539. // A validator is an object with the following key values:
  540. // - priority: an integer
  541. // - requirement: 'string' (default), 'integer', 'number', 'regexp' or an Array of these
  542. // - validateString, validateMultiple, validateNumber: functions returning `true`, `false` or a promise
  543. // Alternatively, a validator can be a function that returns such an object
  544. //
  545. validators: {
  546. notblank: {
  547. validateString: function validateString(value) {
  548. return (/\S/.test(value)
  549. );
  550. },
  551. priority: 2
  552. },
  553. required: {
  554. validateMultiple: function validateMultiple(values) {
  555. return values.length > 0;
  556. },
  557. validateString: function validateString(value) {
  558. return (/\S/.test(value)
  559. );
  560. },
  561. priority: 512
  562. },
  563. type: {
  564. validateString: function validateString(value, type) {
  565. var _ref = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
  566. var _ref$step = _ref.step;
  567. var step = _ref$step === undefined ? '1' : _ref$step;
  568. var _ref$base = _ref.base;
  569. var base = _ref$base === undefined ? 0 : _ref$base;
  570. var regex = typeRegexes[type];
  571. if (!regex) {
  572. throw new Error('validator type `' + type + '` is not supported');
  573. }
  574. if (!regex.test(value)) return false;
  575. if ('number' === type) {
  576. if (!/^any$/i.test(step || '')) {
  577. var nb = Number(value);
  578. var decimals = Math.max(decimalPlaces(step), decimalPlaces(base));
  579. if (decimalPlaces(nb) > decimals) // Value can't have too many decimals
  580. return false;
  581. // Be careful of rounding errors by using integers.
  582. var toInt = function toInt(f) {
  583. return Math.round(f * Math.pow(10, decimals));
  584. };
  585. if ((toInt(nb) - toInt(base)) % toInt(step) != 0) return false;
  586. }
  587. }
  588. return true;
  589. },
  590. requirementType: {
  591. '': 'string',
  592. step: 'string',
  593. base: 'number'
  594. },
  595. priority: 256
  596. },
  597. pattern: {
  598. validateString: function validateString(value, regexp) {
  599. return regexp.test(value);
  600. },
  601. requirementType: 'regexp',
  602. priority: 64
  603. },
  604. minlength: {
  605. validateString: function validateString(value, requirement) {
  606. return value.length >= requirement;
  607. },
  608. requirementType: 'integer',
  609. priority: 30
  610. },
  611. maxlength: {
  612. validateString: function validateString(value, requirement) {
  613. return value.length <= requirement;
  614. },
  615. requirementType: 'integer',
  616. priority: 30
  617. },
  618. length: {
  619. validateString: function validateString(value, min, max) {
  620. return value.length >= min && value.length <= max;
  621. },
  622. requirementType: ['integer', 'integer'],
  623. priority: 30
  624. },
  625. mincheck: {
  626. validateMultiple: function validateMultiple(values, requirement) {
  627. return values.length >= requirement;
  628. },
  629. requirementType: 'integer',
  630. priority: 30
  631. },
  632. maxcheck: {
  633. validateMultiple: function validateMultiple(values, requirement) {
  634. return values.length <= requirement;
  635. },
  636. requirementType: 'integer',
  637. priority: 30
  638. },
  639. check: {
  640. validateMultiple: function validateMultiple(values, min, max) {
  641. return values.length >= min && values.length <= max;
  642. },
  643. requirementType: ['integer', 'integer'],
  644. priority: 30
  645. },
  646. min: {
  647. validateNumber: function validateNumber(value, requirement) {
  648. return value >= requirement;
  649. },
  650. requirementType: 'number',
  651. priority: 30
  652. },
  653. max: {
  654. validateNumber: function validateNumber(value, requirement) {
  655. return value <= requirement;
  656. },
  657. requirementType: 'number',
  658. priority: 30
  659. },
  660. range: {
  661. validateNumber: function validateNumber(value, min, max) {
  662. return value >= min && value <= max;
  663. },
  664. requirementType: ['number', 'number'],
  665. priority: 30
  666. },
  667. equalto: {
  668. validateString: function validateString(value, refOrValue) {
  669. var $reference = $(refOrValue);
  670. if ($reference.length) return value === $reference.val();else return value === refOrValue;
  671. },
  672. priority: 256
  673. }
  674. }
  675. };
  676. var ParsleyUI = {};
  677. var diffResults = function diffResults(newResult, oldResult, deep) {
  678. var added = [];
  679. var kept = [];
  680. for (var i = 0; i < newResult.length; i++) {
  681. var found = false;
  682. for (var j = 0; j < oldResult.length; j++) if (newResult[i].assert.name === oldResult[j].assert.name) {
  683. found = true;
  684. break;
  685. }
  686. if (found) kept.push(newResult[i]);else added.push(newResult[i]);
  687. }
  688. return {
  689. kept: kept,
  690. added: added,
  691. removed: !deep ? diffResults(oldResult, newResult, true).added : []
  692. };
  693. };
  694. ParsleyUI.Form = {
  695. _actualizeTriggers: function _actualizeTriggers() {
  696. var _this2 = this;
  697. this.$element.on('submit.Parsley', function (evt) {
  698. _this2.onSubmitValidate(evt);
  699. });
  700. this.$element.on('click.Parsley', 'input[type="submit"], button[type="submit"]', function (evt) {
  701. _this2.onSubmitButton(evt);
  702. });
  703. // UI could be disabled
  704. if (false === this.options.uiEnabled) return;
  705. this.$element.attr('novalidate', '');
  706. },
  707. focus: function focus() {
  708. this._focusedField = null;
  709. if (true === this.validationResult || 'none' === this.options.focus) return null;
  710. for (var i = 0; i < this.fields.length; i++) {
  711. var field = this.fields[i];
  712. if (true !== field.validationResult && field.validationResult.length > 0 && 'undefined' === typeof field.options.noFocus) {
  713. this._focusedField = field.$element;
  714. if ('first' === this.options.focus) break;
  715. }
  716. }
  717. if (null === this._focusedField) return null;
  718. return this._focusedField.focus();
  719. },
  720. _destroyUI: function _destroyUI() {
  721. // Reset all event listeners
  722. this.$element.off('.Parsley');
  723. }
  724. };
  725. ParsleyUI.Field = {
  726. _reflowUI: function _reflowUI() {
  727. this._buildUI();
  728. // If this field doesn't have an active UI don't bother doing something
  729. if (!this._ui) return;
  730. // Diff between two validation results
  731. var diff = diffResults(this.validationResult, this._ui.lastValidationResult);
  732. // Then store current validation result for next reflow
  733. this._ui.lastValidationResult = this.validationResult;
  734. // Handle valid / invalid / none field class
  735. this._manageStatusClass();
  736. // Add, remove, updated errors messages
  737. this._manageErrorsMessages(diff);
  738. // Triggers impl
  739. this._actualizeTriggers();
  740. // If field is not valid for the first time, bind keyup trigger to ease UX and quickly inform user
  741. if ((diff.kept.length || diff.added.length) && !this._failedOnce) {
  742. this._failedOnce = true;
  743. this._actualizeTriggers();
  744. }
  745. },
  746. // Returns an array of field's error message(s)
  747. getErrorsMessages: function getErrorsMessages() {
  748. // No error message, field is valid
  749. if (true === this.validationResult) return [];
  750. var messages = [];
  751. for (var i = 0; i < this.validationResult.length; i++) messages.push(this.validationResult[i].errorMessage || this._getErrorMessage(this.validationResult[i].assert));
  752. return messages;
  753. },
  754. // It's a goal of Parsley that this method is no longer required [#1073]
  755. addError: function addError(name) {
  756. var _ref2 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  757. var message = _ref2.message;
  758. var assert = _ref2.assert;
  759. var _ref2$updateClass = _ref2.updateClass;
  760. var updateClass = _ref2$updateClass === undefined ? true : _ref2$updateClass;
  761. this._buildUI();
  762. this._addError(name, { message: message, assert: assert });
  763. if (updateClass) this._errorClass();
  764. },
  765. // It's a goal of Parsley that this method is no longer required [#1073]
  766. updateError: function updateError(name) {
  767. var _ref3 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  768. var message = _ref3.message;
  769. var assert = _ref3.assert;
  770. var _ref3$updateClass = _ref3.updateClass;
  771. var updateClass = _ref3$updateClass === undefined ? true : _ref3$updateClass;
  772. this._buildUI();
  773. this._updateError(name, { message: message, assert: assert });
  774. if (updateClass) this._errorClass();
  775. },
  776. // It's a goal of Parsley that this method is no longer required [#1073]
  777. removeError: function removeError(name) {
  778. var _ref4 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  779. var _ref4$updateClass = _ref4.updateClass;
  780. var updateClass = _ref4$updateClass === undefined ? true : _ref4$updateClass;
  781. this._buildUI();
  782. this._removeError(name);
  783. // edge case possible here: remove a standard Parsley error that is still failing in this.validationResult
  784. // but highly improbable cuz' manually removing a well Parsley handled error makes no sense.
  785. if (updateClass) this._manageStatusClass();
  786. },
  787. _manageStatusClass: function _manageStatusClass() {
  788. if (this.hasConstraints() && this.needsValidation() && true === this.validationResult) this._successClass();else if (this.validationResult.length > 0) this._errorClass();else this._resetClass();
  789. },
  790. _manageErrorsMessages: function _manageErrorsMessages(diff) {
  791. if ('undefined' !== typeof this.options.errorsMessagesDisabled) return;
  792. // Case where we have errorMessage option that configure an unique field error message, regardless failing validators
  793. if ('undefined' !== typeof this.options.errorMessage) {
  794. if (diff.added.length || diff.kept.length) {
  795. this._insertErrorWrapper();
  796. if (0 === this._ui.$errorsWrapper.find('.parsley-custom-error-message').length) this._ui.$errorsWrapper.append($(this.options.errorTemplate).addClass('parsley-custom-error-message'));
  797. return this._ui.$errorsWrapper.addClass('filled').find('.parsley-custom-error-message').html(this.options.errorMessage);
  798. }
  799. return this._ui.$errorsWrapper.removeClass('filled').find('.parsley-custom-error-message').remove();
  800. }
  801. // Show, hide, update failing constraints messages
  802. for (var i = 0; i < diff.removed.length; i++) this._removeError(diff.removed[i].assert.name);
  803. 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 });
  804. 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 });
  805. },
  806. _addError: function _addError(name, _ref5) {
  807. var message = _ref5.message;
  808. var assert = _ref5.assert;
  809. this._insertErrorWrapper();
  810. this._ui.$errorsWrapper.addClass('filled').append($(this.options.errorTemplate).addClass('parsley-' + name).html(message || this._getErrorMessage(assert)));
  811. },
  812. _updateError: function _updateError(name, _ref6) {
  813. var message = _ref6.message;
  814. var assert = _ref6.assert;
  815. this._ui.$errorsWrapper.addClass('filled').find('.parsley-' + name).html(message || this._getErrorMessage(assert));
  816. },
  817. _removeError: function _removeError(name) {
  818. this._ui.$errorsWrapper.removeClass('filled').find('.parsley-' + name).remove();
  819. },
  820. _getErrorMessage: function _getErrorMessage(constraint) {
  821. var customConstraintErrorMessage = constraint.name + 'Message';
  822. if ('undefined' !== typeof this.options[customConstraintErrorMessage]) return window.Parsley.formatMessage(this.options[customConstraintErrorMessage], constraint.requirements);
  823. return window.Parsley.getErrorMessage(constraint);
  824. },
  825. _buildUI: function _buildUI() {
  826. // UI could be already built or disabled
  827. if (this._ui || false === this.options.uiEnabled) return;
  828. var _ui = {};
  829. // Give field its Parsley id in DOM
  830. this.$element.attr(this.options.namespace + 'id', this.__id__);
  831. /** Generate important UI elements and store them in this **/
  832. // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes
  833. _ui.$errorClassHandler = this._manageClassHandler();
  834. // $errorsWrapper is a div that would contain the various field errors, it will be appended into $errorsContainer
  835. _ui.errorsWrapperId = 'parsley-id-' + (this.options.multiple ? 'multiple-' + this.options.multiple : this.__id__);
  836. _ui.$errorsWrapper = $(this.options.errorsWrapper).attr('id', _ui.errorsWrapperId);
  837. // ValidationResult UI storage to detect what have changed bwt two validations, and update DOM accordingly
  838. _ui.lastValidationResult = [];
  839. _ui.validationInformationVisible = false;
  840. // Store it in this for later
  841. this._ui = _ui;
  842. },
  843. // Determine which element will have `parsley-error` and `parsley-success` classes
  844. _manageClassHandler: function _manageClassHandler() {
  845. // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
  846. if ('string' === typeof this.options.classHandler && $(this.options.classHandler).length) return $(this.options.classHandler);
  847. // Class handled could also be determined by function given in Parsley options
  848. var $handler = this.options.classHandler.call(this, this);
  849. // If this function returned a valid existing DOM element, go for it
  850. if ('undefined' !== typeof $handler && $handler.length) return $handler;
  851. // Otherwise, if simple element (input, texatrea, select...) it will perfectly host the classes
  852. if (!this.options.multiple || this.$element.is('select')) return this.$element;
  853. // But if multiple element (radio, checkbox), that would be their parent
  854. return this.$element.parent();
  855. },
  856. _insertErrorWrapper: function _insertErrorWrapper() {
  857. var $errorsContainer;
  858. // Nothing to do if already inserted
  859. if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
  860. if ('string' === typeof this.options.errorsContainer) {
  861. 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');
  862. } else if ('function' === typeof this.options.errorsContainer) $errorsContainer = this.options.errorsContainer.call(this, this);
  863. if ('undefined' !== typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
  864. var $from = this.$element;
  865. if (this.options.multiple) $from = $from.parent();
  866. return $from.after(this._ui.$errorsWrapper);
  867. },
  868. _actualizeTriggers: function _actualizeTriggers() {
  869. var _this3 = this;
  870. var $toBind = this._findRelated();
  871. var trigger;
  872. // Remove Parsley events already bound on this field
  873. $toBind.off('.Parsley');
  874. if (this._failedOnce) $toBind.on(ParsleyUtils__default.namespaceEvents(this.options.triggerAfterFailure, 'Parsley'), function () {
  875. _this3.validate();
  876. });else if (trigger = ParsleyUtils__default.namespaceEvents(this.options.trigger, 'Parsley')) {
  877. $toBind.on(trigger, function (event) {
  878. _this3._eventValidate(event);
  879. });
  880. }
  881. },
  882. _eventValidate: function _eventValidate(event) {
  883. // For keyup, keypress, keydown, input... events that could be a little bit obstrusive
  884. // do not validate if val length < min threshold on first validation. Once field have been validated once and info
  885. // about success or failure have been displayed, always validate with this trigger to reflect every yalidation change.
  886. if (/key|input/.test(event.type)) if (!(this._ui && this._ui.validationInformationVisible) && this.getValue().length <= this.options.validationThreshold) return;
  887. this.validate();
  888. },
  889. _resetUI: function _resetUI() {
  890. // Reset all event listeners
  891. this._failedOnce = false;
  892. this._actualizeTriggers();
  893. // Nothing to do if UI never initialized for this field
  894. if ('undefined' === typeof this._ui) return;
  895. // Reset all errors' li
  896. this._ui.$errorsWrapper.removeClass('filled').children().remove();
  897. // Reset validation class
  898. this._resetClass();
  899. // Reset validation flags and last validation result
  900. this._ui.lastValidationResult = [];
  901. this._ui.validationInformationVisible = false;
  902. },
  903. _destroyUI: function _destroyUI() {
  904. this._resetUI();
  905. if ('undefined' !== typeof this._ui) this._ui.$errorsWrapper.remove();
  906. delete this._ui;
  907. },
  908. _successClass: function _successClass() {
  909. this._ui.validationInformationVisible = true;
  910. this._ui.$errorClassHandler.removeClass(this.options.errorClass).addClass(this.options.successClass);
  911. },
  912. _errorClass: function _errorClass() {
  913. this._ui.validationInformationVisible = true;
  914. this._ui.$errorClassHandler.removeClass(this.options.successClass).addClass(this.options.errorClass);
  915. },
  916. _resetClass: function _resetClass() {
  917. this._ui.$errorClassHandler.removeClass(this.options.successClass).removeClass(this.options.errorClass);
  918. }
  919. };
  920. var ParsleyForm = function ParsleyForm(element, domOptions, options) {
  921. this.__class__ = 'ParsleyForm';
  922. this.$element = $(element);
  923. this.domOptions = domOptions;
  924. this.options = options;
  925. this.parent = window.Parsley;
  926. this.fields = [];
  927. this.validationResult = null;
  928. };
  929. var ParsleyForm__statusMapping = { pending: null, resolved: true, rejected: false };
  930. ParsleyForm.prototype = {
  931. onSubmitValidate: function onSubmitValidate(event) {
  932. var _this4 = this;
  933. // This is a Parsley generated submit event, do not validate, do not prevent, simply exit and keep normal behavior
  934. if (true === event.parsley) return;
  935. // If we didn't come here through a submit button, use the first one in the form
  936. var $submitSource = this._$submitSource || this.$element.find('input[type="submit"], button[type="submit"]').first();
  937. this._$submitSource = null;
  938. this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true);
  939. if ($submitSource.is('[formnovalidate]')) return;
  940. var promise = this.whenValidate({ event: event });
  941. if ('resolved' === promise.state() && false !== this._trigger('submit')) {
  942. // All good, let event go through. We make this distinction because browsers
  943. // differ in their handling of `submit` being called from inside a submit event [#1047]
  944. } else {
  945. // Rejected or pending: cancel this submit
  946. event.stopImmediatePropagation();
  947. event.preventDefault();
  948. if ('pending' === promise.state()) promise.done(function () {
  949. _this4._submit($submitSource);
  950. });
  951. }
  952. },
  953. onSubmitButton: function onSubmitButton(event) {
  954. this._$submitSource = $(event.target);
  955. },
  956. // internal
  957. // _submit submits the form, this time without going through the validations.
  958. // Care must be taken to "fake" the actual submit button being clicked.
  959. _submit: function _submit($submitSource) {
  960. if (false === this._trigger('submit')) return;
  961. // Add submit button's data
  962. if ($submitSource) {
  963. var $synthetic = this.$element.find('.parsley-synthetic-submit-button').prop('disabled', false);
  964. if (0 === $synthetic.length) $synthetic = $('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element);
  965. $synthetic.attr({
  966. name: $submitSource.attr('name'),
  967. value: $submitSource.attr('value')
  968. });
  969. }
  970. this.$element.trigger($.extend($.Event('submit'), { parsley: true }));
  971. },
  972. // Performs validation on fields while triggering events.
  973. // @returns `true` if all validations succeeds, `false`
  974. // if a failure is immediately detected, or `null`
  975. // if dependant on a promise.
  976. // Consider using `whenValidate` instead.
  977. validate: function validate(options) {
  978. if (arguments.length >= 1 && !$.isPlainObject(options)) {
  979. ParsleyUtils__default.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.');
  980. var _arguments = _slice.call(arguments);
  981. var group = _arguments[0];
  982. var force = _arguments[1];
  983. var event = _arguments[2];
  984. options = { group: group, force: force, event: event };
  985. }
  986. return ParsleyForm__statusMapping[this.whenValidate(options).state()];
  987. },
  988. whenValidate: function whenValidate() {
  989. var _$$when$done$fail$always,
  990. _this5 = this;
  991. var _ref7 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  992. var group = _ref7.group;
  993. var force = _ref7.force;
  994. var event = _ref7.event;
  995. this.submitEvent = event;
  996. if (event) {
  997. this.submitEvent = $.extend({}, event, { preventDefault: function preventDefault() {
  998. ParsleyUtils__default.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`");
  999. _this5.validationResult = false;
  1000. } });
  1001. }
  1002. this.validationResult = true;
  1003. // fire validate event to eventually modify things before very validation
  1004. this._trigger('validate');
  1005. // Refresh form DOM options and form's fields that could have changed
  1006. this._refreshFields();
  1007. var promises = this._withoutReactualizingFormOptions(function () {
  1008. return $.map(_this5.fields, function (field) {
  1009. return field.whenValidate({ force: force, group: group });
  1010. });
  1011. });
  1012. return (_$$when$done$fail$always = $.when.apply($, _toConsumableArray(promises)).done(function () {
  1013. _this5._trigger('success');
  1014. }).fail(function () {
  1015. _this5.validationResult = false;
  1016. _this5.focus();
  1017. _this5._trigger('error');
  1018. }).always(function () {
  1019. _this5._trigger('validated');
  1020. })).pipe.apply(_$$when$done$fail$always, _toConsumableArray(this._pipeAccordingToValidationResult()));
  1021. },
  1022. // Iterate over refreshed fields, and stop on first failure.
  1023. // Returns `true` if all fields are valid, `false` if a failure is detected
  1024. // or `null` if the result depends on an unresolved promise.
  1025. // Prefer using `whenValid` instead.
  1026. isValid: function isValid(options) {
  1027. if (arguments.length >= 1 && !$.isPlainObject(options)) {
  1028. ParsleyUtils__default.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.');
  1029. var _arguments2 = _slice.call(arguments);
  1030. var group = _arguments2[0];
  1031. var force = _arguments2[1];
  1032. options = { group: group, force: force };
  1033. }
  1034. return ParsleyForm__statusMapping[this.whenValid(options).state()];
  1035. },
  1036. // Iterate over refreshed fields and validate them.
  1037. // Returns a promise.
  1038. // A validation that immediately fails will interrupt the validations.
  1039. whenValid: function whenValid() {
  1040. var _this6 = this;
  1041. var _ref8 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  1042. var group = _ref8.group;
  1043. var force = _ref8.force;
  1044. this._refreshFields();
  1045. var promises = this._withoutReactualizingFormOptions(function () {
  1046. return $.map(_this6.fields, function (field) {
  1047. return field.whenValid({ group: group, force: force });
  1048. });
  1049. });
  1050. return $.when.apply($, _toConsumableArray(promises));
  1051. },
  1052. _refreshFields: function _refreshFields() {
  1053. return this.actualizeOptions()._bindFields();
  1054. },
  1055. _bindFields: function _bindFields() {
  1056. var _this7 = this;
  1057. var oldFields = this.fields;
  1058. this.fields = [];
  1059. this.fieldsMappedById = {};
  1060. this._withoutReactualizingFormOptions(function () {
  1061. _this7.$element.find(_this7.options.inputs).not(_this7.options.excluded).each(function (_, element) {
  1062. var fieldInstance = new window.Parsley.Factory(element, {}, _this7);
  1063. // Only add valid and not excluded `ParsleyField` and `ParsleyFieldMultiple` children
  1064. if (('ParsleyField' === fieldInstance.__class__ || 'ParsleyFieldMultiple' === fieldInstance.__class__) && true !== fieldInstance.options.excluded) if ('undefined' === typeof _this7.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__]) {
  1065. _this7.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__] = fieldInstance;
  1066. _this7.fields.push(fieldInstance);
  1067. }
  1068. });
  1069. $(oldFields).not(_this7.fields).each(function (_, field) {
  1070. field._trigger('reset');
  1071. });
  1072. });
  1073. return this;
  1074. },
  1075. // Internal only.
  1076. // Looping on a form's fields to do validation or similar
  1077. // will trigger reactualizing options on all of them, which
  1078. // in turn will reactualize the form's options.
  1079. // To avoid calling actualizeOptions so many times on the form
  1080. // for nothing, _withoutReactualizingFormOptions temporarily disables
  1081. // the method actualizeOptions on this form while `fn` is called.
  1082. _withoutReactualizingFormOptions: function _withoutReactualizingFormOptions(fn) {
  1083. var oldActualizeOptions = this.actualizeOptions;
  1084. this.actualizeOptions = function () {
  1085. return this;
  1086. };
  1087. var result = fn();
  1088. this.actualizeOptions = oldActualizeOptions;
  1089. return result;
  1090. },
  1091. // Internal only.
  1092. // Shortcut to trigger an event
  1093. // Returns true iff event is not interrupted and default not prevented.
  1094. _trigger: function _trigger(eventName) {
  1095. return this.trigger('form:' + eventName);
  1096. }
  1097. };
  1098. var ConstraintFactory = function ConstraintFactory(parsleyField, name, requirements, priority, isDomConstraint) {
  1099. if (!/ParsleyField/.test(parsleyField.__class__)) throw new Error('ParsleyField or ParsleyFieldMultiple instance expected');
  1100. var validatorSpec = window.Parsley._validatorRegistry.validators[name];
  1101. var validator = new ParsleyValidator(validatorSpec);
  1102. $.extend(this, {
  1103. validator: validator,
  1104. name: name,
  1105. requirements: requirements,
  1106. priority: priority || parsleyField.options[name + 'Priority'] || validator.priority,
  1107. isDomConstraint: true === isDomConstraint
  1108. });
  1109. this._parseRequirements(parsleyField.options);
  1110. };
  1111. var capitalize = function capitalize(str) {
  1112. var cap = str[0].toUpperCase();
  1113. return cap + str.slice(1);
  1114. };
  1115. ConstraintFactory.prototype = {
  1116. validate: function validate(value, instance) {
  1117. var _validator;
  1118. return (_validator = this.validator).validate.apply(_validator, [value].concat(_toConsumableArray(this.requirementList), [instance]));
  1119. },
  1120. _parseRequirements: function _parseRequirements(options) {
  1121. var _this8 = this;
  1122. this.requirementList = this.validator.parseRequirements(this.requirements, function (key) {
  1123. return options[_this8.name + capitalize(key)];
  1124. });
  1125. }
  1126. };
  1127. var ParsleyField = function ParsleyField(field, domOptions, options, parsleyFormInstance) {
  1128. this.__class__ = 'ParsleyField';
  1129. this.$element = $(field);
  1130. // Set parent if we have one
  1131. if ('undefined' !== typeof parsleyFormInstance) {
  1132. this.parent = parsleyFormInstance;
  1133. }
  1134. this.options = options;
  1135. this.domOptions = domOptions;
  1136. // Initialize some properties
  1137. this.constraints = [];
  1138. this.constraintsByName = {};
  1139. this.validationResult = true;
  1140. // Bind constraints
  1141. this._bindConstraints();
  1142. };
  1143. var parsley_field__statusMapping = { pending: null, resolved: true, rejected: false };
  1144. ParsleyField.prototype = {
  1145. // # Public API
  1146. // Validate field and trigger some events for mainly `ParsleyUI`
  1147. // @returns `true`, an array of the validators that failed, or
  1148. // `null` if validation is not finished. Prefer using whenValidate
  1149. validate: function validate(options) {
  1150. if (arguments.length >= 1 && !$.isPlainObject(options)) {
  1151. ParsleyUtils__default.warnOnce('Calling validate on a parsley field without passing arguments as an object is deprecated.');
  1152. options = { options: options };
  1153. }
  1154. var promise = this.whenValidate(options);
  1155. if (!promise) // If excluded with `group` option
  1156. return true;
  1157. switch (promise.state()) {
  1158. case 'pending':
  1159. return null;
  1160. case 'resolved':
  1161. return true;
  1162. case 'rejected':
  1163. return this.validationResult;
  1164. }
  1165. },
  1166. // Validate field and trigger some events for mainly `ParsleyUI`
  1167. // @returns a promise that succeeds only when all validations do
  1168. // or `undefined` if field is not in the given `group`.
  1169. whenValidate: function whenValidate() {
  1170. var _whenValid$always$done$fail$always,
  1171. _this9 = this;
  1172. var _ref9 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  1173. var force = _ref9.force;
  1174. var group = _ref9.group;
  1175. // do not validate a field if not the same as given validation group
  1176. this.refreshConstraints();
  1177. if (group && !this._isInGroup(group)) return;
  1178. this.value = this.getValue();
  1179. // Field Validate event. `this.value` could be altered for custom needs
  1180. this._trigger('validate');
  1181. return (_whenValid$always$done$fail$always = this.whenValid({ force: force, value: this.value, _refreshed: true }).always(function () {
  1182. _this9._reflowUI();
  1183. }).done(function () {
  1184. _this9._trigger('success');
  1185. }).fail(function () {
  1186. _this9._trigger('error');
  1187. }).always(function () {
  1188. _this9._trigger('validated');
  1189. })).pipe.apply(_whenValid$always$done$fail$always, _toConsumableArray(this._pipeAccordingToValidationResult()));
  1190. },
  1191. hasConstraints: function hasConstraints() {
  1192. return 0 !== this.constraints.length;
  1193. },
  1194. // An empty optional field does not need validation
  1195. needsValidation: function needsValidation(value) {
  1196. if ('undefined' === typeof value) value = this.getValue();
  1197. // If a field is empty and not required, it is valid
  1198. // Except if `data-parsley-validate-if-empty` explicitely added, useful for some custom validators
  1199. if (!value.length && !this._isRequired() && 'undefined' === typeof this.options.validateIfEmpty) return false;
  1200. return true;
  1201. },
  1202. _isInGroup: function _isInGroup(group) {
  1203. if ($.isArray(this.options.group)) return -1 !== $.inArray(group, this.options.group);
  1204. return this.options.group === group;
  1205. },
  1206. // Just validate field. Do not trigger any event.
  1207. // Returns `true` iff all constraints pass, `false` if there are failures,
  1208. // or `null` if the result can not be determined yet (depends on a promise)
  1209. // See also `whenValid`.
  1210. isValid: function isValid(options) {
  1211. if (arguments.length >= 1 && !$.isPlainObject(options)) {
  1212. ParsleyUtils__default.warnOnce('Calling isValid on a parsley field without passing arguments as an object is deprecated.');
  1213. var _arguments3 = _slice.call(arguments);
  1214. var force = _arguments3[0];
  1215. var value = _arguments3[1];
  1216. options = { force: force, value: value };
  1217. }
  1218. var promise = this.whenValid(options);
  1219. if (!promise) // Excluded via `group`
  1220. return true;
  1221. return parsley_field__statusMapping[promise.state()];
  1222. },
  1223. // Just validate field. Do not trigger any event.
  1224. // @returns a promise that succeeds only when all validations do
  1225. // or `undefined` if the field is not in the given `group`.
  1226. // The argument `force` will force validation of empty fields.
  1227. // If a `value` is given, it will be validated instead of the value of the input.
  1228. whenValid: function whenValid() {
  1229. var _this10 = this;
  1230. var _ref10 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  1231. var _ref10$force = _ref10.force;
  1232. var force = _ref10$force === undefined ? false : _ref10$force;
  1233. var value = _ref10.value;
  1234. var group = _ref10.group;
  1235. var _refreshed = _ref10._refreshed;
  1236. // Recompute options and rebind constraints to have latest changes
  1237. if (!_refreshed) this.refreshConstraints();
  1238. // do not validate a field if not the same as given validation group
  1239. if (group && !this._isInGroup(group)) return;
  1240. this.validationResult = true;
  1241. // A field without constraint is valid
  1242. if (!this.hasConstraints()) return $.when();
  1243. // Value could be passed as argument, needed to add more power to 'field:validate'
  1244. if ('undefined' === typeof value || null === value) value = this.getValue();
  1245. if (!this.needsValidation(value) && true !== force) return $.when();
  1246. var groupedConstraints = this._getGroupedConstraints();
  1247. var promises = [];
  1248. $.each(groupedConstraints, function (_, constraints) {
  1249. // Process one group of constraints at a time, we validate the constraints
  1250. // and combine the promises together.
  1251. var promise = $.when.apply($, _toConsumableArray($.map(constraints, function (constraint) {
  1252. return _this10._validateConstraint(value, constraint);
  1253. })));
  1254. promises.push(promise);
  1255. if (promise.state() === 'rejected') return false; // Interrupt processing if a group has already failed
  1256. });
  1257. return $.when.apply($, promises);
  1258. },
  1259. // @returns a promise
  1260. _validateConstraint: function _validateConstraint(value, constraint) {
  1261. var _this11 = this;
  1262. var result = constraint.validate(value, this);
  1263. // Map false to a failed promise
  1264. if (false === result) result = $.Deferred().reject();
  1265. // Make sure we return a promise and that we record failures
  1266. return $.when(result).fail(function (errorMessage) {
  1267. if (!(_this11.validationResult instanceof Array)) _this11.validationResult = [];
  1268. _this11.validationResult.push({
  1269. assert: constraint,
  1270. errorMessage: 'string' === typeof errorMessage && errorMessage
  1271. });
  1272. });
  1273. },
  1274. // @returns Parsley field computed value that could be overrided or configured in DOM
  1275. getValue: function getValue() {
  1276. var value;
  1277. // Value could be overriden in DOM or with explicit options
  1278. 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();
  1279. // Handle wrong DOM or configurations
  1280. if ('undefined' === typeof value || null === value) return '';
  1281. return this._handleWhitespace(value);
  1282. },
  1283. // Actualize options that could have change since previous validation
  1284. // Re-bind accordingly constraints (could be some new, removed or updated)
  1285. refreshConstraints: function refreshConstraints() {
  1286. return this.actualizeOptions()._bindConstraints();
  1287. },
  1288. /**
  1289. * Add a new constraint to a field
  1290. *
  1291. * @param {String} name
  1292. * @param {Mixed} requirements optional
  1293. * @param {Number} priority optional
  1294. * @param {Boolean} isDomConstraint optional
  1295. */
  1296. addConstraint: function addConstraint(name, requirements, priority, isDomConstraint) {
  1297. if (window.Parsley._validatorRegistry.validators[name]) {
  1298. var constraint = new ConstraintFactory(this, name, requirements, priority, isDomConstraint);
  1299. // if constraint already exist, delete it and push new version
  1300. if ('undefined' !== this.constraintsByName[constraint.name]) this.removeConstraint(constraint.name);
  1301. this.constraints.push(constraint);
  1302. this.constraintsByName[constraint.name] = constraint;
  1303. }
  1304. return this;
  1305. },
  1306. // Remove a constraint
  1307. removeConstraint: function removeConstraint(name) {
  1308. for (var i = 0; i < this.constraints.length; i++) if (name === this.constraints[i].name) {
  1309. this.constraints.splice(i, 1);
  1310. break;
  1311. }
  1312. delete this.constraintsByName[name];
  1313. return this;
  1314. },
  1315. // Update a constraint (Remove + re-add)
  1316. updateConstraint: function updateConstraint(name, parameters, priority) {
  1317. return this.removeConstraint(name).addConstraint(name, parameters, priority);
  1318. },
  1319. // # Internals
  1320. // Internal only.
  1321. // Bind constraints from config + options + DOM
  1322. _bindConstraints: function _bindConstraints() {
  1323. var constraints = [];
  1324. var constraintsByName = {};
  1325. // clean all existing DOM constraints to only keep javascript user constraints
  1326. for (var i = 0; i < this.constraints.length; i++) if (false === this.constraints[i].isDomConstraint) {
  1327. constraints.push(this.constraints[i]);
  1328. constraintsByName[this.constraints[i].name] = this.constraints[i];
  1329. }
  1330. this.constraints = constraints;
  1331. this.constraintsByName = constraintsByName;
  1332. // then re-add Parsley DOM-API constraints
  1333. for (var name in this.options) this.addConstraint(name, this.options[name], undefined, true);
  1334. // finally, bind special HTML5 constraints
  1335. return this._bindHtml5Constraints();
  1336. },
  1337. // Internal only.
  1338. // Bind specific HTML5 constraints to be HTML5 compliant
  1339. _bindHtml5Constraints: function _bindHtml5Constraints() {
  1340. // html5 required
  1341. if (this.$element.hasClass('required') || this.$element.attr('required')) this.addConstraint('required', true, undefined, true);
  1342. // html5 pattern
  1343. if ('string' === typeof this.$element.attr('pattern')) this.addConstraint('pattern', this.$element.attr('pattern'), undefined, true);
  1344. // range
  1345. 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);
  1346. // HTML5 min
  1347. else if ('undefined' !== typeof this.$element.attr('min')) this.addConstraint('min', this.$element.attr('min'), undefined, true);
  1348. // HTML5 max
  1349. else if ('undefined' !== typeof this.$element.attr('max')) this.addConstraint('max', this.$element.attr('max'), undefined, true);
  1350. // length
  1351. 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);
  1352. // HTML5 minlength
  1353. else if ('undefined' !== typeof this.$element.attr('minlength')) this.addConstraint('minlength', this.$element.attr('minlength'), undefined, true);
  1354. // HTML5 maxlength
  1355. else if ('undefined' !== typeof this.$element.attr('maxlength')) this.addConstraint('maxlength', this.$element.attr('maxlength'), undefined, true);
  1356. // html5 types
  1357. var type = this.$element.attr('type');
  1358. if ('undefined' === typeof type) return this;
  1359. // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
  1360. if ('number' === type) {
  1361. return this.addConstraint('type', ['number', {
  1362. step: this.$element.attr('step'),
  1363. base: this.$element.attr('min') || this.$element.attr('value')
  1364. }], undefined, true);
  1365. // Regular other HTML5 supported types
  1366. } else if (/^(email|url|range)$/i.test(type)) {
  1367. return this.addConstraint('type', type, undefined, true);
  1368. }
  1369. return this;
  1370. },
  1371. // Internal only.
  1372. // Field is required if have required constraint without `false` value
  1373. _isRequired: function _isRequired() {
  1374. if ('undefined' === typeof this.constraintsByName.required) return false;
  1375. return false !== this.constraintsByName.required.requirements;
  1376. },
  1377. // Internal only.
  1378. // Shortcut to trigger an event
  1379. _trigger: function _trigger(eventName) {
  1380. return this.trigger('field:' + eventName);
  1381. },
  1382. // Internal only
  1383. // Handles whitespace in a value
  1384. // Use `data-parsley-whitespace="squish"` to auto squish input value
  1385. // Use `data-parsley-whitespace="trim"` to auto trim input value
  1386. _handleWhitespace: function _handleWhitespace(value) {
  1387. if (true === this.options.trimValue) ParsleyUtils__default.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"');
  1388. if ('squish' === this.options.whitespace) value = value.replace(/\s{2,}/g, ' ');
  1389. if ('trim' === this.options.whitespace || 'squish' === this.options.whitespace || true === this.options.trimValue) value = ParsleyUtils__default.trimString(value);
  1390. return value;
  1391. },
  1392. // Internal only.
  1393. // Returns the constraints, grouped by descending priority.
  1394. // The result is thus an array of arrays of constraints.
  1395. _getGroupedConstraints: function _getGroupedConstraints() {
  1396. if (false === this.options.priorityEnabled) return [this.constraints];
  1397. var groupedConstraints = [];
  1398. var index = {};
  1399. // Create array unique of priorities
  1400. for (var i = 0; i < this.constraints.length; i++) {
  1401. var p = this.constraints[i].priority;
  1402. if (!index[p]) groupedConstraints.push(index[p] = []);
  1403. index[p].push(this.constraints[i]);
  1404. }
  1405. // Sort them by priority DESC
  1406. groupedConstraints.sort(function (a, b) {
  1407. return b[0].priority - a[0].priority;
  1408. });
  1409. return groupedConstraints;
  1410. }
  1411. };
  1412. var parsley_field = ParsleyField;
  1413. var ParsleyMultiple = function ParsleyMultiple() {
  1414. this.__class__ = 'ParsleyFieldMultiple';
  1415. };
  1416. ParsleyMultiple.prototype = {
  1417. // Add new `$element` sibling for multiple field
  1418. addElement: function addElement($element) {
  1419. this.$elements.push($element);
  1420. return this;
  1421. },
  1422. // See `ParsleyField.refreshConstraints()`
  1423. refreshConstraints: function refreshConstraints() {
  1424. var fieldConstraints;
  1425. this.constraints = [];
  1426. // Select multiple special treatment
  1427. if (this.$element.is('select')) {
  1428. this.actualizeOptions()._bindConstraints();
  1429. return this;
  1430. }
  1431. // Gather all constraints for each input in the multiple group
  1432. for (var i = 0; i < this.$elements.length; i++) {
  1433. // Check if element have not been dynamically removed since last binding
  1434. if (!$('html').has(this.$elements[i]).length) {
  1435. this.$elements.splice(i, 1);
  1436. continue;
  1437. }
  1438. fieldConstraints = this.$elements[i].data('ParsleyFieldMultiple').refreshConstraints().constraints;
  1439. for (var j = 0; j < fieldConstraints.length; j++) this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);
  1440. }
  1441. return this;
  1442. },
  1443. // See `ParsleyField.getValue()`
  1444. getValue: function getValue() {
  1445. // Value could be overriden in DOM
  1446. if ('function' === typeof this.options.value) return this.options.value(this);else if ('undefined' !== typeof this.options.value) return this.options.value;
  1447. // Radio input case
  1448. if (this.$element.is('input[type=radio]')) return this._findRelated().filter(':checked').val() || '';
  1449. // checkbox input case
  1450. if (this.$element.is('input[type=checkbox]')) {
  1451. var values = [];
  1452. this._findRelated().filter(':checked').each(function () {
  1453. values.push($(this).val());
  1454. });
  1455. return values;
  1456. }
  1457. // Select multiple case
  1458. if (this.$element.is('select') && null === this.$element.val()) return [];
  1459. // Default case that should never happen
  1460. return this.$element.val();
  1461. },
  1462. _init: function _init() {
  1463. this.$elements = [this.$element];
  1464. return this;
  1465. }
  1466. };
  1467. var ParsleyFactory = function ParsleyFactory(element, options, parsleyFormInstance) {
  1468. this.$element = $(element);
  1469. // If the element has already been bound, returns its saved Parsley instance
  1470. var savedparsleyFormInstance = this.$element.data('Parsley');
  1471. if (savedparsleyFormInstance) {
  1472. // If the saved instance has been bound without a ParsleyForm parent and there is one given in this call, add it
  1473. if ('undefined' !== typeof parsleyFormInstance && savedparsleyFormInstance.parent === window.Parsley) {
  1474. savedparsleyFormInstance.parent = parsleyFormInstance;
  1475. savedparsleyFormInstance._resetOptions(savedparsleyFormInstance.options);
  1476. }
  1477. return savedparsleyFormInstance;
  1478. }
  1479. // Parsley must be instantiated with a DOM element or jQuery $element
  1480. if (!this.$element.length) throw new Error('You must bind Parsley on an existing element.');
  1481. if ('undefined' !== typeof parsleyFormInstance && 'ParsleyForm' !== parsleyFormInstance.__class__) throw new Error('Parent instance must be a ParsleyForm instance');
  1482. this.parent = parsleyFormInstance || window.Parsley;
  1483. return this.init(options);
  1484. };
  1485. ParsleyFactory.prototype = {
  1486. init: function init(options) {
  1487. this.__class__ = 'Parsley';
  1488. this.__version__ = '2.3.13';
  1489. this.__id__ = ParsleyUtils__default.generateID();
  1490. // Pre-compute options
  1491. this._resetOptions(options);
  1492. // A ParsleyForm instance is obviously a `<form>` element but also every node that is not an input and has the `data-parsley-validate` attribute
  1493. if (this.$element.is('form') || ParsleyUtils__default.checkAttr(this.$element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)) return this.bind('parsleyForm');
  1494. // Every other element is bound as a `ParsleyField` or `ParsleyFieldMultiple`
  1495. return this.isMultiple() ? this.handleMultiple() : this.bind('parsleyField');
  1496. },
  1497. isMultiple: function isMultiple() {
  1498. return this.$element.is('input[type=radio], input[type=checkbox]') || this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple');
  1499. },
  1500. // Multiples fields are a real nightmare :(
  1501. // Maybe some refactoring would be appreciated here...
  1502. handleMultiple: function handleMultiple() {
  1503. var _this12 = this;
  1504. var name;
  1505. var multiple;
  1506. var parsleyMultipleInstance;
  1507. // Handle multiple name
  1508. if (this.options.multiple) ; // We already have our 'multiple' identifier
  1509. 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');
  1510. // Special select multiple input
  1511. if (this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple')) {
  1512. this.options.multiple = this.options.multiple || this.__id__;
  1513. return this.bind('parsleyFieldMultiple');
  1514. // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it
  1515. } else if (!this.options.multiple) {
  1516. 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);
  1517. return this;
  1518. }
  1519. // Remove special chars
  1520. this.options.multiple = this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g, '');
  1521. // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
  1522. if ('undefined' !== typeof name) {
  1523. $('input[name="' + name + '"]').each(function (i, input) {
  1524. if ($(input).is('input[type=radio], input[type=checkbox]')) $(input).attr(_this12.options.namespace + 'multiple', _this12.options.multiple);
  1525. });
  1526. }
  1527. // Check here if we don't already have a related multiple instance saved
  1528. var $previouslyRelated = this._findRelated();
  1529. for (var i = 0; i < $previouslyRelated.length; i++) {
  1530. parsleyMultipleInstance = $($previouslyRelated.get(i)).data('Parsley');
  1531. if ('undefined' !== typeof parsleyMultipleInstance) {
  1532. if (!this.$element.data('ParsleyFieldMultiple')) {
  1533. parsleyMultipleInstance.addElement(this.$element);
  1534. }
  1535. break;
  1536. }
  1537. }
  1538. // Create a secret ParsleyField instance for every multiple field. It will be stored in `data('ParsleyFieldMultiple')`
  1539. // And will be useful later to access classic `ParsleyField` stuff while being in a `ParsleyFieldMultiple` instance
  1540. this.bind('parsleyField', true);
  1541. return parsleyMultipleInstance || this.bind('parsleyFieldMultiple');
  1542. },
  1543. // Return proper `ParsleyForm`, `ParsleyField` or `ParsleyFieldMultiple`
  1544. bind: function bind(type, doNotStore) {
  1545. var parsleyInstance;
  1546. switch (type) {
  1547. case 'parsleyForm':
  1548. parsleyInstance = $.extend(new ParsleyForm(this.$element, this.domOptions, this.options), new ParsleyAbstract(), window.ParsleyExtend)._bindFields();
  1549. break;
  1550. case 'parsleyField':
  1551. parsleyInstance = $.extend(new parsley_field(this.$element, this.domOptions, this.options, this.parent), new ParsleyAbstract(), window.ParsleyExtend);
  1552. break;
  1553. case 'parsleyFieldMultiple':
  1554. parsleyInstance = $.extend(new parsley_field(this.$element, this.domOptions, this.options, this.parent), new ParsleyMultiple(), new ParsleyAbstract(), window.ParsleyExtend)._init();
  1555. break;
  1556. default:
  1557. throw new Error(type + 'is not a supported Parsley type');
  1558. }
  1559. if (this.options.multiple) ParsleyUtils__default.setAttr(this.$element, this.options.namespace, 'multiple', this.options.multiple);
  1560. if ('undefined' !== typeof doNotStore) {
  1561. this.$element.data('ParsleyFieldMultiple', parsleyInstance);
  1562. return parsleyInstance;
  1563. }
  1564. // Store the freshly bound instance in a DOM element for later access using jQuery `data()`
  1565. this.$element.data('Parsley', parsleyInstance);
  1566. // Tell the world we have a new ParsleyForm or ParsleyField instance!
  1567. parsleyInstance._actualizeTriggers();
  1568. parsleyInstance._trigger('init');
  1569. return parsleyInstance;
  1570. }
  1571. };
  1572. var vernums = $.fn.jquery.split('.');
  1573. if (parseInt(vernums[0]) <= 1 && parseInt(vernums[1]) < 8) {
  1574. throw "The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.";
  1575. }
  1576. if (!vernums.forEach) {
  1577. ParsleyUtils__default.warn('Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim');
  1578. }
  1579. // Inherit `on`, `off` & `trigger` to Parsley:
  1580. var Parsley = $.extend(new ParsleyAbstract(), {
  1581. $element: $(document),
  1582. actualizeOptions: null,
  1583. _resetOptions: null,
  1584. Factory: ParsleyFactory,
  1585. version: '2.3.13'
  1586. });
  1587. // Supplement ParsleyField and Form with ParsleyAbstract
  1588. // This way, the constructors will have access to those methods
  1589. $.extend(parsley_field.prototype, ParsleyUI.Field, ParsleyAbstract.prototype);
  1590. $.extend(ParsleyForm.prototype, ParsleyUI.Form, ParsleyAbstract.prototype);
  1591. // Inherit actualizeOptions and _resetOptions:
  1592. $.extend(ParsleyFactory.prototype, ParsleyAbstract.prototype);
  1593. // ### jQuery API
  1594. // `$('.elem').parsley(options)` or `$('.elem').psly(options)`
  1595. $.fn.parsley = $.fn.psly = function (options) {
  1596. if (this.length > 1) {
  1597. var instances = [];
  1598. this.each(function () {
  1599. instances.push($(this).parsley(options));
  1600. });
  1601. return instances;
  1602. }
  1603. // Return undefined if applied to non existing DOM element
  1604. if (!$(this).length) {
  1605. ParsleyUtils__default.warn('You must bind Parsley on an existing element.');
  1606. return;
  1607. }
  1608. return new ParsleyFactory(this, options);
  1609. };
  1610. // ### ParsleyField and ParsleyForm extension
  1611. // Ensure the extension is now defined if it wasn't previously
  1612. if ('undefined' === typeof window.ParsleyExtend) window.ParsleyExtend = {};
  1613. // ### Parsley config
  1614. // Inherit from ParsleyDefault, and copy over any existing values
  1615. Parsley.options = $.extend(ParsleyUtils__default.objectCreate(ParsleyDefaults), window.ParsleyConfig);
  1616. window.ParsleyConfig = Parsley.options; // Old way of accessing global options
  1617. // ### Globals
  1618. window.Parsley = window.psly = Parsley;
  1619. window.ParsleyUtils = ParsleyUtils__default;
  1620. // ### Define methods that forward to the registry, and deprecate all access except through window.Parsley
  1621. var registry = window.Parsley._validatorRegistry = new ParsleyValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
  1622. window.ParsleyValidator = {};
  1623. $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator'.split(' '), function (i, method) {
  1624. window.Parsley[method] = $.proxy(registry, method);
  1625. window.ParsleyValidator[method] = function () {
  1626. var _window$Parsley;
  1627. ParsleyUtils__default.warnOnce('Accessing the method \'' + method + '\' through ParsleyValidator is deprecated. Simply call \'window.Parsley.' + method + '(...)\'');
  1628. return (_window$Parsley = window.Parsley)[method].apply(_window$Parsley, arguments);
  1629. };
  1630. });
  1631. // ### ParsleyUI
  1632. // Deprecated global object
  1633. window.Parsley.UI = ParsleyUI;
  1634. window.ParsleyUI = {
  1635. removeError: function removeError(instance, name, doNotUpdateClass) {
  1636. var updateClass = true !== doNotUpdateClass;
  1637. 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.');
  1638. return instance.removeError(name, { updateClass: updateClass });
  1639. },
  1640. getErrorsMessages: function getErrorsMessages(instance) {
  1641. ParsleyUtils__default.warnOnce('Accessing ParsleyUI is deprecated. Call \'getErrorsMessages\' on the instance directly.');
  1642. return instance.getErrorsMessages();
  1643. }
  1644. };
  1645. $.each('addError updateError'.split(' '), function (i, method) {
  1646. window.ParsleyUI[method] = function (instance, name, message, assert, doNotUpdateClass) {
  1647. var updateClass = true !== doNotUpdateClass;
  1648. 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.');
  1649. return instance[method](name, { message: message, assert: assert, updateClass: updateClass });
  1650. };
  1651. });
  1652. // ### PARSLEY auto-binding
  1653. // Prevent it by setting `ParsleyConfig.autoBind` to `false`
  1654. if (false !== window.ParsleyConfig.autoBind) {
  1655. $(function () {
  1656. // Works only on `data-parsley-validate`.
  1657. if ($('[data-parsley-validate]').length) $('[data-parsley-validate]').parsley();
  1658. });
  1659. }
  1660. var o = $({});
  1661. var deprecated = function deprecated() {
  1662. ParsleyUtils__default.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley");
  1663. };
  1664. // Returns an event handler that calls `fn` with the arguments it expects
  1665. function adapt(fn, context) {
  1666. // Store to allow unbinding
  1667. if (!fn.parsleyAdaptedCallback) {
  1668. fn.parsleyAdaptedCallback = function () {
  1669. var args = Array.prototype.slice.call(arguments, 0);
  1670. args.unshift(this);
  1671. fn.apply(context || o, args);
  1672. };
  1673. }
  1674. return fn.parsleyAdaptedCallback;
  1675. }
  1676. var eventPrefix = 'parsley:';
  1677. // Converts 'parsley:form:validate' into 'form:validate'
  1678. function eventName(name) {
  1679. if (name.lastIndexOf(eventPrefix, 0) === 0) return name.substr(eventPrefix.length);
  1680. return name;
  1681. }
  1682. // $.listen is deprecated. Use Parsley.on instead.
  1683. $.listen = function (name, callback) {
  1684. var context;
  1685. deprecated();
  1686. if ('object' === typeof arguments[1] && 'function' === typeof arguments[2]) {
  1687. context = arguments[1];
  1688. callback = arguments[2];
  1689. }
  1690. if ('function' !== typeof callback) throw new Error('Wrong parameters');
  1691. window.Parsley.on(eventName(name), adapt(callback, context));
  1692. };
  1693. $.listenTo = function (instance, name, fn) {
  1694. deprecated();
  1695. if (!(instance instanceof parsley_field) && !(instance instanceof ParsleyForm)) throw new Error('Must give Parsley instance');
  1696. if ('string' !== typeof name || 'function' !== typeof fn) throw new Error('Wrong parameters');
  1697. instance.on(eventName(name), adapt(fn));
  1698. };
  1699. $.unsubscribe = function (name, fn) {
  1700. deprecated();
  1701. if ('string' !== typeof name || 'function' !== typeof fn) throw new Error('Wrong arguments');
  1702. window.Parsley.off(eventName(name), fn.parsleyAdaptedCallback);
  1703. };
  1704. $.unsubscribeTo = function (instance, name) {
  1705. deprecated();
  1706. if (!(instance instanceof parsley_field) && !(instance instanceof ParsleyForm)) throw new Error('Must give Parsley instance');
  1707. instance.off(eventName(name));
  1708. };
  1709. $.unsubscribeAll = function (name) {
  1710. deprecated();
  1711. window.Parsley.off(eventName(name));
  1712. $('form,input,textarea,select').each(function () {
  1713. var instance = $(this).data('Parsley');
  1714. if (instance) {
  1715. instance.off(eventName(name));
  1716. }
  1717. });
  1718. };
  1719. // $.emit is deprecated. Use jQuery events instead.
  1720. $.emit = function (name, instance) {
  1721. var _instance;
  1722. deprecated();
  1723. var instanceGiven = instance instanceof parsley_field || instance instanceof ParsleyForm;
  1724. var args = Array.prototype.slice.call(arguments, instanceGiven ? 2 : 1);
  1725. args.unshift(eventName(name));
  1726. if (!instanceGiven) {
  1727. instance = window.Parsley;
  1728. }
  1729. (_instance = instance).trigger.apply(_instance, _toConsumableArray(args));
  1730. };
  1731. var pubsub = {};
  1732. $.extend(true, Parsley, {
  1733. asyncValidators: {
  1734. 'default': {
  1735. fn: function fn(xhr) {
  1736. // By default, only status 2xx are deemed successful.
  1737. // Note: we use status instead of state() because responses with status 200
  1738. // but invalid messages (e.g. an empty body for content type set to JSON) will
  1739. // result in state() === 'rejected'.
  1740. return xhr.status >= 200 && xhr.status < 300;
  1741. },
  1742. url: false
  1743. },
  1744. reverse: {
  1745. fn: function fn(xhr) {
  1746. // If reverse option is set, a failing ajax request is considered successful
  1747. return xhr.status < 200 || xhr.status >= 300;
  1748. },
  1749. url: false
  1750. }
  1751. },
  1752. addAsyncValidator: function addAsyncValidator(name, fn, url, options) {
  1753. Parsley.asyncValidators[name] = {
  1754. fn: fn,
  1755. url: url || false,
  1756. options: options || {}
  1757. };
  1758. return this;
  1759. }
  1760. });
  1761. Parsley.addValidator('remote', {
  1762. requirementType: {
  1763. '': 'string',
  1764. 'validator': 'string',
  1765. 'reverse': 'boolean',
  1766. 'options': 'object'
  1767. },
  1768. validateString: function validateString(value, url, options, instance) {
  1769. var data = {};
  1770. var ajaxOptions;
  1771. var csr;
  1772. var validator = options.validator || (true === options.reverse ? 'reverse' : 'default');
  1773. if ('undefined' === typeof Parsley.asyncValidators[validator]) throw new Error('Calling an undefined async validator: `' + validator + '`');
  1774. url = Parsley.asyncValidators[validator].url || url;
  1775. // Fill current value
  1776. if (url.indexOf('{value}') > -1) {
  1777. url = url.replace('{value}', encodeURIComponent(value));
  1778. } else {
  1779. data[instance.$element.attr('name') || instance.$element.attr('id')] = value;
  1780. }
  1781. // Merge options passed in from the function with the ones in the attribute
  1782. var remoteOptions = $.extend(true, options.options || {}, Parsley.asyncValidators[validator].options);
  1783. // All `$.ajax(options)` could be overridden or extended directly from DOM in `data-parsley-remote-options`
  1784. ajaxOptions = $.extend(true, {}, {
  1785. url: url,
  1786. data: data,
  1787. type: 'GET'
  1788. }, remoteOptions);
  1789. // Generate store key based on ajax options
  1790. instance.trigger('field:ajaxoptions', instance, ajaxOptions);
  1791. csr = $.param(ajaxOptions);
  1792. // Initialise querry cache
  1793. if ('undefined' === typeof Parsley._remoteCache) Parsley._remoteCache = {};
  1794. // Try to retrieve stored xhr
  1795. var xhr = Parsley._remoteCache[csr] = Parsley._remoteCache[csr] || $.ajax(ajaxOptions);
  1796. var handleXhr = function handleXhr() {
  1797. var result = Parsley.asyncValidators[validator].fn.call(instance, xhr, url, options);
  1798. if (!result) // Map falsy results to rejected promise
  1799. result = $.Deferred().reject();
  1800. return $.when(result);
  1801. };
  1802. return xhr.then(handleXhr, handleXhr);
  1803. },
  1804. priority: -1
  1805. });
  1806. Parsley.on('form:submit', function () {
  1807. Parsley._remoteCache = {};
  1808. });
  1809. window.ParsleyExtend.addAsyncValidator = function () {
  1810. ParsleyUtils.warnOnce('Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`');
  1811. return Parsley.addAsyncValidator.apply(Parsley, arguments);
  1812. };
  1813. // This is included with the Parsley library itself,
  1814. // thus there is no use in adding it to your project.
  1815. Parsley.addMessages('en', {
  1816. defaultMessage: "This value seems to be invalid.",
  1817. type: {
  1818. email: "This value should be a valid email.",
  1819. url: "This value should be a valid url.",
  1820. number: "This value should be a valid number.",
  1821. integer: "This value should be a valid integer.",
  1822. digits: "This value should be digits.",
  1823. alphanum: "This value should be alphanumeric."
  1824. },
  1825. notblank: "This value should not be blank.",
  1826. required: "This value is required.",
  1827. pattern: "This value seems to be invalid.",
  1828. min: "This value should be greater than or equal to %s.",
  1829. max: "This value should be lower than or equal to %s.",
  1830. range: "This value should be between %s and %s.",
  1831. minlength: "This value is too short. It should have %s characters or more.",
  1832. maxlength: "This value is too long. It should have %s characters or fewer.",
  1833. length: "This value length is invalid. It should be between %s and %s characters long.",
  1834. mincheck: "You must select at least %s choices.",
  1835. maxcheck: "You must select %s choices or fewer.",
  1836. check: "You must select between %s and %s choices.",
  1837. equalto: "This value should be the same."
  1838. });
  1839. Parsley.setLocale('en');
  1840. /**
  1841. * inputevent - Alleviate browser bugs for input events
  1842. * https://github.com/marcandre/inputevent
  1843. * @version v0.0.3 - (built Thu, Apr 14th 2016, 5:58 pm)
  1844. * @author Marc-Andre Lafortune <github@marc-andre.ca>
  1845. * @license MIT
  1846. */
  1847. function InputEvent() {
  1848. var _this13 = this;
  1849. var globals = window || global;
  1850. // Slightly odd way construct our object. This way methods are force bound.
  1851. // Used to test for duplicate library.
  1852. $.extend(this, {
  1853. // For browsers that do not support isTrusted, assumes event is native.
  1854. isNativeEvent: function isNativeEvent(evt) {
  1855. return evt.originalEvent && evt.originalEvent.isTrusted !== false;
  1856. },
  1857. fakeInputEvent: function fakeInputEvent(evt) {
  1858. if (_this13.isNativeEvent(evt)) {
  1859. $(evt.target).trigger('input');
  1860. }
  1861. },
  1862. misbehaves: function misbehaves(evt) {
  1863. if (_this13.isNativeEvent(evt)) {
  1864. _this13.behavesOk(evt);
  1865. $(document).on('change.inputevent', evt.data.selector, _this13.fakeInputEvent);
  1866. _this13.fakeInputEvent(evt);
  1867. }
  1868. },
  1869. behavesOk: function behavesOk(evt) {
  1870. if (_this13.isNativeEvent(evt)) {
  1871. $(document) // Simply unbinds the testing handler
  1872. .off('input.inputevent', evt.data.selector, _this13.behavesOk).off('change.inputevent', evt.data.selector, _this13.misbehaves);
  1873. }
  1874. },
  1875. // Bind the testing handlers
  1876. install: function install() {
  1877. if (globals.inputEventPatched) {
  1878. return;
  1879. }
  1880. globals.inputEventPatched = '0.0.3';
  1881. var _arr = ['select', 'input[type="checkbox"]', 'input[type="radio"]', 'input[type="file"]'];
  1882. for (var _i = 0; _i < _arr.length; _i++) {
  1883. var selector = _arr[_i];
  1884. $(document).on('input.inputevent', selector, { selector: selector }, _this13.behavesOk).on('change.inputevent', selector, { selector: selector }, _this13.misbehaves);
  1885. }
  1886. },
  1887. uninstall: function uninstall() {
  1888. delete globals.inputEventPatched;
  1889. $(document).off('.inputevent');
  1890. }
  1891. });
  1892. };
  1893. var inputevent = new InputEvent();
  1894. inputevent.install();
  1895. var parsley = Parsley;
  1896. return parsley;
  1897. });
  1898. //# sourceMappingURL=parsley.js.map