/*!

*/

// The source code below is generated by babel as // Parsley is written in ECMAScript 6 // var _slice = Array.prototype.slice;

var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr(), _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) _i(); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target = source; } } } return target; };

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2 = arr; 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 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));
  },

  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, '');
  },

  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);
      });

      var _parsed$map2 = _slicedToArray(_parsed$map, 4);

      var _ = _parsed$map2[0];
      var year = _parsed$map2[1];
      var month = _parsed$map2[2];
      var 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 ' + requirementType + ': "' + string + '"';
    return converted;
  },

  namespaceEvents: function namespaceEvents(events, namespace) {
    events = this.trimString(events || '').split(/\s+/);
    if (!events[0]) return '';
    return $.map(events, function (evt) {
      return evt + '.' + 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;
    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;
  },

  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('[' + this.options.namespace + 'multiple="' + 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 (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-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,

  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-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')
};
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 ValidatorRegistry__parseArguments = function ValidatorRegistry__parseArguments(type, args) {
  return args.map(Utils.parse[type]);
};
// operatorToValidator returns a validating function for an operator function, applied to the given type
var ValidatorRegistry__operatorToValidator = function ValidatorRegistry__operatorToValidator(type, operator) {
  return function (value) {
    for (var _len = arguments.length, requirementsAndInput = 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(undefined, [value].concat(_toConsumableArray(ValidatorRegistry__parseArguments(type, requirementsAndInput))));
  };
};

var ValidatorRegistry__comparisonOperator = function ValidatorRegistry__comparisonOperator(operator) {
  return {
    validateDate: ValidatorRegistry__operatorToValidator('date', operator),
    validateNumber: ValidatorRegistry__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);
  },

  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];

        var _ref$step = _ref.step;
        var step = _ref$step === undefined ? 'any' : _ref$step;
        var _ref$base = _ref.base;
        var base = _ref$base === undefined ? 0 : _ref$base;

        var tester = typeTesters[type];
        if (!tester) {
          throw new Error('validator type `' + type + '` is not supported');
        }
        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) {
        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: ValidatorRegistry__comparisonOperator(function (value, requirement) {
      return value >= requirement;
    }),
    max: ValidatorRegistry__comparisonOperator(function (value, requirement) {
      return value <= requirement;
    }),
    range: ValidatorRegistry__comparisonOperator(function (value, min, max) {
      return value >= min && value <= max;
    }),
    equalto: {
      validateString: function validateString(value, refOrValue) {
        var $reference = $(refOrValue);
        if ($reference.length) return value === $reference.val();else return value === refOrValue;
      },
      priority: 256
    }
  }
};

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 _this2 = this;

    this.$element.on('submit.Parsley', function (evt) {
      _this2.onSubmitValidate(evt);
    });
    this.$element.on('click.Parsley', Utils._SubmitSelector, function (evt) {
      _this2.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 _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.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() {
    // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
    if ('string' === typeof this.options.classHandler) {
      if ($(this.options.classHandler).length === 0) ParsleyUtils.warn('No elements found that match the selector `' + this.options.classHandler + '` set in options.classHandler or data-parsley-class-handler');

      //return element or empty set
      return $(this.options.classHandler);
    }

    // Class handled could also be determined by function given in Parsley options
    if ('function' === typeof this.options.classHandler) 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;

    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;

    // 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 Utils.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);

    return this._inputHolder().after(this._ui.$errorsWrapper);
  },

  _actualizeTriggers: function _actualizeTriggers() {
    var _this3 = 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 () {
      _this3._validateIfNeeded();
    });else if (trigger = Utils.namespaceEvents(this.options.trigger, 'Parsley')) {
      $toBind.on(trigger, function (event) {
        _this3._validateIfNeeded(event);
      });
    }
  },

  _validateIfNeeded: function _validateIfNeeded(event) {
    var _this4 = 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 _this4.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 Form__statusMapping = { pending: null, resolved: true, rejected: false };

Form.prototype = {
  onSubmitValidate: function onSubmitValidate(event) {
    var _this5 = 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')) {
      // 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 () {
          _this5._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 = _slice.call(arguments);

      var group = _arguments[0];
      var force = _arguments[1];
      var event = _arguments[2];

      options = { group: group, force: force, event: event };
    }
    return Form__statusMapping[this.whenValidate(options).state()];
  },

  whenValidate: function whenValidate() {
    var _Utils$all$done$fail$always,
        _this6 = 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 = _extends({}, event, { preventDefault: function preventDefault() {
          Utils.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`");
          _this6.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(_this6.fields, function (field) {
        return field.whenValidate({ force: force, group: group });
      });
    });

    return (_Utils$all$done$fail$always = Utils.all(promises).done(function () {
      _this6._trigger('success');
    }).fail(function () {
      _this6.validationResult = false;
      _this6.focus();
      _this6._trigger('error');
    }).always(function () {
      _this6._trigger('validated');
    })).pipe.apply(_Utils$all$done$fail$always, _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 = _slice.call(arguments);

      var group = _arguments2[0];
      var force = _arguments2[1];

      options = { group: group, force: force };
    }
    return Form__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 _this7 = 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(_this7.fields, function (field) {
        return field.whenValid({ group: group, force: force });
      });
    });
    return Utils.all(promises);
  },

  // 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 _this8 = this;

    var oldFields = this.fields;

    this.fields = [];
    this.fieldsMappedById = {};

    this._withoutReactualizingFormOptions(function () {
      _this8.$element.find(_this8.options.inputs).not(_this8.options.excluded).each(function (_, element) {
        var fieldInstance = new window.Parsley.Factory(element, {}, _this8);

        // Only add valid and not excluded `Field` and `FieldMultiple` children
        if (('Field' === fieldInstance.__class__ || 'FieldMultiple' === fieldInstance.__class__) && true !== fieldInstance.options.excluded) {
          var uniqueId = fieldInstance.__class__ + '-' + fieldInstance.__id__;
          if ('undefined' === typeof _this8.fieldsMappedById[uniqueId]) {
            _this8.fieldsMappedById[uniqueId] = fieldInstance;
            _this8.fields.push(fieldInstance);
          }
        }
      });

      $.each(Utils.difference(oldFields, _this8.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 _validator;

    return (_validator = this.validator).validate.apply(_validator, [value].concat(_toConsumableArray(this.requirementList), [instance]));
  },

  _parseRequirements: function _parseRequirements(options) {
    var _this9 = this;

    this.requirementList = this.validator.parseRequirements(this.requirements, function (key) {
      return options[_this9.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 parsley_field__statusMapping = { 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 _whenValid$always$done$fail$always,
        _this10 = 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 (_whenValid$always$done$fail$always = this.whenValid({ force: force, value: this.value, _refreshed: true }).always(function () {
      _this10._reflowUI();
    }).done(function () {
      _this10._trigger('success');
    }).fail(function () {
      _this10._trigger('error');
    }).always(function () {
      _this10._trigger('validated');
    })).pipe.apply(_whenValid$always$done$fail$always, _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 _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 _this11 = 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 = Utils.all($.map(constraints, function (constraint) {
        return _this11._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 _this12 = 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 (!(_this12.validationResult instanceof Array)) _this12.validationResult = [];
      _this12.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 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 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 = this.element.type;

    // 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 parsley_field = Field;

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') {
      if (this.element.type === 'radio') return this._findRelated().filter(':checked').val() || '';

      // checkbox input case
      if (this.element.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.7.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() {
    return this.element.type === 'radio' || this.element.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 _this13 = this;

    var name;
    var multiple;
    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) {
        if (input.type === 'radio' || input.type === 'checkbox') input.setAttribute(_this13.options.namespace + 'multiple', _this13.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 parsley_field(this.element, this.domOptions, this.options, this.parent), new Base(), window.ParsleyExtend);
        break;
      case 'parsleyFieldMultiple':
        parsleyInstance = $.extend(new parsley_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.7.2'
});

// Supplement Field and Form with Base
// This way, the constructors will have access to those methods
_extends(parsley_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) {
    Utils.warn('You must bind Parsley on an existing element.');

    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'.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 \'' + method + '\' through Validator is deprecated. Simply call \'window.Parsley.' + 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 \'' + 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 parsley_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 parsley_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 parsley_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));
};

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.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,
// 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 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."
});

Parsley.setLocale('en');

/**
 * inputevent - Alleviate browser bugs for input events
 * https://github.com/marcandre/inputevent
 * @version v0.0.3 - (built Thu, Apr 14th 2016, 5:58 pm)
 * @author Marc-Andre Lafortune <github@marc-andre.ca>
 * @license MIT
 */

function InputEvent() {
  var _this14 = 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 (_this14.isNativeEvent(evt)) {
        $(evt.target).trigger('input');
      }
    },

    misbehaves: function misbehaves(evt) {
      if (_this14.isNativeEvent(evt)) {
        _this14.behavesOk(evt);
        $(document).on('change.inputevent', evt.data.selector, _this14.fakeInputEvent);
        _this14.fakeInputEvent(evt);
      }
    },

    behavesOk: function behavesOk(evt) {
      if (_this14.isNativeEvent(evt)) {
        $(document) // Simply unbinds the testing handler
        .off('input.inputevent', evt.data.selector, _this14.behavesOk).off('change.inputevent', evt.data.selector, _this14.misbehaves);
      }
    },

    // Bind the testing handlers
    install: function install() {
      if (globals.inputEventPatched) {
        return;
      }
      globals.inputEventPatched = '0.0.3';
      var _arr = ['select', 'input[type="checkbox"]', 'input[type="radio"]', 'input[type="file"]'];
      for (var _i = 0; _i < _arr.length; _i++) {
        var selector = _arr[_i];
        $(document).on('input.inputevent', selector, { selector: selector }, _this14.behavesOk).on('change.inputevent', selector, { selector: selector }, _this14.misbehaves);
      }
    },

    uninstall: function uninstall() {
      delete globals.inputEventPatched;
      $(document).off('.inputevent');
    }

  });
};

var inputevent = new InputEvent();

inputevent.install();

var parsley = Parsley;

return parsley;

}); //# sourceMappingURL=parsley.js.map