PageSourceSearch

https://www.frees-life.com/wp-content/themes/freeslife/js/jquery.validationEngine.js

js frees-life.com collected 2026-10-08 04:30:38 UTC 73,899 bytes, 2,163 lines download raw bytes

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

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