PageSourceSearch

https://www.claudiana.it/js/validationengine2/js/jquery.validationEngine.js

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

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.