PageSourceSearch

https://3ds.co.jp/assets/js/form/jquery.validationEngine.js

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