/*!
* Parsley.js
* Version 2.8.1 - built Sat, Feb 3rd 2018, 2:27 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;

var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try {
for (var _i = arr[Symbol.iterator](), _s; ! (_n = (_s = _i.next()).done); _n = true) {
						_arr.push( _s.value ); if (i && _arr.length === i) {
			break;
						} } } catch (err) {
			_d = true; _e = err; } finally { try {
				if ( ! _n && _i['return']) {
						_i['return']();
				} } 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[i]; for (var key in source) {
				if (Object.prototype.hasOwnProperty.call( source, key )) {
	target[key] = source[key]; } } } return target; };

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 Utils = {
			// Parsley DOM-API
			// returns object from dom attributes and values
			attr: function attr(element, namespace, obj) {
			  var i;
			  var attribute;
			  var attributes;
			  var regex = new RegExp( '^' + namespace, 'i' );

			  if ('undefined' === typeof obj) {
obj = {};} else {
								// Clear all own properties. This won't affect prototype's values
								for (i in obj) {
					if (obj.hasOwnProperty( i )) {
							delete obj[i];
				}
								}
			  }

			  if ( ! element) {
						return obj;
			}

		attributes = element.attributes;
		for (i = attributes.length; i--;) {
						  attribute = attributes[i];

						  if (attribute && attribute.specified && regex.test( attribute.name )) {
					obj[this.camelize( attribute.name.slice( namespace.length ) )] = this.deserializeValue( attribute.value );
							  }
			  }

		return obj;
				  },

			checkAttr: function checkAttr(element, namespace, _checkAttr) {
			  return element.hasAttribute( namespace + _checkAttr );
				  },

			setAttr: function setAttr(element, namespace, attr, value) {
			  element.setAttribute( this.dasherize( namespace + attr ), String( value ) );
				  },

			getType: function getType(element) {
			  return element.getAttribute( 'type' ) || 'text';
				  },

			generateID: function generateID() {
			  return '' + globalID++;
				  },

			/** Third party functions **/
			deserializeValue: function deserializeValue(value) {
			  var num;

			  try {
					return value ? value == "true" || (value == "false" ? false : value == "null" ? null : ! isNaN( num = Number( value ) ) ? num : /^[\[\{]/.test( value ) ? JSON.parse( value ) : value) : value;
			  } catch (e) {
					return value;
			  }
				  },

			// Zepto camelize function
			camelize: function camelize(str) {
			return str.replace(
				/-+(.)?/g,
				function (match, chr) {
				return chr ? chr.toUpperCase() : '';
			  }
				);
				  },

			// Zepto dasherize function
			dasherize: function dasherize(str) {
			  return str.replace( /::/g, '/' ).replace( /([A-Z]+)([A-Z][a-z])/g, '$1_$2' ).replace( /([a-z\d])([A-Z])/g, '$1_$2' ).replace( /_/g, '-' ).toLowerCase();
				  },

			warn: function warn() {
			  var _window$console;

			  if (window.console && 'function' === typeof window.console.warn) {
(_window$console = window.console ).warn.apply( _window$console, arguments );
			}
				  },

			warnOnce: function warnOnce(msg) {
			  if ( ! pastWarnings[msg]) {
					pastWarnings[msg] = true;
					this.warn.apply( this, arguments );
			  }
				  },

			_resetWarnings: function _resetWarnings() {
			  pastWarnings = {};
				  },

			trimString: function trimString(string) {
			  return string.replace( /^\s+|\s+$/g, '' );
				  },

			parse: {
			  date: function date(string) {
					var parsed = string.match( /^(\d{4,})-(\d\d)-(\d\d)$/ );
					if ( ! parsed) {
		return null;
						}

					var _parsed$map = parsed.map(
					function (x) {
					  return parseInt( x, 10 );
						}
					);

					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-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-zA-Z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/,

			// Follow https://www.w3.org/TR/html5/infrastructure.html#floating-point-numbers
			number: /^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,

			integer: /^-?\d+$/,

			digits: /^\d+$/,

			alphanum: /^\w+$/i,

			date: {
			  test: function test(value) {
					return Utils.parse.date( value ) !== null;
			  }
				  },

			url: new RegExp(
			  "^" +
			// protocol identifier
			"(?:(?:https?|ftp)://)?" + // ** mod: make scheme optional
			// user:pass authentication
			"(?:\\S+(?::\\S*)?@)?" + "(?:" +
			// IP address exclusion
			// private & local networks
			// "(?!(?:10|127)(?:\\.\\d{1,3}){3})" +   // ** mod: allow local networks
			// "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" +  // ** mod: allow local networks
			// "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" +  // ** mod: allow local networks
			// IP address dotted notation octets
			// excludes loopback network 0.0.0.0
			// excludes reserved space >= 224.0.0.0
			// excludes network & broacast addresses
			// (first & last IP address of each class)
			"(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + "|" +
			// host name
			'(?:(?:[a-zA-Z\\u00a1-\\uffff0-9]-*)*[a-zA-Z\\u00a1-\\uffff0-9]+)' +
			// domain name
			'(?:\\.(?:[a-zA-Z\\u00a1-\\uffff0-9]-*)*[a-zA-Z\\u00a1-\\uffff0-9]+)*' +
			// TLD identifier
			'(?:\\.(?:[a-zA-Z\\u00a1-\\uffff]{2,}))' + ")" +
			// port number
			"(?::\\d{2,5})?" +
			// resource path
			"(?:/\\S*)?" + "$"
		)
  };
  typeTesters.range = typeTesters.number;

  // See http://stackoverflow.com/a/10454560/8279
  var decimalPlaces = function decimalPlaces(num) {
			var match = ('' + num).match( /(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/ );
			if ( ! match) {
			  return 0;
				  }
			return Math.max(
			  0,
			// Number of digits right of decimal point.
			(match[1] ? match[1].length : 0) - (
			// Adjust for scientific notation.
			match[2] ? +match[2] : 0)
			  );
  };

  // parseArguments('number', ['1', '2']) => [1, 2]
  var 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 );
				  },

			hasValidator: function hasValidator(name) {
			  return ! ! this.validators[name];
				  },

			updateValidator: function updateValidator(name, arg1, arg2) {
			  if ( ! this.validators[name]) {
					Utils.warn( 'Validator "' + name + '" is not already defined.' );
					return this.addValidator.apply( this, arguments );
			  }
			  return this._setValidator.apply( this, arguments );
				  },

			removeValidator: function removeValidator(name) {
			  if ( ! this.validators[name]) {
Utils.warn( 'Validator "' + name + '" is not defined.' );
			}

			  delete this.validators[name];

			  return this;
				  },

			_setValidator: function _setValidator(name, validator, priority) {
			  if ('object' !== typeof validator) {
					// Old style validator, with `fn` and `priority`
					validator = {
							fn: validator,
							priority: priority
						};
			  }
			  if ( ! validator.validate) {
					validator = new Validator( validator );
			  }
		this.validators[name] = validator;

		for (var locale in validator.messages || {}) {
						this.addMessage( locale, name, validator.messages[locale] );
			}

		return this;
				  },

			getErrorMessage: function getErrorMessage(constraint) {
			  var message;

			  // Type constraints are a bit different, we have to match their requirements too to find right error message
			  if ('type' === constraint.name) {
					var typeMessages = this.catalog[this.locale][constraint.name] || {};
					message          = typeMessages[constraint.requirements];
			  } else {
message = this.formatMessage( this.catalog[this.locale][constraint.name], constraint.requirements );
			}

		return message || this.catalog[this.locale].defaultMessage || this.catalog.en.defaultMessage;
				  },

			// Kind of light `sprintf()` implementation
			formatMessage: function formatMessage(string, parameters) {
			  if ('object' === typeof parameters) {
					for (var i in parameters) {
			  string = this.formatMessage( string, parameters[i] );
						}

					return string;
			  }

			  return 'string' === typeof string ? string.replace( /%s/i, parameters ) : '';
				  },

			// Here is the Parsley default validators list.
			// A validator is an object with the following key values:
			// - priority: an integer
			// - requirement: 'string' (default), 'integer', 'number', 'regexp' or an Array of these
			// - validateString, validateMultiple, validateNumber: functions returning `true`, `false` or a promise
			// Alternatively, a validator can be a function that returns such an object
			//
			validators: {
			  notblank: {
					validateString: function validateString(value) {
						return (/\S/.test( value )
						);
						},
					priority: 2
			  },
			  required: {
					validateMultiple: function validateMultiple(values) {
						return values.length > 0;
						},
					validateString: function validateString(value) {
					  return (/\S/.test( value )
					  );
						},
					priority: 512
			  },
			  type: {
					validateString: function validateString(value, type) {
						var _ref = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

						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.$errorClassHandler.attr( 'aria-describedby', this._ui.errorsWrapperId );
			  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.$errorClassHandler.removeAttr( 'aria-describedby' );
			  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() {
			  // Class handled could also be determined by function given in Parsley options
			  if ('string' === typeof this.options.classHandler && $( this.options.classHandler ).length) {
return $( this.options.classHandler );
			}

			  // Class handled could also be determined by function given in Parsley options
			  var $handlerFunction = this.options.classHandler;

			  // It might also be the function name of a global function
			  if ('string' === typeof this.options.classHandler && 'function' === typeof window[this.options.classHandler]) {
$handlerFunction = window[this.options.classHandler];
			}

		if ('function' === typeof $handlerFunction) {
					  var $handler = $handlerFunction.call( this, this );

					  // If this function returned a valid existing DOM element, go for it
					  if ('undefined' !== typeof $handler && $handler.length) {
	  return $handler;
						}
			  } else if ('object' === typeof $handlerFunction && $handlerFunction instanceof jQuery && $handlerFunction.length) {
return $handlerFunction;
		} else if ($handlerFunction) {
						Utils.warn( 'The class handler `' + $handlerFunction + '` does not exist in DOM nor as a global JS function' );
		}

		return this._inputHolder();
				  },

			_inputHolder: function _inputHolder() {
			  // if simple element (input, texatrea, select...) it will perfectly host the classes and precede the error container
			  if ( ! this.options.multiple || this.element.nodeName === 'SELECT') {
return this.$element;
			}

			  // But if multiple element (radio, checkbox), that would be their parent
			  return this.$element.parent();
				  },

			_insertErrorWrapper: function _insertErrorWrapper() {
			  var $errorsContainer = this.options.errorsContainer;

			  // Nothing to do if already inserted
			  if (0 !== this._ui.$errorsWrapper.parent().length) {
return this._ui.$errorsWrapper.parent();
			}

			  if ('string' === typeof $errorsContainer) {
					if ($( $errorsContainer ).length) {
					  return $( $errorsContainer ).append( this._ui.$errorsWrapper );} else if ('function' === typeof window[$errorsContainer]) {
						  $errorsContainer = window[$errorsContainer];} else {
Utils.warn( 'The errors container `' + $errorsContainer + '` does not exist in DOM nor as a global JS function' );
							}
			  }

		if ('function' === typeof $errorsContainer) {
						$errorsContainer = $errorsContainer.call( this, this );
			}

		if ('object' === typeof $errorsContainer && $errorsContainer.length) {
						return $errorsContainer.append( this._ui.$errorsWrapper );
			}

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

			_actualizeTriggers: function _actualizeTriggers() {
			  var _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 );
				  },

			refresh: function refresh() {
			  this._refreshFields();
			  return this;
				  },

			// Reset UI
			reset: function reset() {
			  // Form case: emit a reset event for each field
			  for (var i = 0; i < this.fields.length; i++) {
this.fields[i].reset();
			}

			  this._trigger( 'reset' );
				  },

			// Destroy Parsley instance (+ UI)
			destroy: function destroy() {
			  // Field case: emit destroy event to clean UI and then destroy stored instance
			  this._destroyUI();

			  // Form case: destroy all its fields and then destroy stored instance
			  for (var i = 0; i < this.fields.length; i++) {
this.fields[i].destroy();
			}

			  this.$element.removeData( 'Parsley' );
			  this._trigger( 'destroy' );
				  },

			_refreshFields: function _refreshFields() {
			  return this.actualizeOptions()._bindFields();
				  },

			_bindFields: function _bindFields() {
			  var _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.refresh();
			  if (group && ! this._isInGroup( group )) {
return;
			}

			  this.value = this.getValue();

			  // Field Validate event. `this.value` could be altered for custom needs
			  this._trigger( 'validate' );

			return (_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.refresh();
			}
			  // do not validate a field if not the same as given validation group
			  if (group && ! this._isInGroup( group )) {
return;
			}

		this.validationResult = true;

		// A field without constraint is valid
		if ( ! this.hasConstraints()) {
						return $.when();
			}

		// Value could be passed as argument, needed to add more power to 'field:validate'
		if ('undefined' === typeof value || null === value) {
						value = this.getValue();
			}

		if ( ! this.needsValidation( value ) && true !== force) {
						return $.when();
			}

		var groupedConstraints = this._getGroupedConstraints();
		var promises           = [];
		$.each(
		  groupedConstraints,
		  function (_, constraints) {
						// Process one group of constraints at a time, we validate the constraints
						// and combine the promises together.
						var promise = Utils.all(
					$.map(
					constraints,
					function (constraint) {
					return _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 and rebind constraints
			refresh: function refresh() {
			  this._refreshConstraints();
			  return this;
				  },

			_refreshConstraints: function _refreshConstraints() {
			  return this.actualizeOptions()._bindConstraints();
				  },

			refreshConstraints: function refreshConstraints() {
			  Utils.warnOnce( "Parsley's refreshConstraints is deprecated. Please use refresh" );
			  return this.refresh();
				  },

			/**
			 * Add a new constraint to a field
			 *
			 * @param {String}   name
			 * @param {Mixed}    requirements      optional
			 * @param {Number}   priority          optional
			 * @param {Boolean}  isDomConstraint   optional
			 */
			addConstraint: function addConstraint(name, requirements, priority, isDomConstraint) {

			  if (window.Parsley._validatorRegistry.validators[name]) {
					var constraint = new Constraint( this, name, requirements, priority, isDomConstraint );

					// if constraint already exist, delete it and push new version
					if ('undefined' !== this.constraintsByName[constraint.name]) {
			  this.removeConstraint( constraint.name );
						}

					this.constraints.push( constraint );
					this.constraintsByName[constraint.name] = constraint;
			  }

			  return this;
				  },

			// Remove a constraint
			removeConstraint: function removeConstraint(name) {
			  for (var i = 0; i < this.constraints.length; i++) {
if (name === this.constraints[i].name) {
							  this.constraints.splice( i, 1 );
							  break;
						}
			}
			  delete this.constraintsByName[name];
			  return this;
				  },

			// Update a constraint (Remove + re-add)
			updateConstraint: function updateConstraint(name, parameters, priority) {
			  return this.removeConstraint( name ).addConstraint( name, parameters, priority );
				  },

			// # Internals

			// Internal only.
			// Bind constraints from config + options + DOM
			_bindConstraints: function _bindConstraints() {
			  var constraints       = [];
			  var constraintsByName = {};

			  // clean all existing DOM constraints to only keep javascript user constraints
			  for (var i = 0; i < this.constraints.length; i++) {
if (false === this.constraints[i].isDomConstraint) {
							  constraints.push( this.constraints[i] );
							  constraintsByName[this.constraints[i].name] = this.constraints[i];
						}
			}

			  this.constraints       = constraints;
			  this.constraintsByName = constraintsByName;

			  // then re-add Parsley DOM-API constraints
			  for (var name in this.options) {
this.addConstraint( name, this.options[name], undefined, true );
			}

		// finally, bind special HTML5 constraints
		return this._bindHtml5Constraints();
				  },

			// Internal only.
			// Bind specific HTML5 constraints to be HTML5 compliant
			_bindHtml5Constraints: function _bindHtml5Constraints() {
			  // html5 required
			  if (null !== this.element.getAttribute( 'required' )) {
this.addConstraint( 'required', true, undefined, true );
			}

			  // html5 pattern
			  if (null !== this.element.getAttribute( 'pattern' )) {
this.addConstraint( 'pattern', this.element.getAttribute( 'pattern' ), undefined, true );
			}

		// range
		var min = this.element.getAttribute( 'min' );
		var max = this.element.getAttribute( 'max' );
		if (null !== min && null !== max) {
						this.addConstraint( 'range', [min, max], undefined, true );
			}

		// HTML5 min
		else if (null !== min) {
						this.addConstraint( 'min', min, undefined, true );
			}

		  // HTML5 max
		  else if (null !== max) {
						this.addConstraint( 'max', max, undefined, true );
		}

		// length
		if (null !== this.element.getAttribute( 'minlength' ) && null !== this.element.getAttribute( 'maxlength' )) {
						this.addConstraint( 'length', [this.element.getAttribute( 'minlength' ), this.element.getAttribute( 'maxlength' )], undefined, true );
			}

		// HTML5 minlength
		else if (null !== this.element.getAttribute( 'minlength' )) {
						this.addConstraint( 'minlength', this.element.getAttribute( 'minlength' ), undefined, true );
			}

		  // HTML5 maxlength
		  else if (null !== this.element.getAttribute( 'maxlength' )) {
						this.addConstraint( 'maxlength', this.element.getAttribute( 'maxlength' ), undefined, true );
		}

		// html5 types
		var type = Utils.getType( this.element );

		// Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
		if ('number' === type) {
					return this.addConstraint(
						'type',
						['number', {
					  step: this.element.getAttribute( 'step' ) || '1',
					  base: min || this.element.getAttribute( 'value' )
								  }],
							undefined,
							true
								);
							  // Regular other HTML5 supported types
		} else if (/^(email|url|range|date)$/i.test( type )) {
						return this.addConstraint( 'type', type, undefined, true );
		  }
		return this;
				  },

			// Internal only.
			// Field is required if have required constraint without `false` value
			_isRequired: function _isRequired() {
			  if ('undefined' === typeof this.constraintsByName.required) {
return false;
			}

			  return false !== this.constraintsByName.required.requirements;
				  },

			// Internal only.
			// Shortcut to trigger an event
			_trigger: function _trigger(eventName) {
			  return this.trigger( 'field:' + eventName );
				  },

			// Internal only
			// Handles whitespace in a value
			// Use `data-parsley-whitespace="squish"` to auto squish input value
			// Use `data-parsley-whitespace="trim"` to auto trim input value
			_handleWhitespace: function _handleWhitespace(value) {
			  if (true === this.options.trimValue) {
Utils.warnOnce( 'data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"' );
			}

			  if ('squish' === this.options.whitespace) {
value = value.replace( /\s{2,}/g, ' ' );
			}

		if ('trim' === this.options.whitespace || 'squish' === this.options.whitespace || true === this.options.trimValue) {
						value = Utils.trimString( value );
			}

		return value;
				  },

			_isDateInput: function _isDateInput() {
			  var c = this.constraintsByName.type;
			  return c && c.requirements === 'date';
				  },

			// Internal only.
			// Returns the constraints, grouped by descending priority.
			// The result is thus an array of arrays of constraints.
			_getGroupedConstraints: function _getGroupedConstraints() {
			  if (false === this.options.priorityEnabled) {
return [this.constraints];
			}

			  var groupedConstraints = [];
			  var index              = {};

			  // Create array unique of priorities
			  for (var i = 0; i < this.constraints.length; i++) {
					var p = this.constraints[i].priority;
					if ( ! index[p]) {
					  groupedConstraints.push( index[p] = [] );
						}
					index[p].push( this.constraints[i] );
			  }
		// Sort them by priority DESC
		groupedConstraints.sort(
		  function (a, b) {
						return b[0].priority - a[0].priority;
			  }
				);

			  return groupedConstraints;
				  }

  };

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

					  // checkbox input case
					  if (type === 'checkbox') {
						  var values = [];

						this._findRelated().filter( ':checked' ).each(
						  function () {
							values.push( $( this ).val() );
							  }
							  );

							  return values;
						  }
			  }

		// Select multiple case
		if (this.element.nodeName === 'SELECT' && null === this.$element.val()) {
							  return [];
			}

		// Default case that should never happen
		return this.$element.val();
				  },

			_init: function _init() {
			  this.$elements = [this.$element];

			  return this;
				  }
  };

  var Factory = function Factory(element, options, parsleyFormInstance) {
			this.element  = element;
			this.$element = $( element );

			// If the element has already been bound, returns its saved Parsley instance
			var savedparsleyFormInstance = this.$element.data( 'Parsley' );
			if (savedparsleyFormInstance) {

			  // If the saved instance has been bound without a Form parent and there is one given in this call, add it
			  if ('undefined' !== typeof parsleyFormInstance && savedparsleyFormInstance.parent === window.Parsley) {
					savedparsleyFormInstance.parent = parsleyFormInstance;
					savedparsleyFormInstance._resetOptions( savedparsleyFormInstance.options );
			  }

			  if ('object' === typeof options) {
					_extends( savedparsleyFormInstance.options, options );
			  }

		return savedparsleyFormInstance;
				  }

			// Parsley must be instantiated with a DOM element or jQuery $element
			if ( ! this.$element.length) {
throw new Error( 'You must bind Parsley on an existing element.' );
				}

			if ('undefined' !== typeof parsleyFormInstance && 'Form' !== parsleyFormInstance.__class__) {
throw new Error( 'Parent instance must be a Form instance' );
				}

			this.parent = parsleyFormInstance || window.Parsley;
			return this.init( options );
  };

  Factory.prototype = {
			init: function init(options) {
			  this.__class__   = 'Parsley';
			  this.__version__ = '2.8.1';
			  this.__id__      = Utils.generateID();

			  // Pre-compute options
			  this._resetOptions( options );

			  // A Form instance is obviously a `<form>` element but also every node that is not an input and has the `data-parsley-validate` attribute
			  if (this.element.nodeName === 'FORM' || Utils.checkAttr( this.element, this.options.namespace, 'validate' ) && ! this.$element.is( this.options.inputs )) {
return this.bind( 'parsleyForm' );
			}

			  // Every other element is bound as a `Field` or `FieldMultiple`
			  return this.isMultiple() ? this.handleMultiple() : this.bind( 'parsleyField' );
				  },

			isMultiple: function isMultiple() {
			  var type = Utils.getType( this.element );
			  return type === 'radio' || type === 'checkbox' || this.element.nodeName === 'SELECT' && null !== this.element.getAttribute( 'multiple' );
				  },

			// Multiples fields are a real nightmare :(
			// Maybe some refactoring would be appreciated here...
			handleMultiple: function handleMultiple() {
			  var _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) {
						var type = Utils.getType( input );
						if (type === 'radio' || 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.8.1'
  }
	  );

  // 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 == 0) {
			  return;
				  }

			return new Factory( this[0], options );
  };

  // ### Field and Form extension
  // Ensure the extension is now defined if it wasn't previously
  if ('undefined' === typeof window.ParsleyExtend) {
			window.ParsleyExtend = {};
  }

  // ### Parsley config
  // Inherit from ParsleyDefault, and copy over any existing values
  Parsley.options      = _extends( Utils.objectCreate( Defaults ), window.ParsleyConfig );
  window.ParsleyConfig = Parsley.options; // Old way of accessing global options

  // ### Globals
  window.Parsley      = window.psly = Parsley;
  Parsley.Utils       = Utils;
  window.ParsleyUtils = {};
$.each(
	  Utils,
	  function (key, value) {
			if ('function' === typeof value) {
				window.ParsleyUtils[key] = function () {
				  Utils.warnOnce( 'Accessing `window.ParsleyUtils` is deprecated. Use `window.Parsley.Utils` instead.' );
				  return Utils[key].apply( Utils, arguments );
				};
				}
  }
	  );

  // ### Define methods that forward to the registry, and deprecate all access except through window.Parsley
  var registry            = window.Parsley._validatorRegistry = new ValidatorRegistry( window.ParsleyConfig.validators, window.ParsleyConfig.i18n );
  window.ParsleyValidator = {};
$.each(
	  'setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator hasValidator'.split( ' ' ),
	  function (i, method) {
			window.Parsley[method]          = function () {
			  return registry[method].apply( registry, arguments );
				};
			window.ParsleyValidator[method] = function () {
			  var _window$Parsley;

			  Utils.warnOnce( 'Accessing the method \'' + 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;
}
	);
