From 698331bc77514e63171425687e895604e7bdb454 Mon Sep 17 00:00:00 2001
From: root <cosimo.volpicelli@inaf.it>
Date: Tue, 23 Mar 2021 11:08:39 +0100
Subject: [PATCH]  Modifiche Prima pagina

---
 Acquisti/settings.py                 |    2 +
 home/templates/home/primapagina.html |   51 +
 static/validator/parsley.css         |  116 ++
 static/validator/parsley.js          | 2472 ++++++++++++++++++++++++++
 utenti/templates/plain.html          |   72 +-
 5 files changed, 2709 insertions(+), 4 deletions(-)
 create mode 100644 static/validator/parsley.css
 create mode 100644 static/validator/parsley.js

diff --git a/Acquisti/settings.py b/Acquisti/settings.py
index 3ff9a4e9..fd7a974a 100644
--- a/Acquisti/settings.py
+++ b/Acquisti/settings.py
@@ -180,3 +180,5 @@ EMAIL_HOST_PASSWORD = 'caV#290957#Vac'
 EMAIL_PORT = 587
 EMAIL_USE_TLS =True
 EMAIL_USE_SSL = False
+
+REPOSITORY_ALLEGATI = '/srv/Acquisti/allegati/' 
\ No newline at end of file
diff --git a/home/templates/home/primapagina.html b/home/templates/home/primapagina.html
index 7077726e..e33043d4 100644
--- a/home/templates/home/primapagina.html
+++ b/home/templates/home/primapagina.html
@@ -130,7 +130,53 @@
               </div>
             </div>
             </div>
+<div class="x_content">
+                    <div class="row">
+                      <div class="animated flipInY col-lg-3 col-md-3 col-sm-6  " data-href="completate">
+                        <div class="tile-stats">
+                          <div class="icon"><i class="fa fa-check"></i>
+                          </div>
+                          <div class="count">179</div>
+
+                          <h3>Completate</h3>
+                          <p>Lorem ipsum psdea itgum rixt.</p>
+                        </div>
+                      </div>
+                      <div class="animated flipInY col-lg-3 col-md-3 col-sm-6  " data-href="inviate">
+                        <div class="tile-stats">
+                          <div class="icon"><i class="fa fa-mail-forward"></i>
+                          </div>
+                          <div class="count">179</div>
+
+                          <h3>Inviate</h3>
+                          <p>Lorem ipsum psdea itgum rixt.</p>
+                        </div>
+                      </div>
+                      <div class="animated flipInY col-lg-3 col-md-3 col-sm-6  " data-href="lavorazione">
+                        <div class="tile-stats">
+                          <div class="icon"><i class="fa fa-gears"></i>
+                          </div>
+                          <div class="count">179</div>
+
+                          <h3>In lavorazione</h3>
+                          <p>Lorem ipsum psdea itgum rixt.</p>
+                        </div>
+                      </div>
+                      <div class="animated flipInY col-lg-3 col-md-3 col-sm-6  " data-href="create">
+                        <div class="tile-stats">
+                          <div class="icon"><i class="fa fa-comment-o"></i>
+                          </div>
+                          <div class="count">179</div>
+
+                          <h3>Create</h3>
+                          <p>Lorem ipsum psdea itgum rixt.</p>
+                        </div>
+                      </div>
+                      </div>
+                      </div>
+
         </div>
+
                        {% endblock right_col %}
 
 
@@ -144,6 +190,11 @@
     <script src="{% static '/DataTables/dataTables.bootstrap5.min.js' %}"></script>
     <script src="{% static '/datepicker/js/bootstrap-datepicker.js' %}"></script>
  
+ <script>
+$('.animated').on('click',function(ev){
+  alert($(this).attr('data-href'))
+})
+ </script>
 
 {% endblock javascripts %}
 
diff --git a/static/validator/parsley.css b/static/validator/parsley.css
new file mode 100644
index 00000000..61d3c21b
--- /dev/null
+++ b/static/validator/parsley.css
@@ -0,0 +1,116 @@
+.validate {
+  margin-top: 10px; }
+
+.invalid-form-error-message {
+  margin-top: 10px;
+  padding: 5px; }
+
+.invalid-form-error-message.filled {
+  border-left: 2px solid #E74C3C; }
+
+p.parsley-success {
+  color: #468847;
+  background-color: #DFF0D8;
+  border: 1px solid #D6E9C6; }
+
+p.parsley-error {
+  color: #B94A48;
+  background-color: #F2DEDE;
+  border: 1px solid #EED3D7; }
+
+ul.parsley-errors-list {
+  list-style: none;
+  color: #E74C3C;
+  padding-left: 0; }
+
+input.parsley-error, textarea.parsley-error, select.parsley-error {
+  background: #FAEDEC;
+  border: 1px solid #E85445; }
+
+.btn-group .parsley-errors-list {
+  display: none; }
+
+.bad input, .bad select, .bad textarea {
+  border: 1px solid #CE5454;
+  -webkit-box-shadow: 0 0 4px -2px #CE5454;
+          box-shadow: 0 0 4px -2px #CE5454;
+  position: relative;
+  left: 0;
+  -moz-animation: .7s 1 shake linear;
+  -webkit-animation: 0.7s 1 shake linear; }
+
+  .item {
+  display: -webkit-box;
+  display: -ms-flexbox;
+  display: flex; }
+
+.item input, .item textarea {
+  -webkit-transition: 0.42s;
+  transition: 0.42s; }
+
+/* alerts (when validation fails) */
+.item .alert {
+  float: left;
+  margin: 0 0 0 20px;
+  padding: 3px 10px;
+  color: #FFF;
+  border-radius: 3px 4px 4px 3px;
+  background-color: #CE5454;
+  max-width: 170px;
+  white-space: pre;
+  position: relative;
+  left: -15px;
+  opacity: 0;
+  z-index: 1;
+  -webkit-transition: 0.15s ease-out;
+  transition: 0.15s ease-out; }
+
+.item .alert::after {
+  content: '';
+  display: block;
+  height: 0;
+  width: 0;
+  border-color: transparent #CE5454 transparent transparent;
+  border-style: solid;
+  border-width: 11px 7px;
+  position: absolute;
+  left: -13px;
+  top: 1px; }
+
+.item.bad .alert {
+  left: 0;
+  opacity: 1; }
+
+.inl-bl {
+  display: inline-block; }
+
+.well {
+  min-height: 20px;
+  padding: 19px;
+  margin-bottom: 20px;
+  background-color: #f5f5f5;
+  border: 1px solid #e3e3e3;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); }
+.well .markup {
+  background: #fff;
+  color: #777;
+  position: relative;
+  padding: 45px 15px 15px;
+  margin: 15px 0 0 0;
+  background-color: #fff;
+  border-radius: 0 0 4px 4px;
+  -webkit-box-shadow: none;
+          box-shadow: none; }
+
+.well .markup::after {
+  content: "Example";
+  position: absolute;
+  top: 15px;
+  left: 15px;
+  font-size: 12px;
+  font-weight: bold;
+  color: #bbb;
+  text-transform: uppercase;
+  letter-spacing: 1px; }
diff --git a/static/validator/parsley.js b/static/validator/parsley.js
new file mode 100644
index 00000000..0f5718d8
--- /dev/null
+++ b/static/validator/parsley.js
@@ -0,0 +1,2472 @@
+/*!
+* Parsley.js
+* Version 2.9.2 - built Tue, Dec 10th 2019, 6:18 pm
+* http://parsleyjs.org
+* Guillaume Potier - <guillaume@wisembly.com>
+* Marc-Andre Lafortune - <petroselinum@marc-andre.ca>
+* MIT Licensed
+*/
+
+// The source code below is generated by babel as
+// Parsley is written in ECMAScript 6
+//
+
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) :
+  typeof define === 'function' && define.amd ? define(['jquery'], factory) :
+  (global = global || self, global.parsley = factory(global.jQuery));
+}(this, (function ($) { 'use strict';
+
+  function _typeof(obj) {
+    if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
+      _typeof = function (obj) {
+        return typeof obj;
+      };
+    } else {
+      _typeof = function (obj) {
+        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+      };
+    }
+
+    return _typeof(obj);
+  }
+
+  function _extends() {
+    _extends = Object.assign || function (target) {
+      for (var i = 1; i < arguments.length; i++) {
+        var source = arguments[i];
+
+        for (var key in source) {
+          if (Object.prototype.hasOwnProperty.call(source, key)) {
+            target[key] = source[key];
+          }
+        }
+      }
+
+      return target;
+    };
+
+    return _extends.apply(this, arguments);
+  }
+
+  function _slicedToArray(arr, i) {
+    return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
+  }
+
+  function _toConsumableArray(arr) {
+    return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
+  }
+
+  function _arrayWithoutHoles(arr) {
+    if (Array.isArray(arr)) {
+      for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
+
+      return arr2;
+    }
+  }
+
+  function _arrayWithHoles(arr) {
+    if (Array.isArray(arr)) return arr;
+  }
+
+  function _iterableToArray(iter) {
+    if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
+  }
+
+  function _iterableToArrayLimit(arr, i) {
+    if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) {
+      return;
+    }
+
+    var _arr = [];
+    var _n = true;
+    var _d = false;
+    var _e = undefined;
+
+    try {
+      for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
+        _arr.push(_s.value);
+
+        if (i && _arr.length === i) break;
+      }
+    } catch (err) {
+      _d = true;
+      _e = err;
+    } finally {
+      try {
+        if (!_n && _i["return"] != null) _i["return"]();
+      } finally {
+        if (_d) throw _e;
+      }
+    }
+
+    return _arr;
+  }
+
+  function _nonIterableSpread() {
+    throw new TypeError("Invalid attempt to spread non-iterable instance");
+  }
+
+  function _nonIterableRest() {
+    throw new TypeError("Invalid attempt to destructure non-iterable instance");
+  }
+
+  var globalID = 1;
+  var pastWarnings = {};
+  var Utils = {
+    // Parsley DOM-API
+    // returns object from dom attributes and values
+    attr: function attr(element, namespace, obj) {
+      var i;
+      var attribute;
+      var attributes;
+      var regex = new RegExp('^' + namespace, 'i');
+      if ('undefined' === typeof obj) obj = {};else {
+        // Clear all own properties. This won't affect prototype's values
+        for (i in obj) {
+          if (obj.hasOwnProperty(i)) delete obj[i];
+        }
+      }
+      if (!element) return obj;
+      attributes = element.attributes;
+
+      for (i = attributes.length; i--;) {
+        attribute = attributes[i];
+
+        if (attribute && attribute.specified && regex.test(attribute.name)) {
+          obj[this.camelize(attribute.name.slice(namespace.length))] = this.deserializeValue(attribute.value);
+        }
+      }
+
+      return obj;
+    },
+    checkAttr: function checkAttr(element, namespace, _checkAttr) {
+      return element.hasAttribute(namespace + _checkAttr);
+    },
+    setAttr: function setAttr(element, namespace, attr, value) {
+      element.setAttribute(this.dasherize(namespace + attr), String(value));
+    },
+    getType: function getType(element) {
+      return element.getAttribute('type') || 'text';
+    },
+    generateID: function generateID() {
+      return '' + globalID++;
+    },
+
+    /** Third party functions **/
+    deserializeValue: function deserializeValue(value) {
+      var num;
+
+      try {
+        return value ? value == "true" || (value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? JSON.parse(value) : value) : value;
+      } catch (e) {
+        return value;
+      }
+    },
+    // Zepto camelize function
+    camelize: function camelize(str) {
+      return str.replace(/-+(.)?/g, function (match, chr) {
+        return chr ? chr.toUpperCase() : '';
+      });
+    },
+    // Zepto dasherize function
+    dasherize: function dasherize(str) {
+      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();
+    },
+    warn: function warn() {
+      var _window$console;
+
+      if (window.console && 'function' === typeof window.console.warn) (_window$console = window.console).warn.apply(_window$console, arguments);
+    },
+    warnOnce: function warnOnce(msg) {
+      if (!pastWarnings[msg]) {
+        pastWarnings[msg] = true;
+        this.warn.apply(this, arguments);
+      }
+    },
+    _resetWarnings: function _resetWarnings() {
+      pastWarnings = {};
+    },
+    trimString: function trimString(string) {
+      return string.replace(/^\s+|\s+$/g, '');
+    },
+    parse: {
+      date: function date(string) {
+        var parsed = string.match(/^(\d{4,})-(\d\d)-(\d\d)$/);
+        if (!parsed) return null;
+
+        var _parsed$map = parsed.map(function (x) {
+          return parseInt(x, 10);
+        }),
+            _parsed$map2 = _slicedToArray(_parsed$map, 4),
+            _ = _parsed$map2[0],
+            year = _parsed$map2[1],
+            month = _parsed$map2[2],
+            day = _parsed$map2[3];
+
+        var date = new Date(year, month - 1, day);
+        if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) return null;
+        return date;
+      },
+      string: function string(_string) {
+        return _string;
+      },
+      integer: function integer(string) {
+        if (isNaN(string)) return null;
+        return parseInt(string, 10);
+      },
+      number: function number(string) {
+        if (isNaN(string)) throw null;
+        return parseFloat(string);
+      },
+      'boolean': function _boolean(string) {
+        return !/^\s*false\s*$/i.test(string);
+      },
+      object: function object(string) {
+        return Utils.deserializeValue(string);
+      },
+      regexp: function regexp(_regexp) {
+        var flags = ''; // Test if RegExp is literal, if not, nothing to be done, otherwise, we need to isolate flags and pattern
+
+        if (/^\/.*\/(?:[gimy]*)$/.test(_regexp)) {
+          // Replace the regexp literal string with the first match group: ([gimy]*)
+          // If no flag is present, this will be a blank string
+          flags = _regexp.replace(/.*\/([gimy]*)$/, '$1'); // Again, replace the regexp literal string with the first match group:
+          // everything excluding the opening and closing slashes and the flags
+
+          _regexp = _regexp.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
+        } else {
+          // Anchor regexp:
+          _regexp = '^' + _regexp + '$';
+        }
+
+        return new RegExp(_regexp, flags);
+      }
+    },
+    parseRequirement: function parseRequirement(requirementType, string) {
+      var converter = this.parse[requirementType || 'string'];
+      if (!converter) throw 'Unknown requirement specification: "' + requirementType + '"';
+      var converted = converter(string);
+      if (converted === null) throw "Requirement is not a ".concat(requirementType, ": \"").concat(string, "\"");
+      return converted;
+    },
+    namespaceEvents: function namespaceEvents(events, namespace) {
+      events = this.trimString(events || '').split(/\s+/);
+      if (!events[0]) return '';
+      return $.map(events, function (evt) {
+        return "".concat(evt, ".").concat(namespace);
+      }).join(' ');
+    },
+    difference: function difference(array, remove) {
+      // This is O(N^2), should be optimized
+      var result = [];
+      $.each(array, function (_, elem) {
+        if (remove.indexOf(elem) == -1) result.push(elem);
+      });
+      return result;
+    },
+    // Alter-ego to native Promise.all, but for jQuery
+    all: function all(promises) {
+      // jQuery treats $.when() and $.when(singlePromise) differently; let's avoid that and add spurious elements
+      return $.when.apply($, _toConsumableArray(promises).concat([42, 42]));
+    },
+    // Object.create polyfill, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Polyfill
+    objectCreate: Object.create || function () {
+      var Object = function Object() {};
+
+      return function (prototype) {
+        if (arguments.length > 1) {
+          throw Error('Second argument not supported');
+        }
+
+        if (_typeof(prototype) != 'object') {
+          throw TypeError('Argument must be an object');
+        }
+
+        Object.prototype = prototype;
+        var result = new Object();
+        Object.prototype = null;
+        return result;
+      };
+    }(),
+    _SubmitSelector: 'input[type="submit"], button:submit'
+  };
+
+  // All these options could be overriden and specified directly in DOM using
+  // `data-parsley-` default DOM-API
+  // eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"`
+  // eg: `data-parsley-stop-on-first-failing-constraint="false"`
+  var Defaults = {
+    // ### General
+    // Default data-namespace for DOM API
+    namespace: 'data-parsley-',
+    // Supported inputs by default
+    inputs: 'input, textarea, select',
+    // Excluded inputs by default
+    excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden]',
+    // Stop validating field on highest priority failing constraint
+    priorityEnabled: true,
+    // ### Field only
+    // identifier used to group together inputs (e.g. radio buttons...)
+    multiple: null,
+    // identifier (or array of identifiers) used to validate only a select group of inputs
+    group: null,
+    // ### UI
+    // Enable\Disable error messages
+    uiEnabled: true,
+    // Key events threshold before validation
+    validationThreshold: 3,
+    // Focused field on form validation error. 'first'|'last'|'none'
+    focus: 'first',
+    // event(s) that will trigger validation before first failure. eg: `input`...
+    trigger: false,
+    // event(s) that will trigger validation after first failure.
+    triggerAfterFailure: 'input',
+    // Class that would be added on every failing validation Parsley field
+    errorClass: 'parsley-error',
+    // Same for success validation
+    successClass: 'parsley-success',
+    // Return the `$element` that will receive these above success or error classes
+    // Could also be (and given directly from DOM) a valid selector like `'#div'`
+    classHandler: function classHandler(Field) {},
+    // Return the `$element` where errors will be appended
+    // Could also be (and given directly from DOM) a valid selector like `'#div'`
+    errorsContainer: function errorsContainer(Field) {},
+    // ul elem that would receive errors' list
+    errorsWrapper: '<ul class="parsley-errors-list"></ul>',
+    // li elem that would receive error message
+    errorTemplate: '<li></li>'
+  };
+
+  var Base = function Base() {
+    this.__id__ = Utils.generateID();
+  };
+
+  Base.prototype = {
+    asyncSupport: true,
+    // Deprecated
+    _pipeAccordingToValidationResult: function _pipeAccordingToValidationResult() {
+      var _this = this;
+
+      var pipe = function pipe() {
+        var r = $.Deferred();
+        if (true !== _this.validationResult) r.reject();
+        return r.resolve().promise();
+      };
+
+      return [pipe, pipe];
+    },
+    actualizeOptions: function actualizeOptions() {
+      Utils.attr(this.element, this.options.namespace, this.domOptions);
+      if (this.parent && this.parent.actualizeOptions) this.parent.actualizeOptions();
+      return this;
+    },
+    _resetOptions: function _resetOptions(initOptions) {
+      this.domOptions = Utils.objectCreate(this.parent.options);
+      this.options = Utils.objectCreate(this.domOptions); // Shallow copy of ownProperties of initOptions:
+
+      for (var i in initOptions) {
+        if (initOptions.hasOwnProperty(i)) this.options[i] = initOptions[i];
+      }
+
+      this.actualizeOptions();
+    },
+    _listeners: null,
+    // Register a callback for the given event name
+    // Callback is called with context as the first argument and the `this`
+    // The context is the current parsley instance, or window.Parsley if global
+    // A return value of `false` will interrupt the calls
+    on: function on(name, fn) {
+      this._listeners = this._listeners || {};
+      var queue = this._listeners[name] = this._listeners[name] || [];
+      queue.push(fn);
+      return this;
+    },
+    // Deprecated. Use `on` instead
+    subscribe: function subscribe(name, fn) {
+      $.listenTo(this, name.toLowerCase(), fn);
+    },
+    // Unregister a callback (or all if none is given) for the given event name
+    off: function off(name, fn) {
+      var queue = this._listeners && this._listeners[name];
+
+      if (queue) {
+        if (!fn) {
+          delete this._listeners[name];
+        } else {
+          for (var i = queue.length; i--;) {
+            if (queue[i] === fn) queue.splice(i, 1);
+          }
+        }
+      }
+
+      return this;
+    },
+    // Deprecated. Use `off`
+    unsubscribe: function unsubscribe(name, fn) {
+      $.unsubscribeTo(this, name.toLowerCase());
+    },
+    // Trigger an event of the given name
+    // A return value of `false` interrupts the callback chain
+    // Returns false if execution was interrupted
+    trigger: function trigger(name, target, extraArg) {
+      target = target || this;
+      var queue = this._listeners && this._listeners[name];
+      var result;
+
+      if (queue) {
+        for (var i = queue.length; i--;) {
+          result = queue[i].call(target, target, extraArg);
+          if (result === false) return result;
+        }
+      }
+
+      if (this.parent) {
+        return this.parent.trigger(name, target, extraArg);
+      }
+
+      return true;
+    },
+    asyncIsValid: function asyncIsValid(group, force) {
+      Utils.warnOnce("asyncIsValid is deprecated; please use whenValid instead");
+      return this.whenValid({
+        group: group,
+        force: force
+      });
+    },
+    _findRelated: function _findRelated() {
+      return this.options.multiple ? $(this.parent.element.querySelectorAll("[".concat(this.options.namespace, "multiple=\"").concat(this.options.multiple, "\"]"))) : this.$element;
+    }
+  };
+
+  var convertArrayRequirement = function convertArrayRequirement(string, length) {
+    var m = string.match(/^\s*\[(.*)\]\s*$/);
+    if (!m) throw 'Requirement is not an array: "' + string + '"';
+    var values = m[1].split(',').map(Utils.trimString);
+    if (values.length !== length) throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed';
+    return values;
+  };
+
+  var convertExtraOptionRequirement = function convertExtraOptionRequirement(requirementSpec, string, extraOptionReader) {
+    var main = null;
+    var extra = {};
+
+    for (var key in requirementSpec) {
+      if (key) {
+        var value = extraOptionReader(key);
+        if ('string' === typeof value) value = Utils.parseRequirement(requirementSpec[key], value);
+        extra[key] = value;
+      } else {
+        main = Utils.parseRequirement(requirementSpec[key], string);
+      }
+    }
+
+    return [main, extra];
+  }; // A Validator needs to implement the methods `validate` and `parseRequirements`
+
+
+  var Validator = function Validator(spec) {
+    $.extend(true, this, spec);
+  };
+
+  Validator.prototype = {
+    // Returns `true` iff the given `value` is valid according the given requirements.
+    validate: function validate(value, requirementFirstArg) {
+      if (this.fn) {
+        // Legacy style validator
+        if (arguments.length > 3) // If more args then value, requirement, instance...
+          requirementFirstArg = [].slice.call(arguments, 1, -1); // Skip first arg (value) and last (instance), combining the rest
+
+        return this.fn(value, requirementFirstArg);
+      }
+
+      if (Array.isArray(value)) {
+        if (!this.validateMultiple) throw 'Validator `' + this.name + '` does not handle multiple values';
+        return this.validateMultiple.apply(this, arguments);
+      } else {
+        var instance = arguments[arguments.length - 1];
+
+        if (this.validateDate && instance._isDateInput()) {
+          arguments[0] = Utils.parse.date(arguments[0]);
+          if (arguments[0] === null) return false;
+          return this.validateDate.apply(this, arguments);
+        }
+
+        if (this.validateNumber) {
+          if (!value) // Builtin validators all accept empty strings, except `required` of course
+            return true;
+          if (isNaN(value)) return false;
+          arguments[0] = parseFloat(arguments[0]);
+          return this.validateNumber.apply(this, arguments);
+        }
+
+        if (this.validateString) {
+          return this.validateString.apply(this, arguments);
+        }
+
+        throw 'Validator `' + this.name + '` only handles multiple values';
+      }
+    },
+    // Parses `requirements` into an array of arguments,
+    // according to `this.requirementType`
+    parseRequirements: function parseRequirements(requirements, extraOptionReader) {
+      if ('string' !== typeof requirements) {
+        // Assume requirement already parsed
+        // but make sure we return an array
+        return Array.isArray(requirements) ? requirements : [requirements];
+      }
+
+      var type = this.requirementType;
+
+      if (Array.isArray(type)) {
+        var values = convertArrayRequirement(requirements, type.length);
+
+        for (var i = 0; i < values.length; i++) {
+          values[i] = Utils.parseRequirement(type[i], values[i]);
+        }
+
+        return values;
+      } else if ($.isPlainObject(type)) {
+        return convertExtraOptionRequirement(type, requirements, extraOptionReader);
+      } else {
+        return [Utils.parseRequirement(type, requirements)];
+      }
+    },
+    // Defaults:
+    requirementType: 'string',
+    priority: 2
+  };
+
+  var ValidatorRegistry = function ValidatorRegistry(validators, catalog) {
+    this.__class__ = 'ValidatorRegistry'; // Default Parsley locale is en
+
+    this.locale = 'en';
+    this.init(validators || {}, catalog || {});
+  };
+
+  var typeTesters = {
+    email: /^((([a-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-zA-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-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))$/,
+    // Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
+    number: /^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,
+    integer: /^-?\d+$/,
+    digits: /^\d+$/,
+    alphanum: /^\w+$/i,
+    date: {
+      test: function test(value) {
+        return Utils.parse.date(value) !== null;
+      }
+    },
+    url: new RegExp("^" + // protocol identifier
+    "(?:(?:https?|ftp)://)?" + // ** mod: make scheme optional
+    // user:pass authentication
+    "(?:\\S+(?::\\S*)?@)?" + "(?:" + // IP address exclusion
+    // private & local networks
+    // "(?!(?:10|127)(?:\\.\\d{1,3}){3})" +   // ** mod: allow local networks
+    // "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" +  // ** mod: allow local networks
+    // "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" +  // ** mod: allow local networks
+    // IP address dotted notation octets
+    // excludes loopback network 0.0.0.0
+    // excludes reserved space >= 224.0.0.0
+    // excludes network & broacast addresses
+    // (first & last IP address of each class)
+    "(?:[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]))" + "|" + // host name
+    "(?:(?:[a-zA-Z\\u00a1-\\uffff0-9]-*)*[a-zA-Z\\u00a1-\\uffff0-9]+)" + // domain name
+    "(?:\\.(?:[a-zA-Z\\u00a1-\\uffff0-9]-*)*[a-zA-Z\\u00a1-\\uffff0-9]+)*" + // TLD identifier
+    "(?:\\.(?:[a-zA-Z\\u00a1-\\uffff]{2,}))" + ")" + // port number
+    "(?::\\d{2,5})?" + // resource path
+    "(?:/\\S*)?" + "$")
+  };
+  typeTesters.range = typeTesters.number; // See http://stackoverflow.com/a/10454560/8279
+
+  var decimalPlaces = function decimalPlaces(num) {
+    var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
+
+    if (!match) {
+      return 0;
+    }
+
+    return Math.max(0, // Number of digits right of decimal point.
+    (match[1] ? match[1].length : 0) - ( // Adjust for scientific notation.
+    match[2] ? +match[2] : 0));
+  }; // parseArguments('number', ['1', '2']) => [1, 2]
+
+
+  var parseArguments = function parseArguments(type, args) {
+    return args.map(Utils.parse[type]);
+  }; // operatorToValidator returns a validating function for an operator function, applied to the given type
+
+
+  var operatorToValidator = function operatorToValidator(type, operator) {
+    return function (value) {
+      for (var _len = arguments.length, requirementsAndInput = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+        requirementsAndInput[_key - 1] = arguments[_key];
+      }
+
+      requirementsAndInput.pop(); // Get rid of `input` argument
+
+      return operator.apply(void 0, [value].concat(_toConsumableArray(parseArguments(type, requirementsAndInput))));
+    };
+  };
+
+  var comparisonOperator = function comparisonOperator(operator) {
+    return {
+      validateDate: operatorToValidator('date', operator),
+      validateNumber: operatorToValidator('number', operator),
+      requirementType: operator.length <= 2 ? 'string' : ['string', 'string'],
+      // Support operators with a 1 or 2 requirement(s)
+      priority: 30
+    };
+  };
+
+  ValidatorRegistry.prototype = {
+    init: function init(validators, catalog) {
+      this.catalog = catalog; // Copy prototype's validators:
+
+      this.validators = _extends({}, this.validators);
+
+      for (var name in validators) {
+        this.addValidator(name, validators[name].fn, validators[name].priority);
+      }
+
+      window.Parsley.trigger('parsley:validator:init');
+    },
+    // Set new messages locale if we have dictionary loaded in ParsleyConfig.i18n
+    setLocale: function setLocale(locale) {
+      if ('undefined' === typeof this.catalog[locale]) throw new Error(locale + ' is not available in the catalog');
+      this.locale = locale;
+      return this;
+    },
+    // Add a new messages catalog for a given locale. Set locale for this catalog if set === `true`
+    addCatalog: function addCatalog(locale, messages, set) {
+      if ('object' === _typeof(messages)) this.catalog[locale] = messages;
+      if (true === set) return this.setLocale(locale);
+      return this;
+    },
+    // Add a specific message for a given constraint in a given locale
+    addMessage: function addMessage(locale, name, message) {
+      if ('undefined' === typeof this.catalog[locale]) this.catalog[locale] = {};
+      this.catalog[locale][name] = message;
+      return this;
+    },
+    // Add messages for a given locale
+    addMessages: function addMessages(locale, nameMessageObject) {
+      for (var name in nameMessageObject) {
+        this.addMessage(locale, name, nameMessageObject[name]);
+      }
+
+      return this;
+    },
+    // Add a new validator
+    //
+    //    addValidator('custom', {
+    //        requirementType: ['integer', 'integer'],
+    //        validateString: function(value, from, to) {},
+    //        priority: 22,
+    //        messages: {
+    //          en: "Hey, that's no good",
+    //          fr: "Aye aye, pas bon du tout",
+    //        }
+    //    })
+    //
+    // Old API was addValidator(name, function, priority)
+    //
+    addValidator: function addValidator(name, arg1, arg2) {
+      if (this.validators[name]) Utils.warn('Validator "' + name + '" is already defined.');else if (Defaults.hasOwnProperty(name)) {
+        Utils.warn('"' + name + '" is a restricted keyword and is not a valid validator name.');
+        return;
+      }
+      return this._setValidator.apply(this, arguments);
+    },
+    hasValidator: function hasValidator(name) {
+      return !!this.validators[name];
+    },
+    updateValidator: function updateValidator(name, arg1, arg2) {
+      if (!this.validators[name]) {
+        Utils.warn('Validator "' + name + '" is not already defined.');
+        return this.addValidator.apply(this, arguments);
+      }
+
+      return this._setValidator.apply(this, arguments);
+    },
+    removeValidator: function removeValidator(name) {
+      if (!this.validators[name]) Utils.warn('Validator "' + name + '" is not defined.');
+      delete this.validators[name];
+      return this;
+    },
+    _setValidator: function _setValidator(name, validator, priority) {
+      if ('object' !== _typeof(validator)) {
+        // Old style validator, with `fn` and `priority`
+        validator = {
+          fn: validator,
+          priority: priority
+        };
+      }
+
+      if (!validator.validate) {
+        validator = new Validator(validator);
+      }
+
+      this.validators[name] = validator;
+
+      for (var locale in validator.messages || {}) {
+        this.addMessage(locale, name, validator.messages[locale]);
+      }
+
+      return this;
+    },
+    getErrorMessage: function getErrorMessage(constraint) {
+      var message; // Type constraints are a bit different, we have to match their requirements too to find right error message
+
+      if ('type' === constraint.name) {
+        var typeMessages = this.catalog[this.locale][constraint.name] || {};
+        message = typeMessages[constraint.requirements];
+      } else message = this.formatMessage(this.catalog[this.locale][constraint.name], constraint.requirements);
+
+      return message || this.catalog[this.locale].defaultMessage || this.catalog.en.defaultMessage;
+    },
+    // Kind of light `sprintf()` implementation
+    formatMessage: function formatMessage(string, parameters) {
+      if ('object' === _typeof(parameters)) {
+        for (var i in parameters) {
+          string = this.formatMessage(string, parameters[i]);
+        }
+
+        return string;
+      }
+
+      return 'string' === typeof string ? string.replace(/%s/i, parameters) : '';
+    },
+    // Here is the Parsley default validators list.
+    // A validator is an object with the following key values:
+    //  - priority: an integer
+    //  - requirement: 'string' (default), 'integer', 'number', 'regexp' or an Array of these
+    //  - validateString, validateMultiple, validateNumber: functions returning `true`, `false` or a promise
+    // Alternatively, a validator can be a function that returns such an object
+    //
+    validators: {
+      notblank: {
+        validateString: function validateString(value) {
+          return /\S/.test(value);
+        },
+        priority: 2
+      },
+      required: {
+        validateMultiple: function validateMultiple(values) {
+          return values.length > 0;
+        },
+        validateString: function validateString(value) {
+          return /\S/.test(value);
+        },
+        priority: 512
+      },
+      type: {
+        validateString: function validateString(value, type) {
+          var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
+              _ref$step = _ref.step,
+              step = _ref$step === void 0 ? 'any' : _ref$step,
+              _ref$base = _ref.base,
+              base = _ref$base === void 0 ? 0 : _ref$base;
+
+          var tester = typeTesters[type];
+
+          if (!tester) {
+            throw new Error('validator type `' + type + '` is not supported');
+          }
+
+          if (!value) return true; // Builtin validators all accept empty strings, except `required` of course
+
+          if (!tester.test(value)) return false;
+
+          if ('number' === type) {
+            if (!/^any$/i.test(step || '')) {
+              var nb = Number(value);
+              var decimals = Math.max(decimalPlaces(step), decimalPlaces(base));
+              if (decimalPlaces(nb) > decimals) // Value can't have too many decimals
+                return false; // Be careful of rounding errors by using integers.
+
+              var toInt = function toInt(f) {
+                return Math.round(f * Math.pow(10, decimals));
+              };
+
+              if ((toInt(nb) - toInt(base)) % toInt(step) != 0) return false;
+            }
+          }
+
+          return true;
+        },
+        requirementType: {
+          '': 'string',
+          step: 'string',
+          base: 'number'
+        },
+        priority: 256
+      },
+      pattern: {
+        validateString: function validateString(value, regexp) {
+          if (!value) return true; // Builtin validators all accept empty strings, except `required` of course
+
+          return regexp.test(value);
+        },
+        requirementType: 'regexp',
+        priority: 64
+      },
+      minlength: {
+        validateString: function validateString(value, requirement) {
+          if (!value) return true; // Builtin validators all accept empty strings, except `required` of course
+
+          return value.length >= requirement;
+        },
+        requirementType: 'integer',
+        priority: 30
+      },
+      maxlength: {
+        validateString: function validateString(value, requirement) {
+          return value.length <= requirement;
+        },
+        requirementType: 'integer',
+        priority: 30
+      },
+      length: {
+        validateString: function validateString(value, min, max) {
+          if (!value) return true; // Builtin validators all accept empty strings, except `required` of course
+
+          return value.length >= min && value.length <= max;
+        },
+        requirementType: ['integer', 'integer'],
+        priority: 30
+      },
+      mincheck: {
+        validateMultiple: function validateMultiple(values, requirement) {
+          return values.length >= requirement;
+        },
+        requirementType: 'integer',
+        priority: 30
+      },
+      maxcheck: {
+        validateMultiple: function validateMultiple(values, requirement) {
+          return values.length <= requirement;
+        },
+        requirementType: 'integer',
+        priority: 30
+      },
+      check: {
+        validateMultiple: function validateMultiple(values, min, max) {
+          return values.length >= min && values.length <= max;
+        },
+        requirementType: ['integer', 'integer'],
+        priority: 30
+      },
+      min: comparisonOperator(function (value, requirement) {
+        return value >= requirement;
+      }),
+      max: comparisonOperator(function (value, requirement) {
+        return value <= requirement;
+      }),
+      range: comparisonOperator(function (value, min, max) {
+        return value >= min && value <= max;
+      }),
+      equalto: {
+        validateString: function validateString(value, refOrValue) {
+          if (!value) return true; // Builtin validators all accept empty strings, except `required` of course
+
+          var $reference = $(refOrValue);
+          if ($reference.length) return value === $reference.val();else return value === refOrValue;
+        },
+        priority: 256
+      },
+      euvatin: {
+        validateString: function validateString(value, refOrValue) {
+          if (!value) {
+            return true; // Builtin validators all accept empty strings, except `required` of course
+          }
+
+          var re = /^[A-Z][A-Z][A-Za-z0-9 -]{2,}$/;
+          return re.test(value);
+        },
+        priority: 30
+      }
+    }
+  };
+
+  var UI = {};
+
+  var diffResults = function diffResults(newResult, oldResult, deep) {
+    var added = [];
+    var kept = [];
+
+    for (var i = 0; i < newResult.length; i++) {
+      var found = false;
+
+      for (var j = 0; j < oldResult.length; j++) {
+        if (newResult[i].assert.name === oldResult[j].assert.name) {
+          found = true;
+          break;
+        }
+      }
+
+      if (found) kept.push(newResult[i]);else added.push(newResult[i]);
+    }
+
+    return {
+      kept: kept,
+      added: added,
+      removed: !deep ? diffResults(oldResult, newResult, true).added : []
+    };
+  };
+
+  UI.Form = {
+    _actualizeTriggers: function _actualizeTriggers() {
+      var _this = this;
+
+      this.$element.on('submit.Parsley', function (evt) {
+        _this.onSubmitValidate(evt);
+      });
+      this.$element.on('click.Parsley', Utils._SubmitSelector, function (evt) {
+        _this.onSubmitButton(evt);
+      }); // UI could be disabled
+
+      if (false === this.options.uiEnabled) return;
+      this.element.setAttribute('novalidate', '');
+    },
+    focus: function focus() {
+      this._focusedField = null;
+      if (true === this.validationResult || 'none' === this.options.focus) return null;
+
+      for (var i = 0; i < this.fields.length; i++) {
+        var field = this.fields[i];
+
+        if (true !== field.validationResult && field.validationResult.length > 0 && 'undefined' === typeof field.options.noFocus) {
+          this._focusedField = field.$element;
+          if ('first' === this.options.focus) break;
+        }
+      }
+
+      if (null === this._focusedField) return null;
+      return this._focusedField.focus();
+    },
+    _destroyUI: function _destroyUI() {
+      // Reset all event listeners
+      this.$element.off('.Parsley');
+    }
+  };
+  UI.Field = {
+    _reflowUI: function _reflowUI() {
+      this._buildUI(); // If this field doesn't have an active UI don't bother doing something
+
+
+      if (!this._ui) return; // Diff between two validation results
+
+      var diff = diffResults(this.validationResult, this._ui.lastValidationResult); // Then store current validation result for next reflow
+
+      this._ui.lastValidationResult = this.validationResult; // Handle valid / invalid / none field class
+
+      this._manageStatusClass(); // Add, remove, updated errors messages
+
+
+      this._manageErrorsMessages(diff); // Triggers impl
+
+
+      this._actualizeTriggers(); // If field is not valid for the first time, bind keyup trigger to ease UX and quickly inform user
+
+
+      if ((diff.kept.length || diff.added.length) && !this._failedOnce) {
+        this._failedOnce = true;
+
+        this._actualizeTriggers();
+      }
+    },
+    // Returns an array of field's error message(s)
+    getErrorsMessages: function getErrorsMessages() {
+      // No error message, field is valid
+      if (true === this.validationResult) return [];
+      var messages = [];
+
+      for (var i = 0; i < this.validationResult.length; i++) {
+        messages.push(this.validationResult[i].errorMessage || this._getErrorMessage(this.validationResult[i].assert));
+      }
+
+      return messages;
+    },
+    // It's a goal of Parsley that this method is no longer required [#1073]
+    addError: function addError(name) {
+      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+          message = _ref.message,
+          assert = _ref.assert,
+          _ref$updateClass = _ref.updateClass,
+          updateClass = _ref$updateClass === void 0 ? true : _ref$updateClass;
+
+      this._buildUI();
+
+      this._addError(name, {
+        message: message,
+        assert: assert
+      });
+
+      if (updateClass) this._errorClass();
+    },
+    // It's a goal of Parsley that this method is no longer required [#1073]
+    updateError: function updateError(name) {
+      var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+          message = _ref2.message,
+          assert = _ref2.assert,
+          _ref2$updateClass = _ref2.updateClass,
+          updateClass = _ref2$updateClass === void 0 ? true : _ref2$updateClass;
+
+      this._buildUI();
+
+      this._updateError(name, {
+        message: message,
+        assert: assert
+      });
+
+      if (updateClass) this._errorClass();
+    },
+    // It's a goal of Parsley that this method is no longer required [#1073]
+    removeError: function removeError(name) {
+      var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+          _ref3$updateClass = _ref3.updateClass,
+          updateClass = _ref3$updateClass === void 0 ? true : _ref3$updateClass;
+
+      this._buildUI();
+
+      this._removeError(name); // edge case possible here: remove a standard Parsley error that is still failing in this.validationResult
+      // but highly improbable cuz' manually removing a well Parsley handled error makes no sense.
+
+
+      if (updateClass) this._manageStatusClass();
+    },
+    _manageStatusClass: function _manageStatusClass() {
+      if (this.hasConstraints() && this.needsValidation() && true === this.validationResult) this._successClass();else if (this.validationResult.length > 0) this._errorClass();else this._resetClass();
+    },
+    _manageErrorsMessages: function _manageErrorsMessages(diff) {
+      if ('undefined' !== typeof this.options.errorsMessagesDisabled) return; // Case where we have errorMessage option that configure an unique field error message, regardless failing validators
+
+      if ('undefined' !== typeof this.options.errorMessage) {
+        if (diff.added.length || diff.kept.length) {
+          this._insertErrorWrapper();
+
+          if (0 === this._ui.$errorsWrapper.find('.parsley-custom-error-message').length) this._ui.$errorsWrapper.append($(this.options.errorTemplate).addClass('parsley-custom-error-message'));
+
+          this._ui.$errorClassHandler.attr('aria-describedby', this._ui.errorsWrapperId);
+
+          return this._ui.$errorsWrapper.addClass('filled').attr('aria-hidden', 'false').find('.parsley-custom-error-message').html(this.options.errorMessage);
+        }
+
+        this._ui.$errorClassHandler.removeAttr('aria-describedby');
+
+        return this._ui.$errorsWrapper.removeClass('filled').attr('aria-hidden', 'true').find('.parsley-custom-error-message').remove();
+      } // Show, hide, update failing constraints messages
+
+
+      for (var i = 0; i < diff.removed.length; i++) {
+        this._removeError(diff.removed[i].assert.name);
+      }
+
+      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
+        });
+      }
+
+      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
+        });
+      }
+    },
+    _addError: function _addError(name, _ref4) {
+      var message = _ref4.message,
+          assert = _ref4.assert;
+
+      this._insertErrorWrapper();
+
+      this._ui.$errorClassHandler.attr('aria-describedby', this._ui.errorsWrapperId);
+
+      this._ui.$errorsWrapper.addClass('filled').attr('aria-hidden', 'false').append($(this.options.errorTemplate).addClass('parsley-' + name).html(message || this._getErrorMessage(assert)));
+    },
+    _updateError: function _updateError(name, _ref5) {
+      var message = _ref5.message,
+          assert = _ref5.assert;
+
+      this._ui.$errorsWrapper.addClass('filled').find('.parsley-' + name).html(message || this._getErrorMessage(assert));
+    },
+    _removeError: function _removeError(name) {
+      this._ui.$errorClassHandler.removeAttr('aria-describedby');
+
+      this._ui.$errorsWrapper.removeClass('filled').attr('aria-hidden', 'true').find('.parsley-' + name).remove();
+    },
+    _getErrorMessage: function _getErrorMessage(constraint) {
+      var customConstraintErrorMessage = constraint.name + 'Message';
+      if ('undefined' !== typeof this.options[customConstraintErrorMessage]) return window.Parsley.formatMessage(this.options[customConstraintErrorMessage], constraint.requirements);
+      return window.Parsley.getErrorMessage(constraint);
+    },
+    _buildUI: function _buildUI() {
+      // UI could be already built or disabled
+      if (this._ui || false === this.options.uiEnabled) return;
+      var _ui = {}; // Give field its Parsley id in DOM
+
+      this.element.setAttribute(this.options.namespace + 'id', this.__id__);
+      /** Generate important UI elements and store them in this **/
+      // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes
+
+      _ui.$errorClassHandler = this._manageClassHandler(); // $errorsWrapper is a div that would contain the various field errors, it will be appended into $errorsContainer
+
+      _ui.errorsWrapperId = 'parsley-id-' + (this.options.multiple ? 'multiple-' + this.options.multiple : this.__id__);
+      _ui.$errorsWrapper = $(this.options.errorsWrapper).attr('id', _ui.errorsWrapperId); // ValidationResult UI storage to detect what have changed bwt two validations, and update DOM accordingly
+
+      _ui.lastValidationResult = [];
+      _ui.validationInformationVisible = false; // Store it in this for later
+
+      this._ui = _ui;
+    },
+    // Determine which element will have `parsley-error` and `parsley-success` classes
+    _manageClassHandler: function _manageClassHandler() {
+      // Class handled could also be determined by function given in Parsley options
+      if ('string' === typeof this.options.classHandler && $(this.options.classHandler).length) return $(this.options.classHandler); // Class handled could also be determined by function given in Parsley options
+
+      var $handlerFunction = this.options.classHandler; // It might also be the function name of a global function
+
+      if ('string' === typeof this.options.classHandler && 'function' === typeof window[this.options.classHandler]) $handlerFunction = window[this.options.classHandler];
+
+      if ('function' === typeof $handlerFunction) {
+        var $handler = $handlerFunction.call(this, this); // If this function returned a valid existing DOM element, go for it
+
+        if ('undefined' !== typeof $handler && $handler.length) return $handler;
+      } else if ('object' === _typeof($handlerFunction) && $handlerFunction instanceof jQuery && $handlerFunction.length) {
+        return $handlerFunction;
+      } else if ($handlerFunction) {
+        Utils.warn('The class handler `' + $handlerFunction + '` does not exist in DOM nor as a global JS function');
+      }
+
+      return this._inputHolder();
+    },
+    _inputHolder: function _inputHolder() {
+      // if simple element (input, texatrea, select...) it will perfectly host the classes and precede the error container
+      if (!this.options.multiple || this.element.nodeName === 'SELECT') return this.$element; // But if multiple element (radio, checkbox), that would be their parent
+
+      return this.$element.parent();
+    },
+    _insertErrorWrapper: function _insertErrorWrapper() {
+      var $errorsContainer = this.options.errorsContainer; // Nothing to do if already inserted
+
+      if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
+
+      if ('string' === typeof $errorsContainer) {
+        if ($($errorsContainer).length) return $($errorsContainer).append(this._ui.$errorsWrapper);else if ('function' === typeof window[$errorsContainer]) $errorsContainer = window[$errorsContainer];else Utils.warn('The errors container `' + $errorsContainer + '` does not exist in DOM nor as a global JS function');
+      }
+
+      if ('function' === typeof $errorsContainer) $errorsContainer = $errorsContainer.call(this, this);
+      if ('object' === _typeof($errorsContainer) && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
+      return this._inputHolder().after(this._ui.$errorsWrapper);
+    },
+    _actualizeTriggers: function _actualizeTriggers() {
+      var _this2 = this;
+
+      var $toBind = this._findRelated();
+
+      var trigger; // Remove Parsley events already bound on this field
+
+      $toBind.off('.Parsley');
+      if (this._failedOnce) $toBind.on(Utils.namespaceEvents(this.options.triggerAfterFailure, 'Parsley'), function () {
+        _this2._validateIfNeeded();
+      });else if (trigger = Utils.namespaceEvents(this.options.trigger, 'Parsley')) {
+        $toBind.on(trigger, function (event) {
+          _this2._validateIfNeeded(event);
+        });
+      }
+    },
+    _validateIfNeeded: function _validateIfNeeded(event) {
+      var _this3 = this;
+
+      // For keyup, keypress, keydown, input... events that could be a little bit obstrusive
+      // do not validate if val length < min threshold on first validation. Once field have been validated once and info
+      // about success or failure have been displayed, always validate with this trigger to reflect every yalidation change.
+      if (event && /key|input/.test(event.type)) if (!(this._ui && this._ui.validationInformationVisible) && this.getValue().length <= this.options.validationThreshold) return;
+
+      if (this.options.debounce) {
+        window.clearTimeout(this._debounced);
+        this._debounced = window.setTimeout(function () {
+          return _this3.validate();
+        }, this.options.debounce);
+      } else this.validate();
+    },
+    _resetUI: function _resetUI() {
+      // Reset all event listeners
+      this._failedOnce = false;
+
+      this._actualizeTriggers(); // Nothing to do if UI never initialized for this field
+
+
+      if ('undefined' === typeof this._ui) return; // Reset all errors' li
+
+      this._ui.$errorsWrapper.removeClass('filled').children().remove(); // Reset validation class
+
+
+      this._resetClass(); // Reset validation flags and last validation result
+
+
+      this._ui.lastValidationResult = [];
+      this._ui.validationInformationVisible = false;
+    },
+    _destroyUI: function _destroyUI() {
+      this._resetUI();
+
+      if ('undefined' !== typeof this._ui) this._ui.$errorsWrapper.remove();
+      delete this._ui;
+    },
+    _successClass: function _successClass() {
+      this._ui.validationInformationVisible = true;
+
+      this._ui.$errorClassHandler.removeClass(this.options.errorClass).addClass(this.options.successClass);
+    },
+    _errorClass: function _errorClass() {
+      this._ui.validationInformationVisible = true;
+
+      this._ui.$errorClassHandler.removeClass(this.options.successClass).addClass(this.options.errorClass);
+    },
+    _resetClass: function _resetClass() {
+      this._ui.$errorClassHandler.removeClass(this.options.successClass).removeClass(this.options.errorClass);
+    }
+  };
+
+  var Form = function Form(element, domOptions, options) {
+    this.__class__ = 'Form';
+    this.element = element;
+    this.$element = $(element);
+    this.domOptions = domOptions;
+    this.options = options;
+    this.parent = window.Parsley;
+    this.fields = [];
+    this.validationResult = null;
+  };
+
+  var statusMapping = {
+    pending: null,
+    resolved: true,
+    rejected: false
+  };
+  Form.prototype = {
+    onSubmitValidate: function onSubmitValidate(event) {
+      var _this = this;
+
+      // This is a Parsley generated submit event, do not validate, do not prevent, simply exit and keep normal behavior
+      if (true === event.parsley) return; // If we didn't come here through a submit button, use the first one in the form
+
+      var submitSource = this._submitSource || this.$element.find(Utils._SubmitSelector)[0];
+      this._submitSource = null;
+      this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true);
+      if (submitSource && null !== submitSource.getAttribute('formnovalidate')) return;
+      window.Parsley._remoteCache = {};
+      var promise = this.whenValidate({
+        event: event
+      });
+
+      if ('resolved' === promise.state() && false !== this._trigger('submit')) ; else {
+        // Rejected or pending: cancel this submit
+        event.stopImmediatePropagation();
+        event.preventDefault();
+        if ('pending' === promise.state()) promise.done(function () {
+          _this._submit(submitSource);
+        });
+      }
+    },
+    onSubmitButton: function onSubmitButton(event) {
+      this._submitSource = event.currentTarget;
+    },
+    // internal
+    // _submit submits the form, this time without going through the validations.
+    // Care must be taken to "fake" the actual submit button being clicked.
+    _submit: function _submit(submitSource) {
+      if (false === this._trigger('submit')) return; // Add submit button's data
+
+      if (submitSource) {
+        var $synthetic = this.$element.find('.parsley-synthetic-submit-button').prop('disabled', false);
+        if (0 === $synthetic.length) $synthetic = $('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element);
+        $synthetic.attr({
+          name: submitSource.getAttribute('name'),
+          value: submitSource.getAttribute('value')
+        });
+      }
+
+      this.$element.trigger(_extends($.Event('submit'), {
+        parsley: true
+      }));
+    },
+    // Performs validation on fields while triggering events.
+    // @returns `true` if all validations succeeds, `false`
+    // if a failure is immediately detected, or `null`
+    // if dependant on a promise.
+    // Consider using `whenValidate` instead.
+    validate: function validate(options) {
+      if (arguments.length >= 1 && !$.isPlainObject(options)) {
+        Utils.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.');
+
+        var _arguments = Array.prototype.slice.call(arguments),
+            group = _arguments[0],
+            force = _arguments[1],
+            event = _arguments[2];
+
+        options = {
+          group: group,
+          force: force,
+          event: event
+        };
+      }
+
+      return statusMapping[this.whenValidate(options).state()];
+    },
+    whenValidate: function whenValidate() {
+      var _this2 = this,
+          _Utils$all$done$fail$;
+
+      var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+          group = _ref.group,
+          force = _ref.force,
+          event = _ref.event;
+
+      this.submitEvent = event;
+
+      if (event) {
+        this.submitEvent = _extends({}, event, {
+          preventDefault: function preventDefault() {
+            Utils.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`");
+            _this2.validationResult = false;
+          }
+        });
+      }
+
+      this.validationResult = true; // fire validate event to eventually modify things before every validation
+
+      this._trigger('validate'); // Refresh form DOM options and form's fields that could have changed
+
+
+      this._refreshFields();
+
+      var promises = this._withoutReactualizingFormOptions(function () {
+        return $.map(_this2.fields, function (field) {
+          return field.whenValidate({
+            force: force,
+            group: group
+          });
+        });
+      });
+
+      return (_Utils$all$done$fail$ = Utils.all(promises).done(function () {
+        _this2._trigger('success');
+      }).fail(function () {
+        _this2.validationResult = false;
+
+        _this2.focus();
+
+        _this2._trigger('error');
+      }).always(function () {
+        _this2._trigger('validated');
+      })).pipe.apply(_Utils$all$done$fail$, _toConsumableArray(this._pipeAccordingToValidationResult()));
+    },
+    // Iterate over refreshed fields, and stop on first failure.
+    // Returns `true` if all fields are valid, `false` if a failure is detected
+    // or `null` if the result depends on an unresolved promise.
+    // Prefer using `whenValid` instead.
+    isValid: function isValid(options) {
+      if (arguments.length >= 1 && !$.isPlainObject(options)) {
+        Utils.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.');
+
+        var _arguments2 = Array.prototype.slice.call(arguments),
+            group = _arguments2[0],
+            force = _arguments2[1];
+
+        options = {
+          group: group,
+          force: force
+        };
+      }
+
+      return statusMapping[this.whenValid(options).state()];
+    },
+    // Iterate over refreshed fields and validate them.
+    // Returns a promise.
+    // A validation that immediately fails will interrupt the validations.
+    whenValid: function whenValid() {
+      var _this3 = this;
+
+      var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+          group = _ref2.group,
+          force = _ref2.force;
+
+      this._refreshFields();
+
+      var promises = this._withoutReactualizingFormOptions(function () {
+        return $.map(_this3.fields, function (field) {
+          return field.whenValid({
+            group: group,
+            force: force
+          });
+        });
+      });
+
+      return Utils.all(promises);
+    },
+    refresh: function refresh() {
+      this._refreshFields();
+
+      return this;
+    },
+    // Reset UI
+    reset: function reset() {
+      // Form case: emit a reset event for each field
+      for (var i = 0; i < this.fields.length; i++) {
+        this.fields[i].reset();
+      }
+
+      this._trigger('reset');
+    },
+    // Destroy Parsley instance (+ UI)
+    destroy: function destroy() {
+      // Field case: emit destroy event to clean UI and then destroy stored instance
+      this._destroyUI(); // Form case: destroy all its fields and then destroy stored instance
+
+
+      for (var i = 0; i < this.fields.length; i++) {
+        this.fields[i].destroy();
+      }
+
+      this.$element.removeData('Parsley');
+
+      this._trigger('destroy');
+    },
+    _refreshFields: function _refreshFields() {
+      return this.actualizeOptions()._bindFields();
+    },
+    _bindFields: function _bindFields() {
+      var _this4 = this;
+
+      var oldFields = this.fields;
+      this.fields = [];
+      this.fieldsMappedById = {};
+
+      this._withoutReactualizingFormOptions(function () {
+        _this4.$element.find(_this4.options.inputs).not(_this4.options.excluded).not("[".concat(_this4.options.namespace, "excluded=true]")).each(function (_, element) {
+          var fieldInstance = new window.Parsley.Factory(element, {}, _this4); // Only add valid and not excluded `Field` and `FieldMultiple` children
+
+          if ('Field' === fieldInstance.__class__ || 'FieldMultiple' === fieldInstance.__class__) {
+            var uniqueId = fieldInstance.__class__ + '-' + fieldInstance.__id__;
+
+            if ('undefined' === typeof _this4.fieldsMappedById[uniqueId]) {
+              _this4.fieldsMappedById[uniqueId] = fieldInstance;
+
+              _this4.fields.push(fieldInstance);
+            }
+          }
+        });
+
+        $.each(Utils.difference(oldFields, _this4.fields), function (_, field) {
+          field.reset();
+        });
+      });
+
+      return this;
+    },
+    // Internal only.
+    // Looping on a form's fields to do validation or similar
+    // will trigger reactualizing options on all of them, which
+    // in turn will reactualize the form's options.
+    // To avoid calling actualizeOptions so many times on the form
+    // for nothing, _withoutReactualizingFormOptions temporarily disables
+    // the method actualizeOptions on this form while `fn` is called.
+    _withoutReactualizingFormOptions: function _withoutReactualizingFormOptions(fn) {
+      var oldActualizeOptions = this.actualizeOptions;
+
+      this.actualizeOptions = function () {
+        return this;
+      };
+
+      var result = fn();
+      this.actualizeOptions = oldActualizeOptions;
+      return result;
+    },
+    // Internal only.
+    // Shortcut to trigger an event
+    // Returns true iff event is not interrupted and default not prevented.
+    _trigger: function _trigger(eventName) {
+      return this.trigger('form:' + eventName);
+    }
+  };
+
+  var Constraint = function Constraint(parsleyField, name, requirements, priority, isDomConstraint) {
+    var validatorSpec = window.Parsley._validatorRegistry.validators[name];
+    var validator = new Validator(validatorSpec);
+    priority = priority || parsleyField.options[name + 'Priority'] || validator.priority;
+    isDomConstraint = true === isDomConstraint;
+
+    _extends(this, {
+      validator: validator,
+      name: name,
+      requirements: requirements,
+      priority: priority,
+      isDomConstraint: isDomConstraint
+    });
+
+    this._parseRequirements(parsleyField.options);
+  };
+
+  var capitalize = function capitalize(str) {
+    var cap = str[0].toUpperCase();
+    return cap + str.slice(1);
+  };
+
+  Constraint.prototype = {
+    validate: function validate(value, instance) {
+      var _this$validator;
+
+      return (_this$validator = this.validator).validate.apply(_this$validator, [value].concat(_toConsumableArray(this.requirementList), [instance]));
+    },
+    _parseRequirements: function _parseRequirements(options) {
+      var _this = this;
+
+      this.requirementList = this.validator.parseRequirements(this.requirements, function (key) {
+        return options[_this.name + capitalize(key)];
+      });
+    }
+  };
+
+  var Field = function Field(field, domOptions, options, parsleyFormInstance) {
+    this.__class__ = 'Field';
+    this.element = field;
+    this.$element = $(field); // Set parent if we have one
+
+    if ('undefined' !== typeof parsleyFormInstance) {
+      this.parent = parsleyFormInstance;
+    }
+
+    this.options = options;
+    this.domOptions = domOptions; // Initialize some properties
+
+    this.constraints = [];
+    this.constraintsByName = {};
+    this.validationResult = true; // Bind constraints
+
+    this._bindConstraints();
+  };
+
+  var statusMapping$1 = {
+    pending: null,
+    resolved: true,
+    rejected: false
+  };
+  Field.prototype = {
+    // # Public API
+    // Validate field and trigger some events for mainly `UI`
+    // @returns `true`, an array of the validators that failed, or
+    // `null` if validation is not finished. Prefer using whenValidate
+    validate: function validate(options) {
+      if (arguments.length >= 1 && !$.isPlainObject(options)) {
+        Utils.warnOnce('Calling validate on a parsley field without passing arguments as an object is deprecated.');
+        options = {
+          options: options
+        };
+      }
+
+      var promise = this.whenValidate(options);
+      if (!promise) // If excluded with `group` option
+        return true;
+
+      switch (promise.state()) {
+        case 'pending':
+          return null;
+
+        case 'resolved':
+          return true;
+
+        case 'rejected':
+          return this.validationResult;
+      }
+    },
+    // Validate field and trigger some events for mainly `UI`
+    // @returns a promise that succeeds only when all validations do
+    // or `undefined` if field is not in the given `group`.
+    whenValidate: function whenValidate() {
+      var _this$whenValid$alway,
+          _this = this;
+
+      var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+          force = _ref.force,
+          group = _ref.group;
+
+      // do not validate a field if not the same as given validation group
+      this.refresh();
+      if (group && !this._isInGroup(group)) return;
+      this.value = this.getValue(); // Field Validate event. `this.value` could be altered for custom needs
+
+      this._trigger('validate');
+
+      return (_this$whenValid$alway = this.whenValid({
+        force: force,
+        value: this.value,
+        _refreshed: true
+      }).always(function () {
+        _this._reflowUI();
+      }).done(function () {
+        _this._trigger('success');
+      }).fail(function () {
+        _this._trigger('error');
+      }).always(function () {
+        _this._trigger('validated');
+      })).pipe.apply(_this$whenValid$alway, _toConsumableArray(this._pipeAccordingToValidationResult()));
+    },
+    hasConstraints: function hasConstraints() {
+      return 0 !== this.constraints.length;
+    },
+    // An empty optional field does not need validation
+    needsValidation: function needsValidation(value) {
+      if ('undefined' === typeof value) value = this.getValue(); // If a field is empty and not required, it is valid
+      // Except if `data-parsley-validate-if-empty` explicitely added, useful for some custom validators
+
+      if (!value.length && !this._isRequired() && 'undefined' === typeof this.options.validateIfEmpty) return false;
+      return true;
+    },
+    _isInGroup: function _isInGroup(group) {
+      if (Array.isArray(this.options.group)) return -1 !== $.inArray(group, this.options.group);
+      return this.options.group === group;
+    },
+    // Just validate field. Do not trigger any event.
+    // Returns `true` iff all constraints pass, `false` if there are failures,
+    // or `null` if the result can not be determined yet (depends on a promise)
+    // See also `whenValid`.
+    isValid: function isValid(options) {
+      if (arguments.length >= 1 && !$.isPlainObject(options)) {
+        Utils.warnOnce('Calling isValid on a parsley field without passing arguments as an object is deprecated.');
+
+        var _arguments = Array.prototype.slice.call(arguments),
+            force = _arguments[0],
+            value = _arguments[1];
+
+        options = {
+          force: force,
+          value: value
+        };
+      }
+
+      var promise = this.whenValid(options);
+      if (!promise) // Excluded via `group`
+        return true;
+      return statusMapping$1[promise.state()];
+    },
+    // Just validate field. Do not trigger any event.
+    // @returns a promise that succeeds only when all validations do
+    // or `undefined` if the field is not in the given `group`.
+    // The argument `force` will force validation of empty fields.
+    // If a `value` is given, it will be validated instead of the value of the input.
+    whenValid: function whenValid() {
+      var _this2 = this;
+
+      var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+          _ref2$force = _ref2.force,
+          force = _ref2$force === void 0 ? false : _ref2$force,
+          value = _ref2.value,
+          group = _ref2.group,
+          _refreshed = _ref2._refreshed;
+
+      // Recompute options and rebind constraints to have latest changes
+      if (!_refreshed) this.refresh(); // do not validate a field if not the same as given validation group
+
+      if (group && !this._isInGroup(group)) return;
+      this.validationResult = true; // A field without constraint is valid
+
+      if (!this.hasConstraints()) return $.when(); // Value could be passed as argument, needed to add more power to 'field:validate'
+
+      if ('undefined' === typeof value || null === value) value = this.getValue();
+      if (!this.needsValidation(value) && true !== force) return $.when();
+
+      var groupedConstraints = this._getGroupedConstraints();
+
+      var promises = [];
+      $.each(groupedConstraints, function (_, constraints) {
+        // Process one group of constraints at a time, we validate the constraints
+        // and combine the promises together.
+        var promise = Utils.all($.map(constraints, function (constraint) {
+          return _this2._validateConstraint(value, constraint);
+        }));
+        promises.push(promise);
+        if (promise.state() === 'rejected') return false; // Interrupt processing if a group has already failed
+      });
+      return Utils.all(promises);
+    },
+    // @returns a promise
+    _validateConstraint: function _validateConstraint(value, constraint) {
+      var _this3 = this;
+
+      var result = constraint.validate(value, this); // Map false to a failed promise
+
+      if (false === result) result = $.Deferred().reject(); // Make sure we return a promise and that we record failures
+
+      return Utils.all([result]).fail(function (errorMessage) {
+        if (!(_this3.validationResult instanceof Array)) _this3.validationResult = [];
+
+        _this3.validationResult.push({
+          assert: constraint,
+          errorMessage: 'string' === typeof errorMessage && errorMessage
+        });
+      });
+    },
+    // @returns Parsley field computed value that could be overrided or configured in DOM
+    getValue: function getValue() {
+      var value; // Value could be overriden in DOM or with explicit options
+
+      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(); // Handle wrong DOM or configurations
+
+      if ('undefined' === typeof value || null === value) return '';
+      return this._handleWhitespace(value);
+    },
+    // Reset UI
+    reset: function reset() {
+      this._resetUI();
+
+      return this._trigger('reset');
+    },
+    // Destroy Parsley instance (+ UI)
+    destroy: function destroy() {
+      // Field case: emit destroy event to clean UI and then destroy stored instance
+      this._destroyUI();
+
+      this.$element.removeData('Parsley');
+      this.$element.removeData('FieldMultiple');
+
+      this._trigger('destroy');
+    },
+    // Actualize options and rebind constraints
+    refresh: function refresh() {
+      this._refreshConstraints();
+
+      return this;
+    },
+    _refreshConstraints: function _refreshConstraints() {
+      return this.actualizeOptions()._bindConstraints();
+    },
+    refreshConstraints: function refreshConstraints() {
+      Utils.warnOnce("Parsley's refreshConstraints is deprecated. Please use refresh");
+      return this.refresh();
+    },
+
+    /**
+    * Add a new constraint to a field
+    *
+    * @param {String}   name
+    * @param {Mixed}    requirements      optional
+    * @param {Number}   priority          optional
+    * @param {Boolean}  isDomConstraint   optional
+    */
+    addConstraint: function addConstraint(name, requirements, priority, isDomConstraint) {
+      if (window.Parsley._validatorRegistry.validators[name]) {
+        var constraint = new Constraint(this, name, requirements, priority, isDomConstraint); // if constraint already exist, delete it and push new version
+
+        if ('undefined' !== this.constraintsByName[constraint.name]) this.removeConstraint(constraint.name);
+        this.constraints.push(constraint);
+        this.constraintsByName[constraint.name] = constraint;
+      }
+
+      return this;
+    },
+    // Remove a constraint
+    removeConstraint: function removeConstraint(name) {
+      for (var i = 0; i < this.constraints.length; i++) {
+        if (name === this.constraints[i].name) {
+          this.constraints.splice(i, 1);
+          break;
+        }
+      }
+
+      delete this.constraintsByName[name];
+      return this;
+    },
+    // Update a constraint (Remove + re-add)
+    updateConstraint: function updateConstraint(name, parameters, priority) {
+      return this.removeConstraint(name).addConstraint(name, parameters, priority);
+    },
+    // # Internals
+    // Internal only.
+    // Bind constraints from config + options + DOM
+    _bindConstraints: function _bindConstraints() {
+      var constraints = [];
+      var constraintsByName = {}; // clean all existing DOM constraints to only keep javascript user constraints
+
+      for (var i = 0; i < this.constraints.length; i++) {
+        if (false === this.constraints[i].isDomConstraint) {
+          constraints.push(this.constraints[i]);
+          constraintsByName[this.constraints[i].name] = this.constraints[i];
+        }
+      }
+
+      this.constraints = constraints;
+      this.constraintsByName = constraintsByName; // then re-add Parsley DOM-API constraints
+
+      for (var name in this.options) {
+        this.addConstraint(name, this.options[name], undefined, true);
+      } // finally, bind special HTML5 constraints
+
+
+      return this._bindHtml5Constraints();
+    },
+    // Internal only.
+    // Bind specific HTML5 constraints to be HTML5 compliant
+    _bindHtml5Constraints: function _bindHtml5Constraints() {
+      // html5 required
+      if (null !== this.element.getAttribute('required')) this.addConstraint('required', true, undefined, true); // html5 pattern
+
+      if (null !== this.element.getAttribute('pattern')) this.addConstraint('pattern', this.element.getAttribute('pattern'), undefined, true); // range
+
+      var min = this.element.getAttribute('min');
+      var max = this.element.getAttribute('max');
+      if (null !== min && null !== max) this.addConstraint('range', [min, max], undefined, true); // HTML5 min
+      else if (null !== min) this.addConstraint('min', min, undefined, true); // HTML5 max
+        else if (null !== max) this.addConstraint('max', max, undefined, true); // length
+
+      if (null !== this.element.getAttribute('minlength') && null !== this.element.getAttribute('maxlength')) this.addConstraint('length', [this.element.getAttribute('minlength'), this.element.getAttribute('maxlength')], undefined, true); // HTML5 minlength
+      else if (null !== this.element.getAttribute('minlength')) this.addConstraint('minlength', this.element.getAttribute('minlength'), undefined, true); // HTML5 maxlength
+        else if (null !== this.element.getAttribute('maxlength')) this.addConstraint('maxlength', this.element.getAttribute('maxlength'), undefined, true); // html5 types
+
+      var type = Utils.getType(this.element); // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
+
+      if ('number' === type) {
+        return this.addConstraint('type', ['number', {
+          step: this.element.getAttribute('step') || '1',
+          base: min || this.element.getAttribute('value')
+        }], undefined, true); // Regular other HTML5 supported types
+      } else if (/^(email|url|range|date)$/i.test(type)) {
+        return this.addConstraint('type', type, undefined, true);
+      }
+
+      return this;
+    },
+    // Internal only.
+    // Field is required if have required constraint without `false` value
+    _isRequired: function _isRequired() {
+      if ('undefined' === typeof this.constraintsByName.required) return false;
+      return false !== this.constraintsByName.required.requirements;
+    },
+    // Internal only.
+    // Shortcut to trigger an event
+    _trigger: function _trigger(eventName) {
+      return this.trigger('field:' + eventName);
+    },
+    // Internal only
+    // Handles whitespace in a value
+    // Use `data-parsley-whitespace="squish"` to auto squish input value
+    // Use `data-parsley-whitespace="trim"` to auto trim input value
+    _handleWhitespace: function _handleWhitespace(value) {
+      if (true === this.options.trimValue) Utils.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"');
+      if ('squish' === this.options.whitespace) value = value.replace(/\s{2,}/g, ' ');
+      if ('trim' === this.options.whitespace || 'squish' === this.options.whitespace || true === this.options.trimValue) value = Utils.trimString(value);
+      return value;
+    },
+    _isDateInput: function _isDateInput() {
+      var c = this.constraintsByName.type;
+      return c && c.requirements === 'date';
+    },
+    // Internal only.
+    // Returns the constraints, grouped by descending priority.
+    // The result is thus an array of arrays of constraints.
+    _getGroupedConstraints: function _getGroupedConstraints() {
+      if (false === this.options.priorityEnabled) return [this.constraints];
+      var groupedConstraints = [];
+      var index = {}; // Create array unique of priorities
+
+      for (var i = 0; i < this.constraints.length; i++) {
+        var p = this.constraints[i].priority;
+        if (!index[p]) groupedConstraints.push(index[p] = []);
+        index[p].push(this.constraints[i]);
+      } // Sort them by priority DESC
+
+
+      groupedConstraints.sort(function (a, b) {
+        return b[0].priority - a[0].priority;
+      });
+      return groupedConstraints;
+    }
+  };
+
+  var Multiple = function Multiple() {
+    this.__class__ = 'FieldMultiple';
+  };
+
+  Multiple.prototype = {
+    // Add new `$element` sibling for multiple field
+    addElement: function addElement($element) {
+      this.$elements.push($element);
+      return this;
+    },
+    // See `Field._refreshConstraints()`
+    _refreshConstraints: function _refreshConstraints() {
+      var fieldConstraints;
+      this.constraints = []; // Select multiple special treatment
+
+      if (this.element.nodeName === 'SELECT') {
+        this.actualizeOptions()._bindConstraints();
+
+        return this;
+      } // Gather all constraints for each input in the multiple group
+
+
+      for (var i = 0; i < this.$elements.length; i++) {
+        // Check if element have not been dynamically removed since last binding
+        if (!$('html').has(this.$elements[i]).length) {
+          this.$elements.splice(i, 1);
+          continue;
+        }
+
+        fieldConstraints = this.$elements[i].data('FieldMultiple')._refreshConstraints().constraints;
+
+        for (var j = 0; j < fieldConstraints.length; j++) {
+          this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);
+        }
+      }
+
+      return this;
+    },
+    // See `Field.getValue()`
+    getValue: function getValue() {
+      // Value could be overriden in DOM
+      if ('function' === typeof this.options.value) return this.options.value(this);else if ('undefined' !== typeof this.options.value) return this.options.value; // Radio input case
+
+      if (this.element.nodeName === 'INPUT') {
+        var type = Utils.getType(this.element);
+        if (type === 'radio') return this._findRelated().filter(':checked').val() || ''; // checkbox input case
+
+        if (type === 'checkbox') {
+          var values = [];
+
+          this._findRelated().filter(':checked').each(function () {
+            values.push($(this).val());
+          });
+
+          return values;
+        }
+      } // Select multiple case
+
+
+      if (this.element.nodeName === 'SELECT' && null === this.$element.val()) return []; // Default case that should never happen
+
+      return this.$element.val();
+    },
+    _init: function _init() {
+      this.$elements = [this.$element];
+      return this;
+    }
+  };
+
+  var Factory = function Factory(element, options, parsleyFormInstance) {
+    this.element = element;
+    this.$element = $(element); // If the element has already been bound, returns its saved Parsley instance
+
+    var savedparsleyFormInstance = this.$element.data('Parsley');
+
+    if (savedparsleyFormInstance) {
+      // If the saved instance has been bound without a Form parent and there is one given in this call, add it
+      if ('undefined' !== typeof parsleyFormInstance && savedparsleyFormInstance.parent === window.Parsley) {
+        savedparsleyFormInstance.parent = parsleyFormInstance;
+
+        savedparsleyFormInstance._resetOptions(savedparsleyFormInstance.options);
+      }
+
+      if ('object' === _typeof(options)) {
+        _extends(savedparsleyFormInstance.options, options);
+      }
+
+      return savedparsleyFormInstance;
+    } // Parsley must be instantiated with a DOM element or jQuery $element
+
+
+    if (!this.$element.length) throw new Error('You must bind Parsley on an existing element.');
+    if ('undefined' !== typeof parsleyFormInstance && 'Form' !== parsleyFormInstance.__class__) throw new Error('Parent instance must be a Form instance');
+    this.parent = parsleyFormInstance || window.Parsley;
+    return this.init(options);
+  };
+
+  Factory.prototype = {
+    init: function init(options) {
+      this.__class__ = 'Parsley';
+      this.__version__ = '2.9.2';
+      this.__id__ = Utils.generateID(); // Pre-compute options
+
+      this._resetOptions(options); // A Form instance is obviously a `<form>` element but also every node that is not an input and has the `data-parsley-validate` attribute
+
+
+      if (this.element.nodeName === 'FORM' || Utils.checkAttr(this.element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)) return this.bind('parsleyForm'); // Every other element is bound as a `Field` or `FieldMultiple`
+
+      return this.isMultiple() ? this.handleMultiple() : this.bind('parsleyField');
+    },
+    isMultiple: function isMultiple() {
+      var type = Utils.getType(this.element);
+      return type === 'radio' || type === 'checkbox' || this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple');
+    },
+    // Multiples fields are a real nightmare :(
+    // Maybe some refactoring would be appreciated here...
+    handleMultiple: function handleMultiple() {
+      var _this = this;
+
+      var name;
+      var parsleyMultipleInstance; // Handle multiple name
+
+      this.options.multiple = this.options.multiple || (name = this.element.getAttribute('name')) || this.element.getAttribute('id'); // Special select multiple input
+
+      if (this.element.nodeName === 'SELECT' && null !== this.element.getAttribute('multiple')) {
+        this.options.multiple = this.options.multiple || this.__id__;
+        return this.bind('parsleyFieldMultiple'); // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it
+      } else if (!this.options.multiple) {
+        Utils.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);
+        return this;
+      } // Remove special chars
+
+
+      this.options.multiple = this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g, ''); // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
+
+      if (name) {
+        $('input[name="' + name + '"]').each(function (i, input) {
+          var type = Utils.getType(input);
+          if (type === 'radio' || type === 'checkbox') input.setAttribute(_this.options.namespace + 'multiple', _this.options.multiple);
+        });
+      } // Check here if we don't already have a related multiple instance saved
+
+
+      var $previouslyRelated = this._findRelated();
+
+      for (var i = 0; i < $previouslyRelated.length; i++) {
+        parsleyMultipleInstance = $($previouslyRelated.get(i)).data('Parsley');
+
+        if ('undefined' !== typeof parsleyMultipleInstance) {
+          if (!this.$element.data('FieldMultiple')) {
+            parsleyMultipleInstance.addElement(this.$element);
+          }
+
+          break;
+        }
+      } // Create a secret Field instance for every multiple field. It will be stored in `data('FieldMultiple')`
+      // And will be useful later to access classic `Field` stuff while being in a `FieldMultiple` instance
+
+
+      this.bind('parsleyField', true);
+      return parsleyMultipleInstance || this.bind('parsleyFieldMultiple');
+    },
+    // Return proper `Form`, `Field` or `FieldMultiple`
+    bind: function bind(type, doNotStore) {
+      var parsleyInstance;
+
+      switch (type) {
+        case 'parsleyForm':
+          parsleyInstance = $.extend(new Form(this.element, this.domOptions, this.options), new Base(), window.ParsleyExtend)._bindFields();
+          break;
+
+        case 'parsleyField':
+          parsleyInstance = $.extend(new Field(this.element, this.domOptions, this.options, this.parent), new Base(), window.ParsleyExtend);
+          break;
+
+        case 'parsleyFieldMultiple':
+          parsleyInstance = $.extend(new Field(this.element, this.domOptions, this.options, this.parent), new Multiple(), new Base(), window.ParsleyExtend)._init();
+          break;
+
+        default:
+          throw new Error(type + 'is not a supported Parsley type');
+      }
+
+      if (this.options.multiple) Utils.setAttr(this.element, this.options.namespace, 'multiple', this.options.multiple);
+
+      if ('undefined' !== typeof doNotStore) {
+        this.$element.data('FieldMultiple', parsleyInstance);
+        return parsleyInstance;
+      } // Store the freshly bound instance in a DOM element for later access using jQuery `data()`
+
+
+      this.$element.data('Parsley', parsleyInstance); // Tell the world we have a new Form or Field instance!
+
+      parsleyInstance._actualizeTriggers();
+
+      parsleyInstance._trigger('init');
+
+      return parsleyInstance;
+    }
+  };
+
+  var vernums = $.fn.jquery.split('.');
+
+  if (parseInt(vernums[0]) <= 1 && parseInt(vernums[1]) < 8) {
+    throw "The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.";
+  }
+
+  if (!vernums.forEach) {
+    Utils.warn('Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim');
+  } // Inherit `on`, `off` & `trigger` to Parsley:
+
+
+  var Parsley = _extends(new Base(), {
+    element: document,
+    $element: $(document),
+    actualizeOptions: null,
+    _resetOptions: null,
+    Factory: Factory,
+    version: '2.9.2'
+  }); // Supplement Field and Form with Base
+  // This way, the constructors will have access to those methods
+
+
+  _extends(Field.prototype, UI.Field, Base.prototype);
+
+  _extends(Form.prototype, UI.Form, Base.prototype); // Inherit actualizeOptions and _resetOptions:
+
+
+  _extends(Factory.prototype, Base.prototype); // ### jQuery API
+  // `$('.elem').parsley(options)` or `$('.elem').psly(options)`
+
+
+  $.fn.parsley = $.fn.psly = function (options) {
+    if (this.length > 1) {
+      var instances = [];
+      this.each(function () {
+        instances.push($(this).parsley(options));
+      });
+      return instances;
+    } // Return undefined if applied to non existing DOM element
+
+
+    if (this.length == 0) {
+      return;
+    }
+
+    return new Factory(this[0], options);
+  }; // ### Field and Form extension
+  // Ensure the extension is now defined if it wasn't previously
+
+
+  if ('undefined' === typeof window.ParsleyExtend) window.ParsleyExtend = {}; // ### Parsley config
+  // Inherit from ParsleyDefault, and copy over any existing values
+
+  Parsley.options = _extends(Utils.objectCreate(Defaults), window.ParsleyConfig);
+  window.ParsleyConfig = Parsley.options; // Old way of accessing global options
+  // ### Globals
+
+  window.Parsley = window.psly = Parsley;
+  Parsley.Utils = Utils;
+  window.ParsleyUtils = {};
+  $.each(Utils, function (key, value) {
+    if ('function' === typeof value) {
+      window.ParsleyUtils[key] = function () {
+        Utils.warnOnce('Accessing `window.ParsleyUtils` is deprecated. Use `window.Parsley.Utils` instead.');
+        return Utils[key].apply(Utils, arguments);
+      };
+    }
+  }); // ### Define methods that forward to the registry, and deprecate all access except through window.Parsley
+
+  var registry = window.Parsley._validatorRegistry = new ValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
+  window.ParsleyValidator = {};
+  $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator hasValidator'.split(' '), function (i, method) {
+    window.Parsley[method] = function () {
+      return registry[method].apply(registry, arguments);
+    };
+
+    window.ParsleyValidator[method] = function () {
+      var _window$Parsley;
+
+      Utils.warnOnce("Accessing the method '".concat(method, "' through Validator is deprecated. Simply call 'window.Parsley.").concat(method, "(...)'"));
+      return (_window$Parsley = window.Parsley)[method].apply(_window$Parsley, arguments);
+    };
+  }); // ### UI
+  // Deprecated global object
+
+  window.Parsley.UI = UI;
+  window.ParsleyUI = {
+    removeError: function removeError(instance, name, doNotUpdateClass) {
+      var updateClass = true !== doNotUpdateClass;
+      Utils.warnOnce("Accessing UI is deprecated. Call 'removeError' on the instance directly. Please comment in issue 1073 as to your need to call this method.");
+      return instance.removeError(name, {
+        updateClass: updateClass
+      });
+    },
+    getErrorsMessages: function getErrorsMessages(instance) {
+      Utils.warnOnce("Accessing UI is deprecated. Call 'getErrorsMessages' on the instance directly.");
+      return instance.getErrorsMessages();
+    }
+  };
+  $.each('addError updateError'.split(' '), function (i, method) {
+    window.ParsleyUI[method] = function (instance, name, message, assert, doNotUpdateClass) {
+      var updateClass = true !== doNotUpdateClass;
+      Utils.warnOnce("Accessing UI is deprecated. Call '".concat(method, "' on the instance directly. Please comment in issue 1073 as to your need to call this method."));
+      return instance[method](name, {
+        message: message,
+        assert: assert,
+        updateClass: updateClass
+      });
+    };
+  }); // ### PARSLEY auto-binding
+  // Prevent it by setting `ParsleyConfig.autoBind` to `false`
+
+  if (false !== window.ParsleyConfig.autoBind) {
+    $(function () {
+      // Works only on `data-parsley-validate`.
+      if ($('[data-parsley-validate]').length) $('[data-parsley-validate]').parsley();
+    });
+  }
+
+  var o = $({});
+
+  var deprecated = function deprecated() {
+    Utils.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley");
+  }; // Returns an event handler that calls `fn` with the arguments it expects
+
+
+  function adapt(fn, context) {
+    // Store to allow unbinding
+    if (!fn.parsleyAdaptedCallback) {
+      fn.parsleyAdaptedCallback = function () {
+        var args = Array.prototype.slice.call(arguments, 0);
+        args.unshift(this);
+        fn.apply(context || o, args);
+      };
+    }
+
+    return fn.parsleyAdaptedCallback;
+  }
+
+  var eventPrefix = 'parsley:'; // Converts 'parsley:form:validate' into 'form:validate'
+
+  function eventName(name) {
+    if (name.lastIndexOf(eventPrefix, 0) === 0) return name.substr(eventPrefix.length);
+    return name;
+  } // $.listen is deprecated. Use Parsley.on instead.
+
+
+  $.listen = function (name, callback) {
+    var context;
+    deprecated();
+
+    if ('object' === _typeof(arguments[1]) && 'function' === typeof arguments[2]) {
+      context = arguments[1];
+      callback = arguments[2];
+    }
+
+    if ('function' !== typeof callback) throw new Error('Wrong parameters');
+    window.Parsley.on(eventName(name), adapt(callback, context));
+  };
+
+  $.listenTo = function (instance, name, fn) {
+    deprecated();
+    if (!(instance instanceof Field) && !(instance instanceof Form)) throw new Error('Must give Parsley instance');
+    if ('string' !== typeof name || 'function' !== typeof fn) throw new Error('Wrong parameters');
+    instance.on(eventName(name), adapt(fn));
+  };
+
+  $.unsubscribe = function (name, fn) {
+    deprecated();
+    if ('string' !== typeof name || 'function' !== typeof fn) throw new Error('Wrong arguments');
+    window.Parsley.off(eventName(name), fn.parsleyAdaptedCallback);
+  };
+
+  $.unsubscribeTo = function (instance, name) {
+    deprecated();
+    if (!(instance instanceof Field) && !(instance instanceof Form)) throw new Error('Must give Parsley instance');
+    instance.off(eventName(name));
+  };
+
+  $.unsubscribeAll = function (name) {
+    deprecated();
+    window.Parsley.off(eventName(name));
+    $('form,input,textarea,select').each(function () {
+      var instance = $(this).data('Parsley');
+
+      if (instance) {
+        instance.off(eventName(name));
+      }
+    });
+  }; // $.emit is deprecated. Use jQuery events instead.
+
+
+  $.emit = function (name, instance) {
+    var _instance;
+
+    deprecated();
+    var instanceGiven = instance instanceof Field || instance instanceof Form;
+    var args = Array.prototype.slice.call(arguments, instanceGiven ? 2 : 1);
+    args.unshift(eventName(name));
+
+    if (!instanceGiven) {
+      instance = window.Parsley;
+    }
+
+    (_instance = instance).trigger.apply(_instance, _toConsumableArray(args));
+  };
+
+  $.extend(true, Parsley, {
+    asyncValidators: {
+      'default': {
+        fn: function fn(xhr) {
+          // By default, only status 2xx are deemed successful.
+          // Note: we use status instead of state() because responses with status 200
+          // but invalid messages (e.g. an empty body for content type set to JSON) will
+          // result in state() === 'rejected'.
+          return xhr.status >= 200 && xhr.status < 300;
+        },
+        url: false
+      },
+      reverse: {
+        fn: function fn(xhr) {
+          // If reverse option is set, a failing ajax request is considered successful
+          return xhr.status < 200 || xhr.status >= 300;
+        },
+        url: false
+      }
+    },
+    addAsyncValidator: function addAsyncValidator(name, fn, url, options) {
+      Parsley.asyncValidators[name] = {
+        fn: fn,
+        url: url || false,
+        options: options || {}
+      };
+      return this;
+    }
+  });
+  Parsley.addValidator('remote', {
+    requirementType: {
+      '': 'string',
+      'validator': 'string',
+      'reverse': 'boolean',
+      'options': 'object'
+    },
+    validateString: function validateString(value, url, options, instance) {
+      var data = {};
+      var ajaxOptions;
+      var csr;
+      var validator = options.validator || (true === options.reverse ? 'reverse' : 'default');
+      if ('undefined' === typeof Parsley.asyncValidators[validator]) throw new Error('Calling an undefined async validator: `' + validator + '`');
+      url = Parsley.asyncValidators[validator].url || url; // Fill current value
+
+      if (url.indexOf('{value}') > -1) {
+        url = url.replace('{value}', encodeURIComponent(value));
+      } else {
+        data[instance.element.getAttribute('name') || instance.element.getAttribute('id')] = value;
+      } // Merge options passed in from the function with the ones in the attribute
+
+
+      var remoteOptions = $.extend(true, options.options || {}, Parsley.asyncValidators[validator].options); // All `$.ajax(options)` could be overridden or extended directly from DOM in `data-parsley-remote-options`
+
+      ajaxOptions = $.extend(true, {}, {
+        url: url,
+        data: data,
+        type: 'GET'
+      }, remoteOptions); // Generate store key based on ajax options
+
+      instance.trigger('field:ajaxoptions', instance, ajaxOptions);
+      csr = $.param(ajaxOptions); // Initialise querry cache
+
+      if ('undefined' === typeof Parsley._remoteCache) Parsley._remoteCache = {}; // Try to retrieve stored xhr
+
+      var xhr = Parsley._remoteCache[csr] = Parsley._remoteCache[csr] || $.ajax(ajaxOptions);
+
+      var handleXhr = function handleXhr() {
+        var result = Parsley.asyncValidators[validator].fn.call(instance, xhr, url, options);
+        if (!result) // Map falsy results to rejected promise
+          result = $.Deferred().reject();
+        return $.when(result);
+      };
+
+      return xhr.then(handleXhr, handleXhr);
+    },
+    priority: -1
+  });
+  Parsley.on('form:submit', function () {
+    Parsley._remoteCache = {};
+  });
+
+  Base.prototype.addAsyncValidator = function () {
+    Utils.warnOnce('Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`');
+    return Parsley.addAsyncValidator.apply(Parsley, arguments);
+  };
+
+  // This is included with the Parsley library itself,
+  Parsley.addMessages('en', {
+    defaultMessage: "This value seems to be invalid.",
+    type: {
+      email: "This value should be a valid email.",
+      url: "This value should be a valid url.",
+      number: "This value should be a valid number.",
+      integer: "This value should be a valid integer.",
+      digits: "This value should be digits.",
+      alphanum: "This value should be alphanumeric."
+    },
+    notblank: "This value should not be blank.",
+    required: "This value is required.",
+    pattern: "This value seems to be invalid.",
+    min: "This value should be greater than or equal to %s.",
+    max: "This value should be lower than or equal to %s.",
+    range: "This value should be between %s and %s.",
+    minlength: "This value is too short. It should have %s characters or more.",
+    maxlength: "This value is too long. It should have %s characters or fewer.",
+    length: "This value length is invalid. It should be between %s and %s characters long.",
+    mincheck: "You must select at least %s choices.",
+    maxcheck: "You must select %s choices or fewer.",
+    check: "You must select between %s and %s choices.",
+    equalto: "This value should be the same.",
+    euvatin: "It's not a valid VAT Identification Number."
+  });
+  Parsley.setLocale('en');
+
+  function InputEvent() {
+    var _this = this;
+
+    var globals = window || global; // Slightly odd way construct our object. This way methods are force bound.
+    // Used to test for duplicate library.
+
+    _extends(this, {
+      // For browsers that do not support isTrusted, assumes event is native.
+      isNativeEvent: function isNativeEvent(evt) {
+        return evt.originalEvent && evt.originalEvent.isTrusted !== false;
+      },
+      fakeInputEvent: function fakeInputEvent(evt) {
+        if (_this.isNativeEvent(evt)) {
+          $(evt.target).trigger('input');
+        }
+      },
+      misbehaves: function misbehaves(evt) {
+        if (_this.isNativeEvent(evt)) {
+          _this.behavesOk(evt);
+
+          $(document).on('change.inputevent', evt.data.selector, _this.fakeInputEvent);
+
+          _this.fakeInputEvent(evt);
+        }
+      },
+      behavesOk: function behavesOk(evt) {
+        if (_this.isNativeEvent(evt)) {
+          $(document) // Simply unbinds the testing handler
+          .off('input.inputevent', evt.data.selector, _this.behavesOk).off('change.inputevent', evt.data.selector, _this.misbehaves);
+        }
+      },
+      // Bind the testing handlers
+      install: function install() {
+        if (globals.inputEventPatched) {
+          return;
+        }
+
+        globals.inputEventPatched = '0.0.3';
+
+        for (var _i = 0, _arr = ['select', 'input[type="checkbox"]', 'input[type="radio"]', 'input[type="file"]']; _i < _arr.length; _i++) {
+          var selector = _arr[_i];
+          $(document).on('input.inputevent', selector, {
+            selector: selector
+          }, _this.behavesOk).on('change.inputevent', selector, {
+            selector: selector
+          }, _this.misbehaves);
+        }
+      },
+      uninstall: function uninstall() {
+        delete globals.inputEventPatched;
+        $(document).off('.inputevent');
+      }
+    });
+  }
+  var inputevent = new InputEvent();
+
+  inputevent.install();
+
+  return Parsley;
+
+})));
+//# sourceMappingURL=parsley.js.map
diff --git a/utenti/templates/plain.html b/utenti/templates/plain.html
index 51d09531..831ac8ed 100644
--- a/utenti/templates/plain.html
+++ b/utenti/templates/plain.html
@@ -9,6 +9,7 @@
     <link href="{% static '/datepicker/css/datepicker.css' %}" rel="stylesheet">
     
     <link href="{% static '/smartwizard/css/smart_wizard_all.min.css' %}" rel="stylesheet">
+    <link href="{% static '/validator/parsley.css' %}" rel="stylesheet">
     
     <!--
     <link href="https://unpkg.com/smartwizard@5/dist/css/smart_wizard_all.min.css" rel="stylesheet" type="text/css" />
@@ -122,7 +123,7 @@
                                 </span>                            </a>
                         </li>
                         </ul>
-                        <form action="/utenti/save/richiesta" method="POST">
+                        <form action="/utenti/save/richiesta" method="POST" data-parsley-validate>
                         {% csrf_token %}
                         <div class="tab-content">
                        
@@ -135,7 +136,7 @@
                                                     <div class="form-group">
                                                                     <button style="z-index:100" id="pollastro" type="button" data-toggle="popover" title="Info" data-html="true" data-content="Inserire parole chiave per agevolare la tracciabilità e la ricerca della richiesta di acquisto" data-original-title="Info"><span class="fa fa-1x fa-info-circle" aria-hidden="true"></span></button>
                                                         <label>Specificare un titolo breve per questo acquisto in modo da poter essere facilmente ricercato</label>
-                                                        <input id="titolobreve" name="titolobreve" type="text" class="form-control required="required"">
+                                                        <input id="titolobreve" name="titolobreve" type="text" class="form-control" required>
                                                     </div>
                                                     <div class="form-group ">
                                                         <label>Pino Torinese, il 30-05-2020 <br> 
@@ -492,7 +493,7 @@
     
     <script src="{% static '/smartwizard/js/jquery.smartWizard.min.js' %}"></script>
     <script src="{% static '/validator/multifield.js' %}"></script>
-    <script src="{% static '/validator/validator.js' %}"></script>
+    <script src="{% static '/validator/parsley.js' %}"></script>
     <!--
     <script src="https://unpkg.com/smartwizard@5/dist/js/jquery.smartWizard.min.js" type="text/javascript"></script>
  -->
@@ -548,6 +549,7 @@
 </div> 
       </script>
 <script>
+/*
 var validator = new FormValidator();
    document.forms[0].addEventListener('blur', function(e){
     validator.checkField(e.target)
@@ -555,6 +557,7 @@ var validator = new FormValidator();
 document.forms[0].addEventListener('input', function(e){
     validator.checkField(e.target);
 }, true);
+*/
 var app3 = new Vue({
   el: '#informaticiPlus',
   data: {
@@ -763,10 +766,68 @@ $('#smartwizard').smartWizard({
   errorSteps: [], // Highlight step with errors
   hiddenSteps: [] // Hidden steps
 });
-    
+ /* PARSLEY */
+    var validateFront = function () {
+        if (true === $('form').parsley().isValid()) {
+            $('.bs-callout-info').removeClass('hidden');
+            $('.bs-callout-warning').addClass('hidden');
+        } else {
+            $('.bs-callout-info').addClass('hidden');
+            $('.bs-callout-warning').removeClass('hidden');
+        }
+    };
+function init_parsley() {
+
+    if (typeof (parsley) === 'undefined') { return; }
+    console.log('init_parsley');
+
+    $/*.listen*/('parsley:field:validate', function () {
+        validateFront();
+    });
+    $('#demo-form .btn').on('click', function () {
+        $('#demo-form').parsley().validate();
+        validateFront();
+    });
+    var validateFront = function () {
+        if (true === $('#demo-form').parsley().isValid()) {
+            $('.bs-callout-info').removeClass('hidden');
+            $('.bs-callout-warning').addClass('hidden');
+        } else {
+            $('.bs-callout-info').addClass('hidden');
+            $('.bs-callout-warning').removeClass('hidden');
+        }
+    };
+
+    $/*.listen*/('parsley:field:validate', function () {
+        validateFront();
+    });
+    $('#demo-form2 .btn').on('click', function () {
+        $('#demo-form2').parsley().validate();
+        validateFront();
+    });
+    var validateFront = function () {
+        if (true === $('form').parsley().isValid()) {
+            $('.bs-callout-info').removeClass('hidden');
+            $('.bs-callout-warning').addClass('hidden');
+        } else {
+            $('.bs-callout-info').addClass('hidden');
+            $('.bs-callout-warning').removeClass('hidden');
+        }
+    };
+
+    try {
+        hljs.initHighlightingOnLoad();
+    } catch (err) { }
+
+};
+init_parsley();
+
 // Initialize the leaveStep event
 $("#smartwizard").on("leaveStep", function(e, anchorObject, currentStepIndex, nextStepIndex, stepDirection) {
    //console.log("get", $("#smartwizard").steps("getCurrentStep") );
+    $('form').parsley().validate();
+    validateFront();
+    console.log("parsley:", $('form').parsley().isValid());
     if ($('form').valid()) {
         return true;
     } else {
@@ -849,6 +910,9 @@ $("#smartwizard").on("showStep", function(e, anchorObject, stepIndex, stepDirect
    }
    console.log(stepDirection);
 });
+
+
+
     var obiettivifun=[]
     {% for one in ob_fun %}
         j={'id':{{one.id}},'of':'{{one.obiettivofunzione}}','descr': '{{one.descrizione}}',
-- 
GitLab