text: /*!
  * Parsley.js
  * Version 2.3.7 - built Wed, Mar 23rd 2016, 2:56 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
  //
  var _slice = Array.prototype.slice;
  
  function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }
  
  (function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) : typeof define === 'function' && define.amd ? define(['jquery'], factory) : global.parsley = factory(global.jQuery);
  })(this, function ($) {
    'use strict';
  
    var globalID = 1;
    var pastWarnings = {};
  
    var ParsleyUtils__ParsleyUtils = {
      // 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 ('undefined' === typeof $element || 'undefined' === typeof $element[0]) return obj;
  
        attributes = $element[0].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.is('[' + namespace + _checkAttr + ']');
      },
  
      setAttr: function setAttr($element, namespace, attr, value) {
        $element[0].setAttribute(this.dasherize(namespace + attr), String(value));
      },
  
      generateID: function generateID() {
        return '' + globalID++;
      },
  
      /** Third party functions **/
      // Zepto deserialize function
      deserializeValue: function deserializeValue(value) {
        var num;
  
        try {
          return value ? value == "true" || (value == "false" ? false : value == "null" ? null : !isNaN(num = Number(value)) ? num : /^[\[\{]/.test(value) ? $.parseJSON(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, '');
      },
  
      namespaceEvents: function namespaceEvents(events, namespace) {
        events = this.trimString(events || '').split(/\s+/);
        if (!events[0]) return '';
        return $.map(events, function (evt) {
          return evt + '.' + namespace;
        }).join(' ');
      },
  
      // 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;
        };
      })()
    };
  
    var ParsleyUtils__default = ParsleyUtils__ParsleyUtils;
  
    // 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 ParsleyDefaults = {
      // ### 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(ParsleyField) {},
  
      // Return the `$element` where errors will be appended
      // Could also be (and given directly from DOM) a valid selector like `'#div'`
      errorsContainer: function errorsContainer(ParsleyField) {},
  
      // 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 ParsleyAbstract = function ParsleyAbstract() {};
  
    ParsleyAbstract.prototype = {
      asyncSupport: true, // Deprecated
  
      actualizeOptions: function actualizeOptions() {
        ParsleyUtils__default.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 = ParsleyUtils__default.objectCreate(this.parent.options);
        this.options = ParsleyUtils__default.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;
        var parentResult;
        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;
      },
  
      // Reset UI
      reset: function reset() {
        // Field case: just emit a reset event for UI
        if ('ParsleyForm' !== this.__class__) {
          this._resetUI();
          return this._trigger('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();
        if ('ParsleyForm' !== this.__class__) {
          this.$element.removeData('Parsley');
          this.$element.removeData('ParsleyFieldMultiple');
          this._trigger('destroy');
  
          return;
        }
  
        // 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');
      },
  
      asyncIsValid: function asyncIsValid(group, force) {
        ParsleyUtils__default.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.find('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]') : this.$element;
      }
    };
  
    var requirementConverters = {
      string: function string(_string) {
        return _string;
      },
      integer: function integer(string) {
        if (isNaN(string)) throw 'Requirement is not an integer: "' + string + '"';
        return parseInt(string, 10);
      },
      number: function number(string) {
        if (isNaN(string)) throw 'Requirement is not a number: "' + string + '"';
        return parseFloat(string);
      },
      reference: function reference(string) {
        // Unused for now
        var result = $(string);
        if (result.length === 0) throw 'No such reference: "' + string + '"';
        return result;
      },
      boolean: function boolean(string) {
        return string !== 'false';
      },
      object: function object(string) {
        return ParsleyUtils__default.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);
      }
    };
  
    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(ParsleyUtils__default.trimString);
      if (values.length !== length) throw 'Requirement has ' + values.length + ' values when ' + length + ' are needed';
      return values;
    };
  
    var convertRequirement = function convertRequirement(requirementType, string) {
      var converter = requirementConverters[requirementType || 'string'];
      if (!converter) throw 'Unknown requirement specification: "' + requirementType + '"';
      return converter(string);
    };
  
    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 = convertRequirement(requirementSpec[key], value);
          extra[key] = value;
        } else {
          main = convertRequirement(requirementSpec[key], string);
        }
      }
      return [main, extra];
    };
  
    // A Validator needs to implement the methods `validate` and `parseRequirements`
  
    var ParsleyValidator = function ParsleyValidator(spec) {
      $.extend(true, this, spec);
    };
  
    ParsleyValidator.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.call(this, value, requirementFirstArg);
        }
  
        if ($.isArray(value)) {
          if (!this.validateMultiple) throw 'Validator `' + this.name + '` does not handle multiple values';
          return this.validateMultiple.apply(this, arguments);
        } else {
          if (this.validateNumber) {
            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 $.isArray(requirements) ? requirements : [requirements];
        }
        var type = this.requirementType;
        if ($.isArray(type)) {
          var values = convertArrayRequirement(requirements, type.length);
          for (var i = 0; i < values.length; i++) values[i] = convertRequirement(type[i], values[i]);
          return values;
        } else if ($.isPlainObject(type)) {
          return convertExtraOptionRequirement(type, requirements, extraOptionReader);
        } else {
          return [convertRequirement(type, requirements)];
        }
      },
      // Defaults:
      requirementType: 'string',
  
      priority: 2
  
    };
  
    var ParsleyValidatorRegistry = function ParsleyValidatorRegistry(validators, catalog) {
      this.__class__ = 'ParsleyValidatorRegistry';
  
      // Default Parsley locale is en
      this.locale = 'en';
  
      this.init(validators || {}, catalog || {});
    };
  
    var typeRegexes = {
      email: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,
  
      // 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,
  
      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-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)' +
      // domain name
      '(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*' +
      // TLD identifier
      '(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))' + ")" +
      // port number
      "(?::\\d{2,5})?" +
      // resource path
      "(?:/\\S*)?" + "$", 'i')
    };
    typeRegexes.range = typeRegexes.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));
    };
  
    ParsleyValidatorRegistry.prototype = {
      init: function init(validators, catalog) {
        this.catalog = catalog;
        // Copy prototype's validators:
        this.validators = $.extend({}, 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]) ParsleyUtils__default.warn('Validator "' + name + '" is already defined.');else if (ParsleyDefaults.hasOwnProperty(name)) {
          ParsleyUtils__default.warn('"' + name + '" is a restricted keyword and is not a valid validator name.');
          return;
        }
        return this._setValidator.apply(this, arguments);
      },
  
      updateValidator: function updateValidator(name, arg1, arg2) {
        if (!this.validators[name]) {
          ParsleyUtils__default.warn('Validator "' + name + '" is not already defined.');
          return this.addValidator.apply(this, arguments);
        }
        return this._setValidator(this, arguments);
      },
  
      removeValidator: function removeValidator(name) {
        if (!this.validators[name]) ParsleyUtils__default.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 ParsleyValidator(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];
  
            var _ref$step = _ref.step;
            var step = _ref$step === undefined ? '1' : _ref$step;
            var _ref$base = _ref.base;
            var base = _ref$base === undefined ? 0 : _ref$base;
  
            var regex = typeRegexes[type];
            if (!regex) {
              throw new Error('validator type `' + type + '` is not supported');
            }
            if (!regex.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) {
            return regexp.test(value);
          },
          requirementType: 'regexp',
          priority: 64
        },
        minlength: {
          validateString: function validateString(value, requirement) {
            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) {
            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: {
          validateNumber: function validateNumber(value, requirement) {
            return value >= requirement;
          },
          requirementType: 'number',
          priority: 30
        },
        max: {
          validateNumber: function validateNumber(value, requirement) {
            return value <= requirement;
          },
          requirementType: 'number',
          priority: 30
        },
        range: {
          validateNumber: function validateNumber(value, min, max) {
            return value >= min && value <= max;
          },
          requirementType: ['number', 'number'],
          priority: 30
        },
        equalto: {
          validateString: function validateString(value, refOrValue) {
            var $reference = $(refOrValue);
            if ($reference.length) return value === $reference.val();else return value === refOrValue;
          },
          priority: 256
        }
      }
    };
  
    var ParsleyUI = {};
  
    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 : []
      };
    };
  
    ParsleyUI.Form = {
  
      _actualizeTriggers: function _actualizeTriggers() {
        var _this = this;
  
        this.$element.on('submit.Parsley', function (evt) {
          _this.onSubmitValidate(evt);
        });
        this.$element.on('click.Parsley', 'input[type="submit"], button[type="submit"]', function (evt) {
          _this.onSubmitButton(evt);
        });
  
        // UI could be disabled
        if (false === this.options.uiEnabled) return;
  
        this.$element.attr('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');
      }
  
    };
  
    ParsleyUI.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 _ref2 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  
        var message = _ref2.message;
        var assert = _ref2.assert;
        var _ref2$updateClass = _ref2.updateClass;
        var updateClass = _ref2$updateClass === undefined ? true : _ref2$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 _ref3 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  
        var message = _ref3.message;
        var assert = _ref3.assert;
        var _ref3$updateClass = _ref3.updateClass;
        var updateClass = _ref3$updateClass === undefined ? true : _ref3$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 _ref4 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  
        var _ref4$updateClass = _ref4.updateClass;
        var updateClass = _ref4$updateClass === undefined ? true : _ref4$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'));
  
            return this._ui.$errorsWrapper.addClass('filled').find('.parsley-custom-error-message').html(this.options.errorMessage);
          }
  
          return this._ui.$errorsWrapper.removeClass('filled').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, _ref5) {
        var message = _ref5.message;
        var assert = _ref5.assert;
  
        this._insertErrorWrapper();
        this._ui.$errorsWrapper.addClass('filled').append($(this.options.errorTemplate).addClass('parsley-' + name).html(message || this._getErrorMessage(assert)));
      },
  
      _updateError: function _updateError(name, _ref6) {
        var message = _ref6.message;
        var assert = _ref6.assert;
  
        this._ui.$errorsWrapper.addClass('filled').find('.parsley-' + name).html(message || this._getErrorMessage(assert));
      },
  
      _removeError: function _removeError(name) {
        this._ui.$errorsWrapper.removeClass('filled').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.attr(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() {
        // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
        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 $handler = this.options.classHandler.call(this, this);
  
        // If this function returned a valid existing DOM element, go for it
        if ('undefined' !== typeof $handler && $handler.length) return $handler;
  
        // Otherwise, if simple element (input, texatrea, select...) it will perfectly host the classes
        if (!this.options.multiple || this.$element.is('select')) return this.$element;
  
        // But if multiple element (radio, checkbox), that would be their parent
        return this.$element.parent();
      },
  
      _insertErrorWrapper: function _insertErrorWrapper() {
        var $errorsContainer;
  
        // Nothing to do if already inserted
        if (0 !== this._ui.$errorsWrapper.parent().length) return this._ui.$errorsWrapper.parent();
  
        if ('string' === typeof this.options.errorsContainer) {
          if ($(this.options.errorsContainer).length) return $(this.options.errorsContainer).append(this._ui.$errorsWrapper);else ParsleyUtils__default.warn('The errors container `' + this.options.errorsContainer + '` does not exist in DOM');
        } else if ('function' === typeof this.options.errorsContainer) $errorsContainer = this.options.errorsContainer.call(this, this);
  
        if ('undefined' !== typeof $errorsContainer && $errorsContainer.length) return $errorsContainer.append(this._ui.$errorsWrapper);
  
        var $from = this.$element;
        if (this.options.multiple) $from = $from.parent();
        return $from.after(this._ui.$errorsWrapper);
      },
  
      _actualizeTriggers: function _actualizeTriggers() {
        var _this2 = this;
  
        var $toBind = this._findRelated();
  
        // Remove Parsley events already bound on this field
        $toBind.off('.Parsley');
        if (this._failedOnce) $toBind.on(ParsleyUtils__default.namespaceEvents(this.options.triggerAfterFailure, 'Parsley'), function () {
          _this2.validate();
        });else {
          $toBind.on(ParsleyUtils__default.namespaceEvents(this.options.trigger, 'Parsley'), function (event) {
            _this2._eventValidate(event);
          });
        }
      },
  
      _eventValidate: function _eventValidate(event) {
        // 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 (/key|input/.test(event.type)) if (!(this._ui && this._ui.validationInformationVisible) && this.getValue().length <= this.options.validationThreshold) return;
  
        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 ParsleyForm = function ParsleyForm(element, domOptions, options) {
      this.__class__ = 'ParsleyForm';
      this.__id__ = ParsleyUtils__default.generateID();
  
      this.$element = $(element);
      this.domOptions = domOptions;
      this.options = options;
      this.parent = window.Parsley;
  
      this.fields = [];
      this.validationResult = null;
    };
  
    var ParsleyForm__statusMapping = { pending: null, resolved: true, rejected: false };
  
    ParsleyForm.prototype = {
      onSubmitValidate: function onSubmitValidate(event) {
        var _this3 = 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('input[type="submit"], button[type="submit"]').first();
        this._$submitSource = null;
        this.$element.find('.parsley-synthetic-submit-button').prop('disabled', true);
        if ($submitSource.is('[formnovalidate]')) return;
  
        var promise = this.whenValidate({ event: event });
  
        if ('resolved' === promise.state() && false !== this._trigger('submit')) {
          // All good, let event go through. We make this distinction because browsers
          // differ in their handling of `submit` being called from inside a submit event [#1047]
        } else {
            // Rejected or pending: cancel this submit
            event.stopImmediatePropagation();
            event.preventDefault();
            if ('pending' === promise.state()) promise.done(function () {
              _this3._submit($submitSource);
            });
          }
      },
  
      onSubmitButton: function onSubmitButton(event) {
        this._$submitSource = $(event.target);
      },
      // 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.attr('name'),
            value: $submitSource.attr('value')
          });
        }
  
        this.$element.trigger($.extend($.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)) {
          ParsleyUtils__default.warnOnce('Calling validate on a parsley form without passing arguments as an object is deprecated.');
  
          var _arguments = _slice.call(arguments);
  
          var group = _arguments[0];
          var force = _arguments[1];
          var event = _arguments[2];
  
          options = { group: group, force: force, event: event };
        }
        return ParsleyForm__statusMapping[this.whenValidate(options).state()];
      },
  
      whenValidate: function whenValidate() {
        var _this4 = this;
  
        var _ref7 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  
        var group = _ref7.group;
        var force = _ref7.force;
        var event = _ref7.event;
  
        this.submitEvent = event;
        if (event) {
          this.submitEvent = $.extend({}, event, { preventDefault: function preventDefault() {
              ParsleyUtils__default.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`");
              _this4.validationResult = false;
            } });
        }
        this.validationResult = true;
  
        // fire validate event to eventually modify things before very 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(_this4.fields, function (field) {
            return field.whenValidate({ force: force, group: group });
          });
        });
  
        var promiseBasedOnValidationResult = function promiseBasedOnValidationResult() {
          var r = $.Deferred();
          if (false === _this4.validationResult) r.reject();
          return r.resolve().promise();
        };
  
        return $.when.apply($, _toConsumableArray(promises)).done(function () {
          _this4._trigger('success');
        }).fail(function () {
          _this4.validationResult = false;
          _this4.focus();
          _this4._trigger('error');
        }).always(function () {
          _this4._trigger('validated');
        }).pipe(promiseBasedOnValidationResult, promiseBasedOnValidationResult);
      },
  
      // 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)) {
          ParsleyUtils__default.warnOnce('Calling isValid on a parsley form without passing arguments as an object is deprecated.');
  
          var _arguments2 = _slice.call(arguments);
  
          var group = _arguments2[0];
          var force = _arguments2[1];
  
          options = { group: group, force: force };
        }
        return ParsleyForm__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 _this5 = this;
  
        var _ref8 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  
        var group = _ref8.group;
        var force = _ref8.force;
  
        this._refreshFields();
  
        var promises = this._withoutReactualizingFormOptions(function () {
          return $.map(_this5.fields, function (field) {
            return field.whenValid({ group: group, force: force });
          });
        });
        return $.when.apply($, _toConsumableArray(promises));
      },
  
      _refreshFields: function _refreshFields() {
        return this.actualizeOptions()._bindFields();
      },
  
      _bindFields: function _bindFields() {
        var _this6 = this;
  
        var oldFields = this.fields;
  
        this.fields = [];
        this.fieldsMappedById = {};
  
        this._withoutReactualizingFormOptions(function () {
          _this6.$element.find(_this6.options.inputs).not(_this6.options.excluded).each(function (_, element) {
            var fieldInstance = new window.Parsley.Factory(element, {}, _this6);
  
            // Only add valid and not excluded `ParsleyField` and `ParsleyFieldMultiple` children
            if (('ParsleyField' === fieldInstance.__class__ || 'ParsleyFieldMultiple' === fieldInstance.__class__) && true !== fieldInstance.options.excluded) if ('undefined' === typeof _this6.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__]) {
              _this6.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__] = fieldInstance;
              _this6.fields.push(fieldInstance);
            }
          });
  
          $(oldFields).not(_this6.fields).each(function (_, field) {
            field._trigger('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 ConstraintFactory = function ConstraintFactory(parsleyField, name, requirements, priority, isDomConstraint) {
      if (!/ParsleyField/.test(parsleyField.__class__)) throw new Error('ParsleyField or ParsleyFieldMultiple instance expected');
  
      var validatorSpec = window.Parsley._validatorRegistry.validators[name];
      var validator = new ParsleyValidator(validatorSpec);
  
      $.extend(this, {
        validator: validator,
        name: name,
        requirements: requirements,
        priority: priority || parsleyField.options[name + 'Priority'] || validator.priority,
        isDomConstraint: true === isDomConstraint
      });
      this._parseRequirements(parsleyField.options);
    };
  
    var capitalize = function capitalize(str) {
      var cap = str[0].toUpperCase();
      return cap + str.slice(1);
    };
  
    ConstraintFactory.prototype = {
      validate: function validate(value, instance) {
        var args = this.requirementList.slice(0); // Make copy
        args.unshift(value);
        args.push(instance);
        return this.validator.validate.apply(this.validator, args);
      },
  
      _parseRequirements: function _parseRequirements(options) {
        var _this7 = this;
  
        this.requirementList = this.validator.parseRequirements(this.requirements, function (key) {
          return options[_this7.name + capitalize(key)];
        });
      }
    };
  
    var ParsleyField = function ParsleyField(field, domOptions, options, parsleyFormInstance) {
      this.__class__ = 'ParsleyField';
      this.__id__ = ParsleyUtils__default.generateID();
  
      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 = [];
  
      // Bind constraints
      this._bindConstraints();
    };
  
    var parsley_field__statusMapping = { pending: null, resolved: true, rejected: false };
  
    ParsleyField.prototype = {
      // # Public API
      // Validate field and trigger some events for mainly `ParsleyUI`
      // @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)) {
          ParsleyUtils__default.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 `ParsleyUI`
      // @returns a promise that succeeds only when all validations do
      // or `undefined` if field is not in the given `group`.
      whenValidate: function whenValidate() {
        var _this8 = this;
  
        var _ref9 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  
        var force = _ref9.force;
        var group = _ref9.group;
  
        // do not validate a field if not the same as given validation group
        this.refreshConstraints();
        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({ force: force, value: this.value, _refreshed: true }).always(function () {
          _this8._reflowUI();
        }).done(function () {
          _this8._trigger('success');
        }).fail(function () {
          _this8._trigger('error');
        }).always(function () {
          _this8._trigger('validated');
        });
      },
  
      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 ($.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)) {
          ParsleyUtils__default.warnOnce('Calling isValid on a parsley field without passing arguments as an object is deprecated.');
  
          var _arguments3 = _slice.call(arguments);
  
          var force = _arguments3[0];
          var value = _arguments3[1];
  
          options = { force: force, value: value };
        }
        var promise = this.whenValid(options);
        if (!promise) // Excluded via `group`
          return true;
        return parsley_field__statusMapping[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 _this9 = this;
  
        var _ref10 = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
  
        var _ref10$force = _ref10.force;
        var force = _ref10$force === undefined ? false : _ref10$force;
        var value = _ref10.value;
        var group = _ref10.group;
        var _refreshed = _ref10._refreshed;
  
        // Recompute options and rebind constraints to have latest changes
        if (!_refreshed) this.refreshConstraints();
        // 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 = $.when.apply($, _toConsumableArray($.map(constraints, function (constraint) {
            return _this9._validateConstraint(value, constraint);
          })));
          promises.push(promise);
          if (promise.state() === 'rejected') return false; // Interrupt processing if a group has already failed
        });
        return $.when.apply($, promises);
      },
  
      // @returns a promise
      _validateConstraint: function _validateConstraint(value, constraint) {
        var _this10 = 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 $.when(result).fail(function (errorMessage) {
          if (true === _this10.validationResult) _this10.validationResult = [];
          _this10.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);
      },
  
      // Actualize options that could have change since previous validation
      // Re-bind accordingly constraints (could be some new, removed or updated)
      refreshConstraints: function refreshConstraints() {
        return this.actualizeOptions()._bindConstraints();
      },
  
      /**
      * 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 ConstraintFactory(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 (this.$element.hasClass('required') || this.$element.attr('required')) this.addConstraint('required', true, undefined, true);
  
        // html5 pattern
        if ('string' === typeof this.$element.attr('pattern')) this.addConstraint('pattern', this.$element.attr('pattern'), undefined, true);
  
        // range
        if ('undefined' !== typeof this.$element.attr('min') && 'undefined' !== typeof this.$element.attr('max')) this.addConstraint('range', [this.$element.attr('min'), this.$element.attr('max')], undefined, true);
  
        // HTML5 min
        else if ('undefined' !== typeof this.$element.attr('min')) this.addConstraint('min', this.$element.attr('min'), undefined, true);
  
          // HTML5 max
          else if ('undefined' !== typeof this.$element.attr('max')) this.addConstraint('max', this.$element.attr('max'), undefined, true);
  
        // length
        if ('undefined' !== typeof this.$element.attr('minlength') && 'undefined' !== typeof this.$element.attr('maxlength')) this.addConstraint('length', [this.$element.attr('minlength'), this.$element.attr('maxlength')], undefined, true);
  
        // HTML5 minlength
        else if ('undefined' !== typeof this.$element.attr('minlength')) this.addConstraint('minlength', this.$element.attr('minlength'), undefined, true);
  
          // HTML5 maxlength
          else if ('undefined' !== typeof this.$element.attr('maxlength')) this.addConstraint('maxlength', this.$element.attr('maxlength'), undefined, true);
  
        // html5 types
        var type = this.$element.attr('type');
  
        if ('undefined' === typeof type) return this;
  
        // 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.attr('step'),
            base: this.$element.attr('min') || this.$element.attr('value')
          }], undefined, true);
          // Regular other HTML5 supported types
        } else if (/^(email|url|range)$/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) ParsleyUtils__default.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 = ParsleyUtils__default.trimString(value);
  
        return value;
      },
  
      // 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 parsley_field = ParsleyField;
  
    var ParsleyMultiple = function ParsleyMultiple() {
      this.__class__ = 'ParsleyFieldMultiple';
    };
  
    ParsleyMultiple.prototype = {
      // Add new `$element` sibling for multiple field
      addElement: function addElement($element) {
        this.$elements.push($element);
  
        return this;
      },
  
      // See `ParsleyField.refreshConstraints()`
      refreshConstraints: function refreshConstraints() {
        var fieldConstraints;
  
        this.constraints = [];
  
        // Select multiple special treatment
        if (this.$element.is('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('ParsleyFieldMultiple').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 `ParsleyField.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.is('input[type=radio]')) return this._findRelated().filter(':checked').val() || '';
  
        // checkbox input case
        if (this.$element.is('input[type=checkbox]')) {
          var values = [];
  
          this._findRelated().filter(':checked').each(function () {
            values.push($(this).val());
          });
  
          return values;
        }
  
        // Select multiple case
        if (this.$element.is('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 ParsleyFactory = function ParsleyFactory(element, options, parsleyFormInstance) {
      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 ParsleyForm 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);
        }
  
        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 && 'ParsleyForm' !== parsleyFormInstance.__class__) throw new Error('Parent instance must be a ParsleyForm instance');
  
      this.parent = parsleyFormInstance || window.Parsley;
      return this.init(options);
    };
  
    ParsleyFactory.prototype = {
      init: function init(options) {
        this.__class__ = 'Parsley';
        this.__version__ = '2.3.7';
        this.__id__ = ParsleyUtils__default.generateID();
  
        // Pre-compute options
        this._resetOptions(options);
  
        // A ParsleyForm 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.is('form') || ParsleyUtils__default.checkAttr(this.$element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)) return this.bind('parsleyForm');
  
        // Every other element is bound as a `ParsleyField` or `ParsleyFieldMultiple`
        return this.isMultiple() ? this.handleMultiple() : this.bind('parsleyField');
      },
  
      isMultiple: function isMultiple() {
        return this.$element.is('input[type=radio], input[type=checkbox]') || this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple');
      },
  
      // Multiples fields are a real nightmare :(
      // Maybe some refactoring would be appreciated here...
      handleMultiple: function handleMultiple() {
        var _this11 = this;
  
        var name;
        var multiple;
        var parsleyMultipleInstance;
  
        // Handle multiple name
        if (this.options.multiple) ; // We already have our 'multiple' identifier
        else if ('undefined' !== typeof this.$element.attr('name') && this.$element.attr('name').length) this.options.multiple = name = this.$element.attr('name');else if ('undefined' !== typeof this.$element.attr('id') && this.$element.attr('id').length) this.options.multiple = this.$element.attr('id');
  
        // Special select multiple input
        if (this.$element.is('select') && 'undefined' !== typeof this.$element.attr('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) {
            ParsleyUtils__default.warn('To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.', this.$element);
            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 ('undefined' !== typeof name) {
          $('input[name="' + name + '"]').each(function (i, input) {
            if ($(input).is('input[type=radio], input[type=checkbox]')) $(input).attr(_this11.options.namespace + 'multiple', _this11.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('ParsleyFieldMultiple')) {
              parsleyMultipleInstance.addElement(this.$element);
            }
  
            break;
          }
        }
  
        // Create a secret ParsleyField instance for every multiple field. It will be stored in `data('ParsleyFieldMultiple')`
        // And will be useful later to access classic `ParsleyField` stuff while being in a `ParsleyFieldMultiple` instance
        this.bind('parsleyField', true);
  
        return parsleyMultipleInstance || this.bind('parsleyFieldMultiple');
      },
  
      // Return proper `ParsleyForm`, `ParsleyField` or `ParsleyFieldMultiple`
      bind: function bind(type, doNotStore) {
        var parsleyInstance;
  
        switch (type) {
          case 'parsleyForm':
            parsleyInstance = $.extend(new ParsleyForm(this.$element, this.domOptions, this.options), window.ParsleyExtend)._bindFields();
            break;
          case 'parsleyField':
            parsleyInstance = $.extend(new parsley_field(this.$element, this.domOptions, this.options, this.parent), window.ParsleyExtend);
            break;
          case 'parsleyFieldMultiple':
            parsleyInstance = $.extend(new parsley_field(this.$element, this.domOptions, this.options, this.parent), new ParsleyMultiple(), window.ParsleyExtend)._init();
            break;
          default:
            throw new Error(type + 'is not a supported Parsley type');
        }
  
        if (this.options.multiple) ParsleyUtils__default.setAttr(this.$element, this.options.namespace, 'multiple', this.options.multiple);
  
        if ('undefined' !== typeof doNotStore) {
          this.$element.data('ParsleyFieldMultiple', 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 ParsleyForm or ParsleyField 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) {
      ParsleyUtils__default.warn('Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim');
    }
    // Inherit `on`, `off` & `trigger` to Parsley:
    var Parsley = $.extend(new ParsleyAbstract(), {
      $element: $(document),
      actualizeOptions: null,
      _resetOptions: null,
      Factory: ParsleyFactory,
      version: '2.3.7'
    });
  
    // Supplement ParsleyField and Form with ParsleyAbstract
    // This way, the constructors will have access to those methods
    $.extend(parsley_field.prototype, ParsleyUI.Field, ParsleyAbstract.prototype);
    $.extend(ParsleyForm.prototype, ParsleyUI.Form, ParsleyAbstract.prototype);
    // Inherit actualizeOptions and _resetOptions:
    $.extend(ParsleyFactory.prototype, ParsleyAbstract.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) {
        ParsleyUtils__default.warn('You must bind Parsley on an existing element.');
  
        return;
      }
  
      return new ParsleyFactory(this, options);
    };
  
    // ### ParsleyField and ParsleyForm 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 = $.extend(ParsleyUtils__default.objectCreate(ParsleyDefaults), window.ParsleyConfig);
    window.ParsleyConfig = Parsley.options; // Old way of accessing global options
  
    // ### Globals
    window.Parsley = window.psly = Parsley;
    window.ParsleyUtils = ParsleyUtils__default;
  
    // ### Define methods that forward to the registry, and deprecate all access except through window.Parsley
    var registry = window.Parsley._validatorRegistry = new ParsleyValidatorRegistry(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
    window.ParsleyValidator = {};
    $.each('setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator'.split(' '), function (i, method) {
      window.Parsley[method] = $.proxy(registry, method);
      window.ParsleyValidator[method] = function () {
        var _window$Parsley;
  
        ParsleyUtils__default.warnOnce('Accessing the method \'' + method + '\' through ParsleyValidator is deprecated. Simply call \'window.Parsley.' + method + '(...)\'');
        return (_window$Parsley = window.Parsley)[method].apply(_window$Parsley, arguments);
      };
    });
  
    // ### ParsleyUI
    // Deprecated global object
    window.Parsley.UI = ParsleyUI;
    window.ParsleyUI = {
      removeError: function removeError(instance, name, doNotUpdateClass) {
        var updateClass = true !== doNotUpdateClass;
        ParsleyUtils__default.warnOnce('Accessing ParsleyUI is deprecated. Call \'removeError\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
        return instance.removeError(name, { updateClass: updateClass });
      },
      getErrorsMessages: function getErrorsMessages(instance) {
        ParsleyUtils__default.warnOnce('Accessing ParsleyUI 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;
        ParsleyUtils__default.warnOnce('Accessing ParsleyUI is deprecated. Call \'' + method + '\' on the instance directly. Please comment in issue 1073 as to your need to call this method.');
        return instance[method](name, { message: message, assert: assert, updateClass: updateClass });
      };
    });
  
    // Alleviate glaring Firefox & IR bugs:
    //  FF: https://bugzilla.mozilla.org/show_bug.cgi?id=1250521
    //  IE: https://connect.microsoft.com/IE/feedback/details/1816207
    // See also https://github.com/guillaumepotier/Parsley.js/issues/1068
    if (/firefox|msie/i.test(navigator.userAgent)) {
      $(document).on('change', 'select', function (evt) {
        $(evt.target).trigger('input');
      });
    }
  
    // ### 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() {
      ParsleyUtils__default.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 parsley_field) && !(instance instanceof ParsleyForm)) 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 parsley_field) && !(instance instanceof ParsleyForm)) 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 parsley_field || instance instanceof ParsleyForm;
      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));
    };
  
    var pubsub = {};
  
    $.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.attr('name') || instance.$element.attr('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 = {};
    });
  
    window.ParsleyExtend.addAsyncValidator = function () {
      ParsleyUtils.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,
    // thus there is no use in adding it to your project.
    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 field 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."
    });
  
    Parsley.setLocale('en');
  
    var parsley = Parsley;
  
    return parsley;
  });
  //# sourceMappingURL=parsley.js.map