PageSourceSearch

https://pataiwan.org/scripts/validationEngine/jquery.validationEngine.js

js pataiwan.org collected 2026-10-07 13:32:56 UTC 72,392 bytes, 1,886 lines download raw bytes

1/*
2 * Inline Form Validation Engine 2.6.2, jQuery plugin
3 *
4 * Copyright(c) 2010, Cedric Dugas
5 * http://www.position-absolute.com
6 *
7 * 2.0 Rewrite by Olivier Refalo
8 * http://www.crionics.com
9 *
10 * Form validation engine allowing custom regex rules to be added.
11 * Licensed under the MIT License
12 */
13 (function($) {
14	"use strict";
15	var methods = {
16		/**
17		* Kind of the constructor, called before any action
18		* @param {Map} user options
19		*/
20		init: function(options) {
21			var form = this;
22			if (!form.data('jqv') || form.data('jqv') == null ) {
23				options = methods._saveOptions(form, options);
24				// bind all formError elements to close on click
25				$(document).on("click", ".formError", function() {
26					$(this).fadeOut(150, function() {
27						// remove prompt once invisible
28						$(this).parent('.formErrorOuter').remove();
29						$(this).remove();
30					});
31				});
32			}
33			return this;
34		 },
35		/**
36		* Attachs jQuery.validationEngine to form.submit and field.blur events
37		* Takes an optional params: a list of options
38		* ie. jQuery("#formID1").validationEngine('attach', {promptPosition : "centerRight"});
39		*/
40		attach: function(userOptions) {
41			var form = this;
42			var options;
43			if(userOptions)
44				options = methods._saveOptions(form, userOptions);
45			else
46				options = form.data('jqv');
47			options.validateAttribute = (form.find("[data-validation-engine*=validate]").length) ? "data-validation-engine" : "class";
48			if (options.binded) {
49				// delegate fields
50				form.on(options.validationEventTrigger, "["+options.validateAttribute+"*=validate]:not([type=checkbox]):not([type=radio]):not(.datepicker)", methods._onFieldEvent);
51				form.on("click", "["+options.validateAttribute+"*=validate][type=checkbox],["+options.validateAttribute+"*=validate][type=radio]", methods._onFieldEvent);
52				form.on(options.validationEventTrigger,"["+options.validateAttribute+"*=validate][class*=datepicker]", {"delay": 300}, methods._onFieldEvent);
53			}
54			if (options.autoPositionUpdate) {
55				$(window).bind("resize", {
56					"noAnimation": true,
57					"formElem": form
58				}, methods.updatePromptsPosition);
59			}
60			form.on("click","a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick);
61			form.removeData('jqv_submitButton');
62			// bind form.submit
63			form.on("submit", methods._onSubmitEvent);
64			return this;
65		},
66		/**
67		* Unregisters any bindings that may point to jQuery.validaitonEngine
68		*/
69		detach: function() {
70			var form = this;
71			var options = form.data('jqv');
72			// unbind fields
73			form.find("["+options.validateAttribute+"*=validate]").not("[type=checkbox]").off(options.validationEventTrigger, methods._onFieldEvent);
74			form.find("["+options.validateAttribute+"*=validate][type=checkbox],[class*=validate][type=radio]").off("click", methods._onFieldEvent);
75			// unbind form.submit
76			form.off("submit", methods._onSubmitEvent);
77			form.removeData('jqv');
78			form.off("click", "a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick);
79			form.removeData('jqv_submitButton');
80			if (options.autoPositionUpdate)
81				$(window).off("resize", methods.updatePromptsPosition);
82			return this;
83		},
84		/**
85		* Validates either a form or a list of fields, shows prompts accordingly.
86		* Note: There is no ajax form validation with this method, only field ajax validation are evaluated
87		*
88		* @return true if the form validates, false if it fails
89		*/
90		validate: function() {
91			var element = $(this);
92			var valid = null;
93			if (element.is("form") || element.hasClass("validationEngineContainer")) {
94				if (element.hasClass('validating')) {
95					// form is already validating.
96					// Should abort old validation and start new one. I don't know how to implement it.
97					return false;
98				} else {
99					element.addClass('validating');
100					var options = element.data('jqv');
101					var valid = methods._validateFields(this);
102					// If the form doesn't validate, clear the 'validating' class before the user has a chance to submit again
103					setTimeout(function(){
104						element.removeClass('validating');
105					}, 100);
106					if (valid && options.onSuccess) {
107						options.onSuccess();
108					} else if (!valid && options.onFailure) {
109						options.onFailure();
110					}
111				}
112			} else if (element.is('form') || element.hasClass('validationEngineContainer')) {
113				element.removeClass('validating');
114			} else {
115				// field validation
116				var form = element.closest('form, .validationEngineContainer'),
117					options = (form.data('jqv')) ? form.data('jqv') : $.validationEngine.defaults,
118					valid = methods._validateField(element, options);
119				if (valid && options.onFieldSuccess)
120					options.onFieldSuccess();
121				else if (options.onFieldFailure && options.InvalidFields.length > 0) {
122					options.onFieldFailure();
123				}
124			}
125			if(options.onValidationComplete) {
126				// !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing
127				return !!options.onValidationComplete(form, valid);
128			}
129			return valid;
130		},
131		/**
132		*  Redraw prompts position, useful when you change the DOM state when validating
133		*/
134		updatePromptsPosition: function(event) {
135			if (event && this == window) {
136				var form = event.data.formElem;
137				var noAnimation = event.data.noAnimation;
138			}
139			else
140				var form = $(this.closest('form, .validationEngineContainer'));
141			var options = form.data('jqv');
142			// No option, take default one
143			form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each(function(){
144				var field = $(this);
145				if (options.prettySelect && field.is(":hidden"))
146				  field = form.find("#" + options.usePrefix + field.attr('id') + options.useSuffix);
147				var prompt = methods._getPrompt(field);
148				var promptText = $(prompt).find(".formErrorContent").html();
149				if(prompt)
150					methods._updatePrompt(field, $(prompt), promptText, undefined, false, options, noAnimation);
151			});
152			return this;
153		},
154		/**
155		* Displays a prompt on a element.
156		* Note that the element needs an id!
157		*
158		* @param {String} promptText html text to display type
159		* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
160		* @param {String} possible values topLeft, topRight, bottomLeft, centerRight, bottomRight
161		*/
162		showPrompt: function(promptText, type, promptPosition, showArrow) {
163			var form = this.closest('form, .validationEngineContainer');
164			var options = form.data('jqv');
165			// No option, take default one
166			if(!options)
167				options = methods._saveOptions(this, options);
168			if(promptPosition)
169				options.promptPosition=promptPosition;
170			options.showArrow = showArrow==true;
171			methods._showPrompt(this, promptText, type, false, options);
172			return this;
173		},
174		/**
175		* Closes form error prompts, CAN be invidual
176		*/
177		hide: function() {
178			 var form = $(this).closest('form, .validationEngineContainer');
179			 var options = form.data('jqv');
180			 var fadeDuration = (options && options.fadeDuration) ? options.fadeDuration : 0.3;
181			 var closingtag;
182			 if($(this).is("form") || $(this).hasClass("validationEngineContainer")) {
183				 closingtag = "parentForm"+methods._getClassName($(this).attr("id"));
184			 } else {
185				 closingtag = methods._getClassName($(this).attr("id")) +"formError";
186			 }
187			 $('.'+closingtag).fadeTo(fadeDuration, 0.3, function() {
188				 $(this).parent('.formErrorOuter').remove();
189				 $(this).remove();
190			 });
191			 return this;
192		 },
193		 /**
194		 * Closes all error prompts on the page
195		 */
196		 hideAll: function() {
197			 var form = this;
198			 var options = form.data('jqv');
199			 var duration = options ? options.fadeDuration:300;
200			 $('.formError').fadeTo(duration, 300, function() {
201				 $(this).parent('.formErrorOuter').remove();
202				 $(this).remove();
203			 });
204			 return this;
205		 },
206		/**
207		* Typically called when user exists a field using tab or a mouse click, triggers a field
208		* validation
209		*/
210		_onFieldEvent: function(event) {
211			var field = $(this);
212			var form = field.closest('form, .validationEngineContainer');
213			var options = form.data('jqv');
214			options.eventTrigger = "field";
215			// validate the current field
216			window.setTimeout(function() {
217				methods._validateField(field, options);
218				if (options.InvalidFields.length == 0 && options.onFieldSuccess) {
219					options.onFieldSuccess();
220				} else if (options.InvalidFields.length > 0 && options.onFieldFailure) {
221					options.onFieldFailure();
222				}
223			}, (event.data) ? event.data.delay : 0);
224		},
225		/**
226		* Called when the form is submited, shows prompts accordingly
227		*
228		* @param {jqObject}
229		*            form
230		* @return false if form submission needs to be cancelled
231		*/
232		_onSubmitEvent: function() {
233			var form = $(this);
234			var options = form.data('jqv');
235			//check if it is trigger from skipped button
236			if (form.data("jqv_submitButton")){
237				var submitButton = $("#" + form.data("jqv_submitButton"));
238				if (submitButton){
239					if (submitButton.length > 0){
240						if (submitButton.hasClass("validate-skip") || submitButton.attr("data-validation-engine-skip") == "true")
241							return true;
242					}
243				}
244			}
245			options.eventTrigger = "submit";
246			// validate each field
247			// (- skip field ajax validation, not necessary IF we will perform an ajax form validation)
248			var r=methods._validateFields(form);
249			if (r && options.ajaxFormValidation) {
250				methods._validateFormWithAjax(form, options);
251				// cancel form auto-submission - process with async call onAjaxFormComplete
252				return false;
253			}
254			if(options.onValidationComplete) {
255				// !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing
256				return !!options.onValidationComplete(form, r);
257			}
258			return r;
259		},
260		/**
261		* Return true if the ajax field validations passed so far
262		* @param {Object} options
263		* @return true, is all ajax validation passed so far (remember ajax is async)
264		*/
265		_checkAjaxStatus: function(options) {
266			var status = true;
267			$.each(options.ajaxValidCache, function(key, value) {
268				if (!value) {
269					status = false;
270					// break the each
271					return false;
272				}
273			});
274			return status;
275		},
276		/**
277		* Return true if the ajax field is validated
278		* @param {String} fieldid
279		* @param {Object} options
280		* @return true, if validation passed, false if false or doesn't exist
281		*/
282		_checkAjaxFieldStatus: function(fieldid, options) {
283			return options.ajaxValidCache[fieldid] == true;
284		},
285		/**
286		* Validates form fields, shows prompts accordingly
287		*
288		* @param {jqObject}
289		*            form
290		* @param {skipAjaxFieldValidation}
291		*            boolean - when set to true, ajax field validation is skipped, typically used when the submit button is clicked
292		*
293		* @return true if form is valid, false if not, undefined if ajax form validation is done
294		*/
295		_validateFields: function(form) {
296			var options = form.data('jqv');
297			// this variable is set to true if an error is found
298			var errorFound = false;
299			// Trigger hook, start validation
300			form.trigger("jqv.form.validating");
301			// first, evaluate status of non ajax fields
302			var first_err=null;
303			form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each( function() {
304				var field = $(this);
305				var names = [];
306				if ($.inArray(field.attr('name'), names) < 0) {
307					errorFound |= methods._validateField(field, options);
308					if (errorFound && first_err==null)
309						if (field.is(":hidden") && options.prettySelect)
310							first_err = field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix);
311						else {
312							//Check if we need to adjust what element to show the prompt on
313							//and and such scroll to instead
314							if(field.data('jqv-prompt-at') instanceof jQuery ){
315								field = field.data('jqv-prompt-at');
316							} else if(field.data('jqv-prompt-at')) {
317								field = $(field.data('jqv-prompt-at'));
318							}
319							first_err=field;
320						}
321					if (options.doNotShowAllErrosOnSubmit)
322						return false;
323					names.push(field.attr('name'));
324					//if option set, stop checking validation rules after one error is found
325					if(options.showOneMessage == true && errorFound){
326						return false;
327					}
328				}
329			});
330			// second, check to see if all ajax calls completed ok
331			// errorFound |= !methods._checkAjaxStatus(options);
332			// third, check status and scroll the container accordingly
333			form.trigger("jqv.form.result", [errorFound]);
334			if (errorFound) {
335				if (options.scroll) {
336					var destination=first_err.offset().top;
337					var fixleft = first_err.offset().left;
338					//prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)
339					var positionType=options.promptPosition;
340					if (typeof(positionType)=='string' && positionType.indexOf(":")!=-1)
341						positionType=positionType.substring(0,positionType.indexOf(":"));
342					if (positionType!="bottomRight" && positionType!="bottomLeft") {
343						var prompt_err= methods._getPrompt(first_err);
344						if (prompt_err) {
345							destination=prompt_err.offset().top;
346						}
347					}
348					// Offset the amount the page scrolls by an amount in px to accomodate fixed elements at top of page
349					if (options.scrollOffset) {
350						destination -= options.scrollOffset;
351					}
352					// get the position of the first error, there should be at least one, no need to check this
353					//var destination = form.find(".formError:not('.greenPopup'):first").offset().top;
354					if (options.isOverflown) {
355						var overflowDIV = $(options.overflownDIV);
356						if(!overflowDIV.length) return false;
357						var scrollContainerScroll = overflowDIV.scrollTop();
358						var scrollContainerPos = -parseInt(overflowDIV.offset().top);
359						destination += scrollContainerScroll + scrollContainerPos - 5;
360						var scrollContainer = $(options.overflownDIV + ":not(:animated)");
361						scrollContainer.animate({ scrollTop: destination }, 1100, function(){
362							if(options.focusFirstField) first_err.focus();
363						});
364					} else {
365						$("html, body").animate({
366							scrollTop: destination
367						}, 1100, function(){
368							if(options.focusFirstField) first_err.focus();
369						});
370						$("html, body").animate({scrollLeft: fixleft},1100)
371					}
372				} else if(options.focusFirstField)
373					first_err.focus();
374				return false;
375			}
376			return true;
377		},
378		/**
379		* This method is called to perform an ajax form validation.
380		* During this process all the (field, value) pairs are sent to the server which returns a list of invalid fields or true
381		*
382		* @param {jqObject} form
383		* @param {Map} options
384		*/
385		_validateFormWithAjax: function(form, options) {
386			var data = form.serialize();
387									var type = (options.ajaxFormValidationMethod) ? options.ajaxFormValidationMethod : "GET";
388			var url = (options.ajaxFormValidationURL) ? options.ajaxFormValidationURL : form.attr("action");
389									var dataType = (options.dataType) ? options.dataType : "json";
390			$.ajax({
391				type: type,
392				url: url,
393				cache: false,
394				dataType: dataType,
395				data: data,
396				form: form,
397				methods: methods,
398				options: options,
399				beforeSend: function() {
400					return options.onBeforeAjaxFormValidation(form, options);
401				},
402				error: function(data, transport) {
403					if (options.onFailure) {
404						options.onFailure(data, transport);
405					} else {
406						methods._ajaxError(data, transport);
407					}
408				},
409				success: function(json) {
410					if ((dataType == "json") && (json !== true)) {
411						// getting to this case doesn't necessary means that the form is invalid
412						// the server may return green or closing prompt actions
413						// this flag helps figuring it out
414						var errorInForm=false;
415						for (var i = 0; i < json.length; i++) {
416							var value = json[i];
417							var errorFieldId = value[0];
418							var errorField = $($("#" + errorFieldId)[0]);
419							// make sure we found the element
420							if (errorField.length == 1) {
421								// promptText or selector
422								var msg = value[2];
423								// if the field is valid
424								if (value[1] == true) {
425									if (msg == ""  || !msg){
426										// if for some reason, status==true and error="", just close the prompt
427										methods._closePrompt(errorField);
428									} else {
429										// the field is valid, but we are displaying a green prompt
430										if (options.allrules[msg]) {
431											var txt = options.allrules[msg].alertTextOk;
432											if (txt)
433												msg = txt;
434										}
435										if (options.showPrompts) methods._showPrompt(errorField, msg, "pass", false, options, true);
436									}
437								} else {
438									// the field is invalid, show the red error prompt
439									errorInForm|=true;
440									if (options.allrules[msg]) {
441										var txt = options.allrules[msg].alertText;
442										if (txt)
443											msg = txt;
444									}
445									if(options.showPrompts) methods._showPrompt(errorField, msg, "", false, options, true);
446								}
447							}
448						}
449						options.onAjaxFormComplete(!errorInForm, form, json, options);
450					} else
451						options.onAjaxFormComplete(true, form, json, options);
452				}
453			});
454		},
455		/**
456		* Validates field, shows prompts accordingly
457		*
458		* @param {jqObject}
459		*            field
460		* @param {Array[String]}
461		*            field's validation rules
462		* @param {Map}
463		*            user options
464		* @return false if field is valid (It is inversed for *fields*, it return false on validate and true on errors.)
465		*/
466		_validateField: function(field, options, skipAjaxValidation) {
467			if (!field.attr("id")) {
468				field.attr("id", "form-validation-field-" + $.validationEngine.fieldIdCounter);
469				++$.validationEngine.fieldIdCounter;
470			}
471           if (!options.validateNonVisibleFields && (field.is(":hidden") && !options.prettySelect || field.parent().is(":hidden")))
472				return false;
473			var rulesParsing = field.attr(options.validateAttribute);
474			var getRules = /validate\[(.*)\]/.exec(rulesParsing);
475			if (!getRules)
476				return false;
477			var str = getRules[1];
478			var rules = str.split(/\[|,|\]/);
479			// true if we ran the ajax validation, tells the logic to stop messing with prompts
480			var isAjaxValidator = false;
481			var fieldName = field.attr("name");
482			var promptText = "";
483			var promptType = "";
484			var required = false;
485			var limitErrors = false;
486			options.isError = false;
487			options.showArrow = true;
488			// If the programmer wants to limit the amount of error messages per field,
489			if (options.maxErrorsPerField > 0) {
490				limitErrors = true;
491			}
492			var form = $(field.closest("form, .validationEngineContainer"));
493			// Fix for adding spaces in the rules
494			for (var i = 0; i < rules.length; i++) {
495				rules[i] = rules[i].replace(" ", "");
496				// Remove any parsing errors
497				if (rules[i] === '') {
498					delete rules[i];
499				}
500			}
501			for (var i = 0, field_errors = 0; i < rules.length; i++) {
502				// If we are limiting errors, and have hit the max, break
503				if (limitErrors && field_errors >= options.maxErrorsPerField) {
504					// If we haven't hit a required yet, check to see if there is one in the validation rules for this
505					// field and that it's index is greater or equal to our current index
506					if (!required) {
507						var have_required = $.inArray('required', rules);
508						required = (have_required != -1 &&  have_required >= i);
509					}
510					break;
511				}
512				var errorMsg = undefined;
513				switch (rules[i]) {
514					case "required":
515						required = true;
516						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._required);
517						break;
518					case "custom":
519						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._custom);
520						break;
521					case "groupRequired":
522						// Check is its the first of group, if not, reload validation with first field
523						// AND continue normal validation on present field
524						var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]";
525						var firstOfGroup = form.find(classGroup).eq(0);
526						if(firstOfGroup[0] != field[0]){
527							methods._validateField(firstOfGroup, options, skipAjaxValidation);
528							options.showArrow = true;
529						}
530						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._groupRequired);
531						if(errorMsg)  required = true;
532						options.showArrow = false;
533						break;
534					case "ajax":
535						// AJAX defaults to returning it's loading message
536						errorMsg = methods._ajax(field, rules, i, options);
537						if (errorMsg) {
538							promptType = "load";
539						}
540						break;
541					case "minSize":
542						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minSize);
543						break;
544					case "maxSize":
545						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxSize);
546						break;
547					case "min":
548						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._min);
549						break;
550					case "max":
551						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._max);
552						break;
553					case "past":
554						errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._past);
555						break;
556					case "future":
557						errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._future);
558						break;
559					case "dateRange":
560						var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]";
561						options.firstOfGroup = form.find(classGroup).eq(0);
562						options.secondOfGroup = form.find(classGroup).eq(1);
563						//if one entry out of the pair has value then proceed to run through validation
564						if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {
565							errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateRange);
566						}
567						if (errorMsg) required = true;
568						options.showArrow = false;
569						break;
570					case "dateTimeRange":
571						var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]";
572						options.firstOfGroup = form.find(classGroup).eq(0);
573						options.secondOfGroup = form.find(classGroup).eq(1);
574						//if one entry out of the pair has value then proceed to run through validation
575						if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {
576							errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateTimeRange);
577						}
578						if (errorMsg) required = true;
579						options.showArrow = false;
580						break;
581					case "maxCheckbox":
582						field = $(form.find("input[name='" + fieldName + "']"));
583						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxCheckbox);
584						break;
585					case "minCheckbox":
586						field = $(form.find("input[name='" + fieldName + "']"));
587						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minCheckbox);
588						break;
589					case "equals":
590						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._equals);
591						break;
592					case "funcCall":
593						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._funcCall);
594						break;
595					case "creditCard":
596						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._creditCard);
597						break;
598					case "condRequired":
599						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._c
599ondRequired);
600						if (errorMsg !== undefined) {
601							required = true;
602						}
603						break;
604					default:
605				}
606				var end_validation = false;
607				// If we were passed back an message object, check what the status was to determine what to do
608				if (typeof errorMsg == "object") {
609					switch (errorMsg.status) {
610						case "_break":
611							end_validation = true;
612							break;
613						// If we have an error message, set errorMsg to the error message
614						case "_error":
615							errorMsg = errorMsg.message;
616							break;
617						// If we want to throw an error, but not show a prompt, return early with true
618						case "_error_no_prompt":
619							return true;
620							break;
621						// Anything else we continue on
622						default:
623							break;
624					}
625				}
626				// If it has been specified that validation should end now, break
627				if (end_validation) {
628					break;
629				}
630				// If we have a string, that means that we have an error, so add it to the error message.
631				if (typeof errorMsg == 'string') {
632					promptText += errorMsg + "<br/>";
633					options.isError = true;
634					field_errors++;
635				}
636			}
637			// If the rules required is not added, an empty field is not validated
638			//the 3rd condition is added so that even empty password fields should be equal
639			//otherwise if one is filled and another left empty, the "equal" condition would fail
640			//which does not make any sense
641			if(!required && !(field.val()) && field.val().length < 1 && rules.indexOf("equals") < 0) options.isError = false;
642			// Hack for radio/checkbox group button, the validation go into the
643			// first radio/checkbox of the group
644			var fieldType = field.prop("type");
645			var positionType=field.data("promptPosition") || options.promptPosition;
646			if ((fieldType == "radio" || fieldType == "checkbox") && form.find("input[name='" + fieldName + "']").size() > 1) {
647				if(positionType === 'inline') {
648					field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:last"));
649				} else {
650				field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:first"));
651				}
652				options.showArrow = false;
653			}
654			if(field.is(":hidden") && options.prettySelect) {
655				field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix);
656			}
657			if (options.isError && options.showPrompts){
658				methods._showPrompt(field, promptText, promptType, false, options);
659			}else{
660				if (!isAjaxValidator) methods._closePrompt(field);
661			}
662			if (!isAjaxValidator) {
663				field.trigger("jqv.field.result", [field, options.isError, promptText]);
664			}
665			/* Record error */
666			var errindex = $.inArray(field[0], options.InvalidFields);
667			if (errindex == -1) {
668				if (options.isError)
669				options.InvalidFields.push(field[0]);
670			} else if (!options.isError) {
671				options.InvalidFields.splice(errindex, 1);
672			}
673			methods._handleStatusCssClasses(field, options);
674			/* run callback function for each field */
675			if (options.isError && options.onFieldFailure)
676				options.onFieldFailure(field);
677			if (!options.isError && options.onFieldSuccess)
678				options.onFieldSuccess(field);
679			return options.isError;
680		},
681		/**
682		* Handling css classes of fields indicating result of validation
683		*
684		* @param {jqObject}
685		*            field
686		* @param {Array[String]}
687		*            field's validation rules
688		* @private
689		*/
690		_handleStatusCssClasses: function(field, options) {
691			/* remove all classes */
692			if(options.addSuccessCssClassToField)
693				field.removeClass(options.addSuccessCssClassToField);
694			if(options.addFailureCssClassToField)
695				field.removeClass(options.addFailureCssClassToField);
696			/* Add classes */
697			if (options.addSuccessCssClassToField && !options.isError)
698				field.addClass(options.addSuccessCssClassToField);
699			if (options.addFailureCssClassToField && options.isError)
700				field.addClass(options.addFailureCssClassToField);
701		},
702		 /********************
703		  * _getErrorMessage
704		  *
705		  * @param form
706		  * @param field
707		  * @param rule
708		  * @param rules
709		  * @param i
710		  * @param options
711		  * @param originalValidationMethod
712		  * @return {*}
713		  * @private
714		  */
715		 _getErrorMessage:function (form, field, rule, rules, i, options, originalValidationMethod) {
716			 // If we are using the custon validation type, build the index for the rule.
717			 // Otherwise if we are doing a function call, make the call and return the object
718			 // that is passed back.
719	 		 var rule_index = jQuery.inArray(rule, rules);
720			 if (rule === "custom" || rule === "funcCall") {
721				 var custom_validation_type = rules[rule_index + 1];
722				 rule = rule + "[" + custom_validation_type + "]";
723				 // Delete the rule from the rules array so that it doesn't try to call the
724			    // same rule over again
725			    delete(rules[rule_index]);
726			 }
727			 // Change the rule to the composite rule, if it was different from the original
728			 var alteredRule = rule;
729			 var element_classes = (field.attr("data-validation-engine")) ? field.attr("data-validation-engine") : field.attr("class");
730			 var element_classes_array = element_classes.split(" ");
731			 // Call the original validation method. If we are dealing with dates or checkboxes, also pass the form
732			 var errorMsg;
733			 if (rule == "future" || rule == "past"  || rule == "maxCheckbox" || rule == "minCheckbox") {
734				 errorMsg = originalValidationMethod(form, field, rules, i, options);
735			 } else {
736				 errorMsg = originalValidationMethod(field, rules, i, options);
737			 }
738			 // If the original validation method returned an error and we have a custom error message,
739			 // return the custom message instead. Otherwise return the original error message.
740			 if (errorMsg != undefined) {
741				 var custom_message = methods._getCustomErrorMessage($(field), element_classes_array, alteredRule, options);
742				 if (custom_message) errorMsg = custom_message;
743			 }
744			 return errorMsg;
745		 },
746		 _getCustomErrorMessage:function (field, classes, rule, options) {
747			var custom_message = false;
748			var validityProp = /^custom\[.*\]$/.test(rule) ? methods._validityProp["custom"] : methods._validityProp[rule];
749			 // If there is a validityProp for this rule, check to see if the field has an attribute for it
750			if (validityProp != undefined) {
751				custom_message = field.attr("data-errormessage-"+validityProp);
752				// If there was an error message for it, return the message
753				if (custom_message != undefined)
754					return custom_message;
755			}
756			custom_message = field.attr("data-errormessage");
757			 // If there is an inline custom error message, return it
758			if (custom_message != undefined)
759				return custom_message;
760			var id = '#' + field.attr("id");
761			// If we have custom messages for the element's id, get the message for the rule from the id.
762			// Otherwise, if we have custom messages for the element's classes, use the first class message we find instead.
763			if (typeof options.custom_error_messages[id] != "undefined" &&
764				typeof options.custom_error_messages[id][rule] != "undefined" ) {
765						  custom_message = options.custom_error_messages[id][rule]['message'];
766			} else if (classes.length > 0) {
767				for (var i = 0; i < classes.length && classes.length > 0; i++) {
768					 var element_class = "." + classes[i];
769					if (typeof options.custom_error_messages[element_class] != "undefined" &&
770						typeof options.custom_error_messages[element_class][rule] != "undefined") {
771							custom_message = options.custom_error_messages[element_class][rule]['message'];
772							break;
773					}
774				}
775			}
776			if (!custom_message &&
777				typeof options.custom_error_messages[rule] != "undefined" &&
778				typeof options.custom_error_messages[rule]['message'] != "undefined"){
779					 custom_message = options.custom_error_messages[rule]['message'];
780			 }
781			 return custom_message;
782		 },
783		 _validityProp: {
784			 "required": "value-missing",
785			 "custom": "custom-error",
786			 "groupRequired": "value-missing",
787			 "ajax": "custom-error",
788			 "minSize": "range-underflow",
789			 "maxSize": "range-overflow",
790			 "min": "range-underflow",
791			 "max": "range-overflow",
792			 "past": "type-mismatch",
793			 "future": "type-mismatch",
794			 "dateRange": "type-mismatch",
795			 "dateTimeRange": "type-mismatch",
796			 "maxCheckbox": "range-overflow",
797			 "minCheckbox": "range-underflow",
798			 "equals": "pattern-mismatch",
799			 "funcCall": "custom-error",
800			 "creditCard": "pattern-mismatch",
801			 "condRequired": "value-missing"
802		 },
803		/**
804		* Required validation
805		*
806		* @param {jqObject} field
807		* @param {Array[String]} rules
808		* @param {int} i rules index
809		* @param {Map}
810		*            user options
811		* @param {bool} condRequired flag when method is used for internal purpose in condRequired check
812		* @return an error string if validation failed
813		*/
814		_required: function(field, rules, i, options, condRequired) {
815			switch (field.prop("type")) {
816				case "text":
817				case "password":
818				case "textarea":
819				case "file":
820				case "select-one":
821				case "select-multiple":
822				default:
823					var field_val      = $.trim( field.val()                               );
824					var dv_placeholder = $.trim( field.attr("data-validation-placeholder") );
825					var placeholder    = $.trim( field.attr("placeholder")                 );
826					if (
827						   ( !field_val                                    )
828						|| ( dv_placeholder && field_val == dv_placeholder )
829						|| ( placeholder    && field_val == placeholder    )
830					) {
831						return options.allrules[rules[i]].alertText;
832					}
833					break;
834				case "radio":
835				case "checkbox":
836					// new validation style to only check dependent field
837					if (condRequired) {
838						if (!field.attr('checked')) {
839							return options.allrules[rules[i]].alertTextCheckboxMultiple;
840						}
841						break;
842					}
843					// old validation style
844					var form = field.closest("form, .validationEngineContainer");
845					var name = field.attr("name");
846					if (form.find("input[name='" + name + "']:checked").size() == 0) {
847						if (form.find("input[name='" + name + "']:visible").size() == 1)
848							return options.allrules[rules[i]].alertTextCheckboxe;
849						else
850							return options.allrules[rules[i]].alertTextCheckboxMultiple;
851					}
852					break;
853			}
854		},
855		/**
856		* Validate that 1 from the group field is required
857		*
858		* @param {jqObject} field
859		* @param {Array[String]} rules
860		* @param {int} i rules index
861		* @param {Map}
862		*            user options
863		* @return an error string if validation failed
864		*/
865		_groupRequired: function(field, rules, i, options) {
866			var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]";
867			var isValid = false;
868			// Check all fields from the group
869			field.closest("form, .validationEngineContainer").find(classGroup).each(function(){
870				if(!methods._required($(this), rules, i, options)){
871					isValid = true;
872					return false;
873				}
874			});
875			if(!isValid) {
876		  return options.allrules[rules[i]].alertText;
877		}
878		},
879		/**
880		* Validate rules
881		*
882		* @param {jqObject} field
883		* @param {Array[String]} rules
884		* @param {int} i rules index
885		* @param {Map}
886		*            user options
887		* @return an error string if validation failed
888		*/
889		_custom: function(field, rules, i, options) {
890			var customRule = rules[i + 1];
891			var rule = options.allrules[customRule];
892			var fn;
893			if(!rule) {
894				alert("jqv:custom rule not found - "+customRule);
895				return;
896			}
897			if(rule["regex"]) {
898				 var ex=rule.regex;
899					if(!ex) {
900						alert("jqv:custom regex not found - "+customRule);
901						return;
902					}
903					var pattern = new RegExp(ex);
904					if (!pattern.test(field.val())) return options.allrules[customRule].alertText;
905			} else if(rule["func"]) {
906				fn = rule["func"];
907				if (typeof(fn) !== "function") {
908					alert("jqv:custom parameter 'function' is no function - "+customRule);
909						return;
910				}
911				if (!fn(field, rules, i, options))
912					return options.allrules[customRule].alertText;
913			} else {
914				alert("jqv:custom type not allowed "+customRule);
915					return;
916			}
917		},
918		/**
919		* Validate custom function outside of the engine scope
920		*
921		* @param {jqObject} field
922		* @param {Array[String]} rules
923		* @param {int} i rules index
924		* @param {Map}
925		*            user options
926		* @return an error string if validation failed
927		*/
928		_funcCall: function(field, rules, i, options) {
929			var functionName = rules[i + 1];
930			var fn;
931			if(functionName.indexOf('.') >-1)
932			{
933				var namespaces = functionName.split('.');
934				var scope = window;
935				while(namespaces.length)
936				{
937					scope = scope[namespaces.shift()];
938				}
939				fn = scope;
940			}
941			else
942				fn = window[functionName] || options.customFunctions[functionName];
943			if (typeof(fn) == 'function')
944				return fn(field, rules, i, options);
945		},
946		/**
947		* Field match
948		*
949		* @param {jqObject} field
950		* @param {Array[String]} rules
951		* @param {int} i rules index
952		* @param {Map}
953		*            user options
954		* @return an error string if validation failed
955		*/
956		_equals: function(field, rules, i, options) {
957			var equalsField = rules[i + 1];
958			if (field.val() != $("#" + equalsField).val())
959				return options.allrules.equals.alertText;
960		},
961		/**
962		* Check the maximum size (in characters)
963		*
964		* @param {jqObject} field
965		* @param {Array[String]} rules
966		* @param {int} i rules index
967		* @param {Map}
968		*            user options
969		* @return an error string if validation failed
970		*/
971		_maxSize: function(field, rules, i, options) {
972			var max = rules[i + 1];
973			var len = field.val().length;
974			if (len > max) {
975				var rule = options.allrules.maxSize;
976				return rule.alertText + max + rule.alertText2;
977			}
978		},
979		/**
980		* Check the minimum size (in characters)
981		*
982		* @param {jqObject} field
983		* @param {Array[String]} rules
984		* @param {int} i rules index
985		* @param {Map}
986		*            user options
987		* @return an error string if validation failed
988		*/
989		_minSize: function(field, rules, i, options) {
990			var min = rules[i + 1];
991			var len = field.val().length;
992			if (len < min) {
993				var rule = options.allrules.minSize;
994				return rule.alertText + min + rule.alertText2;
995			}
996		},
997		/**
998		* Check number minimum value
999		*
1000		* @param {jqObject} field
1001		* @param {Array[String]} rules
1002		* @param {int} i rules index
1003		* @param {Map}
1004		*            user options
1005		* @return an error string if validation failed
1006		*/
1007		_min: function(field, rules, i, options) {
1008			var min = parseFloat(rules[i + 1]);
1009			var len = parseFloat(field.val());
1010			if (len < min) {
1011				var rule = options.allrules.min;
1012				if (rule.alertText2) return rule.alertText + min + rule.alertText2;
1013				return rule.alertText + min;
1014			}
1015		},
1016		/**
1017		* Check number maximum value
1018		*
1019		* @param {jqObject} field
1020		* @param {Array[String]} rules
1021		* @param {int} i rules index
1022		* @param {Map}
1023		*            user options
1024		* @return an error string if validation failed
1025		*/
1026		_max: function(field, rules, i, options) {
1027			var max = parseFloat(rules[i + 1]);
1028			var len = parseFloat(field.val());
1029			if (len >max ) {
1030				var rule = options.allrules.max;
1031				if (rule.alertText2) return rule.alertText + max + rule.alertText2;
1032				//orefalo: to review, also do the translations
1033				return rule.alertText + max;
1034			}
1035		},
1036		/**
1037		* Checks date is in the past
1038		*
1039		* @param {jqObject} field
1040		* @param {Array[String]} rules
1041		* @param {int} i rules index
1042		* @param {Map}
1043		*            user options
1044		* @return an error string if validation failed
1045		*/
1046		_past: function(form, field, rules, i, options) {
1047			var p=rules[i + 1];
1048			var fieldAlt = $(form.find("*[name='" + p.replace(/^#+/, '') + "']"));
1049			var pdate;
1050			if (p.toLowerCase() == "now") {
1051				pdate = new Date();
1052			} else if (undefined != fieldAlt.val()) {
1053				if (fieldAlt.is(":disabled"))
1054					return;
1055				pdate = methods._parseDate(fieldAlt.val());
1056			} else {
1057				pdate = methods._parseDate(p);
1058			}
1059			var vdate = methods._parseDate(field.val());
1060			if (vdate > pdate ) {
1061				var rule = options.allrules.past;
1062				if (rule.alertText2) return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
1063				return rule.alertText + methods._dateToString(pdate);
1064			}
1065		},
1066		/**
1067		* Checks date is in the future
1068		*
1069		* @param {jqObject} field
1070		* @param {Array[String]} rules
1071		* @param {int} i rules index
1072		* @param {Map}
1073		*            user options
1074		* @return an error string if validation failed
1075		*/
1076		_future: function(form, field, rules, i, options) {
1077			var p=rules[i + 1];
1078			var fieldAlt = $(form.find("*[name='" + p.replace(/^#+/, '') + "']"));
1079			var pdate;
1080			if (p.toLowerCase() == "now") {
1081				pdate = new Date();
1082			} else if (undefined != fieldAlt.val()) {
1083				if (fieldAlt.is(":disabled"))
1084					return;
1085				pdate = methods._parseDate(fieldAlt.val());
1086			} else {
1087				pdate = methods._parseDate(p);
1088			}
1089			var vdate = methods._parseDate(field.val());
1090			if (vdate < pdate ) {
1091				var rule = options.allrules.future;
1092				if (rule.alertText2)
1093					return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
1094				return rule.alertText + methods._dateToString(pdate);
1095			}
1096		},
1097		/**
1098		* Checks if valid date
1099		*
1100		* @param {string} date string
1101		* @return a bool based on determination of valid date
1102		*/
1103		_isDate: function (value) {
1104			var dateRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(?:(?:0?[1-9]|1[0-2])(\/|-)(?:0?[1-9]|1\d|2[0-8]))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(0?2(\/|-)29)(\/|-)(?:(?:0[48]00|[13579][26]00|[2468][048]00)|(?:\d\d)?(?:0[48]|[2468][048]|[13579][26]))$/);
1105			return dateRegEx.test(value);
1106		},
1107		/**
1108		* Checks if valid date time
1109		*
1110		* @param {string} date string
1111		* @return a bool based on determination of valid date time
1112		*/
1113		_isDateTime: function (value){
1114			var dateTimeRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1}$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^((1[012]|0?[1-9]){1}\/(0?[1-9]|[12][0-9]|3[01]){1}\/\d{2,4}\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1})$/);
1115			return dateTimeRegEx.test(value);
1116		},
1117		//Checks if the start date is before the end date
1118		//returns true if end is later than start
1119		_dateCompare: function (start, end) {
1120			return (new Date(start.toString()) < new Date(end.toString()));
1121		},
1122		/**
1123		* Checks date range
1124		*
1125		* @param {jqObject} first field name
1126		* @param {jqObject} second field name
1127		* @return an error string if validation failed
1128		*/
1129		_dateRange: function (field, rules, i, options) {
1130			//are not both populated
1131			if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {
1132				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1133			}
1134			//are not both dates
1135			if (!methods._isDate(options.firstOfGroup[0].value) || !methods._isDate(options.secondOfGroup[0].value)) {
1136				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1137			}
1138			//are both dates but range is off
1139			if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {
1140				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1141			}
1142		},
1143		/**
1144		* Checks date time range
1145		*
1146		* @param {jqObject} first field name
1147		* @param {jqObject} second field name
1148		* @return an error string if validation failed
1149		*/
1150		_dateTimeRange: function (field, rules, i, options) {
1151			//are not both populated
1152			if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {
1153				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1154			}
1155			//are not both dates
1156			if (!methods._isDateTime(options.firstOfGroup[0].value) || !methods._isDateTime(options.secondOfGroup[0].value)) {
1157				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1158			}
1159			//are both dates but range is off
1160			if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {
1161				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1162			}
1163		},
1164		/**
1165		* Max number of checkbox selected
1166		*
1167		* @param {jqObject} field
1168		* @param {Array[String]} rules
1169		* @param {int} i rules index
1170		* @param {Map}
1171		*            user options
1172		* @return an error string if validation failed
1173		*/
1174		_maxCheckbox: function(form, field, rules, i, options) {
1175			var nbCheck = rules[i + 1];
1176			var groupname = field.attr("name");
1177			var groupSize = form.find("input[name='" + groupname + "']:checked").size();
1178			if (groupSize > nbCheck) {
1179				options.showArrow = false;
1180				if (options.allrules.maxCheckbox.alertText2)
1181					 return options.allrules.maxCheckbox.alertText + " " + nbCheck + " " + options.allrules.maxCheckbox.alertText2;
1182				return options.allrules.maxCheckbox.alertText;
1183			}
1184		},
1185		/**
1186		* Min number of checkbox selected
1187		*
1188		* @param {jqObject} field
1189		* @param {Array[String]} rules
1190		* @param {int} i rules index
1191		* @param {Map}
1192		*            user options
1193		* @return an error string if validation failed
1194		*/
1195		_minCheckbox: function(form, field, rules, i, options) {
1196			var nbCheck = rules[i + 1];
1197			var groupname = field.attr("name");
1198			var groupSize = form.find("input[name='" + groupname + "']:checked").size();
1199			if (groupSize < nbCheck) {
1200				options.showArrow = false;
1201				return options.allrules.minCheckbox.alertText + " " + nbCheck + " " + options.allrules.minCheckbox.alertText2;
1202			}
1203		},
1204		/**
1205		* Checks that it is a valid credit card number according to the
1206		* Luhn checksum algorithm.
1207		*
1208		* @param {jqObject} field
1209		* @param {Array[String]} rules
1210		* @param {int} i rules index
1211		* @param {Map}
1212		*            user options
1213		* @return an error string if validation failed
1214		*/
1215		_creditCard: function(field, rules, i, options) {
1216			//spaces and dashes may be valid characters, but must be stripped to calculate the checksum.
1217			var valid = false, cardNumber = field.val().replace(/ +/g, '').replace(/-+/g, '');
1218			var numDigits = cardNumber.length;
1219			if (numDigits >= 14 && numDigits <= 16 && parseInt(cardNumber) > 0) {
1220				var sum = 0, i = numDigits - 1, pos = 1, digit, luhn = new String();
1221				do {
1222					digit = parseInt(cardNumber.charAt(i));
1223					luhn += (pos++ % 2 == 0) ? digit * 2 : digit;
1224				} while (--i >= 0)
1225				for (i = 0; i < luhn.length; i++) {
1226					sum += parseInt(luhn.charAt(i));
1227				}
1228				valid = sum % 10 == 0;
1229			}
1230			if (!valid) return options.allrules.creditCard.alertText;
1231		},
1232		/**
1233		* Ajax field validation
1234		*
1235		* @param {jqObject} field
1236		* @param {Array[String]} rules
1237		* @param {int} i rules index
1238		* @param {Map}
1239		*            user options
1240		* @return nothing! the ajax validator handles the prompts itself
1241		*/
1242		 _ajax: function(field, rules, i, options) {
1243			 var errorSelector = rules[i + 1];
1244			 var rule = options.allrules[errorSelector];
1245			 var extraData = rule.extraData;
1246			 var extraDataDynamic = rule.extraDataDynamic;
1247			 var data = {
1248				"fieldId" : field.attr("id"),
1249				"fieldValue" : field.val()
1250			 };
1251			 if (typeof extraData === "object") {
1252				$.extend(data, extraData);
1253			 } else if (typeof extraData === "string") {
1254				var tempData = extraData.split("&");
1255				for(var i = 0; i < tempData.length; i++) {
1256					var values = tempData[i].split("=");
1257					if (values[0] && values[0]) {
1258						data[values[0]] = values[1];
1259					}
1260				}
1261			 }
1262			 if (extraDataDynamic) {
1263				 var tmpData = [];
1264				 var domIds = String(extraDataDynamic).split(",");
1265				 for (var i = 0; i < domIds.length; i++) {
1266					 var id = domIds[i];
1267					 if ($(id).length) {
1268						 var inputValue = field.closest("form, .validationEngineContainer").find(id).val();
1269						 var keyValue = id.replace('#', '') + '=' + escape(inputValue);
1270						 data[id.replace('#', '')] = inputValue;
1271					 }
1272				 }
1273			 }
1274			 // If a field change event triggered this we want to clear the cache for this ID
1275			 if (options.eventTrigger == "field") {
1276				delete(options.ajaxValidCache[field.attr("id")]);
1277			 }
1278			 // If there is an error or if the the field is already validated, do not re-execute AJAX
1279			 if (!options.isError && !methods._checkAjaxFieldStatus(field.attr("id"), options)) {
1280				 $.ajax({
1281					 type: options.ajaxFormValidationMethod,
1282					 url: rule.url,
1283					 cache: false,
1284					 dataType: "json",
1285					 data: data,
1286					 field: field,
1287					 rule: rule,
1288					 methods: methods,
1289					 options: options,
1290					 beforeSend: function() {},
1291					 error: function(data, transport) {
1292						if (options.onFailure) {
1293							options.onFailure(data, transport);
1294						} else {
1295							methods._ajaxError(data, transport);
1296						}
1297					 },
1298					 success: function(json) {
1299						 // asynchronously called on success, data is the json answer from the server
1300						 var errorFieldId = json[0];
1301						 //var errorField = $($("#" + errorFieldId)[0]);
1302						 var errorField = $("#"+ errorFieldId).eq(0);
1303						 // make sure we found the element
1304						 if (errorField.length == 1) {
1305							 var status = json[1];
1306							 // read the optional msg from the server
1307							 var msg = json[2];
1308							 if (!status) {
1309								 // Houston we got a problem - display an red prompt
1310								 options.ajaxValidCache[errorFieldId] = false;
1311								 options.isError = true;
1312								 // resolve the msg prompt
1313								 if(msg) {
1314									 if (options.allrules[msg]) {
1315										 var txt = options.allrules[msg].alertText;
1316										 if (txt) {
1317											msg = txt;
1318							}
1319									 }
1320								 }
1321								 else
1322									msg = rule.alertText;
1323								 if (options.showPrompts) methods._showPrompt(errorField, msg, "", true, options);
1324							 } else {
1325								 options.ajaxValidCache[errorFieldId] = true;
1326								 // resolves the msg prompt
1327								 if(msg) {
1328									 if (options.allrules[msg]) {
1329										 var txt = options.allrules[msg].alertTextOk;
1330										 if (txt) {
1331											msg = txt;
1332							}
1333									 }
1334								 }
1335								 else
1336								 msg = rule.alertTextOk;
1337								 if (options.showPrompts) {
1338									 // see if we should display a green prompt
1339									 if (msg)
1340										methods._showPrompt(errorField, msg, "pass", true, options);
1341									 else
1342										methods._closePrompt(errorField);
1343								}
1344								 // If a submit form triggered this, we want to re-submit the form
1345								 if (options.eventTrigger == "submit")
1346									field.closest("form").submit();
1347							 }
1348						 }
1349						 errorField.trigger("jqv.field.result", [errorField, options.isError, msg]);
1350					 }
1351				 });
1352				 return rule.alertTextLoad;
1353			 }
1354		 },
1355		/**
1356		* Common method to handle ajax errors
1357		*
1358		* @param {Object} data
1359		* @param {Object} transport
1360		*/
1361		_ajaxError: function(data, transport) {
1362			if(data.status == 0 && transport == null)
1363				alert("The page is not served from a server! ajax call failed");
1364			else if(typeof console != "undefined")
1365				console.log("Ajax error: " + data.status + " " + transport);
1366		},
1367		/**
1368		* date -> string
1369		*
1370		* @param {Object} date
1371		*/
1372		_dateToString: function(date) {
1373			return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate();
1374		},
1375		/**
1376		* Parses an ISO date
1377		* @param {String} d
1378		*/
1379		_parseDate: function(d) {
1380			var dateParts = d.split("-");
1381			if(dateParts==d)
1382				dateParts = d.split("/");
1383			if(dateParts==d) {
1384				dateParts = d.split(".");
1385				return new Date(dateParts[2], (dateParts[1] - 1), dateParts[0]);
1386			}
1387			return new Date(dateParts[0], (dateParts[1] - 1) ,dateParts[2]);
1388		},
1389		/**
1390		* Builds or updates a prompt with the given information
1391		*
1392		* @param {jqObject} field
1393		* @param {String} promptText html text to display type
1394		* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
1395		* @param {boolean} ajaxed - use to mark fields than being validated with ajax
1396		* @param {Map} options user options
1397		*/
1398		 _showPrompt: function(field, promptText, type, ajaxed, options, ajaxform) {
1399		 	//Check if we need to adjust what element to show the prompt on
1400			if(field.data('jqv-prompt-at') instanceof jQuery ){
1401				field = field.data('jqv-prompt-at');
1402			} else if(field.data('jqv-prompt-at')) {
1403				field = $(field.data('jqv-prompt-at'));
1404			}
1405			 var prompt = methods._getPrompt(field);
1406			 // The ajax submit errors are not see has an error in the form,
1407			 // When the form errors are returned, the engine see 2 bubbles, but those are ebing closed by the engine at the same time
1408			 // Because no error was found befor submitting
1409			 if(ajaxform) prompt = false;
1410			 // Check that there is indded text
1411			 if($.trim(promptText)){
1412				 if (prompt)
1413					methods._updatePrompt(field, prompt, promptText, type, ajaxed, options);
1414				 else
1415					methods._buildPrompt(field, promptText, type, ajaxed, options);
1416			}
1417		 },
1418		/**
1419		* Builds and shades a prompt for the given field.
1420		*
1421		* @param {jqObject} field
1422		* @param {String} promptText html text to display type
1423		* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
1424		* @param {boolean} ajaxed - use to mark fields than being validated with ajax
1425		* @param {Map} options user options
1426		*/
1427		_buildPrompt: function(field, promptText, type, ajaxed, options) {
1428			// create the prompt
1429			var prompt = $('<div>');
1430			prompt.addClass(methods._getClassName(field.attr("id")) + "formError");
1431			// add a class name to identify the parent form of the prompt
1432			prompt.addClass("parentForm"+methods._getClassName(field.closest('form, .validationEngineContainer').attr("id")));
1433			prompt.addClass("formError");
1434			switch (type) {
1435				case "pass":
1436					prompt.addClass("greenPopup");
1437					break;
1438				case "load":
1439					prompt.addClass("blackPopup");
1440					break;
1441				default:
1442					/* it has error  */
1443					//alert("unknown popup type:"+type);
1444			}
1445			if (ajaxed)
1446				prompt.addClass("ajaxed");
1447			// create the prompt content
1448			var promptContent = $('<div>').addClass("formErrorContent").html(promptText).appendTo(prompt);
1449			// determine position type
1450			var positionType=field.data("promptPosition") || options.promptPosition;
1451			// create the css arrow pointing at the field
1452			// note that there is no triangle on max-checkbox and radio
1453			if (options.showArrow) {
1454				var arrow = $('<div>').addClass("formErrorArrow");
1455				//prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)
1456				if (typeof(positionType)=='string')
1457				{
1458					var pos=positionType.indexOf(":");
1459					if(pos!=-1)
1460						positionType=positionType.substring(0,pos);
1461				}
1462				switch (positionType) {
1463					case "bottomLeft":
1464					case "bottomRight":
1465						prompt.find(".formErrorContent").before(arrow);
1466						arrow.addClass("formErrorArrowBottom").html('<div class="line1"><!-- --></div><div class="line2"><!-- --></div><div class="line3"><!-- --></div><div class="line4"><!-- --></div><div class="line5"><!-- --></div><div class="line6"><!-- --></div><div class="line7"><!-- --></div><div class="line8"><!-- --></div><div class="line9"><!-- --></div><div class="line10"><!-- --></div>');
1467						break;
1468					case "topLeft":
1469					case "topRight":
1470						arrow.html('<div class="line10"><!-- --></div><div class="line9"><!-- --></div><div class="line8"><!-- --></div><div class="line7"><!-- --></div><div class="line6"><!-- --></div><div class="line5"><!-- --></div><div class="line4"><!-- --></div><div class="line3"><!-- --></div><div class="line2"><!-- --></div><div class="line1"><!-- --></div>');
1471						prompt.append(arrow);
1472						break;
1473				}
1474			}
1475			// Add custom prompt class
1476			if (options.addPromptClass)
1477				prompt.addClass(options.addPromptClass);
1478            // Add custom prompt class defined in element
1479            var requiredOverride = field.attr('data-required-class');
1480            if(requiredOverride !== undefined) {
1481                prompt.addClass(requiredOverride);
1482            } else {
1483                if(options.prettySelect) {
1484                    if($('#' + field.attr('id')).next().is('select')) {
1485                        var prettyOverrideClass = $('#' + field.attr('id').substr(options.usePrefix.length).substring(options.useSuffix.length)).attr('data-required-class');
1486                        if(prettyOverrideClass !== undefined) {
1487                            prompt.addClass(prettyOverrideClass);
1488                        }
1489                    }
1490                }
1491            }
1492			prompt.css({
1493				"opacity": 0
1494			});
1495			if(positionType === 'inline') {
1496				prompt.addClass("inline");
1497				if(typeof field.attr('data-prompt-target') !== 'undefined' && $('#'+field.attr('data-prompt-target')).length > 0) {
1498					prompt.appendTo($('#'+field.attr('data-prompt-target')));
1499				} else {
1500					field.after(prompt);
1501				}
1502			} else {
1503				field.before(prompt);
1504			}
1505			var pos = methods._calculatePosition(field, prompt, options);
1506			prompt.css({
1507				'position': positionType === 'inline' ? 'relative' : 'absolute',
1508				"top": pos.callerTopPosition,
1509				"left": pos.callerleftPosition,
1510				"marginTop": pos.marginTopSize,
1511				"opacity": 0
1512			}).data("callerField", field);
1513			if (options.autoHidePrompt) {
1514				setTimeout(function(){
1515					prompt.animate({
1516						"opacity": 0
1517					},function(){
1518						prompt.closest('.formErrorOuter').remove();
1519						prompt.remove();
1520					});
1521				}, options.autoHideDelay);
1522			}
1523			return prompt.animate({
1524				"opacity": 0.87
1525			});
1526		},
1527		/**
1528		* Updates the prompt text field - the field for which the prompt
1529		* @param {jqObject} field
1530		* @param {String} promptText html text to display type
1531		* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
1532		* @param {boolean} ajaxed - use to mark fields than being validated with ajax
1533		* @param {Map} options user options
1534		*/
1535		_updatePrompt: function(field, prompt, promptText, type, ajaxed, options, noAnimation) {
1536			if (prompt) {
1537				if (typeof type !== "undefined") {
1538					if (type == "pass")
1539						prompt.addClass("greenPopup");
1540					else
1541						prompt.removeClass("greenPopup");
1542					if (type == "load")
1543						prompt.addClass("blackPopup");
1544					else
1545						prompt.removeClass("blackPopup");
1546				}
1547				if (ajaxed)
1548					prompt.addClass("ajaxed");
1549				else
1550					prompt.removeClass("ajaxed");
1551				prompt.find(".formErrorContent").html(promptText);
1552				var pos = methods._calculatePosition(field, prompt, options);
1553				var css = {"top": pos.callerTopPosition,
1554				"left": pos.callerleftPosition,
1555				"marginTop": pos.marginTopSize};
1556				if (noAnimation)
1557					prompt.css(css);
1558				else
1559					prompt.animate(css);
1560			}
1561		},
1562		/**
1563		* Closes the prompt associated with the given field
1564		*
1565		* @param {jqObject}
1566		*            field
1567		*/
1568		 _closePrompt: function(field) {
1569			 var prompt = methods._getPrompt(field);
1570			 if (prompt)
1571				 prompt.fadeTo("fast", 0, function() {
1572					 prompt.parent('.formErrorOuter').remove();
1573					 prompt.remove();
1574				 });
1575		 },
1576		 closePrompt: function(field) {
1577			 return methods._closePrompt(field);
1578		 },
1579		/**
1580		* Returns the error prompt matching the field if any
1581		*
1582		* @param {jqObject}
1583		*            field
1584		* @return undefined or the error prompt (jqObject)
1585		*/
1586		_getPrompt: function(field) {
1587				var formId = $(field).closest('form, .validationEngineContainer').attr('id');
1588			var className = methods._getClassName(field.attr("id")) + "formError";
1589				var match = $("." + methods._escapeExpression(className) + '.parentForm' + methods._getClassName(formId))[0];
1590			if (match)
1591			return $(match);
1592		},
1593		/**
1594		  * Returns the escapade classname
1595		  *
1596		  * @param {selector}
1597		  *            className
1598		  */
1599		  _escapeExpression: function (selector) {
1600			  return selector.replace(/([#;&,\.\+\*\~':"\!\^$\[\]\(\)=>\|])/g, "\\$1");
1601		  },
1602		/**
1603		 * returns true if we are in a RTLed document
1604		 *
1605		 * @param {jqObject} field
1606		 */
1607		isRTL: function(field)
1608		{
1609			var $document = $(document);
1610			var $body = $('body');
1611			var rtl =
1612				(field && field.hasClass('rtl')) ||
1613				(field && (field.attr('dir') || '').toLowerCase()==='rtl') ||
1614				$document.hasClass('rtl') ||
1615				($document.attr('dir') || '').toLowerCase()==='rtl' ||
1616				$body.hasClass('rtl') ||
1617				($body.attr('dir') || '').toLowerCase()==='rtl';
1618			return Boolean(rtl);
1619		},
1620		/**
1621		* Calculates prompt position
1622		*
1623		* @param {jqObject}
1624		*            field
1625		* @param {jqObject}
1626		*            the prompt
1627		* @param {Map}
1628		*            options
1629		* @return positions
1630		*/
1631		_calculatePosition: function (field, promptElmt, options) {
1632			var promptTopPosition, promptleftPosition, marginTopSize;
1633			var fieldWidth 	= field.width();
1634			var fieldLeft 	= field.position().left;
1635			var fieldTop 	=  field.position().top;
1636			var fieldHeight 	=  field.height();
1637			var promptHeight = promptElmt.height();
1638			// is the form contained in an overflown container?
1639			promptTopPosition = promptleftPosition = 0;
1640			// compensation for the arrow
1641			marginTopSize = -promptHeight;
1642			//prompt positioning adjustment support
1643			//now you can adjust prompt position
1644			//usage: positionType:Xshift,Yshift
1645			//for example:
1646			//   bottomLeft:+20 means bottomLeft position shifted by 20 pixels right horizontally
1647			//   topRight:20, -15 means topRight position shifted by 20 pixels to right and 15 pixels to top
1648			//You can use +pixels, - pixels. If no sign is provided than + is default.
1649			var positionType=field.data("promptPosition") || options.promptPosition;
1650			var shift1="";
1651			var shift2="";
1652			var shiftX=0;
1653			var shiftY=0;
1654			if (typeof(positionType)=='string') {
1655				//do we have any position adjustments ?
1656				if (positionType.indexOf(":")!=-1) {
1657					shift1=positionType.substring(positionType.indexOf(":")+1);
1658					positionType=positionType.substring(0,positionType.indexOf(":"));
1659					//if any advanced positioning will be needed (percents or something else) - parser should be added here
1660					//for now we use simple parseInt()
1661					//do we have second parameter?
1662					if (shift1.indexOf(",") !=-1) {
1663						shift2=shift1.substring(shift1.indexOf(",") +1);
1664						shift1=shift1.substring(0,shift1.indexOf(","));
1665						shiftY=parseInt(shift2);
1666						if (isNaN(shiftY)) shiftY=0;
1667					};
1668					shiftX=parseInt(shift1);
1669					if (isNaN(shift1)) shift1=0;
1670				};
1671			};
1672			switch (positionType) {
1673				default:
1674				case "topRight":
1675					promptleftPosition +=  fieldLeft + fieldWidth - 30;
1676					promptTopPosition +=  fieldTop;
1677					break;
1678				case "topLeft":
1679					promptTopPosition +=  fieldTop;
1680					promptleftPosition += fieldLeft;
1681					break;
1682				case "centerRight":
1683					promptTopPosition = fieldTop+4;
1684					marginTopSize = 0;
1685					promptleftPosition= fieldLeft + field.outerWidth(true)+5;
1686					break;
1687				case "centerLeft":
1688					promptleftPosition = fieldLeft - (promptElmt.width() + 2);
1689					promptTopPosition = fieldTop+4;
1690					marginTopSize = 0;
1691					break;
1692				case "bottomLeft":
1693					promptTopPosition = fieldTop + field.height() + 5;
1694					marginTopSize = 0;
1695					promptleftPosition = fieldLeft;
1696					break;
1697				case "bottomRight":
1698					promptleftPosition = fieldLeft + fieldWidth - 30;
1699					promptTopPosition =  fieldTop +  field.height() + 5;
1700					marginTopSize = 0;
1701					break;
1702				case "inline":
1703					promptleftPosition = 0;
1704					promptTopPosition = 0;
1705					marginTopSize = 0;
1706			};
1707			//apply adjusments if any
1708			promptleftPosition += shiftX;
1709			promptTopPosition  += shiftY;
1710			return {
1711				"callerTopPosition": promptTopPosition + "px",
1712				"callerleftPosition": promptleftPosition + "px",
1713				"marginTopSize": marginTopSize + "px"
1714			};
1715		},
1716		/**
1717		* Saves the user options and variables in the form.data
1718		*
1719		* @param {jqObject}
1720		*            form - the form where the user option should be saved
1721		* @param {Map}
1722		*            options - the user options
1723		* @return the user options (extended from the defaults)
1724		*/
1725		 _saveOptions: function(form, options) {
1726			 // is there a language localisation ?
1727			 if ($.validationEngineLanguage)
1728			 var allRules = $.validationEngineLanguage.allRules;
1729			 else
1730			 $.error("jQuery.validationEngine rules are not loaded, plz add localization files to the page");
1731			 // --- Internals DO NOT TOUCH or OVERLOAD ---
1732			 // validation rules and i18
1733			 $.validationEngine.defaults.allrules = allRules;
1734			 var userOptions = $.extend(true,{},$.validationEngine.defaults,options);
1735			 form.data('jqv', userOptions);
1736			 return userOptions;
1737		 },
1738		 /**
1739		 * Removes forbidden characters from class name
1740		 * @param {String} className
1741		 */
1742		 _getClassName: function(className) {
1743			 if(className)
1744				 return className.replace(/:/g, "_").replace(/\./g, "_");
1745					  },
1746		/**
1747		 * Escape special character for jQuery selector
1748		 * http://totaldev.com/content/escaping-characters-get-valid-jquery-id
1749		 * @param {String} selector
1750		 */
1751		 _jqSelector: function(str){
1752			return str.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
1753		},
1754		/**
1755		* Conditionally required field
1756		*
1757		* @param {jqObject} field
1758		* @param {Array[String]} rules
1759		* @param {int} i rules index
1760		* @param {Map}
1761		* user options
1762		* @return an error string if validation failed
1763		*/
1764		_condRequired: function(field, rules, i, options) {
1765			var idx, dependingField;
1766			for(idx = (i + 1); idx < rules.length; idx++) {
1767				dependingField = jQuery("#" + rules[idx]).first();
1768				/* Use _required for determining wether dependingField has a value.
1769				 * There is logic there for handling all field types, and default value; so we won't replicate that here
1770				 * Indicate this special use by setting the last parameter to true so we only validate the dependingField on chackboxes and radio buttons (#462)
1771				 */
1772				if (dependingField.length && methods._required(dependingField, ["required"], 0, options, true) == undefined) {
1773					/* We now know any of the depending fields has a value,
1774					 * so we can validate this field as per normal required code
1775					 */
1776					return methods._required(field, ["required"], 0, options);
1777				}
1778			}
1779		},
1780	    _submitButtonClick: function(event) {
1781	        var button = $(this);
1782	        var form = button.closest('form, .validationEngineContainer');
1783	        form.data("jqv_submitButton", button.attr("id"));
1784	    }
1785		  };
1786	 /**
1787	 * Plugin entry point.
1788	 * You may pass an action as a parameter or a list of options.
1789	 * if none, the init and attach methods are being called.
1790	 * Remember: if you pass options, the attached method is NOT called automatically
1791	 *
1792	 * @param {String}
1793	 *            method (optional) action
1794	 */
1795	 $.fn.validationEngine = function(method) {
1796		 var form = $(this);
1797		 if(!form[0]) return form;  // stop here if the form does not exist
1798		 if (typeof(method) == 'string' && method.charAt(0) != '_' && methods[method]) {
1799			 // make sure init is called once
1800			 if(method != "showPrompt" && method != "hide" && method != "hideAll")
1801			 methods.init.apply(form);
1802			 return methods[method].apply(form, Array.prototype.slice.call(arguments, 1));
1803		 } else if (typeof method == 'object' || !method) {
1804			 // default constructor with or without arguments
1805			 methods.init.apply(form, arguments);
1806			 return methods.attach.apply(form);
1807		 } else {
1808			 $.error('Method ' + method + ' does not exist in jQuery.validationEngine');
1809		 }
1810	};
1811	// LEAK GLOBAL OPTIONS
1812	$.validationEngine= {fieldIdCounter: 0,defaults:{
1813		// Name of the event triggering field validation
1814		validationEventTrigger: "blur",
1815		// Automatically scroll viewport to the first error
1816		scroll: true,
1817		// Focus on the first input
1818		focusFirstField:true,
1819		// Show prompts, set to false to disable prompts
1820		showPrompts: true,
1821       // Should we attempt to validate non-visible input fields contained in the form? (Useful in cases of tabbed containers, e.g. jQuery-UI tabs)
1822       validateNonVisibleFields: false,
1823		// Opening box position, possible locations are: topLeft,
1824		// topRight, bottomLeft, centerRight, bottomRight, inline
1825		// inline gets inserted after the validated field or into an element specified in data-prompt-target
1826		promptPosition: "topLeft",
1827		bindMethod:"internal",
1828		// internal, automatically set to true when it parse a _ajax rule
1829		inlineAjax: false,
1830		// if set to true, the form data is sent asynchronously via ajax to the form.action url (get)
1831		ajaxFormValidation: false,
1832		// The url to send the submit ajax validation (default to action)
1833		ajaxFormValidationURL: false,
1834		// HTTP method used for ajax validation
1835		ajaxFormValidationMethod: 'get',
1836		// Ajax form validation callback method: boolean onComplete(form, status, errors, options)
1837		// retuns false if the form.submit event needs to be canceled.
1838		onAjaxFormComplete: $.noop,
1839		// called right before the ajax call, may return false to cancel
1840		onBeforeAjaxFormValidation: $.noop,
1841		// Stops form from submitting and execute function assiciated with it
1842		onValidationComplete: false,
1843		// Used when you have a form fields too close and the errors messages are on top of other disturbing viewing messages
1844		doNotShowAllErrosOnSubmit: false,
1845		// Object where you store custom messages to override the default error messages
1846		custom_error_messages:{},
1847		// true if you want to vind the input fields
1848		binded: true,
1849		// set to true, when the prompt arrow needs to be displayed
1850		showArrow: true,
1851		// did one of the validation fail ? kept global to stop further ajax validations
1852		isError: false,
1853		// Limit how many displayed errors a field can have
1854		maxErrorsPerField: false,
1855		// Caches field validation status, typically only bad status are created.
1856		// the array is used during ajax form validation to detect issues early and prevent an expensive submit
1857		ajaxValidCache: {},
1858		// Auto update prompt position after window resize
1859		autoPositionUpdate: false,
1860		InvalidFields: [],
1861		onFieldSuccess: false,
1862		onFieldFailure: false,
1863		onSuccess: false,
1864		onFailure: false,
1865		validateAttribute: "class",
1866		addSuccessCssClassToField: "",
1867		addFailureCssClassToField: "",
1868		// Auto-hide prompt
1869		autoHidePrompt: true,
1870		// Delay before auto-hide
1871		autoHideDelay: 7000,
1872		// Fade out duration while hiding the validations
1873		fadeDuration: 0.3,
1874		// Use Prettify select library
1875		prettySelect: false,
1876		// Add css class on prompt
1877		addPromptClass : "",
1878		// Custom ID uses prefix
1879		usePrefix: "",
1880		// Custom ID uses suffix
1881		useSuffix: "",
1882		// Only show one message per error prompt
1883		showOneMessage: false
1884	}};
1885	//$(function(){$.validationEngine.defaults.promptPosition = methods.isRTL()?'topLeft':"topRight"});
1886})(jQuery);

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.