PageSourceSearch

https://www.carolynmenke.com/wp-content/plugins/wysija-newsletters…/jquery.validationEngine.js?ver=2.21

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

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.