PageSourceSearch

https://aude.ac.uk/scripts/Umbraco/Validator/jquery.validationEngine.js?v=12.24.00.00

js aude.ac.uk collected 2026-10-02 15:27:48 UTC 67,026 bytes, 1,952 lines download raw bytes

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

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.