PageSourceSearch

https://www.greatlittlebreaks.com/Scripts/parsley/parsley.js

js greatlittlebreaks.com collected 2026-09-29 16:30:06 UTC 93,522 bytes, 2,083 lines download raw bytes

1/*!
2* Parsleyjs
3* Guillaume Potier - <[email protected]>
4* Version 2.0.6 - built Sat Jan 24 2015 14:44:37
5* MIT Licensed
6*
7*/
8!(function (factory) {
9  if (typeof define === 'function' && define.amd) {
10    // AMD. Register as an anonymous module depending on jQuery.
11    define(['jquery'], factory);
12  } else {
13    // No AMD. Register plugin with global jQuery object.
14    factory(jQuery);
15  }
16}(function ($) {
17  // small hack for requirejs if jquery is loaded through map and not path
18  // see http://requirejs.org/docs/jquery.html
19  if ('undefined' === typeof $ && 'undefined' !== typeof window.jQuery)
20    $ = window.jQuery;
21  var ParsleyUtils = {
22    // Parsley DOM-API
23    // returns object from dom attributes and values
24    // if attr is given, returns bool if attr present in DOM or not
25    attr: function ($element, namespace, checkAttr) {
26      var
27        attribute,
28        obj = {},
29        msie = this.msieversion(),
30        regex = new RegExp('^' + namespace, 'i');
31      if ('undefined' === typeof $element || 'undefined' === typeof $element[0])
32        return {};
33      for (var i in $element[0].attributes) {
34        attribute = $element[0].attributes[i];
35        if ('undefined' !== typeof attribute && null !== attribute && (!msie || msie >= 8 || attribute.specified) && regex.test(attribute.name)) {
36          if ('undefined' !== typeof checkAttr && new RegExp(checkAttr + '$', 'i').test(attribute.name))
37            return true;
38          obj[this.camelize(attribute.name.replace(namespace, ''))] = this.deserializeValue(attribute.value);
39        }
40      }
41      return 'undefined' === typeof checkAttr ? obj : false;
42    },
43    setAttr: function ($element, namespace, attr, value) {
44      $element[0].setAttribute(this.dasherize(namespace + attr), String(value));
45    },
46    // Recursive object / array getter
47    get: function (obj, path) {
48      var
49        i = 0,
50        paths = (path || '').split('.');
51      while (this.isObject(obj) || this.isArray(obj)) {
52        obj = obj[paths[i++]];
53        if (i === paths.length)
54          return obj;
55      }
56      return undefined;
57    },
58    hash: function (length) {
59      return String(Math.random()).substring(2, length ? length + 2 : 9);
60    },
61    /** Third party functions **/
62    // Underscore isArray
63    isArray: function (mixed) {
64      return Object.prototype.toString.call(mixed) === '[object Array]';
65    },
66    // Underscore isObject
67    isObject: function (mixed) {
68      return mixed === Object(mixed);
69    },
70    // Zepto deserialize function
71    deserializeValue: function (value) {
72      var num;
73      try {
74        return value ?
75          value == "true" ||
76          (value == "false" ? false :
77          value == "null" ? null :
78          !isNaN(num = Number(value)) ? num :
79          /^[\[\{]/.test(value) ? $.parseJSON(value) :
80          value)
81          : value;
82      } catch (e) { return value; }
83    },
84    // Zepto camelize function
85    camelize: function (str) {
86      return str.replace(/-+(.)?/g, function(match, chr) {
87        return chr ? chr.toUpperCase() : '';
88      });
89    },
90    // Zepto dasherize function
91    dasherize: function (str) {
92      return str.replace(/::/g, '/')
93        .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
94        .replace(/([a-z\d])([A-Z])/g, '$1_$2')
95        .replace(/_/g, '-')
96        .toLowerCase();
97    },
98    // http://support.microsoft.com/kb/167820
99    // http://stackoverflow.com/questions/19999388/jquery-check-if-user-is-using-ie
100    msieversion: function () {
101      var
102        ua = window.navigator.userAgent,
103        msie = ua.indexOf('MSIE ');
104      if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))
105        return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
106      return 0;
107   }
108  };
109// All these options could be overriden and specified directly in DOM using
110// `data-parsley-` default DOM-API
111// eg: `inputs` can be set in DOM using `data-parsley-inputs="input, textarea"`
112// eg: `data-parsley-stop-on-first-failing-constraint="false"`
113  var ParsleyDefaults = {
114    // ### General
115    // Default data-namespace for DOM API
116    namespace: 'data-parsley-',
117    // Supported inputs by default
118    inputs: 'input, textarea, select',
119    // Excluded inputs by default
120    excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden]',
121    // Stop validating field on highest priority failing constraint
122    priorityEnabled: true,
123    // ### UI
124    // Enable\Disable error messages
125    uiEnabled: true,
126    // Key events threshold before validation
127    validationThreshold: 3,
128    // Focused field on form validation error. 'fist'|'last'|'none'
129    focus: 'first',
130    // `$.Event()` that will trigger validation. eg: `keyup`, `change`...
131    trigger: false,
132    // Class that would be added on every failing validation Parsley field
133    errorClass: 'parsley-error',
134    // Same for success validation
135    successClass: 'parsley-success',
136    // Return the `$element` that will receive these above success or error classes
137    // Could also be (and given directly from DOM) a valid selector like `'#div'`
138    classHandler: function (ParsleyField) {},
139    // Return the `$element` where errors will be appended
140    // Could also be (and given directly from DOM) a valid selector like `'#div'`
141    errorsContainer: function (ParsleyField) {},
142    // ul elem that would receive errors' list
143    errorsWrapper: '<ul class="parsley-errors-list"></ul>',
144    // li elem that would receive error message
145    errorTemplate: '<li></li>'
146  };
147
148  var ParsleyAbstract = function() {};
149  ParsleyAbstract.prototype = {
150    asyncSupport: false,
151    actualizeOptions: function () {
152      this.options = this.OptionsFactory.get(this);
153      return this;
154    },
155    // ParsleyValidator validate proxy function . Could be replaced by third party scripts
156    validateThroughValidator: function (value, constraints, priority) {
157      return window.ParsleyValidator.validate(value, constraints, priority);
158    },
159    // Subscribe an event and a handler for a specific field or a specific form
160    // If on a ParsleyForm instance, it will be attached to form instance and also
161    // To every field instance for this form
162    subscribe: function (name, fn) {
163      $.listenTo(this, name.toLowerCase(), fn);
164      return this;
165    },
166    // Same as subscribe above. Unsubscribe an event for field, or form + its fields
167    unsubscribe: function (name) {
168      $.unsubscribeTo(this, name.toLowerCase());
169      return this;
170    },
171    // Reset UI
172    reset: function () {
173      // Field case: just emit a reset event for UI
174      if ('ParsleyForm' !== this.__class__)
175        return $.emit('parsley:field:reset', this);
176      // Form case: emit a reset event for each field
177      for (var i = 0; i < this.fields.length; i++)
178        $.emit('parsley:field:reset', this.fields[i]);
179      $.emit('parsley:form:reset', this);
180    },
181    // Destroy Parsley instance (+ UI)
182    destroy: function () {
183      // Field case: emit destroy event to clean UI and then destroy stored instance
184      if ('ParsleyForm' !== this.__class__) {
185        this.$element.removeData('Parsley');
186        this.$element.removeData('ParsleyFieldMultiple');
187        $.emit('parsley:field:destroy', this);
188        return;
189      }
190      // Form case: destroy all its fields and then destroy stored instance
191      for (var i = 0; i < this.fields.length; i++)
192        this.fields[i].destroy();
193      this.$element.removeData('Parsley');
194      $.emit('parsley:form:destroy', this);
195    }
196  };
197/*!
198* validator.js
199* Guillaume Potier - <[email protected]>
200* Version 1.0.1 - built Mon Aug 25 2014 16:10:10
201* MIT Licensed
202*
203*/
204var Validator = ( function ( ) {
205  var exports = {};
206  /**
207  * Validator
208  */
209  var Validator = function ( options ) {
210    this.__class__ = 'Validator';
211    this.__version__ = '1.0.1';
212    this.options = options || {};
213    this.bindingKey = this.options.bindingKey || '_validatorjsConstraint';
214  };
215  Validator.prototype = {
216    constructor: Validator,
217    /*
218    * Validate string: validate( string, Assert, string ) || validate( string, [ Assert, Assert ], [ string, string ] )
219    * Validate object: validate( object, Constraint, string ) || validate( object, Constraint, [ string, string ] )
220    * Validate binded object: validate( object, string ) || validate( object, [ string, string ] )
221    */
222    validate: function ( objectOrString, AssertsOrConstraintOrGroup, group ) {
223      if ( 'string' !== typeof objectOrString && 'object' !== typeof objectOrString )
224        throw new Error( 'You must validate an object or a string' );
225      // string / array validation
226      if ( 'string' === typeof objectOrString || _isArray(objectOrString) )
227        return this._validateString( objectOrString, AssertsOrConstraintOrGroup, group );
228      // binded object validation
229      if ( this.isBinded( objectOrString ) )
230        return this._validateBindedObject( objectOrString, AssertsOrConstraintOrGroup );
231      // regular object validation
232      return this._validateObject( objectOrString, AssertsOrConstraintOrGroup, group );
233    },
234    bind: function ( object, constraint ) {
235      if ( 'object' !== typeof object )
236        throw new Error( 'Must bind a Constraint to an object' );
237      object[ this.bindingKey ] = new Constraint( constraint );
238      return this;
239    },
240    unbind: function ( object ) {
241      if ( 'undefined' === typeof object._validatorjsConstraint )
242        return this;
243      delete object[ this.bindingKey ];
244      return this;
245    },
246    isBinded: function ( object ) {
247      return 'undefined' !== typeof object[ this.bindingKey ];
248    },
249    getBinded: function ( object ) {
250      return this.isBinded( object ) ? object[ this.bindingKey ] : null;
251    },
252    _validateString: function ( string, assert, group ) {
253      var result, failures = [];
254      if ( !_isArray( assert ) )
255        assert = [ assert ];
256      for ( var i = 0; i < assert.length; i++ ) {
257        if ( ! ( assert[ i ] instanceof Assert) )
258          throw new Error( 'You must give an Assert or an Asserts array to validate a string' );
259        result = assert[ i ].check( string, group );
260        if ( result instanceof Violation )
261          failures.push( result );
262      }
263      return failures.length ? failures : true;
264    },
265    _validateObject: function ( object, constraint, group ) {
266      if ( 'object' !== typeof constraint )
267        throw new Error( 'You must give a constraint to validate an object' );
268      if ( constraint instanceof Constraint )
269        return constraint.check( object, group );
270      return new Constraint( constraint ).check( object, group );
271    },
272    _validateBindedObject: function ( object, group ) {
273      return object[ this.bindingKey ].check( object, group );
274    }
275  };
276  Validator.errorCode = {
277    must_be_a_string: 'must_be_a_string',
278    must_be_an_array: 'must_be_an_array',
279    must_be_a_number: 'must_be_a_number',
280    must_be_a_string_or_array: 'must_be_a_string_or_array'
281  };
282  /**
283  * Constraint
284  */
285  var Constraint = function ( data, options ) {
286    this.__class__ = 'Constraint';
287    this.options = options || {};
288    this.nodes = {};
289    if ( data ) {
290      try {
291        this._bootstrap( data );
292      } catch ( err ) {
293        throw new Error( 'Should give a valid mapping object to Constraint', err, data );
294      }
295    }
296  };
297  Constraint.prototype = {
298    constructor: Constraint,
299    check: function ( object, group ) {
300      var result, failures = {};
301      // check all constraint nodes.
302      for ( var property in this.nodes ) {
303        var isRequired = false;
304        var constraint = this.get(property);
305        var constraints = _isArray( constraint ) ? constraint : [constraint];
306        for (var i = constraints.length - 1; i >= 0; i--) {
307          if ( 'Required' === constraints[i].__class__ ) {
308            isRequired = constraints[i].requiresValidation( group );
309            continue;
310          }
311        }
312        if ( ! this.has( property, object ) && ! this.options.strict && ! isRequired ) {
313          continue;
314        }
315        try {
316          if (! this.has( property, this.options.strict || isRequired ? object : undefined ) ) {
317            // we trigger here a HaveProperty Assert violation to have uniform Violation object in the end
318            new Assert().HaveProperty( property ).validate( object );
319          }
320          result = this._check( property, object[ property ], group );
321          // check returned an array of Violations or an object mapping Violations
322          if ( ( _isArray( result ) && result.length > 0 ) || ( !_isArray( result ) && !_isEmptyObject( result ) ) ) {
323            failures[ property ] = result;
324          }
325        } catch ( violation ) {
326          failures[ property ] = violation;
327        }
328      }
329      return _isEmptyObject(failures) ? true : failures;
330    },
331    add: function ( node, object ) {
332      if ( object instanceof Assert  || ( _isArray( object ) && object[ 0 ] instanceof Assert ) ) {
333        this.nodes[ node ] = object;
334        return this;
335      }
336      if ( 'object' === typeof object && !_isArray( object ) ) {
337        this.nodes[ node ] = object instanceof Constraint ? object : new Constraint( object );
338        return this;
339      }
340      throw new Error( 'Should give an Assert, an Asserts array, a Constraint', object );
341    },
342    has: function ( node, nodes ) {
343      nodes = 'undefined' !== typeof nodes ? nodes : this.nodes;
344      return 'undefined' !== typeof nodes[ node ];
345    },
346    get: function ( node, placeholder ) {
347      return this.has( node ) ? this.nodes[ node ] : placeholder || null;
348    },
349    remove: function ( node ) {
350      var _nodes = [];
351      for ( var i in this.nodes )
352        if ( i !== node )
353          _nodes[ i ] = this.nodes[ i ];
354      this.nodes = _nodes;
355      return this;
356    },
357    _bootstrap: function ( data ) {
358      if ( data instanceof Constraint )
359        return this.nodes = data.nodes;
360      for ( var node in data )
361        this.add( node, data[ node ] );
362    },
363    _check: function ( node, value, group ) {
364      // Assert
365      if ( this.nodes[ node ] instanceof Assert )
366        return this._checkAsserts( value, [ this.nodes[ node ] ], group );
367      // Asserts
368      if ( _isArray( this.nodes[ node ] ) )
369        return this._checkAsserts( value, this.nodes[ node ], group );
370      // Constraint -> check api
371      if ( this.nodes[ node ] instanceof Constraint )
372        return this.nodes[ node ].check( value, group );
373      throw new Error( 'Invalid node', this.nodes[ node ] );
374    },
375    _checkAsserts: function ( value, asserts, group ) {
376      var result, failures = [];
377      for ( var i = 0; i < asserts.length; i++ ) {
378        result = asserts[ i ].check( value, group );
379        if ( 'undefined' !== typeof result && true !== result )
380          failures.push( result );
381        // Some asserts (Collection for example) could return an object
382        // if ( result && ! ( result instanceof Violation ) )
383        //   return result;
384        //
385        // // Vast assert majority return Violation
386        // if ( result instanceof Violation )
387        //   failures.push( result );
388      }
389      return failures;
390    }
391  };
392  /**
393  * Violation
394  */
395  var Violation = function ( assert, value, violation ) {
396    this.__class__ = 'Violation';
397    if ( ! ( assert instanceof Assert ) )
398      throw new Error( 'Should give an assertion implementing the Assert interface' );
399    this.assert = assert;
400    this.value = value;
401    if ( 'undefined' !== typeof violation )
402      this.violation = violation;
403  };
404  Violation.prototype = {
405    show: function () {
406      var show =  {
407        assert: this.assert.__class__,
408        value: this.value
409      };
410      if ( this.violation )
411        show.violation = this.violation;
412      return show;
413    },
414    __toString: function () {
415      if ( 'undefined' !== typeof this.violation )
416        this.violation = '", ' + this.getViolation().constraint + ' expected was ' + this.getViolation().expected;
417      return this.assert.__class__ + ' assert failed for "' + this.value + this.violation || '';
418    },
419    getViolation: function () {
420      var constraint, expected;
421      for ( constraint in this.violation )
422        expected = this.violation[ constraint ];
423      return { constraint: constraint, expected: expected };
424    }
425  };
426  /**
427  * Assert
428  */
429  var Assert = function ( group ) {
430    this.__class__ = 'Assert';
431    this.__parentClass__ = this.__class__;
432    this.groups = [];
433    if ( 'undefined' !== typeof group )
434      this.addGroup( group );
435  };
436  Assert.prototype = {
437    construct: Assert,
438    requiresValidation: function ( group ) {
439      if ( group && !this.hasGroup( group ) )
440        return false;
441      if ( !group && this.hasGroups() )
442        return false;
443      return true;
444    },
445    check: function ( value, group ) {
446      if ( !this.requiresValidation( group ) )
447        return;
448      try {
449        return this.validate( value, group );
450      } catch ( violation ) {
451        return violation;
452      }
453    },
454    hasGroup: function ( group ) {
455      if ( _isArray( group ) )
456        return this.hasOneOf( group );
457      // All Asserts respond to "Any" group
458      if ( 'Any' === group )
459        return true;
460      // Asserts with no group also respond to "Default" group. Else return false
461      if ( !this.hasGroups() )
462        return 'Default' === group;
463      return -1 !== this.groups.indexOf( group );
464    },
465    hasOneOf: function ( groups ) {
466      for ( var i = 0; i < groups.length; i++ )
467        if ( this.hasGroup( groups[ i ] ) )
468          return true;
469      return false;
470    },
471    hasGroups: function () {
472      return this.groups.length > 0;
473    },
474    addGroup: function ( group ) {
475      if ( _isArray( group ) )
476        return this.addGroups( group );
477      if ( !this.hasGroup( group ) )
478        this.groups.push( group );
479      return this;
480    },
481    removeGroup: function ( group ) {
482      var _groups = [];
483      for ( var i = 0; i < this.groups.length; i++ )
484        if ( group !== this.groups[ i ] )
485          _groups.push( this.groups[ i ] );
486      this.groups = _groups;
487      return this;
488    },
489    addGroups: function ( groups ) {
490      for ( var i = 0; i < groups.length; i++ )
491        this.addGroup( groups[ i ] );
492      return this;
493    },
494    /**
495    * Asserts definitions
496    */
497    HaveProperty: function ( node ) {
498      this.__class__ = 'HaveProperty';
499      this.node = node;
500      this.validate = function ( object ) {
501        if ( 'undefined' === typeof object[ this.node ] )
502          throw new Violation( this, object, { value: this.node } );
503        return true;
504      };
505      return this;
506    },
507    Blank: function () {
508      this.__class__ = 'Blank';
509      this.validate = function ( value ) {
510        if ( 'string' !== typeof value )
511          throw new Violation( this, value, { value: Validator.errorCode.must_be_a_string } );
512        if ( '' !== value.replace( /^\s+/g, '' ).replace( /\s+$/g, '' ) )
513          throw new Violation( this, value );
514        return true;
515      };
516      return this;
517    },
518    Callback: function ( fn ) {
519      this.__class__ = 'Callback';
520      this.arguments = Array.prototype.slice.call( arguments );
521      if ( 1 === this.arguments.length )
522        this.arguments = [];
523      else
524        this.arguments.splice( 0, 1 );
525      if ( 'function' !== typeof fn )
526        throw new Error( 'Callback must be instanciated with a function' );
527      this.fn = fn;
528      this.validate = function ( value ) {
529        var result = this.fn.apply( this, [ value ].concat( this.arguments ) );
530        if ( true !== result )
531          throw new Violation( this, value, { result: result } );
532        return true;
533      };
534      return this;
535    },
536    Choice: function ( list ) {
537      this.__class__ = 'Choice';
538      if ( !_isArray( list ) && 'function' !== typeof list )
539        throw new Error( 'Choice must be instanciated with an array or a function' );
540      this.list = list;
541      this.validate = function ( value ) {
542        var list = 'function' === typeof this.list ? this.list() : this.list;
543        for ( var i = 0; i < list.length; i++ )
544          if ( value === list[ i ] )
545            return true;
546        throw new Violation( this, value, { choices: list } );
547      };
548      return this;
549    },
550    Collection: function ( assertOrConstraint ) {
551      this.__class__ = 'Collection';
552      this.constraint = 'undefined' !== typeof assertOrConstraint ? (assertOrConstraint instanceof Assert ? assertOrConstraint : new Constraint( assertOrConstraint )) : false;
553      this.validate = function ( collection, group ) {
554        var result, validator = new Validator(), count = 0, failures = {}, groups = this.groups.length ? this.groups : group;
555        if ( !_isArray( collection ) )
556          throw new Violation( this, collection, { value: Validator.errorCode.must_be_an_array } );
557        for ( var i = 0; i < collection.length; i++ ) {
558          result = this.constraint ?
559            validator.validate( collection[ i ], this.constraint, groups ) :
560            validator.validate( collection[ i ], groups );
561          if ( !_isEmptyObject( result ) )
562            failures[ count ] = result;
563          count++;
564        }
565        return !_isEmptyObject( failures ) ? failures : true;
566      };
567      return this;
568    },
569    Count: function ( count ) {
570      this.__class__ = 'Count';
571      this.count = count;
572      this.validate = function ( array ) {
573        if ( !_isArray( array ) )
574          throw new Violation( this, array, { value: Validator.errorCode.must_be_an_array } );
575        var count = 'function' === typeof this.count ? this.count( array ) : this.count;
576        if ( isNaN( Number( count ) ) )
577          throw new Error( 'Count must be a valid interger', count );
578        if ( count !== array.length )
579          throw new Violation( this, array, { count: count } );
580        return true;
581      };
582      return this;
583    },
584    Email: function () {
585      this.__class__ = 'Email';
586      this.validate = function ( value ) {
587        var regExp = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
588        if ( 'string' !== typeof value )
589          throw new Violation( this, value, { value: Validator.errorCode.must_be_a_string } );
590        if ( !regExp.test( value ) )
591          throw new Violation( this, value );
592        return true;
593      };
594      return this;
595    },
596    EqualTo: function ( reference ) {
597      this.__class__ = 'EqualTo';
598      if ( 'undefined' === typeof reference )
599        throw new Error( 'EqualTo must be instanciated with a value or a function' );
600      this.reference = reference;
601      this.validate = function ( value ) {
602        var reference = 'function' === typeof this.reference ? this.reference( value ) : this.reference;
603        if ( reference !== value )
604          throw new Violation( this, value, { value: reference } );
605        return true;
606      };
607      return this;
608    },
609    GreaterThan: function ( threshold ) {
610      this.__class__ = 'GreaterThan';
611      if ( 'undefined' === typeof threshold )
612        throw new Error( 'Should give a threshold value' );
613      this.threshold = threshold;
614      this.validate = function ( value ) {
615        if ( '' === value || isNaN( Number( value ) ) )
616          throw new Violation( this, value, { value: Validator.errorCode.must_be_a_number } );
617        if ( this.threshold >= value )
618          throw new Violation( this, value, { threshold: this.threshold } );
619        return true;
620      };
621      return this;
622    },
623    GreaterThanOrEqual: function ( threshold ) {
624      this.__class__ = 'GreaterThanOrEqual';
625      if ( 'undefined' === typeof threshold )
626        throw new Error( 'Should give a threshold value' );
627      this.threshold = threshold;
628      this.validate = function ( value ) {
629        if ( '' === value || isNaN( Number( value ) ) )
630          throw new Violation( this, value, { value: Validator.errorCode.must_be_a_number } );
631        if ( this.threshold > value )
632          throw new Violation( this, value, { threshold: this.threshold } );
633        return true;
634      };
635      return this;
636    },
637    InstanceOf: function ( classRef ) {
638      this.__class__ = 'InstanceOf';
639      if ( 'undefined' === typeof classRef )
640        throw new Error( 'InstanceOf must be instanciated with a value' );
641      this.classRef = classRef;
642      this.validate = function ( value ) {
643        if ( true !== (value instanceof this.classRef) )
644          throw new Violation( this, value, { classRef: this.classRef } );
645        return true;
646      };
647      return this;
648    },
649    Length: function ( boundaries ) {
650      this.__class__ = 'Length';
651      if ( !boundaries.min && !boundaries.max )
652        throw new Error( 'Lenth assert must be instanciated with a { min: x, max: y } object' );
653      this.min = boundaries.min;
654      this.max = boundaries.max;
655      this.validate = function ( value ) {
656        if ( 'string' !== typeof value && !_isArray( value ) )
657          throw new Violation( this, value, { value: Validator.errorCode.must_be_a_string_or_array } );
658        if ( 'undefined' !== typeof this.min && this.min === this.max && value.length !== this.min )
659          throw new Violation( this, value, { min: this.min, max: this.max } );
660        if ( 'undefined' !== typeof this.max && value.length > this.max )
661          throw new Violation( this, value, { max: this.max } );
662        if ( 'undefined' !== typeof this.min && value.length < this.min )
663          throw new Violation( this, value, { min: this.min } );
664        return true;
665      };
666      return this;
667    },
668    LessThan: function ( threshold ) {
669      this.__class__ = 'LessThan';
670      if ( 'undefined' === typeof threshold )
671        throw new Error( 'Should give a threshold value' );
672      this.threshold = threshold;
673      this.validate = function ( value ) {
674        if ( '' === value || isNaN( Number( value ) ) )
675          throw new Violation( this, value, { value: Validator.errorCode.must_be_a_number } );
676        if ( this.threshold <= value )
677          throw new Violation( this, value, { threshold: this.threshold } );
678        return true;
679      };
680      return this;
681    },
682    LessThanOrEqual: function ( threshold ) {
683      this.__class__ = 'LessThanOrEqual';
684      if ( 'undefined' === typeof threshold )
685        throw new Error( 'Should give a threshold value' );
686      this.threshold = threshold;
687      this.validate = function ( value ) {
688        if ( '' === value || isNaN( Number( value ) ) )
689          throw new Violation( this, value, { value: Validator.errorCode.must_be_a_number } );
690        if ( this.threshold < value )
691          throw new Violation( this, value, { threshold: this.threshold } );
692        return true;
693      };
694      return this;
695    },
696    NotNull: function () {
697      this.__class__ = 'NotNull';
698      this.validate = function ( value ) {
699        if ( null === value || 'undefined' === typeof value )
700          throw new Violation( this, value );
701        return true;
702      };
703      return this;
704    },
705    NotBlank: function () {
706      this.__class__ = 'NotBlank';
707      this.validate = function ( value ) {
708        if ( 'string' !== typeof value )
709          throw new Violation( this, value, { value: Validator.errorCode.must_be_a_string } );
710        if ( '' === value.replace( /^\s+/g, '' ).replace( /\s+$/g, '' ) )
711          throw new Violation( this, value );
712        return true;
713      };
714      return this;
715    },
716    Null: function () {
717      this.__class__ = 'Null';
718      this.validate = function ( value ) {
719        if ( null !== value )
720          throw new Violation( this, value );
721        return true;
722      };
723      return this;
724    },
725    Range: function ( min, max ) {
726      this.__class__ = 'Range';
727      if ( 'undefined' === typeof min || 'undefined' === typeof max )
728        throw new Error( 'Range assert expects min and max values' );
729      this.min = min;
730      this.max = max;
731      this.validate = function ( value ) {
732          try {
733            // validate strings and objects with their Length
734            if ( ( 'string' === typeof value && isNaN( Number( value ) ) ) || _isArray( value ) )
735              new Assert().Length( { min: this.min, max: this.max } ).validate( value );
736            // validate numbers with their value
737            else
738              new Assert().GreaterThanOrEqual( this.min ).validate( value ) && new Assert().LessThanOrEqual( this.max ).validate( value );
739            return true;
740          } catch ( violation ) {
741            throw new Violation( this, value, violation.violation );
742          }
743        return true;
744      };
745      return this;
746    },
747    Regexp: function ( regexp, flag ) {
748      this.__class__ = 'Regexp';
749      if ( 'undefined' === typeof regexp )
750        throw new Error( 'You must give a regexp' );
751      this.regexp = regexp;
752      this.flag = flag || '';
753      this.validate = function ( value ) {
754        if ( 'string' !== typeof value )
755          throw new Violation( this, value, { value: Validator.errorCode.must_be_a_string } );
756        if ( !new RegExp( this.regexp, this.flag ).test( value ) )
757          throw new Violation( this, value, { regexp: this.regexp, flag: this.flag } );
758        return true;
759      };
760      return this;
761    },
762    Required: function () {
763      this.__class__ = 'Required';
764      this.validate = function ( value ) {
765        if ( 'undefined' === typeof value )
766          throw new Violation( this, value );
767        try {
768          if ( 'string' === typeof value )
769            new Assert().NotNull().validate( value ) && new Assert().NotBlank().validate( value );
770          else if ( true === _isArray( value ) )
771            new Assert().Length( { min: 1 } ).validate( value );
772        } catch ( violation ) {
773          throw new Violation( this, value );
774        }
775        return true;
776      };
777      return this;
778    },
779    // Unique() or Unique ( { key: foo } )
780    Unique: function ( object ) {
781      this.__class__ = 'Unique';
782      if ( 'object' === typeof object )
783        this.key = object.key;
784      this.validate = function ( array ) {
785        var value, store = [];
786        if ( !_isArray( array ) )
787          throw new Violation( this, array, { value: Validator.errorCode.must_be_an_array } );
788        for ( var i = 0; i < array.length; i++ ) {
789          value = 'object' === typeof array[ i ] ? array[ i ][ this.key ] : array[ i ];
790          if ( 'undefined' === typeof value )
791            continue;
792          if ( -1 !== store.indexOf( value ) )
793            throw new Violation( this, array, { value: value } );
794          store.push( value );
795        }
796        return true;
797      };
798      return this;
799    }
800  };
801  // expose to the world these awesome classes
802  exports.Assert = Assert;
803  exports.Validator = Validator;
804  exports.Violation = Violation;
805  exports.Constraint = Constraint;
806  /**
807  * Some useful object prototypes / functions here
808  */
809  // IE8<= compatibility
810  // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
811  if (!Array.prototype.indexOf)
812    Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
813        
814        if (this === null) {
815            throw new TypeError();
816        }
817        var t = Object(this);
818        var len = t.length >>> 0;
819        if (len === 0) {
820            return -1;
821        }
822        var n = 0;
823        if (arguments.length > 1) {
824            n = Number(arguments[1]);
825            if (n != n) { // shortcut for verifying if it's NaN
826                n = 0;
827            } else if (n !== 0 && n != Infinity && n != -Infinity) {
828                n = (n > 0 || -1) * Math.floor(Math.abs(n));
829            }
830        }
831        if (n >= len) {
832            return -1;
833        }
834        var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
835        for (; k < len; k++) {
836            if (k in t && t[k] === searchElement) {
837                return k;
838            }
839        }
840        return -1;
841    };
842  // Test if object is empty, useful for Constraint violations check
843  var _isEmptyObject = function ( obj ) {
844    for ( var property in obj )
845      return false;
846    return true;
847  };
848  var _isArray = function ( obj ) {
849    return Object.prototype.toString.call( obj ) === '[object Array]';
850  };
851  // AMD export
852  if ( typeof define === 'function' && define.amd ) {
853    define( 'vendors/validator.js/dist/validator',[],function() {
854      return exports;
855    } );
856  // commonjs export
857  } else if ( typeof module !== 'undefined' && module.exports ) {
858    module.exports = exports;
859  // browser
860  } else {
861    window[ 'undefined' !== typeof validatorjs_ns ? validatorjs_ns : 'Validator' ] = exports;
862  }
863
864  return exports;
865} )( );
866
867  // This is needed for Browserify usage that requires Validator.js through module.exports
868  Validator = 'undefined' !== typeof Validator ? Validator : ('undefined' !== typeof module ? module.exports : null);
869  var ParsleyValidator = function (validators, catalog) {
870    this.__class__ = 'ParsleyValidator';
871    this.Validator = Validator;
872    // Default Parsley locale is en
873    this.locale = 'en';
874    this.init(validators || {}, catalog || {});
875  };
876  ParsleyValidator.prototype = {
877    init: function (validators, catalog) {
878      this.catalog = catalog;
879      for (var name in validators)
880        this.addValidator(name, validators[name].fn, validators[name].priority, validators[name].requirementsTransformer);
881      $.emit('parsley:validator:init');
882    },
883    // Set new messages locale if we have dictionary loaded in ParsleyConfig.i18n
884    setLocale: function (locale) {
885      if ('undefined' === typeof this.catalog[locale])
886        throw new Error(locale + ' is not available in the catalog');
887      this.locale = locale;
888      return this;
889    },
890    // Add a new messages catalog for a given locale. Set locale for this catalog if set === `true`
891    addCatalog: function (locale, messages, set) {
892      if ('object' === typeof messages)
893        this.catalog[locale] = messages;
894      if (true === set)
895        return this.setLocale(locale);
896      return this;
897    },
898    // Add a specific message for a given constraint in a given locale
899    addMessage: function (locale, name, message) {
900      if ('undefined' === typeof this.catalog[locale])
901        this.catalog[locale] = {};
902      this.catalog[locale][name.toLowerCase()] = message;
903      return this;
904    },
905    validate: function (value, constraints, priority) {
906      return new this.Validator.Validator().validate.apply(new Validator.Validator(), arguments);
907    },
908    // Add a new validator
909    addValidator: function (name, fn, priority, requirementsTransformer) {
910      this.validators[name.toLowerCase()] = function (requirements) {
911        return $.extend(new Validator.Assert().Callback(fn, requirements), {
912          priority: priority,
913          requirementsTransformer: requirementsTransformer
914        });
915      };
916      return this;
917    },
918    updateValidator: function (name, fn, priority, requirementsTransformer) {
919      return this.addValidator(name, fn, priority, requirementsTransformer);
920    },
921    removeValidator: function (name) {
922      delete this.validators[name];
923      return this;
924    },
925    getErrorMessage: function (constraint) {
926      var message;
927      // Type constraints are a bit different, we have to match their requirements too to find right error message
928      if ('type' === constraint.name)
929        message = this.catalog[this.locale][constraint.name][constraint.requirements];
930      else
931        message = this.formatMessage(this.catalog[this.locale][constraint.name], constraint.requirements);
932      return '' !== message ? message : this.catalog[this.locale].defaultMessage;
933    },
934    // Kind of light `sprintf()` implementation
935    formatMessage: function (string, parameters) {
936      if ('object' === typeof parameters) {
937        for (var i in parameters)
938          string = this.formatMessage(string, parameters[i]);
939        return string;
940      }
941      return 'string' === typeof string ? string.replace(new RegExp('%s', 'i'), parameters) : '';
942    },
943    // Here is the Parsley default validators list.
944    // This is basically Validatorjs validators, with different API for some of them
945    // and a Parsley priority set
946    validators: {
947      notblank: function () {
948        return $.extend(new Validator.Assert().NotBlank(), { priority: 2 });
949      },
950      required: function () {
951        return $.extend(new Validator.Assert().Required(), { priority: 512 });
952      },
953      type: function (type) {
954        var assert;
955        switch (type) {
956          case 'email':
957            assert = new Validator.Assert().Email();
958            break;
959          // range type just ensure we have a number here
960          case 'range':
961          case 'number':
962            assert = new Validator.Assert().Regexp('^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)?(?:\\.\\d+)?$');
963            break;
964          case 'integer':
965            assert = new Validator.Assert().Regexp('^-?\\d+$');
966            break;
967          case 'digits':
968            assert = new Validator.Assert().Regexp('^\\d+$');
969            break;
970          case 'alphanum':
971            assert = new Validator.Assert().Regexp('^\\w+$', 'i');
972            break;
973          case 'url':
974            assert = new Validator.Assert().Regexp('(https?:\\/\\/)?(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,24}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)', 'i');
975            break;
976          default:
977            throw new Error('validator type `' + type + '` is not supported');
978        }
979        return $.extend(assert, { priority: 256 });
980      },
981      pattern: function (regexp) {
982        var flags = '';
983        // Test if RegExp is literal, if not, nothing to be done, otherwise, we need to isolate flags and pattern
984        if (!!(/^\/.*\/(?:[gimy]*)$/.test(regexp))) {
985          // Replace the regexp literal string with the first match group: ([gimy]*)
986          // If no flag is present, this will be a blank string
987          flags = regexp.replace(/.*\/([gimy]*)$/, '$1');
988          // Again, replace the regexp literal string with the first match group:
989          // everything excluding the opening and closing slashes and the flags
990          regexp = regexp.replace(new RegExp('^/(.*?)/' + flags + '$'), '$1');
991        }
992        return $.extend(new Validator.Assert().Regexp(regexp, flags), { priority: 64 });
993      },
994      minlength: function (value) {
995        return $.extend(new Validator.Assert().Length({ min: value }), {
996          priority: 30,
997          requirementsTransformer: function () {
998            return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value;
999          }
1000        });
1001      },
1002      maxlength: function (value) {
1003        return $.extend(new Validator.Assert().Length({ max: value }), {
1004          priority: 30,
1005          requirementsTransformer: function () {
1006            return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value;
1007          }
1008        });
1009      },
1010      length: function (array) {
1011        return $.extend(new Validator.Assert().Length({ min: array[0], max: array[1] }), { priority: 32 });
1012      },
1013      mincheck: function (length) {
1014        return this.minlength(length);
1015      },
1016      maxcheck: function (length) {
1017        return this.maxlength(length);
1018      },
1019      check: function (array) {
1020        return this.length(array);
1021      },
1022      min: function (value) {
1023        return $.extend(new Validator.Assert().GreaterThanOrEqual(value), {
1024          priority: 30,
1025          requirementsTransformer: function () {
1026            return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value;
1027          }
1028        });
1029      },
1030      max: function (value) {
1031        return $.extend(new Validator.Assert().LessThanOrEqual(value), {
1032          priority: 30,
1033          requirementsTransformer: function () {
1034            return 'string' === typeof value && !isNaN(value) ? parseInt(value, 10) : value;
1035          }
1036        });
1037      },
1038      range: function (array) {
1039        return $.extend(new Validator.Assert().Range(array[0], array[1]), {
1040          priority: 32,
1041          requirementsTransformer: function () {
1042            for (var i = 0; i < array.length; i++)
1043              array[i] = 'string' === typeof array[i] && !isNaN(array[i]) ? parseInt(array[i], 10) : array[i];
1044            return array;
1045          }
1046        });
1047      },
1048      equalto: function (value) {
1049        return $.extend(new Validator.Assert().EqualTo(value), {
1050          priority: 256,
1051          requirementsTransformer: function () {
1052            return $(value).length ? $(value).val() : value;
1053          }
1054        });
1055      }
1056    }
1057  };
1058
1059  var ParsleyUI = function (options) {
1060    this.__class__ = 'ParsleyUI';
1061  };
1062  ParsleyUI.prototype = {
1063    listen: function () {
1064      $.listen('parsley:form:init', this, this.setupForm);
1065      $.listen('parsley:field:init', this, this.setupField);
1066      $.listen('parsley:field:validated', this, this.reflow);
1067      $.listen('parsley:form:validated', this, this.focus);
1068      $.listen('parsley:field:reset', this, this.reset);
1069      $.listen('parsley:form:destroy', this, this.destroy);
1070      $.listen('parsley:field:destroy', this, this.destroy);
1071      return this;
1072    },
1073    reflow: function (fieldInstance) {
1074      // If this field has not an active UI (case for multiples) don't bother doing something
1075      if ('undefined' === typeof fieldInstance._ui || false === fieldInstance._ui.active)
1076        return;
1077      // Diff between two validation results
1078      var diff = this._diff(fieldInstance.validationResult, fieldInstance._ui.lastValidationResult);
1079      // Then store current validation result for next reflow
1080      fieldInstance._ui.lastValidationResult = fieldInstance.validationResult;
1081      // Field have been validated at least once if here. Useful for binded key events...
1082      fieldInstance._ui.validatedOnce = true;
1083      // Handle valid / invalid / none field class
1084      this.manageStatusClass(fieldInstance);
1085      // Add, remove, updated errors messages
1086      this.manageErrorsMessages(fieldInstance, diff);
1087      // Triggers impl
1088      this.actualizeTriggers(fieldInstance);
1089      // If field is not valid for the first time, bind keyup trigger to ease UX and quickly inform user
1090      if ((diff.kept.length || diff.added.length) && 'undefined' === typeof fieldInstance._ui.failedOnce)
1091        this.manageFailingFieldTrigger(fieldInstance);
1092    },
1093    // Returns an array of field's error message(s)
1094    getErrorsMessages: function (fieldInstance) {
1095      // No error message, field is valid
1096      if (true === fieldInstance.validationResult)
1097        return [];
1098      var messages = [];
1099      for (var i = 0; i < fieldInstance.validationResult.length; i++)
1100        messages.push(this._getErrorMessage(fieldInstance, fieldInstance.validationResult[i].assert));
1101      return messages;
1102    },
1103    manageStatusClass: function (fieldInstance) {
1104      if (true === fieldInstance.validationResult)
1105        this._successClass(fieldInstance);
1106      else if (fieldInstance.validationResult.length > 0)
1107        this._errorClass(fieldInstance);
1108      else
1109        this._resetClass(fieldInstance);
1110    },
1111    manageErrorsMessages: function (fieldInstance, diff) {
1112      if ('undefined' !== typeof fieldInstance.options.errorsMessagesDisabled)
1113        return;
1114      // Case where we have errorMessage option that configure an unique field error message, regardless failing validators
1115      if ('undefined' !== typeof fieldInstance.options.errorMessage) {
1116        if ((diff.added.length || diff.kept.length)) {
1117          if (0 === fieldInstance._ui.$errorsWrapper.find('.parsley-custom-error-message').length)
1118            fieldInstance._ui.$errorsWrapper
1119              .append(
1120                $(fieldInstance.options.errorTemplate)
1121                .addClass('parsley-custom-error-message')
1122              );
1123          return fieldInstance._ui.$errorsWrapper
1124            .addClass('filled')
1125            .find('.parsley-custom-error-message')
1126            .html(fieldInstance.options.errorMessage);
1127        }
1128        return fieldInstance._ui.$errorsWrapper
1129          .removeClass('filled')
1130          .find('.parsley-custom-error-message')
1131          .remove();
1132      }
1133      // Show, hide, update failing constraints messages
1134      for (var i = 0; i < diff.removed.length; i++)
1135        this.removeError(fieldInstance, diff.removed[i].assert.name, true);
1136      for (i = 0; i < diff.added.length; i++)
1137        this.addError(fieldInstance, diff.added[i].assert.name, undefined, diff.added[i].assert, true);
1138      for (i = 0; i < diff.kept.length; i++)
1139        this.updateError(fieldInstance, diff.kept[i].assert.name, undefined, diff.kept[i].assert, true);
1140    },
1141    // TODO: strange API here, intuitive for manual usage with addError(pslyInstance, 'foo', 'bar')
1142    // but a little bit complex for above internal usage, with forced undefined parameter...
1143    addError: function (fieldInstance, name, message, assert, doNotUpdate
1143Class) {
1144      fieldInstance._ui.$errorsWrapper
1145        .addClass('filled')
1146        .append(
1147          $(fieldInstance.options.errorTemplate)
1148          .addClass('parsley-' + name)
1149          .html(message || this._getErrorMessage(fieldInstance, assert))
1150        );
1151      if (true !== doNotUpdateClass)
1152        this._errorClass(fieldInstance);
1153    },
1154    // Same as above
1155    updateError: function (fieldInstance, name, message, assert, doNotUpdateClass) {
1156      fieldInstance._ui.$errorsWrapper
1157        .addClass('filled')
1158        .find('.parsley-' + name)
1159        .html(message || this._getErrorMessage(fieldInstance, assert));
1160      if (true !== doNotUpdateClass)
1161        this._errorClass(fieldInstance);
1162    },
1163    // Same as above twice
1164    removeError: function (fieldInstance, name, doNotUpdateClass) {
1165      fieldInstance._ui.$errorsWrapper
1166        .removeClass('filled')
1167        .find('.parsley-' + name)
1168        .remove();
1169      // edge case possible here: remove a standard Parsley error that is still failing in fieldInstance.validationResult
1170      // but highly improbable cuz' manually removing a well Parsley handled error makes no sense.
1171      if (true !== doNotUpdateClass)
1172        this.manageStatusClass(fieldInstance);
1173    },
1174    focus: function (formInstance) {
1175      if (true === formInstance.validationResult || 'none' === formInstance.options.focus)
1176        return formInstance._focusedField = null;
1177      formInstance._focusedField = null;
1178      for (var i = 0; i < formInstance.fields.length; i++)
1179        if (true !== formInstance.fields[i].validationResult && formInstance.fields[i].validationResult.length > 0 && 'undefined' === typeof formInstance.fields[i].options.noFocus) {
1180          if ('first' === formInstance.options.focus) {
1181            formInstance._focusedField = formInstance.fields[i].$element;
1182            return formInstance._focusedField.focus();
1183          }
1184          formInstance._focusedField = formInstance.fields[i].$element;
1185        }
1186      if (null === formInstance._focusedField)
1187        return null;
1188      return formInstance._focusedField.focus();
1189    },
1190    _getErrorMessage: function (fieldInstance, constraint) {
1191      var customConstraintErrorMessage = constraint.name + 'Message';
1192      if ('undefined' !== typeof fieldInstance.options[customConstraintErrorMessage])
1193        return window.ParsleyValidator.formatMessage(fieldInstance.options[customConstraintErrorMessage], constraint.requirements);
1194      return window.ParsleyValidator.getErrorMessage(constraint);
1195    },
1196    _diff: function (newResult, oldResult, deep) {
1197      var
1198        added = [],
1199        kept = [];
1200      for (var i = 0; i < newResult.length; i++) {
1201        var found = false;
1202        for (var j = 0; j < oldResult.length; j++)
1203          if (newResult[i].assert.name === oldResult[j].assert.name) {
1204            found = true;
1205            break;
1206          }
1207        if (found)
1208          kept.push(newResult[i]);
1209        else
1210          added.push(newResult[i]);
1211      }
1212      return {
1213        kept: kept,
1214        added: added,
1215        removed: !deep ? this._diff(oldResult, newResult, true).added : []
1216      };
1217    },
1218    setupForm: function (formInstance) {
1219      formInstance.$element.on('submit.Parsley', false, $.proxy(formInstance.onSubmitValidate, formInstance));
1220      // UI could be disabled
1221      if (false === formInstance.options.uiEnabled)
1222        return;
1223      formInstance.$element.attr('novalidate', '');
1224    },
1225    setupField: function (fieldInstance) {
1226      var _ui = { active: false };
1227      // UI could be disabled
1228      if (false === fieldInstance.options.uiEnabled)
1229        return;
1230      _ui.active = true;
1231      // Give field its Parsley id in DOM
1232      fieldInstance.$element.attr(fieldInstance.options.namespace + 'id', fieldInstance.__id__);
1233      /** Generate important UI elements and store them in fieldInstance **/
1234      // $errorClassHandler is the $element that woul have parsley-error and parsley-success classes
1235      _ui.$errorClassHandler = this._manageClassHandler(fieldInstance);
1236      // $errorsWrapper is a div that would contain the various field errors, it will be appended into $errorsContainer
1237      _ui.errorsWrapperId = 'parsley-id-' + ('undefined' !== typeof fieldInstance.options.multiple ? 'multiple-' + fieldInstance.options.multiple : fieldInstance.__id__);
1238      _ui.$errorsWrapper = $(fieldInstance.options.errorsWrapper).attr('id', _ui.errorsWrapperId);
1239      // ValidationResult UI storage to detect what have changed bwt two validations, and update DOM accordingly
1240      _ui.lastValidationResult = [];
1241      _ui.validatedOnce = false;
1242      _ui.validationInformationVisible = false;
1243      // Store it in fieldInstance for later
1244      fieldInstance._ui = _ui;
1245      // Stops excluded inputs from getting errorContainer added
1246      if( !fieldInstance.$element.is(fieldInstance.options.excluded) ) {
1247        /** Mess with DOM now **/
1248        this._insertErrorWrapper(fieldInstance);
1249      }
1250      // Bind triggers first time
1251      this.actualizeTriggers(fieldInstance);
1252    },
1253    // Determine which element will have `parsley-error` and `parsley-success` classes
1254    _manageClassHandler: function (fieldInstance) {
1255      // An element selector could be passed through DOM with `data-parsley-class-handler=#foo`
1256      if ('string' === typeof fieldInstance.options.classHandler && $(fieldInstance.options.classHandler).length)
1257        return $(fieldInstance.options.classHandler);
1258      // Class handled could also be determined by function given in Parsley options
1259      var $handler = fieldInstance.options.classHandler(fieldInstance);
1260      // If this function returned a valid existing DOM element, go for it
1261      if ('undefined' !== typeof $handler && $handler.length)
1262        return $handler;
1263      // Otherwise, if simple element (input, texatrea, select...) it will perfectly host the classes
1264      if ('undefined' === typeof fieldInstance.options.multiple || fieldInstance.$element.is('select'))
1265        return fieldInstance.$element;
1266      // But if multiple element (radio, checkbox), that would be their parent
1267      return fieldInstance.$element.parent();
1268    },
1269    _insertErrorWrapper: function (fieldInstance) {
1270      var $errorsContainer;
1271      if ('string' === typeof fieldInstance.options.errorsContainer) {
1272        if ($(fieldInstance.options.errorsContainer).length)
1273          return $(fieldInstance.options.errorsContainer).append(fieldInstance._ui.$errorsWrapper);
1274        else if (window.console && window.console.warn)
1275          window.console.warn('The errors container `' + fieldInstance.options.errorsContainer + '` does not exist in DOM');
1276      }
1277      else if ('function' === typeof fieldInstance.options.errorsContainer)
1278        $errorsContainer = fieldInstance.options.errorsContainer(fieldInstance);
1279      if ('undefined' !== typeof $errorsContainer && $errorsContainer.length)
1280        return $errorsContainer.append(fieldInstance._ui.$errorsWrapper);
1281      return 'undefined' === typeof fieldInstance.options.multiple ? fieldInstance.$element.after(fieldInstance._ui.$errorsWrapper) : fieldInstance.$element.parent().after(fieldInstance._ui.$errorsWrapper);
1282    },
1283    actualizeTriggers: function (fieldInstance) {
1284      var $toBind = fieldInstance.$element;
1285      if (fieldInstance.options.multiple)
1286        $toBind = $('[' + fieldInstance.options.namespace + 'multiple="' + fieldInstance.options.multiple + '"]')
1287      // Remove Parsley events already binded on this field
1288      $toBind.off('.Parsley');
1289      // If no trigger is set, all good
1290      if (false === fieldInstance.options.trigger)
1291        return;
1292      var triggers = fieldInstance.options.trigger.replace(/^\s+/g , '').replace(/\s+$/g , '');
1293      if ('' === triggers)
1294        return;
1295      // Bind fieldInstance.eventValidate if exists (for parsley.ajax for example), ParsleyUI.eventValidate otherwise
1296      $toBind.on(
1297        triggers.split(' ').join('.Parsley ') + '.Parsley',
1298        $.proxy('function' === typeof fieldInstance.eventValidate ? fieldInstance.eventValidate : this.eventValidate, fieldInstance));
1299    },
1300    // Called through $.proxy with fieldInstance. `this` context is ParsleyField
1301    eventValidate: function(event) {
1302      // For keyup, keypress, keydown... events that could be a little bit obstrusive
1303      // do not validate if val length < min threshold on first validation. Once field have been validated once and info
1304      // about success or failure have been displayed, always validate with this trigger to reflect every yalidation change.
1305      if (new RegExp('key').test(event.type))
1306        if (!this._ui.validationInformationVisible && this.getValue().length <= this.options.validationThreshold)
1307          return;
1308      this._ui.validatedOnce = true;
1309      this.validate();
1310    },
1311    manageFailingFieldTrigger: function (fieldInstance) {
1312      fieldInstance._ui.failedOnce = true;
1313      // Radio and checkboxes fields must bind every field multiple
1314      if (fieldInstance.options.multiple)
1315        $('[' + fieldInstance.options.namespace + 'multiple="' + fieldInstance.options.multiple + '"]').each(function () {
1316          if (!new RegExp('change', 'i').test($(this).parsley().options.trigger || ''))
1317            return $(this).on('change.ParsleyFailedOnce', false, $.proxy(fieldInstance.validate, fieldInstance));
1318        });
1319      // Select case
1320      if (fieldInstance.$element.is('select'))
1321        if (!new RegExp('change', 'i').test(fieldInstance.options.trigger || ''))
1322          return fieldInstance.$element.on('change.ParsleyFailedOnce', false, $.proxy(fieldInstance.validate, fieldInstance));
1323      // All other inputs fields
1324      if (!new RegExp('keyup', 'i').test(fieldInstance.options.trigger || ''))
1325        return fieldInstance.$element.on('keyup.ParsleyFailedOnce', false, $.proxy(fieldInstance.validate, fieldInstance));
1326    },
1327    reset: function (parsleyInstance) {
1328      // Reset all event listeners
1329      parsleyInstance.$element.off('.Parsley');
1330      parsleyInstance.$element.off('.ParsleyFailedOnce');
1331      // Nothing to do if UI never initialized for this field
1332      if ('undefined' === typeof parsleyInstance._ui)
1333        return;
1334      if ('ParsleyForm' === parsleyInstance.__class__)
1335        return;
1336      // Reset all errors' li
1337      parsleyInstance._ui.$errorsWrapper
1338        .removeClass('filled')
1339        .children()
1340        .remove();
1341      // Reset validation class
1342      this._resetClass(parsleyInstance);
1343      // Reset validation flags and last validation result
1344      parsleyInstance._ui.validatedOnce = false;
1345      parsleyInstance._ui.lastValidationResult = [];
1346      parsleyInstance._ui.validationInformationVisible = false;
1347    },
1348    destroy: function (parsleyInstance) {
1349      this.reset(parsleyInstance);
1350      if ('ParsleyForm' === parsleyInstance.__class__)
1351        return;
1352      if ('undefined' !== typeof parsleyInstance._ui)
1353        parsleyInstance._ui.$errorsWrapper.remove();
1354      delete parsleyInstance._ui;
1355    },
1356    _successClass: function (fieldInstance) {
1357      fieldInstance._ui.validationInformationVisible = true;
1358      fieldInstance._ui.$errorClassHandler.removeClass(fieldInstance.options.errorClass).addClass(fieldInstance.options.successClass);
1359    },
1360    _errorClass: function (fieldInstance) {
1361      fieldInstance._ui.validationInformationVisible = true;
1362      fieldInstance._ui.$errorClassHandler.removeClass(fieldInstance.options.successClass).addClass(fieldInstance.options.errorClass);
1363    },
1364    _resetClass: function (fieldInstance) {
1365      fieldInstance._ui.$errorClassHandler.removeClass(fieldInstance.options.successClass).removeClass(fieldInstance.options.errorClass);
1366    }
1367  };
1368
1369  var ParsleyOptionsFactory = function (defaultOptions, globalOptions, userOptions, namespace) {
1370    this.__class__ = 'OptionsFactory';
1371    this.__id__ = ParsleyUtils.hash(4);
1372    this.formOptions = null;
1373    this.fieldOptions = null;
1374    this.staticOptions = $.extend(true, {}, defaultOptions, globalOptions, userOptions, { namespace: namespace });
1375  };
1376  ParsleyOptionsFactory.prototype = {
1377    get: function (parsleyInstance) {
1378      if ('undefined' === typeof parsleyInstance.__class__)
1379        throw new Error('Parsley Instance expected');
1380      switch (parsleyInstance.__class__) {
1381        case 'Parsley':
1382          return this.staticOptions;
1383        case 'ParsleyForm':
1384          return this.getFormOptions(parsleyInstance);
1385        case 'ParsleyField':
1386        case 'ParsleyFieldMultiple':
1387          return this.getFieldOptions(parsleyInstance);
1388        default:
1389          throw new Error('Instance ' + parsleyInstance.__class__ + ' is not supported');
1390      }
1391    },
1392    getFormOptions: function (formInstance) {
1393      this.formOptions = ParsleyUtils.attr(formInstance.$element, this.staticOptions.namespace);
1394      // not deep extend, since formOptions is a 1 level deep object
1395      return $.extend({}, this.staticOptions, this.formOptions);
1396    },
1397    getFieldOptions: function (fieldInstance) {
1398      this.fieldOptions = ParsleyUtils.attr(fieldInstance.$element, this.staticOptions.namespace);
1399      if (null === this.formOptions && 'undefined' !== typeof fieldInstance.parent)
1400        this.formOptions = this.getFormOptions(fieldInstance.parent);
1401      // not deep extend, since formOptions and fieldOptions is a 1 level deep object
1402      return $.extend({}, this.staticOptions, this.formOptions, this.fieldOptions);
1403    }
1404  };
1405
1406  var ParsleyForm = function (element, OptionsFactory) {
1407    this.__class__ = 'ParsleyForm';
1408    this.__id__ = ParsleyUtils.hash(4);
1409    if ('OptionsFactory' !== ParsleyUtils.get(OptionsFactory, '__class__'))
1410      throw new Error('You must give an OptionsFactory instance');
1411    this.OptionsFactory = OptionsFactory;
1412    this.$element = $(element);
1413    this.validationResult = null;
1414    this.options = this.OptionsFactory.get(this);
1415  };
1416  ParsleyForm.prototype = {
1417    onSubmitValidate: function (event) {
1418      this.validate(undefined, undefined, event);
1419      // prevent form submission if validation fails
1420      if (false === this.validationResult && event instanceof $.Event) {
1421        event.stopImmediatePropagation();
1422        event.preventDefault();
1423      }
1424      return this;
1425    },
1426    // @returns boolean
1427    validate: function (group, force, event) {
1428      this.submitEvent = event;
1429      this.validationResult = true;
1430      var fieldValidationResult = [];
1431      $.emit('parsley:form:validate', this);
1432      // Refresh form DOM options and form's fields that could have changed
1433      this._refreshFields();
1434      // loop through fields to validate them one by one
1435      for (var i = 0; i < this.fields.length; i++) {
1436        // do not validate a field if not the same as given validation group
1437        if (group && !this._isFieldInGroup(this.fields[i], group))
1438          continue;
1439        fieldValidationResult = this.fields[i].validate(force);
1440        if (true !== fieldValidationResult && fieldValidationResult.length > 0 && this.validationResult)
1441          this.validationResult = false;
1442      }
1443      $.emit('parsley:form:' + (this.validationResult ? 'success' : 'error'), this);
1444      $.emit('parsley:form:validated', this);
1445      return this.validationResult;
1446    },
1447    // Iterate over refreshed fields, and stop on first failure
1448    isValid: function (group, force) {
1449      this._refreshFields();
1450      for (var i = 0; i < this.fields.length; i++) {
1451        // do not validate a field if not the same as given validation group
1452        if (group && !this._isFieldInGroup(this.fields[i], group))
1453          continue;
1454        if (false === this.fields[i].isValid(force))
1455          return false;
1456      }
1457      return true;
1458    },
1459    _isFieldInGroup: function (field, group) {
1460      if(ParsleyUtils.isArray(field.options.group))
1461        return -1 !== $.inArray(group, field.options.group);
1462      return field.options.group === group;
1463    },
1464    _refreshFields: function () {
1465      return this.actualizeOptions()._bindFields();
1466    },
1467    _bindFields: function () {
1468      var self = this;
1469      this.fields = [];
1470      this.fieldsMappedById = {};
1471      this.$element.find(this.options.inputs).each(function () {
1472        var fieldInstance = new window.Parsley(this, {}, self);
1473        // Only add valid and not excluded `ParsleyField` and `ParsleyFieldMultiple` children
1474        if (('ParsleyField' === fieldInstance.__class__ || 'ParsleyFieldMultiple' === fieldInstance.__class__) && !fieldInstance.$element.is(fieldInstance.options.excluded))
1475          if ('undefined' === typeof self.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__]) {
1476            self.fieldsMappedById[fieldInstance.__class__ + '-' + fieldInstance.__id__] = fieldInstance;
1477            self.fields.push(fieldInstance);
1478          }
1479      });
1480      return this;
1481    }
1482  };
1483
1484  var ConstraintFactory = function (parsleyField, name, requirements, priority, isDomConstraint) {
1485    var assert = {};
1486    if (!new RegExp('ParsleyField').test(ParsleyUtils.get(parsleyField, '__class__')))
1487      throw new Error('ParsleyField or ParsleyFieldMultiple instance expected');
1488    if ('function' === typeof window.ParsleyValidator.validators[name])
1489      assert = window.ParsleyValidator.validators[name](requirements);
1490    if ('Assert' !== assert.__parentClass__)
1491      throw new Error('Valid validator expected');
1492    var getPriority = function () {
1493      if ('undefined' !== typeof parsleyField.options[name + 'Priority'])
1494        return parsleyField.options[name + 'Priority'];
1495      return ParsleyUtils.get(assert, 'priority') || 2;
1496    };
1497    priority = priority || getPriority();
1498    // If validator have a requirementsTransformer, execute it
1499    if ('function' === typeof assert.requirementsTransformer) {
1500      requirements = assert.requirementsTransformer();
1501      // rebuild assert with new requirements
1502      assert = window.ParsleyValidator.validators[name](requirements);
1503    }
1504    return $.extend(assert, {
1505      name: name,
1506      requirements: requirements,
1507      priority: priority,
1508      groups: [priority],
1509      isDomConstraint: isDomConstraint || ParsleyUtils.attr(parsleyField.$element, parsleyField.options.namespace, name)
1510    });
1511  };
1512
1513  var ParsleyField = function (field, OptionsFactory, parsleyFormInstance) {
1514    this.__class__ = 'ParsleyField';
1515    this.__id__ = ParsleyUtils.hash(4);
1516    this.$element = $(field);
1517    // If we have a parent `ParsleyForm` instance given, use its `OptionsFactory`, and save parent
1518    if ('undefined' !== typeof parsleyFormInstance) {
1519      this.parent = parsleyFormInstance;
1520      this.OptionsFactory = this.parent.OptionsFactory;
1521      this.options = this.OptionsFactory.get(this);
1522    // Else, take the `Parsley` one
1523    } else {
1524      this.OptionsFactory = OptionsFactory;
1525      this.options = this.OptionsFactory.get(this);
1526    }
1527    // Initialize some properties
1528    this.constraints = [];
1529    this.constraintsByName = {};
1530    this.validationResult = [];
1531    // Bind constraints
1532    this._bindConstraints();
1533  };
1534  ParsleyField.prototype = {
1535    // # Public API
1536    // Validate field and $.emit some events for mainly `ParsleyUI`
1537    // @returns validationResult:
1538    //  - `true` if all constraints pass
1539    //  - `[]` if not required field and empty (not validated)
1540    //  - `[Violation, [Violation...]]` if there were validation errors
1541    validate: function (force) {
1542      this.value = this.getValue();
1543      // Field Validate event. `this.value` could be altered for custom needs
1544      $.emit('parsley:field:validate', this);
1545      $.emit('parsley:field:' + (this.isValid(force, this.value) ? 'success' : 'error'), this);
1546      // Field validated event. `this.validationResult` could be altered for custom needs too
1547      $.emit('parsley:field:validated', this);
1548      return this.validationResult;
1549    },
1550    // Just validate field. Do not trigger any event
1551    // Same @return as `validate()`
1552    isValid: function (force, value) {
1553      // Recompute options and rebind constraints to have latest changes
1554      this.refreshConstraints();
1555      // Sort priorities to validate more important first
1556      var priorities = this._getConstraintsSortedPriorities();
1557      if (0 === priorities.length)
1558        return this.validationResult = [];
1559      // Value could be passed as argument, needed to add more power to 'parsley:field:validate'
1560      if ('undefined' === typeof value || null === value)
1561        value = this.getValue();
1562      // If a field is empty and not required, leave it alone, it's just fine
1563      // Except if `data-parsley-validate-if-empty` explicitely added, useful for some custom validators
1564      if (!value.length && !this._isRequired() && 'undefined' === typeof this.options.validateIfEmpty && true !== force)
1565        return this.validationResult = [];
1566      // If we want to validate field against all constraints, just call Validator and let it do the job
1567      if (false === this.options.priorityEnabled)
1568        return true === (this.validationResult = this.validateThroughValidator(value, this.constraints, 'Any'));
1569      // Else, iterate over priorities one by one, and validate related asserts one by one
1570      for (var i = 0; i < priorities.length; i++)
1571        if (true !== (this.validationResult = this.validateThroughValidator(value, this.constraints, priorities[i])))
1572          return false;
1573      return true;
1574    },
1575    // @returns Parsley field computed value that could be overrided or configured in DOM
1576    getValue: function () {
1577      var value;
1578      // Value could be overriden in DOM
1579      if ('undefined' !== typeof this.options.value)
1580        value = this.options.value;
1581      else
1582        value = this.$element.val();
1583      // Handle wrong DOM or configurations
1584      if ('undefined' === typeof value || null === value)
1585        return '';
1586      // Use `data-parsley-trim-value="true"` to auto trim inputs entry
1587      if (true === this.options.trimValue)
1588        return value.replace(/^\s+|\s+$/g, '');
1589      return value;
1590    },
1591    // Actualize options that could have change since previous validation
1592    // Re-bind accordingly constraints (could be some new, removed or updated)
1593    refreshConstraints: function () {
1594      return this.actualizeOptions()._bindConstraints();
1595    },
1596    /**
1597    * Add a new constraint to a field
1598    *
1599    * @method addConstraint
1600    * @param {String}   name
1601    * @param {Mixed}    requirements      optional
1602    * @param {Number}   priority          optional
1603    * @param {Boolean}  isDomConstraint   optional
1604    */
1605    addConstraint: function (name, requirements, priority, isDomConstraint) {
1606      name = name.toLowerCase();
1607      if ('function' === typeof window.ParsleyValidator.validators[name]) {
1608        var constraint = new ConstraintFactory(this, name, requirements, priority, isDomConstraint);
1609        // if constraint already exist, delete it and push new version
1610        if ('undefined' !== this.constraintsByName[constraint.name])
1611          this.removeConstraint(constraint.name);
1612        this.constraints.push(constraint);
1613        this.constraintsByName[constraint.name] = constraint;
1614      }
1615      return this;
1616    },
1617    // Remove a constraint
1618    removeConstraint: function (name) {
1619      for (var i = 0; i < this.constraints.length; i++)
1620        if (name === this.constraints[i].name) {
1621          this.constraints.splice(i, 1);
1622          break;
1623        }
1624      delete this.constraintsByName[name];
1625      return this;
1626    },
1627    // Update a constraint (Remove + re-add)
1628    updateConstraint: function (name, parameters, priority) {
1629      return this.removeConstraint(name)
1630        .addConstraint(name, parameters, priority);
1631    },
1632    // # Internals
1633    // Internal only.
1634    // Bind constraints from config + options + DOM
1635    _bindConstraints: function () {
1636      var constraints = [], constraintsByName = {};
1637      // clean all existing DOM constraints to only keep javascript user constraints
1638      for (var i = 0; i < this.constraints.length; i++)
1639        if (false === this.constraints[i].isDomConstraint) {
1640          constraints.push(this.constraints[i]);
1641          constraintsByName[this.constraints[i].name] = this.constraints[i];
1642        }
1643      this.constraints = constraints;
1644      this.constraintsByName = constraintsByName;
1645      // then re-add Parsley DOM-API constraints
1646      for (var name in this.options)
1647        this.addConstraint(name, this.options[name]);
1648      // finally, bind special HTML5 constraints
1649      return this._bindHtml5Constraints();
1650    },
1651    // Internal only.
1652    // Bind specific HTML5 constraints to be HTML5 compliant
1653    _bindHtml5Constraints: function () {
1654      // html5 required
1655      if (this.$element.hasClass('required') || this.$element.attr('required'))
1656        this.addConstraint('required', true, undefined, true);
1657      // html5 pattern
1658      if ('string' === typeof this.$element.attr('pattern'))
1659        this.addConstraint('pattern', this.$element.attr('pattern'), undefined, true);
1660      // range
1661      if ('undefined' !== typeof this.$element.attr('min') && 'undefined' !== typeof this.$element.attr('max'))
1662        this.addConstraint('range', [this.$element.attr('min'), this.$element.attr('max')], undefined, true);
1663      // HTML5 min
1664      else if ('undefined' !== typeof this.$element.attr('min'))
1665        this.addConstraint('min', this.$element.attr('min'), undefined, true);
1666      // HTML5 max
1667      else if ('undefined' !== typeof this.$element.attr('max'))
1668        this.addConstraint('max', this.$element.attr('max'), undefined, true);
1669    
1670      // length
1671      if ('undefined' !== typeof this.$element.attr('minlength') && 'undefined' !== typeof this.$element.attr('maxlength'))
1672        this.addConstraint('length', [this.$element.attr('minlength'), this.$element.attr('maxlength')], undefined, true);
1673      // HTML5 minlength
1674      else if ('undefined' !== typeof this.$element.attr('minlength'))
1675        this.addConstraint('minlength', this.$element.attr('minlength'), undefined, true);
1676      // HTML5 maxlength
1677      else if ('undefined' !== typeof this.$element.attr('maxlength'))
1678        this.addConstraint('maxlength', this.$element.attr('maxlength'), undefined, true);
1679
1680      // html5 types
1681      var type = this.$element.attr('type');
1682      if ('undefined' === typeof type)
1683        return this;
1684      // Small special case here for HTML5 number: integer validator if step attribute is undefined or an integer value, number otherwise
1685      if ('number' === type) {
1686        if (('undefined' === typeof this.$element.attr('step')) || (0 === parseFloat(this.$element.attr('step')) % 1)) {
1687          return this.addConstraint('type', 'integer', undefined, true);
1688        } else {
1689          return this.addConstraint('type', 'number', undefined, true);
1690        }
1691      // Regular other HTML5 supported types
1692      } else if (new RegExp(type, 'i').test('email url range')) {
1693        return this.addConstraint('type', type, undefined, true);
1694      }
1695      return this;
1696    },
1697    // Internal only.
1698    // Field is required if have required constraint without `false` value
1699    _isRequired: function () {
1700      if ('undefined' === typeof this.constraintsByName.required)
1701        return false;
1702      return false !== this.constraintsByName.required.requirements;
1703    },
1704    // Internal only.
1705    // Sort constraints by priority DESC
1706    _getConstraintsSortedPriorities: function () {
1707      var priorities = [];
1708      // Create array unique of priorities
1709      for (var i = 0; i < this.constraints.length; i++)
1710        if (-1 === priorities.indexOf(this.constraints[i].priority))
1711          priorities.push(this.constraints[i].priority);
1712      // Sort them by priority DESC
1713      priorities.sort(function (a, b) { return b - a; });
1714      return priorities;
1715    }
1716  };
1717
1718  var ParsleyMultiple = function () {
1719    this.__class__ = 'ParsleyFieldMultiple';
1720  };
1721  ParsleyMultiple.prototype = {
1722    // Add new `$element` sibling for multiple field
1723    addElement: function ($element) {
1724      this.$elements.push($element);
1725      return this;
1726    },
1727    // See `ParsleyField.refreshConstraints()`
1728    refreshConstraints: function () {
1729      var fieldConstraints;
1730      this.constraints = [];
1731      // Select multiple special treatment
1732      if (this.$element.is('select')) {
1733        this.actualizeOptions()._bindConstraints();
1734        return this;
1735      }
1736      // Gather all constraints for each input in the multiple group
1737      for (var i = 0; i < this.$elements.length; i++) {
1738        // Check if element have not been dynamically removed since last binding
1739        if (!$('html').has(this.$elements[i]).length) {
1740          this.$elements.splice(i, 1);
1741          continue;
1742        }
1743        fieldConstraints = this.$elements[i].data('ParsleyFieldMultiple').refreshConstraints().constraints;
1744        for (var j = 0; j < fieldConstraints.length; j++)
1745          this.addConstraint(fieldConstraints[j].name, fieldConstraints[j].requirements, fieldConstraints[j].priority, fieldConstraints[j].isDomConstraint);
1746      }
1747      return this;
1748    },
1749    // See `ParsleyField.getValue()`
1750    getValue: function () {
1751      // Value could be overriden in DOM
1752      if ('undefined' !== typeof this.options.value)
1753        return this.options.value;
1754      // Radio input case
1755      if (this.$element.is('input[type=radio]'))
1756        return $('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]:checked').val() || '';
1757      // checkbox input case
1758      if (this.$element.is('input[type=checkbox]')) {
1759        var values = [];
1760        $('[' + this.options.namespace + 'multiple="' + this.options.multiple + '"]:checked').each(function () {
1761          values.push($(this).val());
1762        });
1763        return values.length ? values : [];
1764      }
1765      // Select multiple case
1766      if (this.$element.is('select') && null === this.$element.val())
1767        return [];
1768      // Default case that should never happen
1769      return this.$element.val();
1770    },
1771    _init: function (multiple) {
1772      this.$elements = [this.$element];
1773      this.options.multiple = multiple;
1774      return this;
1775    }
1776  };
1777
1778  var
1779    o = $({}),
1780    subscribed = {};
1781  // $.listen(name, callback);
1782  // $.listen(name, context, callback);
1783  $.listen = function (name) {
1784    if ('undefined' === typeof subscribed[name])
1785      subscribed[name] = [];
1786    if ('function' === typeof arguments[1])
1787      return subscribed[name].push({ fn: arguments[1] });
1788    if ('object' === typeof arguments[1] && 'function' === typeof arguments[2])
1789      return subscribed[name].push({ fn: arguments[2], ctxt: arguments[1] });
1790    throw new Error('Wrong parameters');
1791  };
1792  $.listenTo = function (instance, name, fn) {
1793    if ('undefined' === typeof subscribed[name])
1794      subscribed[name] = [];
1795    if (!(instance instanceof ParsleyField) && !(instance instanceof ParsleyForm))
1796      throw new Error('Must give Parsley instance');
1797    if ('string' !== typeof name || 'function' !== typeof fn)
1798      throw new Error('Wrong parameters');
1799    subscribed[name].push({ instance: instance, fn: fn });
1800  };
1801  $.unsubscribe = function (name, fn) {
1802    if ('undefined' === typeof subscribed[name])
1803      return;
1804    if ('string' !== typeof name || 'function' !== typeof fn)
1805      throw new Error('Wrong arguments');
1806    for (var i = 0; i < subscribed[name].length; i++)
1807      if (subscribed[name][i].fn === fn)
1808        return subscribed[name].splice(i, 1);
1809  };
1810  $.unsubscribeTo = function (instance, name) {
1811    if ('undefined' === typeof subscribed[name])
1812      return;
1813    if (!(instance instanceof ParsleyField) && !(instance instanceof ParsleyForm))
1814      throw new Error('Must give Parsley instance');
1815    for (var i = 0; i < subscribed[name].length; i++)
1816      if ('undefined' !== typeof subscribed[name][i].instance && subscribed[name][i].instance.__id__ === instance.__id__)
1817        return subscribed[name].splice(i, 1);
1818  };
1819  $.unsubscribeAll = function (name) {
1820    if ('undefined' === typeof subscribed[name])
1821      return;
1822    delete subscribed[name];
1823  };
1824  // $.emit(name [, arguments...]);
1825  // $.emit(name, instance [, arguments...]);
1826  $.emit = function (name, instance) {
1827    if ('undefined' === typeof subscribed[name])
1828      return;
1829    // loop through registered callbacks for this event
1830    for (var i = 0; i < subscribed[name].length; i++) {
1831      // if instance is not registered, simple emit
1832      if ('undefined' === typeof subscribed[name][i].instance) {
1833        subscribed[name][i].fn.apply('undefined' !== typeof subscribed[name][i].ctxt ? subscribed[name][i].ctxt : o, Array.prototype.slice.call(arguments, 1));
1834        continue;
1835      }
1836      // if instance registered but no instance given for the emit, continue
1837      if (!(instance instanceof ParsleyField) && !(instance instanceof ParsleyForm))
1838        continue;
1839      // if instance is registered and same id, emit
1840      if (subscribed[name][i].instance.__id__ === instance.__id__) {
1841        subscribed[name][i].fn.apply(o, Array.prototype.slice.call(arguments, 1));
1842        continue;
1843      }
1844      // if registered instance is a Form and fired one is a Field, loop over all its fields and emit if field found
1845      if (subscribed[name][i].instance instanceof ParsleyForm && instance instanceof ParsleyField)
1846        for (var j = 0; j < subscribed[name][i].instance.fields.length; j++)
1847          if (subscribed[name][i].instance.fields[j].__id__ === instance.__id__) {
1848            subscribed[name][i].fn.apply(o, Array.prototype.slice.call(arguments, 1));
1849            continue;
1850          }
1851    }
1852  };
1853  $.subscribed = function () { return subscribed; };
1854
1855// ParsleyConfig definition if not already set
1856window.ParsleyConfig = window.ParsleyConfig || {};
1857window.ParsleyConfig.i18n = window.ParsleyConfig.i18n || {};
1858// Define then the messages
1859window.ParsleyConfig.i18n.en = $.extend(window.ParsleyConfig.i18n.en || {}, {
1860  defaultMessage: "This value seems to be invalid.",
1861  type: {
1862    email:        "This value should be a valid email.",
1863    url:          "This value should be a valid url.",
1864    number:       "This value should be a valid number.",
1865    integer:      "This value should be a valid integer.",
1866    digits:       "This value should be digits.",
1867    alphanum:     "This value should be alphanumeric."
1868  },
1869  notblank:       "This value should not be blank.",
1870  required:       "This value is required.",
1871  pattern:        "This value seems to be invalid.",
1872  min:            "This value should be greater than or equal to %s.",
1873  max:            "This value should be lower than or equal to %s.",
1874  range:          "This value should be between %s and %s.",
1875  minlength:      "This value is too short. It should have %s characters or more.",
1876  maxlength:      "This value is too long. It should have %s characters or fewer.",
1877  length:         "This value length is invalid. It should be between %s and %s characters long.",
1878  mincheck:       "You must select at least %s choices.",
1879  maxcheck:       "You must select %s choices or fewer.",
1880  check:          "You must select between %s and %s choices.",
1881  equalto:        "This value should be the same."
1882});
1883// If file is loaded after Parsley main file, auto-load locale
1884if ('undefined' !== typeof window.ParsleyValidator)
1885  window.ParsleyValidator.addCatalog('en', window.ParsleyConfig.i18n.en, true);
1886
1887//     Parsley.js 2.0.6
1888//     http://parsleyjs.org
1889//     (c) 20012-2014 Guillaume Potier, Wisembly
1890//     Parsley may be freely distributed under the MIT license.
1891
1892  // ### Parsley factory
1893  var Parsley = function (element, options, parsleyFormInstance) {
1894    this.__class__ = 'Parsley';
1895    this.__version__ = '2.0.6';
1896    this.__id__ = ParsleyUtils.hash(4);
1897    // Parsley must be instantiated with a DOM element or jQuery $element
1898    if ('undefined' === typeof element)
1899      throw new Error('You must give an element');
1900    if ('undefined' !== typeof parsleyFormInstance && 'ParsleyForm' !== parsleyFormInstance.__class__)
1901      throw new Error('Parent instance must be a ParsleyForm instance');
1902    return this.init($(element), options, parsleyFormInstance);
1903  };
1904  Parsley.prototype = {
1905    init: function ($element, options, parsleyFormInstance) {
1906      if (!$element.length)
1907        throw new Error('You must bind Parsley on an existing element.');
1908      this.$element = $element;
1909      // If element have already been binded, returns its saved Parsley instance
1910      if (this.$element.data('Parsley')) {
1911        var savedparsleyFormInstance = this.$element.data('Parsley');
1912        // If saved instance have been binded without a ParsleyForm parent and there is one given in this call, add it
1913        if ('undefined' !== typeof parsleyFormInstance)
1914          savedparsleyFormInstance.parent = parsleyFormInstance;
1915        return savedparsleyFormInstance;
1916      }
1917      // Handle 'static' options
1918      this.OptionsFactory = new ParsleyOptionsFactory(ParsleyDefaults, ParsleyUtils.get(window, 'ParsleyConfig') || {}, options, this.getNamespace(options));
1919      this.options = this.OptionsFactory.get(this);
1920      // A ParsleyForm instance is obviously a `<form>` elem but also every node that is not an input and have `data-parsley-validate` attribute
1921      if (this.$element.is('form') || (ParsleyUtils.attr(this.$element, this.options.namespace, 'validate') && !this.$element.is(this.options.inputs)))
1922        return this.bind('parsleyForm');
1923      // Every other supported element and not excluded element is binded as a `ParsleyField` or `ParsleyFieldMultiple`
1924      else if (this.$element.is(this.options.inputs) && !this.$element.is(this.options.excluded))
1925        return this.isMultiple() ? this.handleMultiple(parsleyFormInstance) : this.bind('parsleyField', parsleyFormInstance);
1926      return this;
1927    },
1928    isMultiple: function () {
1929      return (this.$element.is('input[type=radio], input[type=checkbox]') && 'undefined' === typeof this.options.multiple) || (this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple'));
1930    },
1931    // Multiples fields are a real nightmare :(
1932    // Maybe some refacto would be appreciated here...
1933    handleMultiple: function (parsleyFormInstance) {
1934      var
1935        that = this,
1936        name,
1937        multiple,
1938        parsleyMultipleInstance;
1939      // Get parsleyFormInstance options if exist, mixed with element attributes
1940      this.options = $.extend(this.options, parsleyFormInstance ? parsleyFormInstance.OptionsFactory.get(parsleyFormInstance) : {}, ParsleyUtils.attr(this.$element, this.options.namespace));
1941      // Handle multiple name
1942      if (this.options.multiple)
1943        multiple = this.options.multiple;
1944      else if ('undefined' !== typeof this.$element.attr('name') && this.$element.attr('name').length)
1945        multiple = name = this.$element.attr('name');
1946      else if ('undefined' !== typeof this.$element.attr('id') && this.$element.attr('id').length)
1947        multiple = this.$element.attr('id');
1948      // Special select multiple input
1949      if (this.$element.is('select') && 'undefined' !== typeof this.$element.attr('multiple')) {
1950        return this.bind('parsleyFieldMultiple', parsleyFormInstance, multiple || this.__id__);
1951      // Else for radio / checkboxes, we need a `name` or `data-parsley-multiple` to properly bind it
1952      } else if ('undefined' === typeof multiple) {
1953        if (window.console && window.console.warn)
1954          window.console.warn('To be binded by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.', this.$element);
1955        return this;
1956      }
1957      // Remove special chars
1958      multiple = multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g, '');
1959      // Add proper `data-parsley-multiple` to siblings if we have a valid multiple name
1960      if ('undefined' !== typeof name) {
1961        $('input[name="' + name + '"]').each(function () {
1962          if ($(this).is('input[type=radio], input[type=checkbox]'))
1963            $(this).attr(that.options.namespace + 'multiple', multiple);
1964        });
1965      }
1966      // Check here if we don't already have a related multiple instance saved
1967      if ($('[' + this.options.namespace + 'multiple=' + multiple +']').length) {
1968        for (var i = 0; i < $('[' + this.options.namespace + 'multiple=' + multiple +']').length; i++) {
1969          if ('undefined' !== typeof $($('[' + this.options.namespace + 'multiple=' + multiple +']').get(i)).data('Parsley')) {
1970            parsleyMultipleInstance = $($('[' + this.options.namespace + 'multiple=' + multiple +']').get(i)).data('Parsley');
1971            if (!this.$element.data('ParsleyFieldMultiple')) {
1972              parsleyMultipleInstance.addElement(this.$element);
1973              this.$element.attr(this.options.namespace + 'id', parsleyMultipleInstance.__id__);
1974            }
1975            break;
1976          }
1977        }
1978      }
1979      // Create a secret ParsleyField instance for every multiple field. It would be stored in `data('ParsleyFieldMultiple')`
1980      // And would be useful later to access classic `ParsleyField` stuff while being in a `ParsleyFieldMultiple` instance
1981      this.bind('parsleyField', parsleyFormInstance, multiple, true);
1982      return parsleyMultipleInstance || this.bind('parsleyFieldMultiple', parsleyFormInstance, multiple);
1983    },
1984    // Retrieve namespace used for DOM-API
1985    getNamespace: function (options) {
1986      // `data-parsley-namespace=<namespace>`
1987      if ('undefined' !== typeof this.$element.data('parsleyNamespace'))
1988        return this.$element.data('parsleyNamespace');
1989      if ('undefined' !== typeof ParsleyUtils.get(options, 'namespace'))
1990        return options.namespace;
1991      if ('undefined' !== typeof ParsleyUtils.get(window, 'ParsleyConfig.namespace'))
1992        return window.ParsleyConfig.namespace;
1993      return ParsleyDefaults.namespace;
1994    },
1995    // Return proper `ParsleyForm`, `ParsleyField` or `ParsleyFieldMultiple`
1996    bind: function (type, parentParsleyFormInstance, multiple, doNotStore) {
1997      var parsleyInstance;
1998      switch (type) {
1999        case 'parsleyForm':
2000          parsleyInstance = $.extend(
2001            new ParsleyForm(this.$element, this.OptionsFactory),
2002            new ParsleyAbstract(),
2003            window.ParsleyExtend
2004          )._bindFields();
2005          break;
2006        case 'parsleyField':
2007          parsleyInstance = $.extend(
2008            new ParsleyField(this.$element, this.OptionsFactory, parentParsleyFormInstance),
2009            new ParsleyAbstract(),
2010            window.ParsleyExtend
2011          );
2012          break;
2013        case 'parsleyFieldMultiple':
2014          parsleyInstance = $.extend(
2015            new ParsleyField(this.$element, this.OptionsFactory, parentParsleyFormInstance),
2016            new ParsleyAbstract(),
2017            new ParsleyMultiple(),
2018            window.ParsleyExtend
2019          )._init(multiple);
2020          break;
2021        default:
2022          throw new Error(type + 'is not a supported Parsley type');
2023      }
2024      if ('undefined' !== typeof multiple)
2025        ParsleyUtils.setAttr(this.$element, this.options.namespace, 'multiple', multiple);
2026      if ('undefined' !== typeof doNotStore) {
2027        this.$element.data('ParsleyFieldMultiple', parsleyInstance);
2028        return parsleyInstance;
2029      }
2030      // Store instance if `ParsleyForm`, `ParsleyField` or `ParsleyFieldMultiple`
2031      if (new RegExp('ParsleyF', 'i').test(parsleyInstance.__class__)) {
2032        // Store for later access the freshly binded instance in DOM element itself using jQuery `data()`
2033        this.$element.data('Parsley', parsleyInstance);
2034        // Tell the world we got a new ParsleyForm or ParsleyField instance!
2035        $.emit('parsley:' + ('parsleyForm' === type ? 'form' : 'field') + ':init', parsleyInstance);
2036      }
2037      return parsleyInstance;
2038    }
2039  };
2040  // ### jQuery API
2041  // `$('.elem').parsley(options)` or `$('.elem').psly(options)`
2042  $.fn.parsley = $.fn.psly = function (options) {
2043    if (this.length > 1) {
2044      var instances = [];
2045      this.each(function () {
2046        instances.push($(this).parsley(options));
2047      });
2048      return instances;
2049    }
2050    // Return undefined if applied to non existing DOM element
2051    if (!$(this).length) {
2052      if (window.console && window.console.warn)
2053        window.console.warn('You must bind Parsley on an existing element.');
2054      return;
2055    }
2056    return new Parsley(this, options);
2057  };
2058  // ### ParsleyUI
2059  // UI is a class apart that only listen to some events and them modify DOM accordingly
2060  // Could be overri
2060den by defining a `window.ParsleyConfig.ParsleyUI` appropriate class (with `listen()` method basically)
2061  window.ParsleyUI = 'function' === typeof ParsleyUtils.get(window, 'ParsleyConfig.ParsleyUI') ?
2062    new window.ParsleyConfig.ParsleyUI().listen() : new ParsleyUI().listen();
2063  // ### ParsleyField and ParsleyForm extension
2064  // Ensure that defined if not already the case
2065  if ('undefined' === typeof window.ParsleyExtend)
2066    window.ParsleyExtend = {};
2067  // ### ParsleyConfig
2068  // Ensure that defined if not already the case
2069  if ('undefined' === typeof window.ParsleyConfig)
2070    window.ParsleyConfig = {};
2071  // ### Globals
2072  window.Parsley = window.psly = Parsley;
2073  window.ParsleyUtils = ParsleyUtils;
2074  window.ParsleyValidator = new ParsleyValidator(window.ParsleyConfig.validators, window.ParsleyConfig.i18n);
2075  // ### PARSLEY auto-binding
2076  // Prevent it by setting `ParsleyConfig.autoBind` to `false`
2077  if (false !== ParsleyUtils.get(window, 'ParsleyConfig.autoBind'))
2078    $(function () {
2079      // Works only on `data-parsley-validate`.
2080      if ($('[data-parsley-validate]').length)
2081        $('[data-parsley-validate]').parsley();
2082    });
2083}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.