PageSourceSearch

https://doe.cl/vendor/jsvalidation/js/jsvalidation.js

js doe.cl collected 2026-09-24 21:16:43 UTC 142,746 bytes, 4,263 lines download raw bytes

vendor: 12,127 bytes, lines 1-389
1/*!
2 * jQuery Validation Plugin v1.14.0
3 *
4 * http://jqueryvalidation.org/
5 *
6 * Copyright (c) 2015 Jörn Zaefferer
7 * Released under the MIT license
8 */
9(function( factory ) {
10	if ( typeof define === "function" && define.amd ) {
11		define( ["jquery"], factory );
12	} else {
13		factory( jQuery );
14	}
15}(function( $ ) {
16
17$.extend($.fn, {
18	// http://jqueryvalidation.org/validate/
19	validate: function( options ) {
20
21		// if nothing is selected, return nothing; can't chain anyway
22		if ( !this.length ) {
23			if ( options && options.debug && window.console ) {
24				console.warn( "Nothing selected, can't validate, returning nothing." );
25			}
26			return;
27		}
28
29		// check if a validator for this form was already created
30		var validator = $.data( this[ 0 ], "validator" );
31		if ( validator ) {
32			return validator;
33		}
34
35		// Add novalidate tag if HTML5.
36		this.attr( "novalidate", "novalidate" );
37
38		validator = new $.validator( options, this[ 0 ] );
39		$.data( this[ 0 ], "validator", validator );
40
41		if ( validator.settings.onsubmit ) {
42
43			this.on( "click.validate", ":submit", function( event ) {
44				if ( validator.settings.submitHandler ) {
45					validator.submitButton = event.target;
46				}
47
48				// allow suppressing validation by adding a cancel class to the submit button
49				if ( $( this ).hasClass( "cancel" ) ) {
50					validator.cancelSubmit = true;
51				}
52
53				// allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
54				if ( $( this ).attr( "formnovalidate" ) !== undefined ) {
55					validator.cancelSubmit = true;
56				}
57			});
58
59			// validate the form on submit
60			this.on( "submit.validate", function( event ) {
61				if ( validator.settings.debug ) {
62					// prevent form submit to be able to see console output
63					event.preventDefault();
64				}
65				function handle() {
66					var hidden, result;
67					if ( validator.settings.submitHandler ) {
68						if ( validator.submitButton ) {
69							// insert a hidden input as a replacement for the missing submit button
70							hidden = $( "<input type='hidden'/>" )
71								.attr( "name", validator.submitButton.name )
72								.val( $( validator.submitButton ).val() )
73								.appendTo( validator.currentForm );
74						}
75						result = validator.settings.submitHandler.call( validator, validator.currentForm, event );
76						if ( validator.submitButton ) {
77							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
78							hidden.remove();
79						}
80						if ( result !== undefined ) {
81							return result;
82						}
83						return false;
84					}
85					return true;
86				}
87
88				// prevent submit for invalid forms or custom submit handlers
89				if ( validator.cancelSubmit ) {
90					validator.cancelSubmit = false;
91					return handle();
92				}
93				if ( validator.form() ) {
94					if ( validator.pendingRequest ) {
95						validator.formSubmitted = true;
96						return false;
97					}
98					return handle();
99				} else {
100					validator.focusInvalid();
101					return false;
102				}
103			});
104		}
105
106		return validator;
107	},
108	// http://jqueryvalidation.org/valid/
109	valid: function() {
110		var valid, validator, errorList;
111
112		if ( $( this[ 0 ] ).is( "form" ) ) {
113			valid = this.validate().form();
114		} else {
115			errorList = [];
116			valid = true;
117			validator = $( this[ 0 ].form ).validate();
118			this.each( function() {
119				valid = validator.element( this ) && valid;
120				errorList = errorList.concat( validator.errorList );
121			});
122			validator.errorList = errorList;
123		}
124		return valid;
125	},
126
127	// http://jqueryvalidation.org/rules/
128	rules: function( command, argument ) {
129		var element = this[ 0 ],
130			settings, staticRules, existingRules, data, param, filtered;
131
132		if ( command ) {
133			settings = $.data( element.form, "validator" ).settings;
134			staticRules = settings.rules;
135			existingRules = $.validator.staticRules( element );
136			switch ( command ) {
137			case "add":
138				$.extend( existingRules, $.validator.normalizeRule( argument ) );
139				// remove messages from rules, but allow them to be set separately
140				delete existingRules.messages;
141				staticRules[ element.name ] = existingRules;
142				if ( argument.messages ) {
143					settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );
144				}
145				break;
146			case "remove":
147				if ( !argument ) {
148					delete staticRules[ element.name ];
149					return existingRules;
150				}
151				filtered = {};
152				$.each( argument.split( /\s/ ), function( index, method ) {
153					filtered[ method ] = existingRules[ method ];
154					delete existingRules[ method ];
155					if ( method === "required" ) {
156						$( element ).removeAttr( "aria-required" );
157					}
158				});
159				return filtered;
160			}
161		}
162
163		data = $.validator.normalizeRules(
164		$.extend(
165			{},
166			$.validator.classRules( element ),
167			$.validator.attributeRules( element ),
168			$.validator.dataRules( element ),
169			$.validator.staticRules( element )
170		), element );
171
172		// make sure required is at front
173		if ( data.required ) {
174			param = data.required;
175			delete data.required;
176			data = $.extend( { required: param }, data );
177			$( element ).attr( "aria-required", "true" );
178		}
179
180		// make sure remote is at back
181		if ( data.remote ) {
182			param = data.remote;
183			delete data.remote;
184			data = $.extend( data, { remote: param });
185		}
186
187		return data;
188	}
189});
190
191// Custom selectors
192$.extend( $.expr[ ":" ], {
193	// http://jqueryvalidation.org/blank-selector/
194	blank: function( a ) {
195		return !$.trim( "" + $( a ).val() );
196	},
197	// http://jqueryvalidation.org/filled-selector/
198	filled: function( a ) {
199		return !!$.trim( "" + $( a ).val() );
200	},
201	// http://jqueryvalidation.org/unchecked-selector/
202	unchecked: function( a ) {
203		return !$( a ).prop( "checked" );
204	}
205});
206
207// constructor for validator
208$.validator = function( options, form ) {
209	this.settings = $.extend( true, {}, $.validator.defaults, options );
210	this.currentForm = form;
211	this.init();
212};
213
214// http://jqueryvalidation.org/jQuery.validator.format/
215$.validator.format = function( source, params ) {
216	if ( arguments.length === 1 ) {
217		return function() {
218			var args = $.makeArray( arguments );
219			args.unshift( source );
220			return $.validator.format.apply( this, args );
221		};
222	}
223	if ( arguments.length > 2 && params.constructor !== Array  ) {
224		params = $.makeArray( arguments ).slice( 1 );
225	}
226	if ( params.constructor !== Array ) {
227		params = [ params ];
228	}
229	$.each( params, function( i, n ) {
230		source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() {
231			return n;
232		});
233	});
234	return source;
235};
236
237$.extend( $.validator, {
238
239	defaults: {
240		messages: {},
241		groups: {},
242		rules: {},
243		errorClass: "error",
244		validClass: "valid",
245		errorElement: "label",
246		focusCleanup: false,
247		focusInvalid: true,
248		errorContainer: $( [] ),
249		errorLabelContainer: $( [] ),
250		onsubmit: true,
251		ignore: ":hidden",
252		ignoreTitle: false,
253		onfocusin: function( element ) {
254			this.lastActive = element;
255
256			// Hide error label and remove error class on focus if enabled
257			if ( this.settings.focusCleanup ) {
258				if ( this.settings.unhighlight ) {
259					this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
260				}
261				this.hideThese( this.errorsFor( element ) );
262			}
263		},
264		onfocusout: function( element ) {
265			if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
266				this.element( element );
267			}
268		},
269		onkeyup: function( element, event ) {
270			// Avoid revalidate the field when pressing one of the following keys
271			// Shift       => 16
272			// Ctrl        => 17
273			// Alt         => 18
274			// Caps lock   => 20
275			// End         => 35
276			// Home        => 36
277			// Left arrow  => 37
278			// Up arrow    => 38
279			// Right arrow => 39
280			// Down arrow  => 40
281			// Insert      => 45
282			// Num lock    => 144
283			// AltGr key   => 225
284			var excludedKeys = [
285				16, 17, 18, 20, 35, 36, 37,
286				38, 39, 40, 45, 144, 225
287			];
288
289			if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) {
290				return;
291			} else if ( element.name in this.submitted || element === this.lastElement ) {
292				this.element( element );
293			}
294		},
295		onclick: function( element ) {
296			// click on selects, radiobuttons and checkboxes
297			if ( element.name in this.submitted ) {
298				this.element( element );
299
300			// or option elements, check parent select in that case
301			} else if ( element.parentNode.name in this.submitted ) {
302				this.element( element.parentNode );
303			}
304		},
305		highlight: function( element, errorClass, validClass ) {
306			if ( element.type === "radio" ) {
307				this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
308			} else {
309				$( element ).addClass( errorClass ).removeClass( validClass );
310			}
311		},
312		unhighlight: function( element, errorClass, validClass ) {
313			if ( element.type === "radio" ) {
314				this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
315			} else {
316				$( element ).removeClass( errorClass ).addClass( validClass );
317			}
318		}
319	},
320
321	// http://jqueryvalidation.org/jQuery.validator.setDefaults/
322	setDefaults: function( settings ) {
323		$.extend( $.validator.defaults, settings );
324	},
325
326	messages: {
327		required: "This field is required.",
328		remote: "Please fix this field.",
329		email: "Please enter a valid email address.",
330		url: "Please enter a valid URL.",
331		date: "Please enter a valid date.",
332		dateISO: "Please enter a valid date ( ISO ).",
333		number: "Please enter a valid number.",
334		digits: "Please enter only digits.",
335		creditcard: "Please enter a valid credit card number.",
336		equalTo: "Please enter the same value again.",
337		maxlength: $.validator.format( "Please enter no more than {0} characters." ),
338		minlength: $.validator.format( "Please enter at least {0} characters." ),
339		rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ),
340		range: $.validator.format( "Please enter a value between {0} and {1}." ),
341		max: $.validator.format( "Please enter a value less than or equal to {0}." ),
342		min: $.validator.format( "Please enter a value greater than or equal to {0}." )
343	},
344
345	autoCreateRanges: false,
346
347	prototype: {
348
349		init: function() {
350			this.labelContainer = $( this.settings.errorLabelContainer );
351			this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );
352			this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );
353			this.submitted = {};
354			this.valueCache = {};
355			this.pendingRequest = 0;
356			this.pending = {};
357			this.invalid = {};
358			this.reset();
359
360			var groups = ( this.groups = {} ),
361				rules;
362			$.each( this.settings.groups, function( key, value ) {
363				if ( typeof value === "string" ) {
364					value = value.split( /\s/ );
365				}
366				$.each( value, function( index, name ) {
367					groups[ name ] = key;
368				});
369			});
370			rules = this.settings.rules;
371			$.each( rules, function( key, value ) {
372				rules[ key ] = $.validator.normalizeRule( value );
373			});
374
375			function delegate( event ) {
376				var validator = $.data( this.form, "validator" ),
377					eventType = "on" + event.type.replace( /^validate/, "" ),
378					settings = validator.settings;
379				if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) {
380					settings[ eventType ].call( validator, this, event );
381				}
382			}
383
384			$( this.currentForm )
385				.on( "focusin.validate focusout.validate keyup.validate",
386					":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " +
387					"[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " +
388					"[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " +
389					"[type='radio'], [type='checkbox']", delegate)
390				// Support: Chrome, oldIE
391				// "select" is provided as event.target when clicking a option
392				.on("click.validate", "select, option, [type='radio'], [type='checkbox']", delegate);
393
394			if ( this.settings.invalidHandler ) {
395				$( this.currentForm ).on( "invalid-form.validate", this.settings.invalidHandler );
396			}
397
398			// Add aria-required to any Static/Data/Class required fields before first validation
399			// Screen readers require this attribute to be present before the initial submission http://www.w3.org/TR/WCAG-TECHS/ARIA2.html
400			$( this.currentForm ).find( "[required], [data-rule-required], .required" ).attr( "aria-required", "true" );
401		},
402
403		// http://jqueryvalidation.org/Validator.form/
404		form: function() {
405			this.checkForm();
406			$.extend( this.submitted, this.errorMap );
407			this.invalid = $.extend({}, this.errorMap );
408			if ( !this.valid() ) {
409				$( this.currentForm ).triggerHandler( "invalid-form", [ this ]);
410			}
411			this.showErrors();
412			return this.valid();
413		},
414
415		checkForm: function() {
416			this.prepareForm();
417			for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {
418				this.check( elements[ i ] );
419			}
420			return this.valid();
421		},
422
423		// http://jqueryvalidation.org/Validator.element/
424		element: function( element ) {
425			var cleanElement = this.clean( element ),
426				checkElement = this.validationTargetFor( cleanElement ),
427				result = true;
428
429			this.lastElement = checkElement;
430
431			if ( checkElement === undefined ) {
432				delete this.invalid[ cleanElement.name ];
433			} else {
434				this.prepareElement( checkElement );
435				this.currentElements = $( checkElement );
436
437				result = this.check( checkElement ) !== false;
438				if ( result ) {
439					delete this.invalid[ checkElement.name ];
440				} else {
441					this.invalid[ checkElement.name ] = true;
442				}
443			}
444			// Add aria-invalid status for screen readers
445			$( element ).attr( "aria-invalid", !result );
446
447			if ( !this.numberOfInvalids() ) {
448				// Hide error containers on last error
449				this.toHide = this.toHide.add( this.containers );
450			}
451			this.showErrors();
452			return result;
453		},
454
455		// http://jqueryvalidation.org/Validator.showErrors/
456		showErrors: function( errors ) {
457			if ( errors ) {
458				// add items to error list and map
459				$.extend( this.errorMap, errors );
460				this.errorList = [];
461				for ( var name in errors ) {
462					this.errorList.push({
463						message: errors[ name ],
464						element: this.findByName( name )[ 0 ]
465					});
466				}
467				// remove items from success list
468				this.successList = $.grep( this.successList, function( element ) {
469					return !( element.name in errors );
470				});
471			}
472			if ( this.settings.showErrors ) {
473				this.settings.showErrors.call( this, this.errorMap, this.errorList );
474			} else {
475				this.defaultShowErrors();
476			}
477		},
478
479		// http://jqueryvalidation.org/Validator.resetForm/
480		resetForm: function() {
481			if ( $.fn.resetForm ) {
482				$( this.currentForm ).resetForm();
483			}
484			this.submitted = {};
485			this.lastElement = null;
486			this.prepareForm();
487			this.hideErrors();
488			var i, elements = this.elements()
489				.removeData( "previousValue" )
490				.removeAttr( "aria-invalid" );
491
492			if ( this.settings.unhighlight ) {
493				for ( i = 0; elements[ i ]; i++ ) {
494					this.settings.unhighlight.call( this, elements[ i ],
495						this.settings.errorClass, "" );
496				}
497			} else {
498				elements.removeClass( this.settings.errorClass );
499			}
500		},
501
502		numberOfInvalids: function() {
503			return this.objectLength( this.invalid );
504		},
505
506		objectLength: function( obj ) {
507			/* jshint unused: false */
508			var count = 0,
509				i;
510			for ( i in obj ) {
511				count++;
512			}
513			return count;
514		},
515
516		hideErrors: function() {
517			this.hideThese( this.toHide );
518		},
519
520		hideThese: function( errors ) {
521			errors.not( this.containers ).text( "" );
522			this.addWrapper( errors ).hide();
523		},
524
525		valid: function() {
526			return this.size() === 0;
527		},
528
529		size: function() {
530			return this.errorList.length;
531		},
532
533		focusInvalid: function() {
534			if ( this.settings.focusInvalid ) {
535				try {
536					$( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [])
537					.filter( ":visible" )
538					.focus()
539					// manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
540					.trigger( "focusin" );
541				} catch ( e ) {
vendor: 6,286 bytes, lines 542-743
542					// ignore IE throwing errors when focusing hidden elements
543				}
544			}
545		},
546
547		findLastActive: function() {
548			var lastActive = this.lastActive;
549			return lastActive && $.grep( this.errorList, function( n ) {
550				return n.element.name === lastActive.name;
551			}).length === 1 && lastActive;
552		},
553
554		elements: function() {
555			var validator = this,
556				rulesCache = {};
557
558			// select all valid inputs inside the form (no submit or reset buttons)
559			return $( this.currentForm )
560			.find( "input, select, textarea" )
561			.not( ":submit, :reset, :image, :disabled" )
562			.not( this.settings.ignore )
563			.filter( function() {
564				if ( !this.name && validator.settings.debug && window.console ) {
565					console.error( "%o has no name assigned", this );
566				}
567
568				// select only the first element for each name, and only those with rules specified
569				if ( this.name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
570					return false;
571				}
572
573				rulesCache[ this.name ] = true;
574				return true;
575			});
576		},
577
578		clean: function( selector ) {
579			return $( selector )[ 0 ];
580		},
581
582		errors: function() {
583			var errorClass = this.settings.errorClass.split( " " ).join( "." );
584			return $( this.settings.errorElement + "." + errorClass, this.errorContext );
585		},
586
587		reset: function() {
588			this.successList = [];
589			this.errorList = [];
590			this.errorMap = {};
591			this.toShow = $( [] );
592			this.toHide = $( [] );
593			this.currentElements = $( [] );
594		},
595
596		prepareForm: function() {
597			this.reset();
598			this.toHide = this.errors().add( this.containers );
599		},
600
601		prepareElement: function( element ) {
602			this.reset();
603			this.toHide = this.errorsFor( element );
604		},
605
606		elementValue: function( element ) {
607			var val,
608				$element = $( element ),
609				type = element.type;
610
611			if ( type === "radio" || type === "checkbox" ) {
612				return this.findByName( element.name ).filter(":checked").val();
613			} else if ( type === "number" && typeof element.validity !== "undefined" ) {
614				return element.validity.badInput ? false : $element.val();
615			}
616
617			val = $element.val();
618			if ( typeof val === "string" ) {
619				return val.replace(/\r/g, "" );
620			}
621			return val;
622		},
623
624		check: function( element ) {
625			element = this.validationTargetFor( this.clean( element ) );
626
627			var rules = $( element ).rules(),
628				rulesCount = $.map( rules, function( n, i ) {
629					return i;
630				}).length,
631				dependencyMismatch = false,
632				val = this.elementValue( element ),
633				result, method, rule;
634
635			for ( method in rules ) {
636				rule = { method: method, parameters: rules[ method ] };
637				try {
638
639					result = $.validator.methods[ method ].call( this, val, element, rule.parameters );
640
641					// if a method indicates that the field is optional and therefore valid,
642					// don't mark it as valid when there are no other rules
643					if ( result === "dependency-mismatch" && rulesCount === 1 ) {
644						dependencyMismatch = true;
645						continue;
646					}
647					dependencyMismatch = false;
648
649					if ( result === "pending" ) {
650						this.toHide = this.toHide.not( this.errorsFor( element ) );
651						return;
652					}
653
654					if ( !result ) {
655						this.formatAndAdd( element, rule );
656						return false;
657					}
658				} catch ( e ) {
659					if ( this.settings.debug && window.console ) {
660						console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e );
661					}
662					if ( e instanceof TypeError ) {
663						e.message += ".  Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.";
664					}
665
666					throw e;
667				}
668			}
669			if ( dependencyMismatch ) {
670				return;
671			}
672			if ( this.objectLength( rules ) ) {
673				this.successList.push( element );
674			}
675			return true;
676		},
677
678		// return the custom message for the given element and validation method
679		// specified in the element's HTML5 data attribute
680		// return the generic message if present and no method specific message is present
681		customDataMessage: function( element, method ) {
682			return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() +
683				method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" );
684		},
685
686		// return the custom message for the given element name and validation method
687		customMessage: function( name, method ) {
688			var m = this.settings.messages[ name ];
689			return m && ( m.constructor === String ? m : m[ method ]);
690		},
691
692		// return the first defined argument, allowing empty strings
693		findDefined: function() {
694			for ( var i = 0; i < arguments.length; i++) {
695				if ( arguments[ i ] !== undefined ) {
696					return arguments[ i ];
697				}
698			}
699			return undefined;
700		},
701
702		defaultMessage: function( element, method ) {
703			return this.findDefined(
704				this.customMessage( element.name, method ),
705				this.customDataMessage( element, method ),
706				// title is never undefined, so handle empty string as undefined
707				!this.settings.ignoreTitle && element.title || undefined,
708				$.validator.messages[ method ],
709				"<strong>Warning: No message defined for " + element.name + "</strong>"
710			);
711		},
712
713		formatAndAdd: function( element, rule ) {
714			var message = this.defaultMessage( element, rule.method ),
715				theregex = /\$?\{(\d+)\}/g;
716			if ( typeof message === "function" ) {
717				message = message.call( this, rule.parameters, element );
718			} else if ( theregex.test( message ) ) {
719				message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters );
720			}
721			this.errorList.push({
722				message: message,
723				element: element,
724				method: rule.method
725			});
726
727			this.errorMap[ element.name ] = message;
728			this.submitted[ element.name ] = message;
729		},
730
731		addWrapper: function( toToggle ) {
732			if ( this.settings.wrapper ) {
733				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
734			}
735			return toToggle;
736		},
737
738		defaultShowErrors: function() {
739			var i, elements, error;
740			for ( i = 0; this.errorList[ i ]; i++ ) {
741				error = this.errorList[ i ];
742				if ( this.settings.highlight ) {
743					this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.val
743idClass );
744				}
745				this.showLabel( error.element, error.message );
746			}
747			if ( this.errorList.length ) {
748				this.toShow = this.toShow.add( this.containers );
749			}
750			if ( this.settings.success ) {
751				for ( i = 0; this.successList[ i ]; i++ ) {
752					this.showLabel( this.successList[ i ] );
753				}
754			}
755			if ( this.settings.unhighlight ) {
756				for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {
757					this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass );
758				}
759			}
760			this.toHide = this.toHide.not( this.toShow );
761			this.hideErrors();
762			this.addWrapper( this.toShow ).show();
763		},
764
765		validElements: function() {
766			return this.currentElements.not( this.invalidElements() );
767		},
768
769		invalidElements: function() {
770			return $( this.errorList ).map(function() {
771				return this.element;
772			});
773		},
774
775		showLabel: function( element, message ) {
776			var place, group, errorID,
777				error = this.errorsFor( element ),
778				elementID = this.idOrName( element ),
779				describedBy = $( element ).attr( "aria-describedby" );
780			if ( error.length ) {
781				// refresh error/success class
782				error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
783				// replace message on existing label
784				error.html( message );
785			} else {
786				// create error element
787				error = $( "<" + this.settings.errorElement + ">" )
788					.attr( "id", elementID + "-error" )
789					.addClass( this.settings.errorClass )
790					.html( message || "" );
791
792				// Maintain reference to the element to be placed into the DOM
793				place = error;
794				if ( this.settings.wrapper ) {
795					// make sure the element is visible, even in IE
796					// actually showing the wrapped element is handled elsewhere
797					place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent();
798				}
799				if ( this.labelContainer.length ) {
800					this.labelContainer.append( place );
801				} else if ( this.settings.errorPlacement ) {
802					this.settings.errorPlacement( place, $( element ) );
803				} else {
804					place.insertAfter( element );
805				}
806
807				// Link error back to the element
808				if ( error.is( "label" ) ) {
809					// If the error is a label, then associate using 'for'
810					error.attr( "for", elementID );
811				} else if ( error.parents( "label[for='" + elementID + "']" ).length === 0 ) {
812					// If the element is not a child of an associated label, then it's necessary
813					// to explicitly apply aria-describedby
814
815					errorID = error.attr( "id" ).replace( /(:|\.|\[|\]|\$)/g, "\\$1");
816					// Respect existing non-error aria-describedby
817					if ( !describedBy ) {
818						describedBy = errorID;
819					} else if ( !describedBy.match( new RegExp( "\\b" + errorID + "\\b" ) ) ) {
820						// Add to end of list if not already present
821						describedBy += " " + errorID;
822					}
823					$( element ).attr( "aria-describedby", describedBy );
824
825					// If this element is grouped, then assign to all elements in the same group
826					group = this.groups[ element.name ];
827					if ( group ) {
828						$.each( this.groups, function( name, testgroup ) {
829							if ( testgroup === group ) {
830								$( "[name='" + name + "']", this.currentForm )
831									.attr( "aria-describedby", error.attr( "id" ) );
832							}
833						});
834					}
835				}
836			}
837			if ( !message && this.settings.success ) {
838				error.text( "" );
839				if ( typeof this.settings.success === "string" ) {
840					error.addClass( this.settings.success );
841				} else {
842					this.settings.success( error, element );
843				}
844			}
845			this.toShow = this.toShow.add( error );
846		},
847
848		errorsFor: function( element ) {
849			var name = this.idOrName( element ),
850				describer = $( element ).attr( "aria-describedby" ),
851				selector = "label[for='" + name + "'], label[for='" + name + "'] *";
852
853			// aria-describedby should directly reference the error element
854			if ( describer ) {
855				selector = selector + ", #" + describer.replace( /\s+/g, ", #" );
856			}
857			return this
858				.errors()
859				.filter( selector );
860		},
861
862		idOrName: function( element ) {
863			return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.i
vendor: 9,923 bytes, lines 863-1195
863d || element.name );
864		},
865
866		validationTargetFor: function( element ) {
867
868			// If radio/checkbox, validate first element in group instead
869			if ( this.checkable( element ) ) {
870				element = this.findByName( element.name );
871			}
872
873			// Always apply ignore filter
874			return $( element ).not( this.settings.ignore )[ 0 ];
875		},
876
877		checkable: function( element ) {
878			return ( /radio|checkbox/i ).test( element.type );
879		},
880
881		findByName: function( name ) {
882			return $( this.currentForm ).find( "[name='" + name + "']" );
883		},
884
885		getLength: function( value, element ) {
886			switch ( element.nodeName.toLowerCase() ) {
887			case "select":
888				return $( "option:selected", element ).length;
889			case "input":
890				if ( this.checkable( element ) ) {
891					return this.findByName( element.name ).filter( ":checked" ).length;
892				}
893			}
894			return value.length;
895		},
896
897		depend: function( param, element ) {
898			return this.dependTypes[typeof param] ? this.dependTypes[typeof param]( param, element ) : true;
899		},
900
901		dependTypes: {
902			"boolean": function( param ) {
903				return param;
904			},
905			"string": function( param, element ) {
906				return !!$( param, element.form ).length;
907			},
908			"function": function( param, element ) {
909				return param( element );
910			}
911		},
912
913		optional: function( element ) {
914			var val = this.elementValue( element );
915			return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch";
916		},
917
918		startRequest: function( element ) {
919			if ( !this.pending[ element.name ] ) {
920				this.pendingRequest++;
921				this.pending[ element.name ] = true;
922			}
923		},
924
925		stopRequest: function( element, valid ) {
926			this.pendingRequest--;
927			// sometimes synchronization fails, make sure pendingRequest is never < 0
928			if ( this.pendingRequest < 0 ) {
929				this.pendingRequest = 0;
930			}
931			delete this.pending[ element.name ];
932			if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {
933				$( this.currentForm ).submit();
934				this.formSubmitted = false;
935			} else if (!valid && this.pendingRequest === 0 && this.formSubmitted ) {
936				$( this.currentForm ).triggerHandler( "invalid-form", [ this ]);
937				this.formSubmitted = false;
938			}
939		},
940
941		previousValue: function( element ) {
942			return $.data( element, "previousValue" ) || $.data( element, "previousValue", {
943				old: null,
944				valid: true,
945				message: this.defaultMessage( element, "remote" )
946			});
947		},
948
949		// cleans up all forms and elements, removes validator-specific events
950		destroy: function() {
951			this.resetForm();
952
953			$( this.currentForm )
954				.off( ".validate" )
955				.removeData( "validator" );
956		}
957
958	},
959
960	classRuleSettings: {
961		required: { required: true },
962		email: { email: true },
963		url: { url: true },
964		date: { date: true },
965		dateISO: { dateISO: true },
966		number: { number: true },
967		digits: { digits: true },
968		creditcard: { creditcard: true }
969	},
970
971	addClassRules: function( className, rules ) {
972		if ( className.constructor === String ) {
973			this.classRuleSettings[ className ] = rules;
974		} else {
975			$.extend( this.classRuleSettings, className );
976		}
977	},
978
979	classRules: function( element ) {
980		var rules = {},
981			classes = $( element ).attr( "class" );
982
983		if ( classes ) {
984			$.each( classes.split( " " ), function() {
985				if ( this in $.validator.classRuleSettings ) {
986					$.extend( rules, $.validator.classRuleSettings[ this ]);
987				}
988			});
989		}
990		return rules;
991	},
992
993	normalizeAttributeRule: function( rules, type, method, value ) {
994
995		// convert the value to a number for number inputs, and for text for backwards compability
996		// allows type="date" and others to be compared as strings
997		if ( /min|max/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
998			value = Number( value );
999
1000			// Support Opera Mini, which returns NaN for undefined minlength
1001			if ( isNaN( value ) ) {
1002				value = undefined;
1003			}
1004		}
1005
1006		if ( value || value === 0 ) {
1007			rules[ method ] = value;
1008		} else if ( type === method && type !== "range" ) {
1009
1010			// exception: the jquery validate 'range' method
1011			// does not test for the html5 'range' type
1012			rules[ method ] = true;
1013		}
1014	},
1015
1016	attributeRules: function( element ) {
1017		var rules = {},
1018			$element = $( element ),
1019			type = element.getAttribute( "type" ),
1020			method, value;
1021
1022		for ( method in $.validator.methods ) {
1023
1024			// support for <input required> in both html5 and older browsers
1025			if ( method === "required" ) {
1026				value = element.getAttribute( method );
1027
1028				// Some browsers return an empty string for the required attribute
1029				// and non-HTML5 browsers might have required="" markup
1030				if ( value === "" ) {
1031					value = true;
1032				}
1033
1034				// force non-HTML5 browsers to return bool
1035				value = !!value;
1036			} else {
1037				value = $element.attr( method );
1038			}
1039
1040			this.normalizeAttributeRule( rules, type, method, value );
1041		}
1042
1043		// maxlength may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs
1044		if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {
1045			delete rules.maxlength;
1046		}
1047
1048		return rules;
1049	},
1050
1051	dataRules: function( element ) {
1052		var rules = {},
1053			$element = $( element ),
1054			type = element.getAttribute( "type" ),
1055			method, value;
1056
1057		for ( method in $.validator.methods ) {
1058			value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );
1059			this.normalizeAttributeRule( rules, type, method, value );
1060		}
1061		return rules;
1062	},
1063
1064	staticRules: function( element ) {
1065		var rules = {},
1066			validator = $.data( element.form, "validator" );
1067
1068		if ( validator.settings.rules ) {
1069			rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};
1070		}
1071		return rules;
1072	},
1073
1074	normalizeRules: function( rules, element ) {
1075		// handle dependency check
1076		$.each( rules, function( prop, val ) {
1077			// ignore rule when param is explicitly false, eg. required:false
1078			if ( val === false ) {
1079				delete rules[ prop ];
1080				return;
1081			}
1082			if ( val.param || val.depends ) {
1083				var keepRule = true;
1084				switch ( typeof val.depends ) {
1085				case "string":
1086					keepRule = !!$( val.depends, element.form ).length;
1087					break;
1088				case "function":
1089					keepRule = val.depends.call( element, element );
1090					break;
1091				}
1092				if ( keepRule ) {
1093					rules[ prop ] = val.param !== undefined ? val.param : true;
1094				} else {
1095					delete rules[ prop ];
1096				}
1097			}
1098		});
1099
1100		// evaluate parameters
1101		$.each( rules, function( rule, parameter ) {
1102			rules[ rule ] = $.isFunction( parameter ) ? parameter( element ) : parameter;
1103		});
1104
1105		// clean number parameters
1106		$.each([ "minlength", "maxlength" ], function() {
1107			if ( rules[ this ] ) {
1108				rules[ this ] = Number( rules[ this ] );
1109			}
1110		});
1111		$.each([ "rangelength", "range" ], function() {
1112			var parts;
1113			if ( rules[ this ] ) {
1114				if ( $.isArray( rules[ this ] ) ) {
1115					rules[ this ] = [ Number( rules[ this ][ 0 ]), Number( rules[ this ][ 1 ] ) ];
1116				} else if ( typeof rules[ this ] === "string" ) {
1117					parts = rules[ this ].replace(/[\[\]]/g, "" ).split( /[\s,]+/ );
1118					rules[ this ] = [ Number( parts[ 0 ]), Number( parts[ 1 ] ) ];
1119				}
1120			}
1121		});
1122
1123		if ( $.validator.autoCreateRanges ) {
1124			// auto-create ranges
1125			if ( rules.min != null && rules.max != null ) {
1126				rules.range = [ rules.min, rules.max ];
1127				delete rules.min;
1128				delete rules.max;
1129			}
1130			if ( rules.minlength != null && rules.maxlength != null ) {
1131				rules.rangelength = [ rules.minlength, rules.maxlength ];
1132				delete rules.minlength;
1133				delete rules.maxlength;
1134			}
1135		}
1136
1137		return rules;
1138	},
1139
1140	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
1141	normalizeRule: function( data ) {
1142		if ( typeof data === "string" ) {
1143			var transformed = {};
1144			$.each( data.split( /\s/ ), function() {
1145				transformed[ this ] = true;
1146			});
1147			data = transformed;
1148		}
1149		return data;
1150	},
1151
1152	// http://jqueryvalidation.org/jQuery.validator.addMethod/
1153	addMethod: function( name, method, message ) {
1154		$.validator.methods[ name ] = method;
1155		$.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];
1156		if ( method.length < 3 ) {
1157			$.validator.addClassRules( name, $.validator.normalizeRule( name ) );
1158		}
1159	},
1160
1161	methods: {
1162
1163		// http://jqueryvalidation.org/required-method/
1164		required: function( value, element, param ) {
1165			// check if dependency is met
1166			if ( !this.depend( param, element ) ) {
1167				return "dependency-mismatch";
1168			}
1169			if ( element.nodeName.toLowerCase() === "select" ) {
1170				// could be an array for select-multiple or a string, both are fine this way
1171				var val = $( element ).val();
1172				return val && val.length > 0;
1173			}
1174			if ( this.checkable( element ) ) {
1175				return this.getLength( value, element ) > 0;
1176			}
1177			return value.length > 0;
1178		},
1179
1180		// http://jqueryvalidation.org/email-method/
1181		email: function( value, element ) {
1182			// From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address
1183			// Retrieved 2014-01-14
1184			// If you have a problem with this implementation, report a bug against the above spec
1185			// Or use custom methods to implement your own email validation
1186			return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );
1187		},
1188
1189		// http://jqueryvalidation.org/url-method/
1190		url: function( value, element ) {
1191
1192			// Copyright (c) 2010-2013 Diego Perini, MIT licensed
1193			// https://gist.github.com/dperini/729294
1194			// see also https://mathiasbynens.be/demo/url-regex
1195			// modified to allow protocol-relative URLs
1196			return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value );
1197		},
1198
1199		// http://jqueryvalidation.org/date-method/
1200		date: function( value, element ) {
1201			return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );
1202		},
1203
1204		// http://jqueryvalidation.org/dateISO-method/
1205		dateISO: function( value, element ) {
1206			return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );
1207		},
1208
1209		// http://jqueryvalidation.org/number-method/
1210		number: function( value, element ) {
1211			return this.optional( element ) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value );
1212		},
1213
1214		// http://jqueryvalidation.org/digits-method/
1215		digits: function( value, element ) {
1216			return this.optional( element ) || /^\d+$/.test( value );
1217		},
1218
1219		// http://jqueryvalidation.org/creditcard-method/
1220		// based on http://en.wikipedia.org/wiki/Luhn_algorithm
1221		creditcard: function( value, element ) {
1222			if ( this.optional( element ) ) {
1223				return "dependency-mismatch";
1224			}
1225			// accept only spaces, digits and dashes
1226			if ( /[^0-9 \-]+/.test( value ) ) {
1227				return false;
1228			}
1229			var nCheck = 0,
1230				nDigit = 0,
1231				bEven = false,
1232				n, cDigit;
1233
1234			value = value.replace( /\D/g, "" );
1235
1236			// Basing min and max length on
1237			// http://developer.ean.com/general_info/Valid_Credit_Card_Types
1238			if ( value.length < 13 || value.length > 19 ) {
1239				return false;
1240			}
1241
1242			for ( n = value.length - 1; n >= 0; n--) {
1243				cDigit = value.charAt( n );
1244				nDigit = parseInt( cDigit, 10 );
1245				if ( bEven ) {
1246					if ( ( nDigit *= 2 ) > 9 ) {
1247						nDigit -= 9;
1248					}
1249				}
1250				nCheck += nDigit;
1251				bEven = !bEven;
1252			}
1253
1254			return ( nCheck % 10 ) === 0;
1255		},
1256
1257		// http://jqueryvalidation.org/minlength-method/
1258		minlength: function( value, element, param ) {
1259			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
1260			return this.optional( element ) || length >= param;
1261		},
1262
1263		// http://jqueryvalidation.org/maxlength-method/
1264		maxlength: function( value, element, param ) {
1265			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
1266			return this.optional( element ) || length <= param;
1267		},
1268
1269		// http://jqueryvalidation.org/rangelength-method/
1270		rangelength: function( value, element, param ) {
1271			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
1272			return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );
1273		},
1274
1275		// http://jqueryvalidation.org/min-method/
1276		min: function( value, element, param ) {
1277			return this.optional( element ) || value >= param;
1278		},
1279
1280		// http://jqueryvalidation.org/max-method/
1281		max: function( value, element, param ) {
1282			return this.optional( element ) || value <= param;
1283		},
1284
1285		// http://jqueryvalidation.org/range-method/
1286		range: function( value, element, param ) {
1287			return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
1288		},
1289
1290		// http://jqueryvalidation.org/equalTo-method/
1291		equalTo: function( value, element, param ) {
1292			// bind to the blur event of the target in order to revalidate whenever the target field is updated
1293			// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
1294			var target = $( param );
1295			if ( this.settings.onfocusout ) {
1296				target.off( ".validate-equalTo" ).on( "blur.validate-equalTo", function() {
1297					$( element ).valid();
1298				});
1299			}
1300			return value === target.val();
1301		},
1302
1303		// http://jqueryvalidation.org/remote-method/
1304		remote: function( value, element, param ) {
1305			if ( this.optional( element ) ) {
1306				return "dependency-mismatch";
1307			}
1308
1309			var previous = this.previousValue( element ),
1310				validator, data;
1311
1312			if (!this.settings.messages[ element.name ] ) {
1313				this.settings.messages[ element.name ] = {};
1314			}
1315			previous.originalMessage = this.settings.messages[ element.name ].remote;
1316			this.settings.messages[ element.name ].remote = previous.message;
1317
1318			param = typeof param === "string" && { url: param } || param;
1319
1320			if ( previous.old === value ) {
1321				return previous.valid;
1322			}
1323
1324			previous.old = value;
1325			validator = this;
1326			this.startRequest( element );
1327			data = {};
1328			data[ element.name ] = value;
1329			$.ajax( $.extend( true, {
1330				mode: "abort",
1331				port: "validate" + element.name,
1332				dataType: "json",
1333				data: data,
1334				context: validator.currentForm,
1335				success: function( response ) {
1336					var valid = response === true || response === "true",
1337						errors, message, submitted;
1338
1339					validator.settings.messages[ element.name ].remote = previous.originalMessage;
1340					if ( valid ) {
1341						submitted = validator.formSubmitted;
1342						validator.prepareElement( element );
1343						validator.formSubmitted = submitted;
1344						validator.successList.push( element );
1345						delete validator.invalid[ element.name ];
1346						validator.showErrors();
1347					} else {
1348						errors = {};
1349						message = response || validator.defaultMessage( element, "remote" );
1350						errors[ element.name ] = previous.message = $.isFunction( message ) ? message( value ) : message;
1351						validator.invalid[ element.name ] = true;
1352						validator.showErrors( errors );
1353					}
1354					previous.valid = valid;
1355					validator.stopRequest( element, valid );
1356				}
1357			}, param ) );
1358			return "pending";
1359		}
1360	}
1361
1362});
1363
1364// ajax mode: abort
1365// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
1366// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
1367
1368var pendingRequests = {},
1369	ajax;
1370// Use a prefilter if available (1.5+)
1371if ( $.ajaxPrefilter ) {
1372	$.ajaxPrefilter(function( settings, _, xhr ) {
1373		var port = settings.port;
1374		if ( settings.mode === "abort" ) {
1375			if ( pendingRequests[port] ) {
1376				pendingRequests[port].abort();
1377			}
1378			pendingRequests[port] = xhr;
1379		}
1380	});
1381} else {
1382	// Proxy ajax
1383	ajax = $.ajax;
1384	$.ajax = function( settings ) {
1385		var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
1386			port = ( "port" in settings ? settings : $.ajaxSettings ).port;
1387		if ( mode === "abort" ) {
1388			if ( pendingRequests[port] ) {
1389				pendingRequests[port].abort();
1390			}
1391			pendingRequests[port] = ajax.apply(this, arguments);
1392			return pendingRequests[port];
1393		}
1394		return ajax.apply(this, arguments);
1395	};
1396}
1397
1398}));
1399function strlen (string) {
1400  //  discuss at: http://phpjs.org/functions/strlen/
1401  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
1402  // improved by: Sakimori
1403  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
1404  //    input by: Kirk Strobeck
1405  // bugfixed by: Onno Marsman
1406  //  revised by: Brett Zamir (http://brett-zamir.me)
1407  //        note: May look like overkill, but in order to be truly faithful to handling all Unicode
1408  //        note: characters and to this function in PHP which does not count the number of bytes
1409  //        note: but counts the number of characters, something like this is really necessary.
1410  //   example 1: strlen('Kevin van Zonneveld');
1411  //   returns 1: 19
1412  //   example 2: ini_set('unicode.semantics', 'on');
1413  //   example 2: strlen('A\ud87e\udc04Z');
1414  //   returns 2: 3
1415
1416  var str = string + ''
1417  var i = 0,
1418    chr = '',
1419    lgth = 0
1420
1421  if (!this.php_js || !this.php_js.ini || !this.php_js.ini['unicode.semantics'] || this.php_js.ini[
1422      'unicode.semantics'].local_value.toLowerCase() !== 'on') {
1423    return string.length
1424  }
1425
1426  var getWholeChar = function (str, i) {
1427    var code = str.charCodeAt(i)
1428    var next = '',
1429      prev = ''
1430    if (0xD800 <= code && code <= 0xDBFF) {
1431      // High surrogate (could change last hex to 0xDB7F to treat high private surrogates as single characters)
1432      if (str.length <= (i + 1)) {
1433        throw 'High surrogate without following low surrogate'
1434      }
1435      next = str.charCodeAt(i + 1)
1436      if (0xDC00 > next || next > 0xDFFF) {
1437        throw 'High surrogate without following low surrogate'
1438      }
1439      return str.charAt(i) + str.charAt(i + 1)
1440    } else if (0xDC00 <= code && code <= 0xDFFF) {
1441      // Low surrogate
1442      if (i === 0) {
1443        throw 'Low surrogate without preceding high surrogate'
1444      }
1445      prev = str.charCodeAt(i - 1)
1446      if (0xD800 > prev || prev > 0xDBFF) {
1447        // (could change last hex to 0xDB7F to treat high private surrogates as single characters)
1448        throw 'Low surrogate without preceding high surrogate'
1449      }
1450      // We can pass over low surrogates now as the second component in a pair which we have already processed
1451      return false
1452    }
1453    return str.charAt(i)
1454  }
1455
1456  for (i = 0, lgth = 0; i < str.length; i++) {
1457    if ((chr = getWholeChar(str, i)) === false) {
1458      continue
1459    } // Adapt this line at the top of any loop, passing in the whole string and the current iteration and returning a variable to represent the individual character; purpose is to treat the first part of a surrogate pair as the whole character and then ignore the second part
1460    lgth++
1461  }
1462  return lgth
1463}
1464
1465function array_diff (arr1) {
1466  //  discuss at: http://phpjs.org/functions/array_diff/
1467  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
1468  // improved by: Sanjoy Roy
1469  //  revised by: Brett Zamir (http://brett-zamir.me)
1470  //   example 1: array_diff(['Kevin', 'van', 'Zonneveld'], ['van', 'Zonneveld']);
1471  //   returns 1: {0:'Kevin'}
1472
1473  var retArr = {},
1474    argl = arguments.length,
1475    k1 = '',
1476    i = 1,
1477    k = '',
1478    arr = {}
1479
1480  arr1keys: for (k1 in arr1) {
1481    for (i = 1; i < argl; i++) {
1482      arr = arguments[i]
1483      for (k in arr) {
1484        if (arr[k] === arr1[k1]) {
1485          // If it reaches here, it was found in at least one array, so try next value
1486          continue arr1keys
1487        }
1488      }
1489      retArr[k1] = arr1[k1]
1490    }
1491  }
1492
1493  return retArr
1494}
1495
1496function strtotime (text, now) {
1497  //  discuss at: http://phpjs.org/functions/strtotime/
1498  //     version: 1109.2016
1499  // original by: Caio Ariede (http://caioariede.com)
1500  // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
1501  // improved by: Caio Ariede (http://caioariede.com)
1502  // improved by: A. Matías Quezada (http://amatiasq.com)
1503  // improved by: preuter
1504  // improved by: Brett Zamir (http://brett-zamir.me)
1505  // improved by: Mirko Faber
1506  //    input by: David
1507  // bugfixed by: Wagner B. Soares
1508  // bugfixed by: Artur Tchernychev
1509  // bugfixed by: Stephan Bösch-Plepelits (http://github.com/plepe)
1510  //        note: Examples all have a fixed timestamp to prevent tests to fail because of variable time(zones)
1511  //   example 1: strtotime('+1 day', 1129633200);
1512  //   returns 1: 1129719600
1513  //   example 2: strtotime('+1 week 2 days 4 hours 2 seconds', 1129633200);
1514  //   returns 2: 1130425202
1515  //   example 3: strtotime('last month', 1129633200);
1516  //   returns 3: 1127041200
1517  //   example 4: strtotime('2009-05-04 08:30:00 GMT');
1518  //   returns 4: 1241425800
1519  //   example 5: strtotime('2009-05-04 08:30:00+00');
1520  //   returns 5: 1241425800
1521  //   example 6: strtotime('2009-05-04 08:30:00+02:00');
1522  //   returns 6: 1241418600
1523  //   example 7: strtotime('2009-05-04T08:30:00Z');
1524  //   returns 7: 1241425800
1525
1526  var parsed, match, today, year, date, days, ranges, len, times, regex, i, fail = false
1527
1528  if (!text) {
1529    return fail
1530  }
1531
1532  // Unecessary spaces
1533  text = text.replace(/^\s+|\s+$/g, '')
1534    .replace(/\s{2,}/g, ' ')
1535    .replace(/[\t\r\n]/g, '')
1536    .toLowerCase()
1537
1538  // in contrast to php, js Date.parse function interprets:
1539  // dates given as yyyy-mm-dd as in timezone: UTC,
1540  // dates with "." or "-" as MDY instead of DMY
1541  // dates with two-digit years differently
1542  // etc...etc...
1543  // ...therefore we manually parse lots of common date formats
1544  match = text.match(
1545    /^(\d{1,4})([\-\.\/\:])(\d{1,2})([\-\.\/\:])(\d{1,4})(?:\s(\d{1,2}):(\d{2})?:?(\d{2})?)?(?:\s([A-Z]+)?)?$/)
1546
1547  if (match && match[2] === match[4]) {
1548    if (match[1] > 1901) {
1549      switch (match[2]) {
1550        case '-':
1551          {
1552          // YYYY-M-D
1553            if (match[3] > 12 || match[5] > 31) {
1554              return fail
1555            }
1556
1557            return new Date(match[1], parseInt(match[3], 10) - 1, match[5],
1558            match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000
1559          }
1560        case '.':
1561          {
1562          // YYYY.M.D is not parsed by strtotime()
1563            return fail
1564          }
1565        case '/':
1566          {
1567          // YYYY/M/D
1568            if (match[3] > 12 || match[5] > 31) {
1569              return fail
1570            }
1571
1572            return new Date(match[1], parseInt(match[3], 10) - 1, match[5],
1573            match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000
1574          }
1575      }
1576    } else if (match[5] > 1901) {
1577      switch (match[2]) {
1578        case '-':
1579          {
1580          // D-M-YYYY
1581            if (match[3] > 12 || match[1] > 31) {
1582              return fail
1583            }
1584
1585            return new Date(match[5], parseInt(match[3], 10) - 1, match[1],
1586            match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000
1587          }
1588        case '.':
1589          {
1590          // D.M.YYYY
1591            if (match[3] > 12 || match[1] > 31) {
1592              return fail
1593            }
1594
1595            return new Date(match[5], parseInt(match[3], 10) - 1, match[1],
1596            match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000
1597          }
1598        case '/':
1599          {
1600          // M/D/YYYY
1601            if (match[1] > 12 || match[3] > 31) {
1602              return fail
1603            }
1604
1605            return new Date(match[5], parseInt(match[1], 10) - 1, match[3],
1606            match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000
1607          }
1608      }
1609    } else {
1610      switch (match[2]) {
1611        case '-':
1612          {
1613          // YY-M-D
1614            if (match[3] > 12 || match[5] > 31 || (match[1] < 70 && match[1] > 38)) {
1615              return fail
1616            }
1617
1618            year = match[1] >= 0 && match[1] <= 38 ? +match[1] + 2000 : match[1]
1619            return new Date(year, parseInt(match[3], 10) - 1, match[5],
1620            match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000
1621          }
1622        case '.':
1623          {
1624          // D.M.YY or H.MM.SS
1625            if (match[5] >= 70) {
1626            // D.M.YY
1627              if (match[3] > 12 || match[1] > 31) {
1628                return fail
1629              }
1630
1631              return new Date(match[5], parseInt(match[3], 10) - 1, match[1],
1632              match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000
1633            }
1634            if (match[5] < 60 && !match[6]) {
1635            // H.MM.SS
1636              if (match[1] > 23 || match[3] > 59) {
1637                return fail
1638              }
1639
1640              today = new Date()
1641              return new Date(today.getFullYear(), today.getMonth(), today.getDate(),
1642              match[1] || 0, match[3] || 0, match[5] || 0, match[9] || 0) / 1000
1643            }
1644
1645          // invalid format, cannot be parsed
1646            return fail
1647          }
1648        case '/':
1649          {
1650          // M/D/YY
1651            if (match[1] > 12 || match[3] > 31 || (match[5] < 70 && match[5] > 38)) {
1652              return fail
1653            }
1654
1655            year = match[5] >= 0 && match[5] <= 38 ? +match[5] + 2000 : match[5]
1656            return new Date(year, parseInt(match[1], 10) - 1, match[3],
1657            match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000
1658          }
1659        case ':':
1660          {
1661          // HH:MM:SS
1662            if (match[1] > 23 || match[3] > 59 || match[5] > 59) {
1663              return fail
1664            }
1665
1666            today = new Date()
1667            return new Date(today.getFullYear(), today.getMonth(), today.getDate(),
1668            match[1] || 0, match[3] || 0, match[5] || 0) / 1000
1669          }
1670      }
1671    }
1672  }
1673
1674  // other formats and "now" should be parsed by Date.parse()
1675  if (text === 'now') {
1676    return now === null || isNaN(now) ? new Date()
1677      .getTime() / 1000 | 0 : now | 0
1678  }
1679  if (!isNaN(parsed = Date.parse(text))) {
1680    return parsed / 1000 | 0
1681  }
1682  // Browsers != Chrome have problems parsing ISO 8601 date strings, as they do
1683  // not accept lower case characters, space, or shortened time zones.
1684  // Therefore, fix these problems and try again.
1685  // Examples:
1686  //   2015-04-15 20:33:59+02
1687  //   2015-04-15 20:33:59z
1688  //   2015-04-15t20:33:59+02:00
1689  if (match = text.match(
1690      /^([0-9]{4}-[0-9]{2}-[0-9]{2})[ t]([0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?)([\+-][0-9]{2}(:[0-9]{2})?|z)/)) {
1691    // fix time zone information
1692    if (match[4] == 'z') {
1693      match[4] = 'Z'
1694    } else if (match[4].match(/^([\+-][0-9]{2})$/)) {
1695      match[4] = match[4] + ':00'
1696    }
1697
1698    if (!isNaN(parsed = Date.parse(match[1] + 'T' + match[2] + match[4]))) {
1699      return parsed / 1000 | 0
1700    }
1701  }
1702
1703  date = now ? new Date(now * 1000) : new Date()
1704  days = {
1705    'sun': 0,
1706    'mon': 1,
1707    'tue': 2,
1708    'wed': 3,
1709    'thu': 4,
1710    'fri': 5,
1711    'sat': 6
1712  }
1713  ranges = {
1714    'yea': 'FullYear',
1715    'mon': 'Month',
1716    'day': 'Date',
1717    'hou': 'Hours',
1718    'min': 'Minutes',
1719    'sec': 'Seconds'
1720  }
1721
1722  function lastNext (type, range, modifier) {
1723    var diff, day = days[range]
1724
1725    if (typeof day !== 'undefined') {
1726      diff = day - date.getDay()
1727
1728      if (diff === 0) {
1729        diff = 7 * modifier
1730      } else if (diff > 0 && type === 'last') {
1731        diff -= 7
1732      } else if (diff < 0 && type === 'next') {
1733        diff += 7
1734      }
1735
1736      date.setDate(date.getDate() + diff)
1737    }
1738  }
1739
1740  function process (val) {
1741    var splt = val.split(' '), // Todo: Reconcile this with regex using \s, taking into account browser issues with split and regexes
1742      type = splt[0],
1743      range = splt[1].substring(0, 3),
1744      typeIsNumber = /\d+/.test(type),
1745      ago = splt[2] === 'ago',
1746      num = (type === 'last' ? -1 : 1) * (ago ? -1 : 1)
1747
1748    if (typeIsNumber) {
1749      num *= parseInt(type, 10)
1750    }
1751
1752    if (ranges.hasOwnProperty(range) && !splt[1].match(/^mon(day|\.)?$/i)) {
1753      return date['set' + ranges[range]](date['get' + ranges[range]]() + num)
1754    }
1755
1756    if (range === 'wee') {
1757      return date.setDate(date.getDate() + (num * 7))
1758    }
1759
1760    if (type === 'next' || type === 'last') {
1761      lastNext(type, range, num)
1762    } else if (!typeIsNumber) {
1763      return false
1764    }
1765
1766    return true
1767  }
1768
1769  times = '(years?|months?|weeks?|days?|hours?|minutes?|min|seconds?|sec' +
1770    '|sunday|sun\\.?|monday|mon\\.?|tuesday|tue\\.?|wednesday|wed\\.?' +
1771    '|thursday|thu\\.?|friday|fri\\.?|saturday|sat\\.?)'
1772  regex = '([+-]?\\d+\\s' + times + '|' + '(last|next)\\s' + times + ')(\\sago)?'
1773
1774  match = text.match(new RegExp(regex, 'gi'))
1775  if (!match) {
1776    return fail
1777  }
1778
1779  for (i = 0, len = match.length; i < len; i++) {
1780    if (!process(match[i])) {
1781      return fail
1782    }
1783  }
1784
1785  // ECMAScript 5 only
1786  // if (!match.every(process))
1787  //    return false;
1788
1789  return (date.getTime() / 1000)
1790}
1791
1792function is_numeric (mixed_var) {
1793  //  discuss at: http://phpjs.org/functions/is_numeric/
1794  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
1795  // improved by: David
1796  // improved by: taith
1797  // bugfixed by: Tim de Koning
1798  // bugfixed by: WebDevHobo (http://webdevhobo.blogspot.com/)
1799  // bugfixed by: Brett Zamir (http://brett-zamir.me)
1800  // bugfixed by: Denis Chenu (http://shnoulle.net)
1801  //   example 1: is_numeric(186.31);
1802  //   returns 1: true
1803  //   example 2: is_numeric('Kevin van Zonneveld');
1804  //   returns 2: false
1805  //   example 3: is_numeric(' +186.31e2');
1806  //   returns 3: true
1807  //   example 4: is_numeric('');
1808  //   returns 4: false
1809  //   example 5: is_numeric([]);
1810  //   returns 5: false
1811  //   example 6: is_numeric('1 ');
1812  //   returns 6: false
1813
1814  var whitespace =
1815    ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000'
1816  return (typeof mixed_var === 'number' || (typeof mixed_var === 'string' && whitespace.indexOf(mixed_var.slice(-1)) ===
1817    -1)) && mixed_var !== '' && !isNaN(mixed_var)
1818}
1819
1820/*!
1821 * @copyright Copyright &copy; Kartik Visweswaran, Krajee.com, 2014 - 2017
1822 * @version 1.3.4
1823 *
1824 * Date formatter utility library that allows formatting date/time variables or Date objects using PHP DateTime format.
1825 * This library is a standalone javascript library and does not depend on other libraries or plugins like jQuery.
1826 * 
1827 * @see http://php.net/manual/en/function.date.php
1828 *
1829 * For more JQuery plugins visit http://plugins.krajee.com
1830 * For more Yii related demos visit http://demos.krajee.com
1831 */
1832var DateFormatter;
1833(function () {
1834    "use strict";
1835
1836    var _compare, _lpad, _extend, _indexOf, defaultSettings, DAY, HOUR;
1837    DAY = 1000 * 60 * 60 * 24;
1838    HOUR = 3600;
1839
1840    _compare = function (str1, str2) {
1841        return typeof(str1) === 'string' && typeof(str2) === 'string' && str1.toLowerCase() === str2.toLowerCase();
1842    };
1843    _lpad = function (value, length, chr) {
1844        var val = value.toString();
1845        chr = chr || '0';
1846        return val.length < length ? _lpad(chr + val, length) : val;
1847    };
1848    _extend = function (out) {
1849        var i, obj;
1850        out = out || {};
1851        for (i = 1; i < arguments.length; i++) {
1852            obj = arguments[i];
1853            if (!obj) {
1854                continue;
1855            }
1856            for (var key in obj) {
1857                if (obj.hasOwnProperty(key)) {
1858                    if (typeof obj[key] === 'object') {
1859                        _extend(out[key], obj[key]);
1860                    } else {
1861                        out[key] = obj[key];
1862                    }
1863                }
1864            }
1865        }
1866        return out;
1867    };
1868    _indexOf = function (val, arr) {
1869        for (var i = 0; i < arr.length; i++) {
1870            if (arr[i].toLowerCase() === val.toLowerCase()) {
1871                return i;
1872            }
1873        }
1874        return -1;
1875    };
1876    defaultSettings = {
1877        dateSettings: {
1878            days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
1879            daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
1880            months: [
1881                'January', 'February', 'March', 'April', 'May', 'June', 'July',
1882                'August', 'September', 'October', 'November', 'December'
1883            ],
1884            monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
1885            meridiem: ['AM', 'PM'],
1886            ordinal: function (number) {
1887                var n = number % 10, suffixes = {1: 'st', 2: 'nd', 3: 'rd'};
1888                return Math.floor(number % 100 / 10) === 1 || !suffixes[n] ? 'th' : suffixes[n];
1889            }
1890        },
1891        separators: /[ \-+\/\.T:@]/g,
1892        validParts: /[dDjlNSwzWFmMntLoYyaABgGhHisueTIOPZcrU]/g,
1893        intParts: /[djwNzmnyYhHgGis]/g,
1894        tzParts: /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
1895        tzClip: /[^-+\dA-Z]/g
1896    };
1897
1898    DateFormatter = function (options) {
1899        var self = this, config = _extend(defaultSettings, options);
1900        self.dateSettings = config.dateSettings;
1901        self.separators = config.separators;
1902        self.validParts = config.validParts;
1903        self.intParts = config.intParts;
1904        self.tzParts = config.tzParts;
1905        self.tzClip = config.tzClip;
1906    };
1907
1908    DateFormatter.prototype = {
1909        constructor: DateFormatter,
1910        getMonth: function (val) {
1911            var self = this, i;
1912            i = _indexOf(val, self.dateSettings.monthsShort) + 1;
1913            if (i === 0) {
1914                i = _indexOf(val, self.dateSettings.months) + 1;
1915            }
1916            return i;
1917        },
1918        parseDate: function (vDate, vFormat) {
1919            var self = this, vFormatParts, vDateParts, i, vDateFlag = false, vTimeFlag = false, vDatePart, iDatePart,
1920                vSettings = self.dateSettings, vMonth, vMeriIndex, vMeriOffset, len, mer,
1921                out = {date: null, year: null, month: null, day: null, hour: 0, min: 0, sec: 0};
1922            if (!vDate) {
1923                return null;
1924            }
1925            if (vDate instanceof Date) {
1926                return vDate;
1927            }
1928            if (vFormat === 'U') {
1929                i = parseInt(vDate);
1930                return i ? new Date(i * 1000) : vDate;
1931            }
1932            switch (typeof vDate) {
1933                case 'number':
1934                    return new Date(vDate);
1935                case 'string':
1936                    break;
1937                default:
1938                    return null;
1939            }
1940            vFormatParts = vFormat.match(self.validParts);
1941            if (!vFormatParts || vFormatParts.length === 0) {
1942                throw new Error("Invalid date format definition.");
1943            }
1944            vDateParts = vDate.replace(self.separators, '\0').split('\0');
1945            for (i = 0; i < vDateParts.length; i++) {
1946                vDatePart = vDateParts[i];
1947                iDatePart = parseInt(vDatePart);
1948                switch (vFormatParts[i]) {
1949                    case 'y':
1950                    case 'Y':
1951                        if (iDatePart) {
1952                            len = vDatePart.length;
1953                            out.year = len === 2 ? parseInt((iDatePart < 70 ? '20' : '19') + vDatePart) : iDatePart;
1954                        } else {
1955                            return null;
1956                        }
1957                        vDateFlag = true;
1958                        break;
1959                    case 'm':
1960                    case 'n':
1961                    case 'M':
1962                    case 'F':
1963                        if (isNaN(iDatePart)) {
1964                            vMonth = self.getMonth(vDatePart);
1965                            if (vMonth > 0) {
1966                                out.month = vMonth;
1967                            } else {
1968                                return null;
1969                            }
1970                        } else {
1971                            if (iDatePart >= 1 && iDatePart <= 12) {
1972                                out.month = iDatePart;
1973                            } else {
1974                                return null;
1975                            }
1976                        }
1977                        vDateFlag = true;
1978                        break;
1979                    case 'd':
1980                    case 'j':
1981                        if (iDatePart >= 1 && iDatePart <= 31) {
1982                            out.day = iDatePart;
1983                        } else {
1984                            return null;
1985                        }
1986                        vDateFlag = true;
1987                        break;
1988                    case 'g':
1989                    case 'h':
1990                        vMeriIndex = (vFormatParts.indexOf('a') > -1) ? vFormatParts.indexOf('a') :
1991                            (vFormatParts.indexOf('A') > -1) ? vFormatParts.indexOf('A') : -1;
1992                        mer = vDateParts[vMeriIndex];
1993                        if (vMeriIndex !== -1) {
1994                            vMeriOffset = _compare(mer, vSettings.meridiem[0]) ? 0 :
1995                                (_compare(mer, vSettings.meridiem[1]) ? 12 : -1);
1996                            if (iDatePart >= 1 && iDatePart <= 12 && vMeriOffset !== -1) {
1997                                out.hour = iDatePart % 12 === 0 ? vMeriOffset : iD
1997atePart + vMeriOffset;
1998                            } else {
1999                                if (iDatePart >= 0 && iDatePart <= 23) {
2000                                    out.hour = iDatePart;
2001                                }
2002                            }
2003                        } else {
2004                            if (iDatePart >= 0 && iDatePart <= 23) {
2005                                out.hour = iDatePart;
2006                            } else {
2007                                return null;
2008                            }
2009                        }
2010                        vTimeFlag = true;
2011                        break;
2012                    case 'G':
2013                    case 'H':
2014                        if (iDatePart >= 0 && iDatePart <= 23) {
2015                            out.hour = iDatePart;
2016                        } else {
2017                            return null;
2018                        }
2019                        vTimeFlag = true;
2020                        break;
2021                    case 'i':
2022                        if (iDatePart >= 0 && iDatePart <= 59) {
2023                            out.min = iDatePart;
2024                        } else {
2025                            return null;
2026                        }
2027                        vTimeFlag = true;
2028                        break;
2029                    case 's':
2030                        if (iDatePart >= 0 && iDatePart <= 59) {
2031                            out.sec = iDatePart;
2032                        } else {
2033                            return null;
2034                        }
2035                        vTimeFlag = true;
2036                        break;
2037                }
2038            }
2039            if (vDateFlag === true && out.year && out.month && out.day) {
2040                out.date = new Date(out.year, out.month - 1, out.day, out.hour, out.min, out.sec, 0);
2041            } else {
2042                if (vTimeFlag !== true) {
2043                    return null;
2044                }
2045                out.date = new Date(0, 0, 0, out.hour, out.min, out.sec, 0);
2046            }
2047            return out.date;
2048        },
2049        guessDate: function (vDateStr, vFormat) {
2050            if (typeof vDateStr !== 'string') {
2051                return vDateStr;
2052            }
2053            var self = this, vParts = vDateStr.replace(self.separators, '\0').split('\0'), vPattern = /^[djmn]/g, len,
2054                vFormatParts = vFormat.match(self.validParts), vDate = new Date(), vDigit = 0, vYear, i, n, iPart, iSec;
2055
2056            if (!vPattern.test(vFormatParts[0])) {
2057                return vDateStr;
2058            }
2059
2060            for (i = 0; i < vParts.length; i++) {
2061                vDigit = 2;
2062                iPart = vParts[i];
2063                iSec = parseInt(iPart.substr(0, 2));
2064                if (isNaN(iSec)) {
2065                    return null;
2066                }
2067                switch (i) {
2068                    case 0:
2069                        if (vFormatParts[0] === 'm' || vFormatParts[0] === 'n') {
2070                            vDate.setMonth(iSec - 1);
2071                        } else {
2072                            vDate.setDate(iSec);
2073                        }
2074                        break;
2075                    case 1:
2076                        if (vFormatParts[0] === 'm' || vFormatParts[0] === 'n') {
2077                            vDate.setDate(iSec);
2078                        } else {
2079                            vDate.setMonth(iSec - 1);
2080                        }
2081                        break;
2082                    case 2:
2083                        vYear = vDate.getFullYear();
2084                        len = iPart.length;
2085                        vDigit = len < 4 ? len : 4;
2086                        vYear = parseInt(len < 4 ? vYear.toString().substr(0, 4 - len) + iPart : iPart.substr(0, 4));
2087                        if (!vYear) {
2088                            return null;
2089                        }
2090                        vDate.setFullYear(vYear);
2091                        break;
2092                    case 3:
2093                        vDate.setHours(iSec);
2094                        break;
2095                    case 4:
2096                        vDate.setMinutes(iSec);
2097                        break;
2098                    case 5:
2099                        vDate.setSeconds(iSec);
2100                        break;
2101                }
2102                n = iPart.substr(vDigit);
2103                if (n.length > 0) {
2104                    vParts.splice(i + 1, 0, n);
2105                }
2106            }
2107            return vDate;
2108        },
2109        parseFormat: function (vChar, vDate) {
2110            var self = this, vSettings = self.dateSettings, fmt, backslash = /\\?(.?)/gi, doFormat = function (t, s) {
2111                return fmt[t] ? fmt[t]() : s;
2112            };
2113            fmt = {
2114                /////////
2115                // DAY //
2116                /////////
2117                /**
2118                 * Day of month with leading 0: `01..31`
2119                 * @return {string}
2120                 */
2121                d: function () {
2122                    return _lpad(fmt.j(), 2);
2123                },
2124                /**
2125                 * Shorthand day name: `Mon...Sun`
2126                 * @return {string}
2127                 */
2128                D: function () {
2129                    return vSettings.daysShort[fmt.w()];
2130                },
2131                /**
2132                 * Day of month: `1..31`
2133                 * @return {number}
2134                 */
2135                j: function () {
2136                    return vDate.getDate();
2137                },
2138                /**
2139                 * Full day name: `Monday...Sunday`
2140                 * @return {number}
2141                 */
2142                l: function () {
2143                    return vSettings.days[fmt.w()];
2144                },
2145                /**
2146                 * ISO-8601 day of week: `1[Mon]..7[Sun]`
2147                 * @return {number}
2148                 */
2149                N: function () {
2150                    return fmt.w() || 7;
2151                },
2152                /**
2153                 * Day of week: `0[Sun]..6[Sat]`
2154                 * @return {number}
2155                 */
2156                w: function () {
2157                    return vDate.getDay();
2158                },
2159                /**
2160                 * Day of year: `0..365`
2161                 * @return {number}
2162                 */
2163                z: function () {
2164                    var a = new Date(fmt.Y(), fmt.n() - 1, fmt.j()), b = new Date(fmt.Y(), 0, 1);
2165                    return Math.round((a - b) / DAY);
2166                },
2167
2168                //////////
2169                // WEEK //
2170                //////////
2171                /**
2172                 * ISO-8601 week number
2173                 * @return {number}
2174                 */
2175                W: function () {
2176                    var a = new Date(fmt.Y(), fmt.n() - 1, fmt.j() - fmt.N() + 3), b = new Date(a.getFullYear(), 0, 4);
2177                    return _lpad(1 + Math.round((a - b) / DAY / 7), 2);
2178                },
2179
2180                ///////////
2181                // MONTH //
2182                ///////////
2183                /**
2184                 * Full month name: `January...December`
2185                 * @return {string}
2186                 */
2187                F: function () {
2188                    return vSettings.months[vDate.getMonth()];
2189                },
2190                /**
2191                 * Month w/leading 0: `01..12`
2192                 * @return {string}
2193                 */
2194                m: function () {
2195                    return _lpad(fmt.n(), 2);
2196                },
2197                /**
2198                 * Shorthand month name; `Jan...Dec`
2199                 * @return {string}
2200                 */
2201                M: function () {
2202                    return vSettings.monthsShort[vDate.getMonth()];
2203                },
2204                /**
2205                 * Month: `1...12`
2206                 * @return {number}
2207                 */
2208                n: function () {
2209                    return vDate.getMonth() + 1;
2210                },
2211                /**
2212                 * Days in month: `28...31`
2213                 * @return {number}
2214                 */
2215                t: function () {
2216                    return (new Date(fmt.Y(), fmt.n(), 0)).getDate();
2217                },
2218
2219                //////////
2220                // YEAR //
2221                //////////
2222                /**
2223                 * Is leap year? `0 or 1`
2224                 * @return {number}
2225                 */
2226                L: function () {
2227                    var Y = fmt.Y();
2228                    return (Y % 4 === 0 && Y % 100 !== 0 || Y % 400 === 0) ? 1 : 0;
2229                },
2230                /**
2231                 * ISO-8601 year
2232                 * @return {number}
2233                 */
2234                o: function () {
2235                    var n = fmt.n(), W = fmt.W(), Y = fmt.Y();
2236                    return Y + (n === 12 && W < 9 ? 1 : n === 1 && W > 9 ? -1 : 0);
2237                },
2238                /**
2239                 * Full year: `e.g. 1980...2010`
2240                 * @return {number}
2241                 */
2242                Y: function () {
2243                    return vDate.getFullYear();
2244                },
2245                /**
2246                 * Last two digits of year: `00...99`
2247                 * @return {string}
2248                 */
2249                y: function () {
2250                    return fmt.Y().toString().slice(-2);
2251                },
2252
2253                //////////
2254                // TIME //
2255                //////////
2256                /**
2257                 * Meridian lower: `am or pm`
2258                 * @return {string}
2259                 */
2260                a: function () {
2261                    return fmt.A().toLowerCase();
2262                },
2263                /**
2264                 * Meridian upper: `AM or PM`
2265                 * @return {string}
2266                 */
2267                A: function () {
2268                    var n = fmt.G() < 12 ? 0 : 1;
2269                    return vSettings.meridiem[n];
2270                },
2271                /**
2272                 * Swatch Internet time: `000..999`
2273                 * @return {string}
2274                 */
2275                B: function () {
2276                    var H = vDate.getUTCHours() * HOUR, i = vDate.getUTCMinutes() * 60, s = vDate.getUTCSeconds();
2277                    return _lpad(Math.floor((H + i + s + HOUR) / 86.4) % 1000, 3);
2278                },
2279                /**
2280                 * 12-Hours: `1..12`
2281                 * @return {number}
2282                 */
2283                g: function () {
2284                    return fmt.G() % 12 || 12;
2285                },
2286                /**
2287                 * 24-Hours: `0..23`
2288                 * @return {number}
2289                 */
2290                G: function () {
2291                    return vDate.getHours();
2292                },
2293                /**
2294                 * 12-Hours with leading 0: `01..12`
2295                 * @return {string}
2296                 */
2297                h: function () {
2298                    return _lpad(fmt.g(), 2);
2299                },
2300                /**
2301                 * 24-Hours w/leading 0: `00..23`
2302                 * @return {string}
2303                 */
2304                H: function () {
2305                    return _lpad(fmt.G(), 2);
2306                },
2307                /**
2308                 * Minutes w/leading 0: `00..59`
2309                 * @return {string}
2310                 */
2311                i: function () {
2312                    return _lpad(vDate.getMinutes(), 2);
2313                },
2314                /**
2315                 * Seconds w/leading 0: `00..59`
2316                 * @return {string}
2317                 */
2318                s: function () {
2319                    return _lpad(vDate.getSeconds(), 2);
2320                },
2321                /**
2322                 * Microseconds: `000000-999000`
2323                 * @return {string}
2324                 */
2325                u: function () {
2326                    return _lpad(vDate.getMilliseconds() * 1000, 6);
2327                },
2328
2329                //////////////
2330                // TIMEZONE //
2331                //////////////
2332                /**
2333                 * Timezone identifier: `e.g. Atlantic/Azores, ...`
2334                 * @return {string}
2335                 */
2336                e: function () {
2337                    var str = /\((.*)\)/.exec(String(vDate))[1];
2338                    return str || 'Coordinated Universal Time';
2339                },
2340                /**
2341                 * DST observed? `0 or 1`
2342                 * @return {number}
2343                 */
2344                I: function () {
2345                    var a = new Date(fmt.Y(), 0), c = Date.UTC(fmt.Y(), 0),
2346                        b = new Date(fmt.Y(), 6), d = Date.UTC(fmt.Y(), 6);
2347                    return ((a - c) !== (b - d)) ? 1 : 0;
2348                },
2349                /**
2350                 * Difference to GMT in hour format: `e.g. +0200`
2351                 * @return {string}
2352                 */
2353                O: function () {
2354                    var tzo = vDate.getTimezoneOffset(), a = Math.abs(tzo);
2355                    return (tzo > 0 ? '-' : '+') + _lpad(Math.floor(a / 60) * 100 + a % 60, 4);
2356                },
2357                /**
2358                 * Difference to GMT with colon: `e.g. +02:00`
2359                 * @return {string}
2360                 */
2361                P: function () {
2362                    var O = fmt.O();
2363                    return (O.substr(0, 3) + ':' + O.substr(3, 2));
2364                },
2365                /**
2366                 * Timezone abbreviation: `e.g. EST, MDT, ...`
2367                 * @return {string}
2368                 */
2369                T: function () {
2370                    var str = (String(vDate).match(self.tzParts) || [""]).pop().replace(self.tzClip, "");
2371                    return str || 'UTC';
2372                },
2373                /**
2374                 * Timezone offset in seconds: `-43200...50400`
2375                 * @return {number}
2376                 */
2377                Z: function () {
2378                    return -vDate.getTimezoneOffset() * 60;
2379                },
2380
2381                ////////////////////
2382                // FULL DATE TIME //
2383                ////////////////////
2384                /**
2385                 * ISO-8601 date
2386                 * @return {string}
2387                 */
2388                c: function () {
2389                    return 'Y-m-d\\TH:i:sP'.replace(backslash, doFormat);
2390                },
2391                /**
2392                 * RFC 2822 date
2393                 * @return {string}
2394                 */
2395                r: function () {
2396                    return 'D, d M Y H:i:s O'.replace(backslash, doFormat);
2397                },
2398                /**
2399                 * Seconds since UNIX epoch
2400                 * @return {number}
2401                 */
2402                U: function () {
2403                    return vDate.getTime() / 1000 || 0;
2404                }
2405            };
2406            return doFormat(vChar, vChar);
2407        },
2408        formatDate: function (vDate, vFormat) {
2409            var self = this, i, n, len, str, vChar, vDateStr = '', BACKSLASH = '\\';
2410            if (typeof vDate === 'string') {
2411                vDate = self.parseDate(vDate, vFormat);
2412                if (!vDate) {
2413                    return null;
2414                }
2415            }
2416            if (vDate instanceof Date) {
2417                len = vFormat.length;
2418                for (i = 0; i < len; i++) {
2419                    vChar = vFormat.charAt(i);
2420                    if (vChar === 'S' || vChar === BACKSLASH) {
2421                        continue;
2422                    }
2423                    if (i > 0 && vFormat.charAt(i - 1) === BACKSLASH) {
2424                        vDateStr += vChar;
2425                        continue;
2426                    }
2427                    str = self.parseFormat(vChar, vDate);
2428                    if (i !== (len - 1) && self.intParts.test(vChar) && vFormat.charAt(i + 1) === 'S') {
2429                        n = parseInt(str) || 0;
2430                        str += self.dateSettings.ordinal(n);
2431                    }
2432                    vDateStr += str;
2433                }
2434                return vDateStr;
2435            }
2436            return '';
2437        }
2438    };
2439})();
2440/*!
2441 * Laravel Javascript Validation
2442 *
2443 * https://github.com/proengsoft/laravel-jsvalidation
2444 *
2445 * Copyright (c) 2017 Proengsoft
2446 * Released under the MIT license
2447 */
2448
2449var laravelValidation;
2450laravelValidation = {
2451
2452    implicitRules: ['Required','Confirmed'],
2453
2454    /**
2455     * Initialize laravel validations.
2456     */
2457    init: function () {
2458
2459        // Disable class rules and attribute rules
2460        $.validator.classRuleSettings = {};
2461        $.validator.attributeRules = function () {
2462            this.rules = {}
2463        };
2464
2465        $.validator.dataRules = this.arrayRules;
2466        $.validator.prototype.arrayRulesCache = {};
2467        // Register validations methods
2468        this.setupValidations();
2469    },
2470
2471    arrayRules: function(element) {
2472
2473        var rules = {},
2474            validator = $.data( element.form, "validator"),
2475            cache = validator.arrayRulesCache;
2476
2477        // Is not an Array
2478        if (element.name.indexOf('[') === -1 ) {
2479            return rules;
2480        }
2481
2482        if (! (element.name in cache) ) {
2483            cache[element.name]={};
2484        }
2485
2486        $.each(validator.settings.rules, function(name, tmpRules){
2487            if (name in cache[element.name]) {
2488                $.extend(rules, cache[element.name][name]);
2489            } else {
2490                cache[element.name][name]={};
2491                var nameRegExp = laravelValidation.helpers.regexFromWildcard(name);
2492                if (element.name.match(nameRegExp)) {
2493                    var newRules = $.validator.normalizeRule( tmpRules ) || {};
2494                    cache[element.name][name]=newRules;
2495                    $.extend(rules, newRules);
2496                }
2497            }
2498        });
2499
2500        return rules;
2501    },
2502
2503    setupValidations: function () {
2504
2505        /**
2506         * Create JQueryValidation check to validate Laravel rules.
2507         */
2508
2509        $.validator.addMethod("laravelValidation", function (value, element, params) {
2510            var validator = this;
2511            var validated = true;
2512            var previous = this.previousValue( element );
2513
2514            // put Implicit rules in front
2515            var rules=[];
2516            $.each(params, function (i, param) {
2517                if (param[3] || laravelValidation.implicitRules.indexOf(param[0])!== -1) {
2518                    rules.unshift(param);
2519                } else {
2520                    rules.push(param);
2521                }
2522            });
2523
2524            $.each(rules, function (i, param) {
2525                var implicit = param[3] || laravelValidation.implicitRules.indexOf(param[0])!== -1;
2526                var rule = param[0];
2527                var message = param[2];
2528
2529                if ( !implicit && validator.optional( element ) ) {
2530                    validated="dependency-mismatch";
2531                    return false;
2532                }
2533
2534                if (laravelValidation.methods[rule]!==undefined) {
2535                    validated = laravelValidation.methods[rule].call(validator, value, element, param[1], function(valid) {
2536                        validator.settings.messages[ element.name ].laravelValidationRemote = previous.originalMessage;
2537                        if ( valid ) {
2538                            var submitted = validator.formSubmitted;
2539                            validator.prepareElement( element );
2540                            validator.formSubmitted = submitted;
2541                            validator.successList.push( element );
2542                            delete validator.invalid[ element.name ];
2543                            validator.showErrors();
2544                        } else {
2545                            var errors = {};
2546                            errors[ element.name ] = previous.message = $.isFunction( message ) ? message( value ) : message;
2547                            validator.invalid[ element.name ] = true;
2548                            validator.showErrors( errors );
2549                        }
2550                        validator.showErrors(validator.errorMap);
2551                        previous.valid = valid;
2552                    });
2553                } else {
2554                    validated=false;
2555                }
2556
2557                if (validated !== true) {
2558                    if (!validator.settings.messages[ element.name ] ) {
2559                        validator.settings.messages[ element.name ] = {};
2560                    }
2561                    validator.settings.messages[element.name].laravelValidation= message;
2562                    return false;
2563                }
2564
2565            });
2566            return validated;
2567
2568        }, '');
2569
2570
2571        /**
2572         * Create JQueryValidation check to validate Remote Laravel rules.
2573         */
2574        $.validator.addMethod("laravelValidationRemote", function (value, element, params) {
2575
2576            var implicit = false,
2577                check = params[0][1],
2578                attribute = element.name,
2579                token = check[1],
2580                validateAll = check[2];
2581
2582            $.each(params, function (i, parameters) {
2583                implicit = implicit || parameters[3];
2584            });
2585
2586
2587            if ( !implicit && this.optional( element ) ) {
2588                return "dependency-mismatch";
2589            }
2590
2591            var previous = this.previousValue( element ),
2592                validator, data;
2593
2594            if (!this.settings.messages[ element.name ] ) {
2595                this.settings.messages[ element.name ] = {};
2596            }
2597            previous.originalMessage = this.settings.messages[ element.name ].laravelValidationRemote;
2598            this.settings.messages[ element.name ].laravelValidationRemote = previous.message;
2599
2600            var param = typeof param === "string" && { url: param } || param;
2601
2602            if (laravelValidation.helpers.arrayEquals(previous.old, value) || previous.old === value) {
2603                return previous.valid;
2604            }
2605
2606            previous.old = value;
2607            validator = this;
2608            this.startRequest( element );
2609
2610            data = $(validator.currentForm).serializeArray();
2611
2612            data.push({
2613                'name': '_jsvalidation',
2614                'value': attribute
2615            });
2616
2617            data.push({
2618                'name': '_jsvalidation_validate_all',
2619                'value': validateAll
2620            });
2621
2622            var formMethod = $(validator.currentForm).attr('method');
2623            if($(validator.currentForm).find('input[name="_method"]').length) {
2624                formMethod = $(validator.currentForm).find('input[name="_method"]').val();
2625            }
2626
2627            $.ajax( $.extend( true, {
2628                mode: "abort",
2629                port: "validate" + element.name,
2630                dataType: "json",
2631                data: data,
2632                context: validator.currentForm,
2633                url: $(validator.currentForm).attr('action'),
2634                type: formMethod,
2635
2636                beforeSend: function (xhr) {
2637                    if ($(validator.currentForm).attr('method').toLowerCase() !== 'get' && token) {
2638                        return xhr.setRequestHeader('X-XSRF-TOKEN', token);
2639                    }
2640                }
2641            }, param )
2642            ).always(function( response, textStatus ) {
2643                    var errors, message, submitted, valid;
2644
2645                    if (textStatus === 'error') {
2646                        valid = false;
2647                        response = laravelValidation.helpers.parseErrorResponse(response);
2648                    } else if (textStatus === 'success') {
2649                        valid = response === true || response === "true";
2650                    } else {
2651                        return;
2652                    }
2653
2654                    validator.settings.messages[ element.name ].laravelValidationRemote = previous.originalMessage;
2655
2656                    if ( valid ) {
2657                        submitted = validator.formSubmitted;
2658                        validator.prepareElement( element );
2659                        validator.formSubmitted = submitted;
2660                        validator.successList.push( element );
2661                        delete validator.invalid[ element.name ];
2662                        validator.showErrors();
2663                    } else {
2664                        errors = {};
2665                        message = response || validator.defaultMessage( element, "remote" );
2666                        errors[ element.name ] = previous.message = $.isFunction( message ) ? message( value ) : message[0];
2667                        validator.invalid[ element.name ] = true;
2668                        validator.showErrors( errors );
2669                    }
2670                    validator.showErrors(validator.errorMap);
2671                    previous.valid = valid;
2672                    validator.stopRequest( element, valid );
2673                }
2674            );
2675            return "pending";
2676        }, '');
2677    }
2678};
2679
2680$(function() {
2681    laravelValidation.init();
2682});
2683
2684/*!
2685 * Laravel Javascript Validation
2686 *
2687 * https://github.com/proengsoft/laravel-jsvalidation
2688 *
2689 * Helper functions used by validators
2690 *
2691 * Copyright (c) 2017 Proengsoft
2692 * Released under the MIT license
2693 */
2694
2695$.extend(true, laravelValidation, {
2696
2697    helpers: {
2698
2699        /**
2700         * Numeric rules
2701         */
2702        numericRules: ['Integer', 'Numeric'],
2703
2704        /**
2705         * Gets the file information from file input.
2706         *
2707         * @param fieldObj
2708         * @param index
2709         * @returns {{file: *, extension: string, size: number}}
2710         */
2711        fileinfo: function (fieldObj, index) {
2712            var FileName = fieldObj.value;
2713            index = typeof index !== 'undefined' ? index : 0;
2714            if ( fieldObj.files !== null ) {
2715                if (typeof fieldObj.files[index] !== 'undefined') {
2716                    return {
2717                        file: FileName,
2718                        extension: FileName.substr(FileName.lastIndexOf('.') + 1),
2719                        size: fieldObj.files[index].size / 1024,
2720                        type: fieldObj.files[index].type
2721                    };
2722                }
2723            }
2724            return false;
2725        },
2726
2727
2728        /**
2729         * Gets the selectors for th specified field names.
2730         *
2731         * @param names
2732         * @returns {string}
2733         */
2734        selector: function (names) {
2735            var selector = [];
2736            if (!$.isArray(names))  {
2737                names = [names];
2738            }
2739            for (var i = 0; i < names.length; i++) {
2740                selector.push("[name='" + names[i] + "']");
2741            }
2742            return selector.join();
2743        },
2744
2745
2746        /**
2747         * Check if element has numeric rules.
2748         *
2749         * @param element
2750         * @returns {boolean}
2751         */
2752        hasNumericRules: function (element) {
2753            return this.hasRules(element, this.numericRules);
2754        },
2755
2756        /**
2757         * Check if element has passed rules.
2758         *
2759         * @param element
2760         * @param rules
2761         * @returns {boolean}
2762         */
2763        hasRules: function (element, rules) {
2764
2765            var found = false;
2766            if (typeof rules === 'string') {
2767                rules = [rules];
2768            }
2769
2770            var validator = $.data(element.form, "validator");
2771            var listRules = [];
2772            var cache = validator.arrayRulesCache;
2773            if (element.name in cache) {
2774                $.each(cache[element.name], function (index, arrayRule) {
2775                    listRules.push(arrayRule);
2776                });
2777            }
2778            if (element.name in validator.settings.rules) {
2779                listRules.push(validator.settings.rules[element.name]);
2780            }
2781            $.each(listRules, function(index,objRules){
2782                if ('laravelValidation' in objRules) {
2783                    var _rules=objRules.laravelValidation;
2784                    for (var i = 0; i < _rules.length; i++) {
2785                        if ($.inArray(_rules[i][0],rules) !== -1) {
2786                            found = true;
2787                            return false;
2788                        }
2789                    }
2790                }
2791            });
2792
2793            return found;
2794        },
2795
2796        /**
2797         * Return the string length using PHP function.
2798         * http://php.net/manual/en/function.strlen.php
2799         * http://phpjs.org/functions/strlen/
2800         *
2801         * @param string
2802         */
2803        strlen: function (string) {
2804            return strlen(string);
2805        },
2806
2807        /**
2808         * Get the size of the object depending of his type.
2809         *
2810         * @param obj
2811         * @param element
2812         * @param value
2813         * @returns int
2814         */
2815        getSize: function getSize(obj, element, value) {
2816
2817            if (this.hasNumericRules(element) && this.is_numeric(value)) {
2818                return parseFloat(value);
2819            } else if ($.isArray(value)) {
2820                return parseFloat(value.length);
2821            } else if (element.type === 'file') {
2822                return parseFloat(Math.floor(this.fileinfo(element).size));
2823            }
2824
2825            return parseFloat(this.strlen(value));
2826        },
2827
2828
2829        /**
2830         * Return specified rule from element.
2831         *
2832         * @param rule
2833         * @param element
2834         * @returns object
2835         */
2836        getLaravelValidation: function(rule, element) {
2837
2838            var found = undefined;
2839            $.each($.validator.staticRules(element), function(key, rules) {
2840                if (key==="laravelValidation") {
2841                    $.each(rules, function (i, value) {
2842                        if (value[0]===rule) {
2843                            found=value;
2844                        }
2845                    });
2846                }
2847            });
2848
2849            return found;
2850        },
2851
2852        /**
2853         * Return he timestamp of value passed using format or default format in element.
2854         *
2855         * @param value
2856         * @param format
2857         * @returns {boolean|int}
2858         */
2859        parseTime: function (value, format) {
2860
2861            var timeValue = false;
2862            var fmt = new DateFormatter();
2863
2864            if ($.type(format) === 'object') {
2865                var dateRule=this.getLaravelValidation('DateFormat', format);
2866                if (dateRule !== undefined) {
2867                    format = dateRule[1][0];
2868                } else {
2869                    format = null;
2870                }
2871            }
2872
2873            if (format == null) {
2874                timeValue = this.strtotime(value);
2875            } else {
2876                timeValue = fmt.parseDate(value, format);
2877                if (timeValue) {
2878                    timeValue = Math.round((timeValue.getTime() / 1000));
2879                }
2880            }
2881
2882            return timeValue;
2883        },
2884
2885        /**
2886         * This method allows you to intelligently guess the date by closely matching the specific format.
2887         *
2888         * @param value
2889         * @param format
2890         * @returns {Date}
2891         */
2892        guessDate: function (value, format) {
2893            var fmt = new DateFormatter();
2894            return fmt.guessDate(value, format)
2895        },
2896
2897        /**
2898         * Returns Unix timestamp based on PHP function strototime.
2899         * http://php.net/manual/es/function.strtotime.php
2900         * http://phpjs.org/functions/strtotime/
2901         *
2902         * @param text
2903         * @param now
2904         * @returns {*}
2905         */
2906        strtotime: function (text, now) {
2907            return strtotime(text, now)
2908        },
2909
2910        /**
2911         * Returns if value is numeric.
2912         * http://php.net/manual/es/var.is_numeric.php
2913         * http://phpjs.org/functions/is_numeric/
2914         *
2915         * @param mixed_var
2916         * @returns {*}
2917         */
2918        is_numeric: function (mixed_var) {
2919            return is_numeric(mixed_var)
2920        },
2921
2922        /**
2923         * Returns Array diff based on PHP function array_diff.
2924         * http://php.net/manual/es/function.array_diff.php
2925         * http://phpjs.org/functions/array_diff/
2926         *
2927         * @param arr1
2928         * @param arr2
2929         * @returns {*}
2930         */
2931        arrayDiff: function (arr1, arr2) {
2932            return array_diff(arr1, arr2);
2933        },
2934
2935        /**
2936         * Check whether two arrays are equal to one another.
2937         *
2938         * @param arr1
2939         * @param arr2
2940         * @returns {*}
2941         */
2942        arrayEquals: function (arr1, arr2) {
2943            if (! $.isArray(arr1) || ! $.isArray(arr2)) {
2944                return false;
2945            }
2946            
2947            if (arr1.length !== arr2.length) {
2948                return false;
2949            }
2950            
2951            return $.isEmptyObject(this.arrayDiff(arr1, arr2));
2952        },
2953
2954        /**
2955         * Makes element dependant from other.
2956         *
2957         * @param validator
2958         * @param element
2959         * @param name
2960         * @returns {*}
2961         */
2962        dependentElement: function(validator, element, name) {
2963
2964            var el=validator.findByName(name);
2965
2966            if ( el[0]!==undefined  && validator.settings.onfocusout ) {
2967                var event = 'blur';
2968                if (el[0].tagName === 'SELECT' ||
2969                    el[0].tagName === 'OPTION' ||
2970                    el[0].type === 'checkbox' ||
2971                    el[0].type === 'radio'
2972                ) {
2973                    event = 'click';
2974                }
2975
2976                var ruleName = '.validate-laravelValidation';
2977                el.off( ruleName )
2978                    .off(event + ruleName + '-' + element.name)
2979                    .on( event + ruleName + '-' + element.name, function() {
2980                        $( element ).valid();
2981                    });
2982            }
2983
2984            return el[0];
2985        },
2986
2987        /**
2988         * Parses error Ajax response and gets the message.
2989         *
2990         * @param response
2991         * @returns {string[]}
2992         */
2993        parseErrorResponse: function (response) {
2994            var newResponse = ['Whoops, looks like something went wrong.'];
2995            if ('responseText' in response) {
2996                var errorMsg = response.responseText.match(/<h1\s*>(.*)<\/h1\s*>/i);
2997                if ($.isArray(errorMsg)) {
2998                    newResponse = [errorMsg[1]];
2999                }
3000            }
3001            return newResponse;
3002        },
3003
3004        /**
3005         * Escape string to use as Regular Expression.
3006         *
3007         * @param str
3008         * @returns string
3009         */
3010        escapeRegExp: function (str) {
3011            return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
3012        },
3013
3014        /**
3015         * Generate RegExp from wildcard attributes.
3016         *
3017         * @param name
3018         * @returns {RegExp}
3019         */
3020        regexFromWildcard: function(name) {
3021            var nameParts = name.split("[*]");
3022            if (nameParts.length === 1) {
3023                nameParts.push('');
3024            }
3025            var regexpParts = nameParts.map(function(currentValue, index) {
3026                if (index % 2 === 0) {
3027                    currentValue = currentValue + '[';
3028                } else {
3029                    currentValue = ']' +currentValue;
3030                }
3031
3032                return laravelValidation.helpers.escapeRegExp(currentValue);
3033            });
3034
3035            return new RegExp('^'+regexpParts.join('.*')+'$');
3036        }
3037    }
3038});
3039
3040/*!
3041 * Laravel Javascript Validation
3042 *
3043 * https://github.com/proengsoft/laravel-jsvalidation
3044 *
3045 * Timezone Helper functions used by validators
3046 *
3047 * Copyright (c) 2017 Proengsoft
3048 * Released under the MIT license
3049 */
3050
3051$.extend(true, laravelValidation, {
3052
3053    helpers: {
3054
3055        /**
3056         * Check if the specified timezone is valid.
3057         *
3058         * @param value
3059         * @returns {boolean}
3060         */
3061        isTimezone: function (value) {
3062
3063            var timezones={
3064                "africa": [
3065                    "abidjan",
3066                    "accra",
3067                    "addis_ababa",
3068                    "algiers",
3069                    "asmara",
3070                    "bamako",
3071                    "bangui",
3072                    "banjul",
3073                    "bissau",
3074                    "blantyre",
3075                    "brazzaville",
3076                    "bujumbura",
3077                    "cairo",
3078                    "casablanca",
3079                    "ceuta",
3080                    "conakry",
3081                    "dakar",
3082                    "dar_es_salaam",
3083                    "djibouti",
3084                    "douala",
3085                    "el_aaiun",
3086                    "freetown",
3087                    "gaborone",
3088                    "harare",
3089                    "johannesburg",
3090                    "juba",
3091                    "kampala",
3092                    "khartoum",
3093                    "kigali",
3094                    "kinshasa",
3095                    "lagos",
3096                    "libreville",
3097                    "lome",
3098                    "luanda",
3099                    "lubumbashi",
3100                    "lusaka",
3101                    "malabo",
3102                    "maputo",
3103                    "maseru",
3104                    "mbabane",
3105                    "mogadishu",
3106                    "monrovia",
3107                    "nairobi",
3108                    "ndjamena",
3109                    "niamey",
3110                    "nouakchott",
3111                    "ouagadougou",
3112                    "porto-novo",
3113                    "sao_tome",
3114                    "tripoli",
3115                    "tunis",
3116                    "windhoek"
3117                ],
3118                "america": [
3119                    "adak",
3120                    "anchorage",
3121                    "anguilla",
3122                    "antigua",
3123                    "araguaina",
3124                    "argentina\/buenos_aires",
3125                    "argentina\/catamarca",
3126                    "argentina\/cordoba",
3127                    "argentina\/jujuy",
3128                    "argentina\/la_rioja",
3129                    "argentina\/mendoza",
3130                    "argentina\/rio_gallegos",
3131                    "argentina\/salta",
3132                    "argentina\/san_juan",
3133                    "argentina\/san_luis",
3134                    "argentina\/tucuman",
3135                    "argentina\/ushuaia",
3136                    "aruba",
3137                    "asuncion",
3138                    "atikokan",
3139                    "bahia",
3140                    "bahia_banderas",
3141                    "barbados",
3142                    "belem",
3143                    "belize",
3144                    "blanc-sablon",
3145                    "boa_vista",
3146                    "bogota",
3147                    "boise",
3148                    "cambridge_bay",
3149                    "campo_grande",
3150                    "cancun",
3151                    "caracas",
3152                    "cayenne",
3153                    "cayman",
3154                    "chicago",
3155                    "chihuahua",
3156                    "costa_rica",
3157                    "creston",
3158                    "cuiaba",
3159                    "curacao",
3160                    "danmarkshavn",
3161                    "dawson",
3162                    "dawson_creek",
3163                    "denver",
3164                    "detroit",
3165                    "dominica",
3166                    "edmonton",
3167                    "eirunepe",
3168                    "el_salvador",
3169                    "fortaleza",
3170                    "glace_bay",
3171                    "godthab",
3172                    "goose_bay",
3173                    "grand_turk",
3174                    "grenada",
3175                    "guadeloupe",
3176                    "guatemala",
3177                    "guayaquil",
3178                    "guyana",
3179                    "halifax",
3180                    "havana",
3181                    "hermosillo",
3182                    "indiana\/indianapolis",
3183                    "indiana\/knox",
3184                    "indiana\/marengo",
3185                    "indiana\/petersburg",
3186                    "indiana\/tell_city",
3187                    "indiana\/vevay",
3188                    "indiana\/vincennes",
3189                    "indiana\/winamac",
3190                    "inuvik",
3191                    "iqaluit",
3192                    "jamaica",
3193                    "juneau",
3194                    "kentucky\/louisville",
3195                    "kentucky\/monticello",
3196                    "kralendijk",
3197                    "la_paz",
3198                    "lima",
3199                    "los_angeles",
3200                    "lower_princes",
3201                    "maceio",
3202                    "managua",
3203                    "manaus",
3204                    "marigot",
3205                    "martinique",
3206                    "matamoros",
3207                    "mazatlan",
3208                    "menominee",
3209                    "merida",
3210                    "metlakatla",
3211                    "mexico_city",
3212                    "miquelon",
3213                    "moncton",
3214                    "monterrey",
3215                    "montevideo",
3216                    "montreal",
3217                    "montserrat",
3218                    "nassau",
3219                    "new_york",
3220                    "nipigon",
3221                    "nome",
3222                    "noronha",
3223                    "north_dakota\/beulah",
3224                    "north_dakota\/center",
3225                    "north_dakota\/new_salem",
3226                    "ojinaga",
3227                    "panama",
3228                    "pangnirtung",
3229                    "paramaribo",
3230                    "phoenix",
3231                    "port-au-prince",
3232                    "port_of_spain",
3233                    "porto_velho",
3234                    "puerto_rico",
3235                    "rainy_river",
3236                    "rankin_inlet",
3237                    "recife",
3238                    "regina",
3239                    "resolute",
3240                    "rio_branco",
3241                    "santa_isabel",
3242                    "santarem",
3243                    "santiago",
3244                    "santo_domingo",
3245                    "sao_paulo",
3246                    "scoresbysund",
3247                    "shiprock",
3248                    "sitka",
3249                    "st_barthelemy",
3250                    "st_johns",
3251                    "st_kitts",
3252                    "st_lucia",
3253                    "st_thomas",
3254                    "st_vincent",
3255                    "swift_current",
3256                    "tegucigalpa",
3257                    "thule",
3258                    "thunder_bay",
3259                    "tijuana",
3260                    "toronto",
3261                    "tortola",
3262                    "vancouver",
3263                    "whitehorse",
3264                    "winnipeg",
3265                    "yakutat",
3266                    "yellowknife"
3267                ],
3268                "antarctica": [
3269                    "casey",
3270                    "davis",
3271                    "dumontdurville",
3272                    "macquarie",
3273                    "mawson",
3274                    "mcmurdo",
3275                    "palmer",
3276                    "rothera",
3277                    "south_pole",
3278                    "syowa",
3279                    "vostok"
3280                ],
3281                "arctic": [
3282                    "longyearbyen"
3283                ],
3284                "asia": [
3285                    "aden",
3286                    "almaty",
3287                    "amman",
3288                    "anadyr",
3289                    "aqtau",
3290                    "aqtobe",
3291                    "ashgabat",
3292                    "baghdad",
3293                    "bahrain",
3294                    "baku",
3295                    "bangkok",
3296                    "beirut",
3297                    "bishkek",
3298                    "brunei",
3299                    "choibalsan",
3300                    "chongqing",
3301                    "colombo",
3302                    "damascus",
3303                    "dhaka",
3304                    "dili",
3305                    "dubai",
3306                    "dushanbe",
3307                    "gaza",
3308                    "harbin",
3309                    "hebron",
3310                    "ho_chi_minh",
3311                    "hong_kong",
3312                    "hovd",
3313                    "irkutsk",
3314                    "jakarta",
3315                    "jayapura",
3316                    "jerusalem",
3317                    "kabul",
3318                    "kamchatka",
3319                    "karachi",
3320                    "kashgar",
3321                    "kathmandu",
3322                    "khandyga",
3323                    "kolkata",
3324                    "krasnoyarsk",
3325                    "kuala_lumpur",
3326                    "kuching",
3327                    "kuwait",
3328                    "macau",
3329                    "magadan",
3330                    "makassar",
3331                    "manila",
3332                    "muscat",
3333                    "nicosia",
3334                    "novokuznetsk",
3335                    "novosibirsk",
3336                    "omsk",
3337                    "oral",
3338                    "phnom_penh",
3339                    "pontianak",
3340                    "pyongyang",
3341                    "qatar",
3342                    "qyzylorda",
3343                    "rangoon",
3344                    "riyadh",
3345                    "sakhalin",
3346                    "samarkand",
3347                    "seoul",
3348                    "shanghai",
3349                    "singapore",
3350                    "taipei",
3351                    "tashkent",
3352                    "tbilisi",
3353                    "tehran",
3354                    "thimphu",
3355                    "tokyo",
3356                    "ulaanbaatar",
3357                    "urumqi",
3358                    "ust-nera",
3359                    "vientiane",
3360                    "vladivostok",
3361                    "yakutsk",
3362                    "yekaterinburg",
3363                    "yerevan"
3364                ],
3365                "atlantic": [
3366                    "azores",
3367                    "bermuda",
3368                    "canary",
3369                    "cape_verde",
3370                    "faroe",
3371                    "madeira",
3372                    "reykjavik",
3373                    "south_georgia",
3374                    "st_helena",
3375                    "stanley"
3376                ],
3377                "australia": [
3378                    "adelaide",
3379                    "brisbane",
3380                    "broken_hill",
3381                    "currie",
3382                    "darwin",
3383                    "eucla",
3384                    "hobart",
3385                    "lindeman",
3386                    "lord_howe",
3387                    "melbourne",
3388                    "perth",
3389                    "sydney"
3390                ],
3391                "europe": [
3392                    "amsterdam",
3393                    "andorra",
3394                    "athens",
3395                    "belgrade",
3396                    "berlin",
3397                    "bratislava",
3398                    "brussels",
3399                    "bucharest",
3400                    "budapest",
3401                    "busingen",
3402                    "chisinau",
3403                    "copenhagen",
3404                    "dublin",
3405                    "gibraltar",
3406                    "guernsey",
3407                    "helsinki",
3408                    "isle_of_man",
3409                    "istanbul",
3410                    "jersey",
3411                    "kaliningrad",
3412                    "kiev",
3413                    "lisbon",
3414                    "ljubljana",
3415                    "london",
3416                    "luxembourg",
3417                    "madrid",
3418                    "malta",
3419                    "mariehamn",
3420                    "minsk",
3421                    "monaco",
3422                    "moscow",
3423                    "oslo",
3424                    "paris",
3425                    "podgorica",
3426                    "prague",
3427                    "riga",
3428                    "rome",
3429                    "samara",
3430                    "san_marino",
3431                    "sarajevo",
3432                    "simferopol",
3433                    "skopje",
3434                    "sofia",
3435                    "stockholm",
3436                    "tallinn",
3437                    "tirane",
3438                    "uzhgorod",
3439                    "vaduz",
3440                    "vatican",
3441                    "vienna",
3442                    "vilnius",
3443                    "volgograd",
3444                    "warsaw",
3445                    "zagreb",
3446                    "zaporozhye",
3447                    "zurich"
3448                ],
3449                "indian": [
3450                    "antananarivo",
3451                    "chagos",
3452                    "christmas",
3453                    "cocos",
3454                    "comoro",
3455                    "kerguelen",
3456                    "mahe",
3457                    "maldives",
3458                    "mauritius",
3459                    "mayotte",
3460                    "reunion"
3461                ],
3462                "pacific": [
3463                    "apia",
3464                    "auckland",
3465                    "chatham",
3466                    "chuuk",
3467                    "easter",
3468                    "efate",
3469                    "enderbury",
3470                    "fakaofo",
3471                    "fiji",
3472                    "funafuti",
3473                    "galapagos",
3474                    "gambier",
3475                    "guadalcanal",
3476                    "guam",
3477                    "honolulu",
3478                    "johnston",
3479                    "kiritimati",
3480                    "kosrae",
3481                    "kwajalein",
3482                    "majuro",
3483                    "marquesas",
3484                    "midway",
3485                    "nauru",
3486                    "niue",
3487                    "norfolk",
3488                    "noumea",
3489                    "pago_pago",
3490                    "palau",
3491                    "pitcairn",
3492                    "pohnpei",
3493                    "port_moresby",
3494                    "rarotonga",
3495                    "saipan",
3496                    "tahiti",
3497                    "tarawa",
3498                    "tongatapu",
3499                    "wake",
3500                    "wallis"
3501                ],
3502                "utc": [
3503                    ""
3504                ]
3505            };
3506
3507            var tzparts= value.split('/',2);
3508            var continent=tzparts[0].toLowerCase();
3509            var city='';
3510            if (tzparts[1]) {
3511                city=tzparts[1].toLowerCase();
3512            }
3513
3514            return (continent in timezones && ( timezones[continent].length===0 || timezones[continent].indexOf(city)!==-1))
3515        }
3516    }
3517});
3518
3519/*!
3520 * Laravel Javascript Validation
3521 *
3522 * https://github.com/proengsoft/laravel-jsvalidation
3523 *
3524 * Methods that implement Laravel Validations
3525 *
3526 * Copyright (c) 2017 Proengsoft
3527 * Released under the MIT license
3528 */
3529
3530$.extend(true, laravelValidation, {
3531
3532    methods:{
3533
3534        helpers: laravelValidation.helpers,
3535
3536        jsRemoteTimer:0,
3537
3538        /**
3539         * "Validate" optional attributes.
3540         * Always returns true, just lets us put sometimes in rules.
3541         *
3542         * @return {boolean}
3543         */
3544        Sometimes: function() {
3545            return true;
3546        },
3547
3548        /**
3549         * Bail This is the default behaivour os JSValidation.
3550         * Always returns true, just lets us put sometimes in rules.
3551         *
3552         * @return {boolean}
3553         */
3554        Bail: function() {
3555            return true;
3556        },
3557
3558        /**
3559         * "Indicate" validation should pass if value is null.
3560         * Always returns true, just lets us put "nullable" in rules.
3561         *
3562         * @return {boolean}
3563         */
3564        Nullable: function() {
3565            return true;
3566        },
3567
3568        /**
3569         * Validate the given attribute is filled if it is present.
3570         */
3571        Filled: function(value, element) {
3572            return $.validator.methods.required.call(this, value, element, true);
3573        },
3574
3575
3576        /**
3577         * Validate that a required attribute exists.
3578         */
3579        Required: function(value, element) {
3580            return  $.validator.methods.required.call(this, value, element);
3581        },
3582
3583        /**
3584         * Validate that an attribute exists when any other attribute exists.
3585         *
3586         * @return {boolean}
3587         */
3588        RequiredWith: function(value, element, params) {
3589            var validator=this,
3590                required=false;
3591            var currentObject=this;
3592
3593            $.each(params,function(i,param) {
3594                var target=laravelValidation.helpers.dependentElement(
3595                    currentObject, element, param
3596                );
3597                required=required || (
3598                    target!==undefined &&
3599                    $.validator.methods.required.call(
3600                        validator,
3601                        currentObject.elementValue(target),
3602                        target,true
3603                    ));
3604            });
3605
3606            if (required) {
3607                return  $.validator.methods.required.call(this, value, element, true);
3608            }
3609            return true;
3610        },
3611
3612        /**
3613         * Validate that an attribute exists when all other attribute exists.
3614         *
3615         * @return {boolean}
3616         */
3617        RequiredWithAll: function(value, element, params) {
3618            var validator=this,
3619                required=true;
3620            var currentObject=this;
3621
3622            $.each(params,function(i,param) {
3623                var target=laravelValidation.helpers.dependentElement(
3624                    currentObject, element, param
3625                );
3626                required = required && (
3627                      target!==undefined &&
3628                      $.validator.methods.required.call(
3629                          validator,
3630                          currentObject.elementValue(target),
3631                          target,true
3632                      ));
3633            });
3634
3635            if (required) {
3636                return  $.validator.methods.required.call(this, value, element, true);
3637            }
3638            return true;
3639        },
3640
3641        /**
3642         * Validate that an attribute exists when any other attribute does not exists.
3643         *
3644         * @return {boolean}
3645         */
3646        RequiredWithout: function(value, element, params) {
3647            var validator=this,
3648                required=false;
3649            var currentObject=this;
3650
3651            $.each(params,function(i,param) {
3652                var target=laravelValidation.helpers.dependentElement(
3653                    currentObject, element, param
3654                );
3655                required = required ||
3656                    target===undefined||
3657                    !$.validator.methods.required.call(
3658                        validator,
3659                        currentObject.elementValue(target),
3660                        target,true
3661                    );
3662            });
3663
3664            if (required) {
3665                return  $.validator.methods.required.call(this, value, element, true);
3666            }
3667            return true;
3668        },
3669
3670        /**
3671         * Validate that an attribute exists when all other attribute does not exists.
3672         *
3673         * @return {boolean}
3674         */
3675        RequiredWithoutAll: function(value, element, params) {
3676            var validator=this,
3677                required=true,
3678                currentObject=this;
3679
3680            $.each(params,function(i, param) {
3681                var target=laravelValidation.helpers.dependentElement(
3682                    currentObject, element, param
3683                );
3684                required = required && (
3685                    target===undefined ||
3686                    !$.validator.methods.required.call(
3687                        validator,
3688                        currentObject.elementValue(target),
3689                        target,true
3690                    ));
3691            });
3692
3693            if (required) {
3694                return  $.validator.methods.required.call(this, value, element, true);
3695            }
3696            return true;
3697        },
3698
3699        /**
3700         * Validate that an attribute exists when another attribute has a given value.
3701         *
3702         * @return {boolean}
3703         */
3704        RequiredIf: function(value, element, params) {
3705
3706            var target=laravelValidation.helpers.dependentElement(
3707                this, element, params[0]
3708            );
3709
3710            if (target!==undefined) {
3711                var val=String(this.elementValue(target));
3712                if (typeof val !== 'undefined') {
3713                    var data = params.slice(1);
3714                    if ($.inArray(val, data) !== -1) {
3715                        return $.validator.methods.required.call(
3716                            this, value, element, true
3717                        );
3718                    }
3719                }
3720            }
3721
3722            return true;
3723        },
3724
3725        /**
3726         * Validate that an attribute exists when another
3727         * attribute does not have a given value.
3728         *
3729         * @return {boolean}
3730         */
3731        RequiredUnless: function(value, element, params) {
3732
3733            var target=laravelValidation.helpers.dependentElement(
3734                this, element, params[0]
3735            );
3736
3737            if (target!==undefined) {
3738                var val=String(this.elementValue(target));
3739                if (typeof val !== 'undefined') {
3740                    var data = params.slice(1);
3741                    if ($.inArray(val, data) !== -1) {
3742                        return true;
3743                    }
3744                }
3745            }
3746
3747            return $.validator.methods.required.call(
3748                this, value, element, true
3749            );
3750
3751        },
3752
3753        /**
3754         * Validate that an attribute has a matching confirmation.
3755         *
3756         * @return {boolean}
3757         */
3758        Confirmed: function(value, element, params) {
3759            return laravelValidation.methods.Same.call(this,value, element, params);
3760        },
3761
3762        /**
3763         * Validate that two attributes match.
3764         *
3765         * @return {boolean}
3766         */
3767        Same: function(value, element, params) {
3768
3769            var target=laravelValidation.helpers.dependentElement(
3770                this, element, params[0]
3771            );
3772
3773            if (target!==undefined) {
3774                return String(value) === String(this.elementValue(target));
3775            }
3776            return false;
3777        },
3778
3779        /**
3780         * Validate that the values of an attribute is in another attribute.
3781         *
3782         * @param value
3783         * @param element
3784         * @param params
3785         * @returns {boolean}
3786         * @constructor
3787         */
3788        InArray: function (value, element, params) {
3789            if (typeof params[0] === 'undefined') {
3790                return false;
3791            }
3792            var elements = this.elements();
3793            var found = false;
3794            var nameRegExp = laravelValidation.helpers.regexFromWildcard(params[0]);
3795
3796            for ( var i = 0; i < elements.length ; i++ ) {
3797                var targetName = elements[i].name;
3798                if (targetName.match(nameRegExp)) {
3799                    var equals = laravelValidation.methods.Same.call(this,value, element, [targetName]);
3800                    found = found || equals;
3801                }
3802            }
3803
3804            return found;
3805        },
3806
3807        /**
3808         * Validate an attribute is unique among other values.
3809         *
3810         * @param value
3811         * @param element
3812         * @param params
3813         * @returns {boolean}
3814         */
3815        Distinct: function (value, element, params) {
3816            if (typeof params[0] === 'undefined') {
3817                return false;
3818            }
3819
3820            var elements = this.elements();
3821            var found = false;
3822            var nameRegExp = laravelValidation.helpers.regexFromWildcard(params[0]);
3823
3824            for ( var i = 0; i < elements.length ; i++ ) {
3825                var targetName = elements[i].name;
3826                if (targetName !== element.name && targetName.match(nameRegExp)) {
3827                    var equals = laravelValidation.methods.Same.call(this,value, element, [targetName]);
3828                    found = found || equals;
3829                }
3830            }
3831
3832            return !found;
3833        },
3834
3835
3836        /**
3837         * Validate that an attribute is different from another attribute.
3838         *
3839         * @return {boolean}
3840         */
3841        Different: function(value, element, params) {
3842            return ! laravelValidation.methods.Same.call(this,value, element, params);
3843        },
3844
3845        /**
3846         * Validate that an attribute was "accepted".
3847         * This validation rule implies the attribute is "required".
3848         *
3849         * @return {boolean}
3850         */
3851        Accepted: function(value) {
3852            var regex = new RegExp("^(?:(yes|on|1|true))$",'i');
3853            return regex.test(value);
3854        },
3855
3856        /**
3857         * Validate that an attribute is an array.
3858         *
3859         * @param value
3860         * @param element
3861         */
3862        Array: function(value, element) {
3863            if (element.name.indexOf('[') !== -1 && element.name.indexOf(']') !== -1) {
3864                return true;
3865            }
3866
3867            return $.isArray(value);
3868        },
3869
3870        /**
3871         * Validate that an attribute is a boolean.
3872         *
3873         * @return {boolean}
3874         */
3875        Boolean: function(value) {
3876            var regex= new RegExp("^(?:(true|false|1|0))$",'i');
3877            return  regex.test(value);
3878        },
3879
3880        /**
3881         * Validate that an attribute is an integer.
3882         *
3883         * @return {boolean}
3884         */
3885        Integer: function(value) {
3886            var regex= new RegExp("^(?:-?\\d+)$",'i');
3887            return  regex.test(value);
3888        },
3889
3890        /**
3891         * Validate that an attribute is numeric.
3892         */
3893        Numeric: function(value, element) {
3894            return $.validator.methods.number.call(this, value, element, true);
3895        },
3896
3897        /**
3898         * Validate that an attribute is a string.
3899         *
3900         * @return {boolean}
3901         */
3902        String: function(value) {
3903            return typeof value === 'string';
3904        },
3905
3906        /**
3907         * The field under validation must be numeric and must have an exact length of value.
3908         */
3909        Digits: function(value, element, params) {
3910            return (
3911                $.validator.methods.number.call(this, value, element, true) &&
3912                value.length === parseInt(params, 10)
3913            );
3914        },
3915
3916        /**
3917         * The field under validation must have a length between the given min and max.
3918         */
3919        DigitsBetween: function(value, element, params) {
3920            return ($.validator.methods.number.call(this, value, element, true)
3921                && value.length>=parseFloat(params[0]) && value.length<=parseFloat(params[1]));
3922        },
3923
3924        /**
3925         * Validate the size of an attribute.
3926         *
3927         * @return {boolean}
3928         */
3929        Size: function(value, element, params) {
3930            return laravelValidation.helpers.getSize(this, element,value) === parseFloat(params[0]);
3931        },
3932
3933        /**
3934         * Validate the size of an attribute is between a set of values.
3935         *
3936         * @return {boolean}
3937         */
3938        Between: function(value, element, params) {
3939            return ( laravelValidation.helpers.getSize(this, element,value) >= parseFloat(params[0]) &&
3940                laravelValidation.helpers.getSize(this,element,value) <= parseFloat(params[1]));
3941        },
3942
3943        /**
3944         * Validate the size of an attribute is greater than a minimum value.
3945         *
3946         * @return {boolean}
3947         */
3948        Min: function(value, element, params) {
3949            return laravelValidation.helpers.getSize(this, element,value) >= parseFloat(params[0]);
3950        },
3951
3952        /**
3953         * Validate the size of an attribute is less than a maximum value.
3954         *
3955         * @return {boolean}
3956         */
3957        Max: function(value, element, params) {
3958            return laravelValidation.helpers.getSize(this, element,value) <= parseFloat(params[0]);
3959        },
3960
3961        /**
3962         * Validate an attribute is contained within a list of values.
3963         *
3964         * @return {boolean}
3965         */
3966        In: function(value, element, params) {
3967            if ($.isArray(value) && laravelValidation.helpers.hasRules(element, "Array")) {
3968                var diff = laravelValidation.helpers.arrayDiff(value, params);
3969                return Object.keys(diff).length === 0;
3970            }
3971            return params.indexOf(value.toString()) !== -1;
3972        },
3973
3974        /**
3975         * Validate an attribute is not contained within a list of values.
3976         *
3977         * @return {boolean}
3978         */
3979        NotIn: function(value, element, params) {
3980            return params.indexOf(value.toString()) === -1;
3981        },
3982
3983        /**
3984         * Validate that an attribute is a valid IP.
3985         *
3986         * @return {boolean}
3987         */
3988        Ip: function(value) {
3989            return /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test(value) ||
3990                /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(value);
3991        },
3992
3993        /**
3994         * Validate that an attribute is a valid e-mail address.
3995         */
3996        Email: function(value, element) {
3997            return $.validator.methods.email.call(this, value, element, true);
3998        },
3999
4000        /**
4001         * Validate that an attribute is a valid URL.
4002         */
4003        Url: function(value, element) {
4004            return $.validator.methods.url.call(this, value, element, true);
4005        },
4006
4007        /**
4008         * The field under validation must be a successfully uploaded file.
4009         *
4010         * @return {boolean}
4011         */
4012        File: function(value, element) {
4013            if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
4014                return true;
4015            }
4016            if ('files' in element ) {
4017                return (element.files.length > 0);
4018            }
4019            return false;
4020        },
4021
4022        /**
4023         * Validate the MIME type of a file upload attribute is in a set of MIME types.
4024         *
4025         * @return {boolean}
4026         */
4027        Mimes: function(value, element, params) {
4028            if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
4029                return true;
4030            }
4031            var lowerParams = $.map(params, function(item) {
4032                return item.toLowerCase();
4033            });
4034
4035            var fileinfo = laravelValidation.helpers.fileinfo(element);
4036            return (fileinfo !== false && lowerParams.indexOf(fileinfo.extension.toLowerCase())!==-1);
4037        },
4038
4039        /**
4040         * The file under validation must match one of the given MIME types.
4041         *
4042         * @return {boolean}
4043         */
4044        Mimetypes: function(value, element, params) {
4045            if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
4046                return true;
4047            }
4048            var lowerParams = $.map(params, function(item) {
4049                return item.toLowerCase();
4050            });
4051
4052            var fileinfo = laravelValidation.helpers.fileinfo(element);
4053
4054            if (fileinfo === false) {
4055                return false;
4056            }
4057            return (lowerParams.indexOf(fileinfo.type.toLowerCase())!==-1);
4058        },
4059
4060        /**
4061         * Validate the MIME type of a file upload attribute is in a set of MIME types.
4062         */
4063        Image: function(value, element) {
4064            return laravelValidation.methods.Mimes.call(this, value, element, [
4065                'jpg', 'png', 'gif', 'bmp', 'svg', 'jpeg'
4066            ]);
4067        },
4068
4069        /**
4070         * Validate dimensions of Image.
4071         *
4072         * @return {boolean|string}
4073         */
4074        Dimensions: function(value, element, params, callback) {
4075            if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
4076                return true;
4077            }
4078            if (element.files === null || typeof element.files[0] === 'undefined') {
4079                return false;
4080            }
4081
4082            var fr = new FileReader;
4083            fr.onload = function () {
4084                var img = new Image();
4085                img.onload = function () {
4086                    var height = parseFloat(img.naturalHeight);
4087                    var width = parseFloat(img.naturalWidth);
4088                    var ratio = width / height;
4089                    var notValid = ((params['width']) && parseFloat(params['width'] !== width)) ||
4090                        ((params['min_width']) && parseFloat(params['min_width']) > width) ||
4091                        ((params['max_width']) && parseFloat(params['max_width']) < width) ||
4092                        ((params['height']) && parseFloat(params['height']) !== height) ||
4093                        ((params['min_height']) && parseFloat(params['min_height']) > height) ||
4094                        ((params['max_height']) && parseFloat(params['max_height']) < height) ||
4095                        ((params['ratio']) && ratio !== parseFloat(eval(params['ratio']))
4096                        );
4097                    callback(! notValid);
4098                };
4099                img.onerror = function() {
4100                    callback(false);
4101                };
4102                img.src = fr.result;
4103            };
4104            fr.readAsDataURL(element.files[0]);
4105
4106            return 'pending';
4107        },
4108
4109        /**
4110         * Validate that an attribute contains only alphabetic characters.
4111         *
4112         * @return {boolean}
4113         */
4114        Alpha: function(value) {
4115            if (typeof  value !== 'string') {
4116                return false;
4117            }
4118
4119            var regex = new RegExp("^(?:^[a-z\u00E0-\u00FC]+$)$",'i');
4120            return  regex.test(value);
4121
4122        },
4123
4124        /**
4125         * Validate that an attribute contains only alpha-numeric characters.
4126         *
4127         * @return {boolean}
4128         */
4129        AlphaNum: function(value) {
4130            if (typeof  value !== 'string') {
4131                return false;
4132            }
4133            var regex = new RegExp("^(?:^[a-z0-9\u00E0-\u00FC]+$)$",'i');
4134            return regex.test(value);
4135        },
4136
4137        /**
4138         * Validate that an attribute contains only alphabetic characters.
4139         *
4140         * @return {boolean}
4141         */
4142        AlphaDash: function(value) {
4143            if (typeof  value !== 'string') {
4144                return false;
4145            }
4146            var regex = new RegExp("^(?:^[a-z0-9\u00E0-\u00FC_-]+$)$",'i');
4147            return regex.test(value);
4148        },
4149
4150        /**
4151         * Validate that an attribute passes a regular expression check.
4152         *
4153         * @return {boolean}
4154         */
4155        Regex: function(value, element, params) {
4156            var invalidModifiers=['x','s','u','X','U','A'];
4157            // Converting php regular expression
4158            var phpReg= new RegExp('^(?:\/)(.*\\\/?[^\/]*|[^\/]*)(?:\/)([gmixXsuUAJ]*)?$');
4159            var matches=params[0].match(phpReg);
4160            if (matches === null) {
4161                return false;
4162            }
4163            // checking modifiers
4164            var php_modifiers=[];
4165            if (matches[2]!==undefined) {
4166                php_modifiers=matches[2].split('');
4167                for (var i=0; i<php_modifiers.length<i ;i++) {
4168                    if (invalidModifiers.indexOf(php_modifiers[i])!==-1) {
4169                        return true;
4170                    }
4171                }
4172            }
4173            var regex = new RegExp("^(?:"+matches[1]+")$",php_modifiers.join());
4174            return   regex.test(value);
4175        },
4176
4177        /**
4178         * Validate that an attribute is a valid date.
4179         *
4180         * @return {boolean}
4181         */
4182        Date: function(value) {
4183            return (laravelValidation.helpers.strtotime(value)!==false);
4184        },
4185
4186        /**
4187         * Validate that an attribute matches a date format.
4188         *
4189         * @return {boolean}
4190         */
4191        DateFormat: function(value, element, params) {
4192            return laravelValidation.helpers.parseTime(value,params[0])!==false;
4193        },
4194
4195        /**
4196         * Validate the date is before a given date.
4197         *
4198         * @return {boolean}
4199         */
4200        Before: function(value, element, params) {
4201
4202            var timeCompare=parseFloat(params);
4203            if (isNaN(timeCompare)) {
4204                var target=laravelValidation.helpers.dependentElement(this, element, params);
4205                if (target===undefined) {
4206                    return false;
4207                }
4208                timeCompare= laravelValidation.helpers.parseTime(this.elementValue(target), target);
4209            }
4210
4211            var timeValue=laravelValidation.helpers.parseTime(value, element);
4212            return  (timeValue !==false && timeValue < timeCompare);
4213
4214        },
4215
4216        /**
4217         * Validate the date is after a given date.
4218         *
4219         * @return {boolean}
4220         */
4221        After: function(value, element, params) {
4222            var timeCompare=parseFloat(params);
4223            if (isNaN(timeCompare)) {
4224                var target=laravelValidation.helpers.dependentElement(this, element, params);
4225                if (target===undefined) {
4226                    return false;
4227                }
4228                timeCompare= laravelValidation.helpers.parseTime(this.elementValue(target), target);
4229            }
4230
4231            var timeValue=laravelValidation.helpers.parseTime(value, element);
4232            return  (timeValue !==false && timeValue > timeCompare);
4233
4234        },
4235
4236
4237        /**
4238         * Validate that an attribute is a valid date.
4239         */
4240        Timezone: function(value) {
4241            return  laravelValidation.helpers.isTimezone(value);
4242        },
4243
4244
4245        /**
4246         * Validate the attribute is a valid JSON string.
4247         *
4248         * @param  value
4249         * @return bool
4250         */
4251        Json: function(value) {
4252            var result = true;
4253            try {
4254                JSON.parse(value);
4255            } catch (e) {
4256                result = false;
4257            }
4258            return result;
4259        }
4260    }
4261});
4262
4263//# sourceMappingURL=jsvalidation.js.map

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.