| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881 | /* * Inline Form Validation Engine 2.5.5.1, jQuery plugin * * Copyright(c) 2010, Cedric Dugas * http://www.position-absolute.com * * 2.0 Rewrite by Olivier Refalo * http://www.crionics.com * * Form validation engine allowing custom regex rules to be added. * Licensed under the MIT License */ (function($) {	 "use strict";	 var methods = {		 /**		 * Kind of the constructor, called before any action		 * @param {Map} user options		 */		 init: function(options) {			 var form = this;			 if (!form.data('jqv') || form.data('jqv') == null ) {				 options = methods._saveOptions(form, options);				 // bind all formError elements to close on click				 $(".formError").live("click", function() {					 $(this).fadeOut(150, function() {						 // remove prompt once invisible						 $(this).parent('.formErrorOuter').remove();						 $(this).remove();					 });				 });			 }			 return this;		 },		/**		* Attachs jQuery.validationEngine to form.submit and field.blur events		* Takes an optional params: a list of options		* ie. jQuery("#formID1").validationEngine('attach', {promptPosition : "centerRight"});		*/		attach: function(userOptions) {			if(!$(this).is("form")) {				alert("Sorry, jqv.attach() only applies to a form");				return this;			}						var form = this;			var options;			if(userOptions)				options = methods._saveOptions(form, userOptions);			else				options = form.data('jqv');			options.validateAttribute = (form.find("[data-validation-engine*=validate]").length) ? "data-validation-engine" : "class";			if (options.binded) {				// bind fields				form.find("["+options.validateAttribute+"*=validate]").not("[type=checkbox]").not("[type=radio]").not(".datepicker").bind(options.validationEventTrigger, methods._onFieldEvent);				form.find("["+options.validateAttribute+"*=validate][type=checkbox],["+options.validateAttribute+"*=validate][type=radio]").bind("click", methods._onFieldEvent);				form.find("["+options.validateAttribute+"*=validate][class*=datepicker]").bind(options.validationEventTrigger,{"delay": 300}, methods._onFieldEvent);			}			if (options.autoPositionUpdate) {				$(window).bind("resize", {					"noAnimation": true,					"formElem": form				}, methods.updatePromptsPosition);			}			// bind form.submit			form.bind("submit", methods._onSubmitEvent);			return this;		},		/**		* Unregisters any bindings that may point to jQuery.validaitonEngine		*/		detach: function() {						if(!$(this).is("form")) {				alert("Sorry, jqv.detach() only applies to a form");				return this;			}			var form = this;			var options = form.data('jqv');			// unbind fields			form.find("["+options.validateAttribute+"*=validate]").not("[type=checkbox]").unbind(options.validationEventTrigger, methods._onFieldEvent);			form.find("["+options.validateAttribute+"*=validate][type=checkbox],[class*=validate][type=radio]").unbind("click", methods._onFieldEvent);			// unbind form.submit			form.unbind("submit", methods.onAjaxFormComplete);			// unbind live fields (kill)			form.find("["+options.validateAttribute+"*=validate]").not("[type=checkbox]").die(options.validationEventTrigger, methods._onFieldEvent);			form.find("["+options.validateAttribute+"*=validate][type=checkbox]").die("click", methods._onFieldEvent);			// unbind form.submit			form.die("submit", methods.onAjaxFormComplete);			form.removeData('jqv');			if (options.autoPositionUpdate)				$(window).unbind("resize", methods.updatePromptsPosition);			return this;		},		/**		* Validates either a form or a list of fields, shows prompts accordingly.		* Note: There is no ajax form validation with this method, only field ajax validation are evaluated		*		* @return true if the form validates, false if it fails		*/		validate: function() {			if($(this).is("form"))				return methods._validateFields(this);			else {				// field validation				var form = $(this).closest('form');				var options = form.data('jqv');  				var r = methods._validateField($(this), options);				if (options.onSuccess && options.InvalidFields.length == 0)					options.onSuccess();				else if (options.onFailure && options.InvalidFields.length > 0)					options.onFailure();				return r;			}		},		/**		*  Redraw prompts position, useful when you change the DOM state when validating		*/		updatePromptsPosition: function(event) {			if (event && this == window) {				var form = event.data.formElem;				var noAnimation = event.data.noAnimation;			}			else				var form = $(this.closest('form'));			var options = form.data('jqv');			// No option, take default one			form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each(function(){				var field = $(this);				var prompt = methods._getPrompt(field);				var promptText = $(prompt).find(".formErrorContent").html();				if(prompt)					methods._updatePrompt(field, $(prompt), promptText, undefined, false, options, noAnimation);			});			return this;		},		/**		* Displays a prompt on a element.		* Note that the element needs an id!		*		* @param {String} promptText html text to display type		* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)		* @param {String} possible values topLeft, topRight, bottomLeft, centerRight, bottomRight		*/		showPrompt: function(promptText, type, promptPosition, showArrow) {			var form = this.closest('form');			var options = form.data('jqv');			// No option, take default one			if(!options)				options = methods._saveOptions(this, options);			if(promptPosition)				options.promptPosition=promptPosition;			options.showArrow = showArrow==true;			methods._showPrompt(this, promptText, type, false, options);			return this;		},		/**		* Closes form error prompts, CAN be invidual		*/		hide: function() {			 var form = $(this).closest('form');			 if(form.length == 0)				return this;			 var options = form.data('jqv');			 var closingtag;			 if($(this).is("form")) {				 closingtag = "parentForm"+methods._getClassName($(this).attr("id"));			 } else {				 closingtag = methods._getClassName($(this).attr("id")) +"formError";			 }			 $('.'+closingtag).fadeTo(options.fadeDuration, 0.3, function() {				 $(this).parent('.formErrorOuter').remove();				 $(this).remove();			 });			 return this;		 },		 /**		 * Closes all error prompts on the page		 */		 hideAll: function() {			 var form = this;			 var options = form.data('jqv');			 var duration = options ? options.fadeDuration:0.3;			 $('.formError').fadeTo(duration, 0.3, function() {				 $(this).parent('.formErrorOuter').remove();				 $(this).remove();			 });			 return this;		 },		/**		* Typically called when user exists a field using tab or a mouse click, triggers a field		* validation		*/		_onFieldEvent: function(event) {			var field = $(this);			var form = field.closest('form');			var options = form.data('jqv');			options.eventTrigger = "field";			// validate the current field			window.setTimeout(function() {				methods._validateField(field, options);				if (options.InvalidFields.length == 0 && options.onSuccess) {					options.onSuccess();				} else if (options.InvalidFields.length > 0 && options.onFailure) {					options.onFailure();				}			}, (event.data) ? event.data.delay : 0);		},		/**		* Called when the form is submited, shows prompts accordingly		*		* @param {jqObject}		*            form		* @return false if form submission needs to be cancelled		*/		_onSubmitEvent: function() {			var form = $(this);			var options = form.data('jqv');			options.eventTrigger = "submit";			// validate each field 			// (- skip field ajax validation, not necessary IF we will perform an ajax form validation)			var r=methods._validateFields(form);			if (r && options.ajaxFormValidation) {				methods._validateFormWithAjax(form, options);				// cancel form auto-submission - process with async call onAjaxFormComplete				return false;			}			if(options.onValidationComplete) {				// !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing				return !!options.onValidationComplete(form, r);			}			return r;		},		/**		* Return true if the ajax field validations passed so far		* @param {Object} options		* @return true, is all ajax validation passed so far (remember ajax is async)		*/		_checkAjaxStatus: function(options) {			var status = true;			$.each(options.ajaxValidCache, function(key, value) {				if (!value) {					status = false;					// break the each					return false;				}			});			return status;		},				/**		* Return true if the ajax field is validated		* @param {String} fieldid		* @param {Object} options		* @return true, if validation passed, false if false or doesn't exist		*/		_checkAjaxFieldStatus: function(fieldid, options) {			return options.ajaxValidCache[fieldid] == true;		},		/**		* Validates form fields, shows prompts accordingly		*		* @param {jqObject}		*            form		* @param {skipAjaxFieldValidation}		*            boolean - when set to true, ajax field validation is skipped, typically used when the submit button is clicked		*		* @return true if form is valid, false if not, undefined if ajax form validation is done		*/		_validateFields: function(form) {			var options = form.data('jqv');			// this variable is set to true if an error is found			var errorFound = false;			// Trigger hook, start validation			form.trigger("jqv.form.validating");			// first, evaluate status of non ajax fields			var first_err=null;			form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each( function() {				var field = $(this);				var names = [];				if ($.inArray(field.attr('name'), names) < 0) {					errorFound |= methods._validateField(field, options);					if (errorFound && first_err==null)						if (field.is(":hidden") && options.prettySelect)                first_err = field = form.find("#" + options.usePrefix + field.attr('id') + options.useSuffix);            else                first_err=field;					if (options.doNotShowAllErrosOnSubmit)						return false;					names.push(field.attr('name'));				}			});			// second, check to see if all ajax calls completed ok			// errorFound |= !methods._checkAjaxStatus(options);			// third, check status and scroll the container accordingly			form.trigger("jqv.form.result", [errorFound]);			if (errorFound) {				if (options.scroll) {					var destination=first_err.offset().top;					var fixleft = first_err.offset().left;					//prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)					var positionType=options.promptPosition;					if (typeof(positionType)=='string' && positionType.indexOf(":")!=-1)						positionType=positionType.substring(0,positionType.indexOf(":"));					if (positionType!="bottomRight" && positionType!="bottomLeft") {						var prompt_err= methods._getPrompt(first_err);						//destination=prompt_err.offset().top;					}					// get the position of the first error, there should be at least one, no need to check this					//var destination = form.find(".formError:not('.greenPopup'):first").offset().top;					if (options.isOverflown) {						var overflowDIV = $(options.overflownDIV);						if(!overflowDIV.length) return false;						var scrollContainerScroll = overflowDIV.scrollTop();						var scrollContainerPos = -parseInt(overflowDIV.offset().top);						destination += scrollContainerScroll + scrollContainerPos - 5;						var scrollContainer = $(options.overflownDIV + ":not(:animated)");						scrollContainer.animate({ scrollTop: destination }, 1100, function(){							if(options.focusFirstField) first_err.focus();						});					} else {						$("html:not(:animated),body:not(:animated)").animate({							scrollTop: destination,							scrollLeft: fixleft						}, 1100, function(){							if(options.focusFirstField) first_err.focus();						});					}				} else if(options.focusFirstField)					first_err.focus();				return false;			}			return true;		},		/**		* This method is called to perform an ajax form validation.		* During this process all the (field, value) pairs are sent to the server which returns a list of invalid fields or true		*		* @param {jqObject} form		* @param {Map} options		*/		_validateFormWithAjax: function(form, options) {			var data = form.serialize();                        	var type = (options.ajaxmethod) ? options.ajaxmethod : "GET";			var url = (options.ajaxFormValidationURL) ? options.ajaxFormValidationURL : form.attr("action");                        	var dataType = (options.dataType) ? options.dataType : "json";			$.ajax({				type: type,				url: url,				cache: false,				dataType: dataType,				data: data,				form: form,				methods: methods,				options: options,				beforeSend: function() {					return options.onBeforeAjaxFormValidation(form, options);				},				error: function(data, transport) {					methods._ajaxError(data, transport);				},				success: function(json) {					if (json !== true) {						// getting to this case doesn't necessary means that the form is invalid						// the server may return green or closing prompt actions						// this flag helps figuring it out						var errorInForm=false;						for (var i = 0; i < json.length; i++) {							var value = json[i];							var errorFieldId = value[0];							var errorField = $($("#" + errorFieldId)[0]);							// make sure we found the element							if (errorField.length == 1) {								// promptText or selector								var msg = value[2];								// if the field is valid								if (value[1] == true) {									if (msg == ""  || !msg){										// if for some reason, status==true and error="", just close the prompt										methods._closePrompt(errorField);									} else {										// the field is valid, but we are displaying a green prompt										if (options.allrules[msg]) {											var txt = options.allrules[msg].alertTextOk;											if (txt)												msg = txt;										}										methods._showPrompt(errorField, msg, "pass", false, options, true);									}								} else {									// the field is invalid, show the red error prompt									errorInForm|=true;									if (options.allrules[msg]) {										var txt = options.allrules[msg].alertText;										if (txt)											msg = txt;									}									methods._showPrompt(errorField, msg, "", false, options, true);								}							}						}						options.onAjaxFormComplete(!errorInForm, form, json, options);					} else						options.onAjaxFormComplete(true, form, "", options);				}			});		},		/**		* Validates field, shows prompts accordingly		*		* @param {jqObject}		*            field		* @param {Array[String]}		*            field's validation rules		* @param {Map}		*            user options		* @return false if field is valid (It is inversed for *fields*, it return false on validate and true on errors.)		*/		_validateField: function(field, options, skipAjaxValidation) {			if (!field.attr("id")) {				field.attr("id", "form-validation-field-" + $.validationEngine.fieldIdCounter);				++$.validationEngine.fieldIdCounter;			}			if (field.is(":hidden") && !options.prettySelect || field.parent().is(":hidden"))				return false;			var rulesParsing = field.attr(options.validateAttribute);			var getRules = /validate\[(.*)\]/.exec(rulesParsing);			if (!getRules)				return false;			var str = getRules[1];			var rules = str.split(/\[|,|\]/);			// true if we ran the ajax validation, tells the logic to stop messing with prompts			var isAjaxValidator = false;			var fieldName = field.attr("name");			var promptText = "";			var promptType = "";			var required = false;			options.isError = false;			options.showArrow = true;			var form = $(field.closest("form"));			for (var i = 0; i < rules.length; i++) {				// Fix for adding spaces in the rules				rules[i] = rules[i].replace(" ", ""); 				var errorMsg = undefined;				switch (rules[i]) {					case "required":						required = true;						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._required);						break;					case "custom":						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._custom);						break;					case "groupRequired":						// Check is its the first of group, if not, reload validation with first field						// AND continue normal validation on present field						var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]";						var firstOfGroup = form.find(classGroup).eq(0);						if(firstOfGroup[0] != field[0]){							methods._validateField(firstOfGroup, options, skipAjaxValidation); 							options.showArrow = true;							continue;						}						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._groupRequired);						if(errorMsg)  required = true;						options.showArrow = false;						break;					case "ajax":						// AJAX defaults to returning it's loading message						errorMsg = methods._ajax(field, rules, i, options);						if (errorMsg) {							promptType = "load";						}						break;					case "minSize":						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minSize);						break;					case "maxSize":						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxSize);						break;					case "min":						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._min);						break;					case "max":						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._max);						break;					case "past":						errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._past);						break;					case "future":						errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._future);						break;					case "dateRange":						var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]";						options.firstOfGroup = form.find(classGroup).eq(0);						options.secondOfGroup = form.find(classGroup).eq(1);						//if one entry out of the pair has value then proceed to run through validation						if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {							errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateRange);						}						if (errorMsg) required = true;						options.showArrow = false;						break;					case "dateTimeRange":						var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]";						options.firstOfGroup = form.find(classGroup).eq(0);						options.secondOfGroup = form.find(classGroup).eq(1);						//if one entry out of the pair has value then proceed to run through validation						if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {							errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateTimeRange);						}						if (errorMsg) required = true;						options.showArrow = false;						break;					case "maxCheckbox":						field = $(form.find("input[name='" + fieldName + "']"));						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxCheckbox);						break;					case "minCheckbox":						field = $(form.find("input[name='" + fieldName + "']"));						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minCheckbox);						break;					case "equals":						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._equals);						break;					case "funcCall":						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._funcCall);						break;					case "creditCard":						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._creditCard);						break;					case "condRequired":						errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._condRequired);						if (errorMsg !== undefined) {							required = true;						}						break;					default:				}				if (errorMsg !== undefined) {					promptText += errorMsg.replace('* ', '') + " ";					options.isError = true;				}				//if option set, stop checking validation rules after one error is found				if(options.showOneMessage === true && options.isError === true)					break;			}			// If the rules required is not added, an empty field is not validated			if(!required && field.val().length < 1) options.isError = false;			// Hack for radio/checkbox group button, the validation go into the			// first radio/checkbox of the group			var fieldType = field.prop("type");			if ((fieldType == "radio" || fieldType == "checkbox") && form.find("input[name='" + fieldName + "']").size() > 1) {				field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:first"));				options.showArrow = false;			}			if(field.is(":hidden") && options.prettySelect) {				field = form.find("#" + options.usePrefix + field.attr('id') + options.useSuffix);			}			if (options.isError){				methods._showPrompt(field, promptText, promptType, false, options);			}else{				if (!isAjaxValidator) methods._closePrompt(field);			}			if (!isAjaxValidator) {				field.trigger("jqv.field.result", [field, options.isError, promptText]);			}			/* Record error */			var errindex = $.inArray(field[0], options.InvalidFields);			if (errindex == -1) {				if (options.isError)				options.InvalidFields.push(field[0]);			} else if (!options.isError) {				options.InvalidFields.splice(errindex, 1);			}			return options.isError;		},		 /********************		  * _getErrorMessage		  *		  * @param form		  * @param field		  * @param rule		  * @param rules		  * @param i		  * @param options		  * @param originalValidationMethod		  * @return {*}		  * @private		  */		 _getErrorMessage:function (form, field, rule, rules, i, options, originalValidationMethod) {			 // If we are using the custon validation type, build the index for the rule.			 // Otherwise if we are doing a function call, make the call and return the object			 // that is passed back.			 var beforeChangeRule = rule;			 if (rule == "custom") {				 var custom_validation_type_index = jQuery.inArray(rule, rules)+ 1;				 var custom_validation_type = rules[custom_validation_type_index];				 rule = "custom[" + custom_validation_type + "]";			 }			 var element_classes = (field.attr("data-validation-engine")) ? field.attr("data-validation-engine") : field.attr("class");			 var element_classes_array = element_classes.split(" ");			 // Call the original validation method. If we are dealing with dates, also pass the form			 var errorMsg;			 if (rule == "future" || rule == "past"  || rule == "maxCheckbox" || rule == "minCheckbox") {				 errorMsg = originalValidationMethod(form, field, rules, i, options);			 } else {				 errorMsg = originalValidationMethod(field, rules, i, options);			 }			 // If the original validation method returned an error and we have a custom error message,			 // return the custom message instead. Otherwise return the original error message.			 if (errorMsg != undefined) {				 var custom_message = methods._getCustomErrorMessage($(field), element_classes_array, beforeChangeRule, options);				 if (custom_message) return custom_message;			 }			 return errorMsg;		 },		 _getCustomErrorMessage:function (field, classes, rule, options) {			var custom_message = false;			var validityProp = methods._validityProp[rule];			if (validityProp != undefined) {				custom_message = field.attr("data-errormessage-"+validityProp);				if (custom_message != undefined) 					return custom_message;			}			custom_message = field.attr("data-errormessage");			if (custom_message != undefined) 				return custom_message;			var id = '#' + field.attr("id");			// If we have custom messages for the element's id, get the message for the rule from the id.			// Otherwise, if we have custom messages for the element's classes, use the first class message we find instead.			if (typeof options.custom_error_messages[id] != "undefined" &&				typeof options.custom_error_messages[id][rule] != "undefined" ) {				        custom_message = options.custom_error_messages[id][rule]['message'];			} else if (classes.length > 0) {				for (var i = 0; i < classes.length && classes.length > 0; i++) {					 var element_class = "." + classes[i];					if (typeof options.custom_error_messages[element_class] != "undefined" &&						typeof options.custom_error_messages[element_class][rule] != "undefined") {							custom_message = options.custom_error_messages[element_class][rule]['message'];							break;					}				}			}			if (!custom_message &&				typeof options.custom_error_messages[rule] != "undefined" &&				typeof options.custom_error_messages[rule]['message'] != "undefined"){					 custom_message = options.custom_error_messages[rule]['message'];			 }			 return custom_message;		 },		 _validityProp: {			 "required": "value-missing",			 "custom": "custom-error",			 "groupRequired": "value-missing",			 "ajax": "custom-error",			 "minSize": "range-underflow",			 "maxSize": "range-overflow",			 "min": "range-underflow",			 "max": "range-overflow",			 "past": "type-mismatch",			 "future": "type-mismatch",			 "dateRange": "type-mismatch",			 "dateTimeRange": "type-mismatch",			 "maxCheckbox": "range-overflow",			 "minCheckbox": "range-underflow",			 "equals": "pattern-mismatch",			 "funcCall": "custom-error",			 "creditCard": "pattern-mismatch",			 "condRequired": "value-missing"		 },		/**		* Required validation		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_required: function(field, rules, i, options) {			switch (field.prop("type")) {				case "text":				case "password":				case "textarea":				case "file":				case "select-one":				case "select-multiple":				default:					if (! $.trim(field.val()) || field.val() == field.attr("data-validation-placeholder") || field.val() == field.attr("placeholder"))						return options.allrules[rules[i]].alertText;					break;				case "radio":				case "checkbox":									var form = field.closest("form");					var name = field.attr("name");					if (form.find("input[name='" + name + "']:checked").size() == 0) 					{										if (form.find("input[name='" + name + "']").size() == 1)						{							return options.allrules[rules[i]].alertTextCheckboxe;						}						else						{														return options.allrules[rules[i]].alertTextCheckboxMultiple;						}					}					break;			}		},		/**		* Validate that 1 from the group field is required		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_groupRequired: function(field, rules, i, options) {			var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]";			var isValid = false;			// Check all fields from the group			field.closest("form").find(classGroup).each(function(){				if(!methods._required($(this), rules, i, options)){					isValid = true;					return false;				}			}); 			if(!isValid) {        return options.allrules[rules[i]].alertText;      }		},		/**		* Validate rules		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_custom: function(field, rules, i, options) {			var customRule = rules[i + 1];			var rule = options.allrules[customRule];			var fn;			if(!rule) {				alert("jqv:custom rule not found - "+customRule);				return;			}						if(rule["regex"]) {				 var ex=rule.regex;					if(!ex) {						alert("jqv:custom regex not found - "+customRule);						return;					}					var pattern = new RegExp(ex);					if (!pattern.test(field.val())) return options.allrules[customRule].alertText;								} else if(rule["func"]) {				fn = rule["func"]; 				 				if (typeof(fn) !== "function") {					alert("jqv:custom parameter 'function' is no function - "+customRule);						return;				}				 				if (!fn(field, rules, i, options))					return options.allrules[customRule].alertText;			} else {				alert("jqv:custom type not allowed "+customRule);					return;			}		},		/**		* Validate custom function outside of the engine scope		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_funcCall: function(field, rules, i, options) {			var functionName = rules[i + 1];			var fn;			if(functionName.indexOf('.') >-1)			{				var namespaces = functionName.split('.');				var scope = window;				while(namespaces.length)				{					scope = scope[namespaces.shift()];				}				fn = scope;			}			else				fn = window[functionName] || options.customFunctions[functionName];			if (typeof(fn) == 'function')				return fn(field, rules, i, options);		},		/**		* Field match		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_equals: function(field, rules, i, options) {			var equalsField = rules[i + 1];			if (field.val() != $("#" + equalsField).val())				return options.allrules.equals.alertText;		},		/**		* Check the maximum size (in characters)		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_maxSize: function(field, rules, i, options) {			var max = rules[i + 1];			var len = field.val().length;			if (len > max) {				var rule = options.allrules.maxSize;				//return rule.alertText + max + rule.alertText2;				return rule.alertText + rule.alertText2;			}		},		/**		* Check the minimum size (in characters)		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_minSize: function(field, rules, i, options) {			var min = rules[i + 1];			var len = field.val().length;			if (len < min) {				var rule = options.allrules.minSize;				//return rule.alertText + min + rule.alertText2;				return rule.alertText + rule.alertText2;			}		},		/**		* Check number minimum value		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_min: function(field, rules, i, options) {			var min = parseFloat(rules[i + 1]);			var len = parseFloat(field.val());			if (len < min) {				var rule = options.allrules.min;				if (rule.alertText2) return rule.alertText + min + rule.alertText2;				return rule.alertText + min;			}		},		/**		* Check number maximum value		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_max: function(field, rules, i, options) {			var max = parseFloat(rules[i + 1]);			var len = parseFloat(field.val());			if (len >max ) {				var rule = options.allrules.max;				if (rule.alertText2) return rule.alertText + max + rule.alertText2;				//orefalo: to review, also do the translations				return rule.alertText + max;			}		},		/**		* Checks date is in the past		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_past: function(form, field, rules, i, options) {			var p=rules[i + 1];			var fieldAlt = $(form.find("input[name='" + p.replace(/^#+/, '') + "']"));			var pdate;			if (p.toLowerCase() == "now") {				pdate = new Date();			} else if (undefined != fieldAlt.val()) {				if (fieldAlt.is(":disabled"))					return;				pdate = methods._parseDate(fieldAlt.val());			} else {				pdate = methods._parseDate(p);			}			var vdate = methods._parseDate(field.val());			if (vdate > pdate ) {				var rule = options.allrules.past;				if (rule.alertText2) return rule.alertText + methods._dateToString(pdate) + rule.alertText2;				return rule.alertText + methods._dateToString(pdate);			}		},		/**		* Checks date is in the future		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_future: function(form, field, rules, i, options) {			var p=rules[i + 1];			var fieldAlt = $(form.find("input[name='" + p.replace(/^#+/, '') + "']"));			var pdate;			if (p.toLowerCase() == "now") {				pdate = new Date();			} else if (undefined != fieldAlt.val()) {				if (fieldAlt.is(":disabled"))					return;				pdate = methods._parseDate(fieldAlt.val());			} else {				pdate = methods._parseDate(p);			}			var vdate = methods._parseDate(field.val());			if (vdate < pdate ) {				var rule = options.allrules.future;				if (rule.alertText2)					return rule.alertText + methods._dateToString(pdate) + rule.alertText2;				return rule.alertText + methods._dateToString(pdate);			}		},		/**		* Checks if valid date		*		* @param {string} date string		* @return a bool based on determination of valid date		*/		_isDate: function (value) {			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]))$/);			return dateRegEx.test(value);		},		/**		* Checks if valid date time		*		* @param {string} date string		* @return a bool based on determination of valid date time		*/		_isDateTime: function (value){			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})$/);			return dateTimeRegEx.test(value);		},		//Checks if the start date is before the end date		//returns true if end is later than start		_dateCompare: function (start, end) {			return (new Date(start.toString()) < new Date(end.toString()));		},		/**		* Checks date range		*		* @param {jqObject} first field name		* @param {jqObject} second field name		* @return an error string if validation failed		*/		_dateRange: function (field, rules, i, options) {			//are not both populated			if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;			}			//are not both dates			if (!methods._isDate(options.firstOfGroup[0].value) || !methods._isDate(options.secondOfGroup[0].value)) {				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;			}			//are both dates but range is off			if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;			}		},		/**		* Checks date time range		*		* @param {jqObject} first field name		* @param {jqObject} second field name		* @return an error string if validation failed		*/		_dateTimeRange: function (field, rules, i, options) {			//are not both populated			if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;			}			//are not both dates			if (!methods._isDateTime(options.firstOfGroup[0].value) || !methods._isDateTime(options.secondOfGroup[0].value)) {				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;			}			//are both dates but range is off			if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {				return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;			}		},		/**		* Max number of checkbox selected		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_maxCheckbox: function(form, field, rules, i, options) {			var nbCheck = rules[i + 1];			var groupname = field.attr("name");			var groupSize = form.find("input[name='" + groupname + "']:checked").size();			if (groupSize > nbCheck) {				options.showArrow = false;				if (options.allrules.maxCheckbox.alertText2)					 return options.allrules.maxCheckbox.alertText + " " + nbCheck + " " + options.allrules.maxCheckbox.alertText2;				return options.allrules.maxCheckbox.alertText;			}		},		/**		* Min number of checkbox selected		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_minCheckbox: function(form, field, rules, i, options) {			var nbCheck = rules[i + 1];			var groupname = field.attr("name");			var groupSize = form.find("input[name='" + groupname + "']:checked").size();			if (groupSize < nbCheck) {				options.showArrow = false;				return options.allrules.minCheckbox.alertText + " " + nbCheck + " " + options.allrules.minCheckbox.alertText2;			}		},		/**		* Checks that it is a valid credit card number according to the		* Luhn checksum algorithm.		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return an error string if validation failed		*/		_creditCard: function(field, rules, i, options) {			//spaces and dashes may be valid characters, but must be stripped to calculate the checksum.			var valid = false, cardNumber = field.val().replace(/ +/g, '').replace(/-+/g, '');			var numDigits = cardNumber.length;			if (numDigits >= 14 && numDigits <= 16 && parseInt(cardNumber) > 0) {				var sum = 0, i = numDigits - 1, pos = 1, digit, luhn = new String();				do {					digit = parseInt(cardNumber.charAt(i));					luhn += (pos++ % 2 == 0) ? digit * 2 : digit;				} while (--i >= 0)				for (i = 0; i < luhn.length; i++) {					sum += parseInt(luhn.charAt(i));				}				valid = sum % 10 == 0;			}			if (!valid) return options.allrules.creditCard.alertText;		},		/**		* Ajax field validation		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		*            user options		* @return nothing! the ajax validator handles the prompts itself		*/		 _ajax: function(field, rules, i, options) {			 var errorSelector = rules[i + 1];			 var rule = options.allrules[errorSelector];			 var extraData = rule.extraData;			 var extraDataDynamic = rule.extraDataDynamic;			 var data = {				"fieldId" : field.attr("id"),				"fieldValue" : field.val()			 };			 if (typeof extraData === "object") {				$.extend(data, extraData);			 } else if (typeof extraData === "string") {				var tempData = extraData.split("&");				for(var i = 0; i < tempData.length; i++) {					var values = tempData[i].split("=");					if (values[0] && values[0]) {						data[values[0]] = values[1];					}				}			 }			 if (extraDataDynamic) {				 var tmpData = [];				 var domIds = String(extraDataDynamic).split(",");				 for (var i = 0; i < domIds.length; i++) {					 var id = domIds[i];					 if ($(id).length) {						 var inputValue = field.closest("form").find(id).val();						 var keyValue = id.replace('#', '') + '=' + escape(inputValue);						 data[id.replace('#', '')] = inputValue;					 }				 }			 }			 			 // If a field change event triggered this we want to clear the cache for this ID			 if (options.eventTrigger == "field") {				delete(options.ajaxValidCache[field.attr("id")]);			 }			 // If there is an error or if the the field is already validated, do not re-execute AJAX			 if (!options.isError && !methods._checkAjaxFieldStatus(field.attr("id"), options)) {				 $.ajax({					 type: options.ajaxFormValidationMethod,					 url: rule.url,					 cache: false,					 dataType: "json",					 data: data,					 field: field,					 rule: rule,					 methods: methods,					 options: options,					 beforeSend: function() {},					 error: function(data, transport) {						 methods._ajaxError(data, transport);					 },					 success: function(json) {						 // asynchronously called on success, data is the json answer from the server						 var errorFieldId = json[0];						 //var errorField = $($("#" + errorFieldId)[0]);						 var errorField = $($("input[id='" + errorFieldId +"']")[0]);						 // make sure we found the element						 if (errorField.length == 1) {							 var status = json[1];							 // read the optional msg from the server							 var msg = json[2];							 if (!status) {								 // Houston we got a problem - display an red prompt								 options.ajaxValidCache[errorFieldId] = false;								 options.isError = true;								 // resolve the msg prompt								 if(msg) {									 if (options.allrules[msg]) {										 var txt = options.allrules[msg].alertText;										 if (txt) {											msg = txt;                     }									 }								 }								 else									msg = rule.alertText;								 methods._showPrompt(errorField, msg, "", true, options);							 } else {								 options.ajaxValidCache[errorFieldId] = true;								 // resolves the msg prompt								 if(msg) {									 if (options.allrules[msg]) {										 var txt = options.allrules[msg].alertTextOk;										 if (txt) {											msg = txt;                     }									 }								 }								 else								 msg = rule.alertTextOk;								 // see if we should display a green prompt								 if (msg)									methods._showPrompt(errorField, msg, "pass", true, options);								 else									methods._closePrompt(errorField);																 // If a submit form triggered this, we want to re-submit the form								 if (options.eventTrigger == "submit")									field.closest("form").submit();							 }						 }						 errorField.trigger("jqv.field.result", [errorField, options.isError, msg]);					 }				 });				 				 return rule.alertTextLoad;			 }		 },		/**		* Common method to handle ajax errors		*		* @param {Object} data		* @param {Object} transport		*/		_ajaxError: function(data, transport) {			if(data.status == 0 && transport == null)				alert("The page is not served from a server! ajax call failed");			else if(typeof console != "undefined")				console.log("Ajax error: " + data.status + " " + transport);		},		/**		* date -> string		*		* @param {Object} date		*/		_dateToString: function(date) {			return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate();		},		/**		* Parses an ISO date		* @param {String} d		*/		_parseDate: function(d) {			var dateParts = d.split("-");			if(dateParts==d)				dateParts = d.split("/");			return new Date(dateParts[0], (dateParts[1] - 1) ,dateParts[2]);		},		/**		* Builds or updates a prompt with the given information		*		* @param {jqObject} field		* @param {String} promptText html text to display type		* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)		* @param {boolean} ajaxed - use to mark fields than being validated with ajax		* @param {Map} options user options		*/		 _showPrompt: function(field, promptText, type, ajaxed, options, ajaxform) {			 var prompt = methods._getPrompt(field);			 // The ajax submit errors are not see has an error in the form,			 // When the form errors are returned, the engine see 2 bubbles, but those are ebing closed by the engine at the same time			 // Because no error was found befor submitting			 if(ajaxform) prompt = false;			 			 if(options.promptType == 'diy' && (field.attr('type') == 'text' || field.attr('type') == 'password' || field.attr('type') == 'checkbox'))			{				// create the prompt				var prompt = $('<div>');				prompt.addClass(methods._getClassName(field.attr("id")) + "formError");				// add a class name to identify the parent form of the prompt				prompt.addClass("parentForm"+methods._getClassName(field.parents('form').attr("id")));				prompt.addClass("error-text");				prompt.html(promptText);				field.parent().find('.error-text').remove();				if(field.parent().attr('style') == 'font-size:16px;')				{					if(field.parent().parent().next().attr('class') != 'error-text')					{						field.parent().parent().after(prompt);					}				}				else if(field.next().length)				{					field.next().after(prompt);				}				else				{					field.after(prompt);				}								switch (type) {					case "pass":						prompt.addClass("greenPopup");						break;					case "load":						prompt.addClass("blackPopup");						break;					default:						/* it has error  */						//alert("unknown popup type:"+type);				}				if (ajaxed)				{					prompt.addClass("ajaxed");				}								if(type == 'pass')				{					prompt.hide();				}								return;			}			 if (prompt)				methods._updatePrompt(field, prompt, promptText, type, ajaxed, options);			 else				methods._buildPrompt(field, promptText, type, ajaxed, options);		 },		/**		* Builds and shades a prompt for the given field.		*		* @param {jqObject} field		* @param {String} promptText html text to display type		* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)		* @param {boolean} ajaxed - use to mark fields than being validated with ajax		* @param {Map} options user options		*/		_buildPrompt: function(field, promptText, type, ajaxed, options) {						// create the prompt			var prompt = $('<div>');			prompt.addClass(methods._getClassName(field.attr("id")) + "formError");			// add a class name to identify the parent form of the prompt			prompt.addClass("parentForm"+methods._getClassName(field.parents('form').attr("id")));			prompt.addClass("formError");			switch (type) {				case "pass":					prompt.addClass("greenPopup");					break;				case "load":					prompt.addClass("blackPopup");					break;				default:					/* it has error  */					//alert("unknown popup type:"+type);			}			if (ajaxed)				prompt.addClass("ajaxed");			// create the prompt content			var promptContent = $('<div>').addClass("formErrorContent").html(promptText).appendTo(prompt);			// create the css arrow pointing at the field			// note that there is no triangle on max-checkbox and radio			if (options.showArrow) {				var arrow = $('<div>').addClass("formErrorArrow");				//prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)				var positionType=field.data("promptPosition") || options.promptPosition;				if (typeof(positionType)=='string') 				{					var pos=positionType.indexOf(":");					if(pos!=-1)						positionType=positionType.substring(0,pos);				}				switch (positionType) {					case "bottomLeft":					case "bottomRight":						prompt.find(".formErrorContent").before(arrow);						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>');						break;					case "topLeft":					case "topRight":						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>');						prompt.append(arrow);						break;				}			}			// Modify z-indexes  for jquery ui			if (field.closest('.ui-dialog').length)				prompt.addClass('formErrorInsideDialog');			prompt.css({				"opacity": 0,				'position':'absolute'			});			field.before(prompt);						var pos = methods._calculatePosition(field, prompt, options);			prompt.css({				"top": pos.callerTopPosition,				"left": pos.callerleftPosition,				"marginTop": pos.marginTopSize,				"opacity": 0			}).data("callerField", field);			if (options.autoHidePrompt) {				setTimeout(function(){					prompt.animate({						"opacity": 0					},function(){						prompt.closest('.formErrorOuter').remove();						prompt.remove();					});				}, options.autoHideDelay);			} 			return prompt.animate({				"opacity": 0.87			});		},		/**		* Updates the prompt text field - the field for which the prompt		* @param {jqObject} field		* @param {String} promptText html text to display type		* @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)		* @param {boolean} ajaxed - use to mark fields than being validated with ajax		* @param {Map} options user options		*/		_updatePrompt: function(field, prompt, promptText, type, ajaxed, options, noAnimation) {			if (prompt) {				if (typeof type !== "undefined") {					if (type == "pass")						prompt.addClass("greenPopup");					else						prompt.removeClass("greenPopup");					if (type == "load")						prompt.addClass("blackPopup");					else						prompt.removeClass("blackPopup");				}				if (ajaxed)					prompt.addClass("ajaxed");				else					prompt.removeClass("ajaxed");				prompt.find(".formErrorContent").html(promptText);				var pos = methods._calculatePosition(field, prompt, options);				var css = {"top": pos.callerTopPosition,				"left": pos.callerleftPosition,				"marginTop": pos.marginTopSize};				if (noAnimation)					prompt.css(css);				else					prompt.animate(css);			}		},		/**		* Closes the prompt associated with the given field		*		* @param {jqObject}		*            field		*/		 _closePrompt: function(field) {			 var prompt = methods._getPrompt(field);			 if (prompt)				 prompt.fadeTo("fast", 0, function() {					 prompt.parent('.formErrorOuter').remove();					 prompt.remove();				 });		 },		 closePrompt: function(field) {			 return methods._closePrompt(field);		 },		/**		* Returns the error prompt matching the field if any		*		* @param {jqObject}		*            field		* @return undefined or the error prompt (jqObject)		*/		_getPrompt: function(field) {				var formId = $(field).closest('form').attr('id');			var className = methods._getClassName(field.attr("id")) + "formError";				var match = $("." + methods._escapeExpression(className) + '.parentForm' + formId)[0];			if (match)			return $(match);		},		/**		  * Returns the escapade classname		  *		  * @param {selector}		  *            className		  */		  _escapeExpression: function (selector) {			  return selector.replace(/([#;&,\.\+\*\~':"\!\^$\[\]\(\)=>\|])/g, "\\$1");		  },		/**		 * returns true if we are in a RTLed document		 *		 * @param {jqObject} field		 */		isRTL: function(field)		{			var $document = $(document);			var $body = $('body');			var rtl =				(field && field.hasClass('rtl')) ||				(field && (field.attr('dir') || '').toLowerCase()==='rtl') ||				$document.hasClass('rtl') ||				($document.attr('dir') || '').toLowerCase()==='rtl' ||				$body.hasClass('rtl') ||				($body.attr('dir') || '').toLowerCase()==='rtl';			return Boolean(rtl);		},		/**		* Calculates prompt position		*		* @param {jqObject}		*            field		* @param {jqObject}		*            the prompt		* @param {Map}		*            options		* @return positions		*/		_calculatePosition: function (field, promptElmt, options) {			var promptTopPosition, promptleftPosition, marginTopSize;			var fieldWidth 	= field.width();			var fieldLeft 	= field.position().left; 			var fieldTop 	=  field.position().top;			var fieldHeight 	=  field.height();				var promptHeight = promptElmt.height();			// is the form contained in an overflown container?			promptTopPosition = promptleftPosition = 0;			// compensation for the arrow			marginTopSize = -promptHeight;					//prompt positioning adjustment support			//now you can adjust prompt position			//usage: positionType:Xshift,Yshift			//for example:			//   bottomLeft:+20 means bottomLeft position shifted by 20 pixels right horizontally			//   topRight:20, -15 means topRight position shifted by 20 pixels to right and 15 pixels to top			//You can use +pixels, - pixels. If no sign is provided than + is default.			var positionType=field.data("promptPosition") || options.promptPosition;			var shift1="";			var shift2="";			var shiftX=0;			var shiftY=0;			if (typeof(positionType)=='string') {				//do we have any position adjustments ?				if (positionType.indexOf(":")!=-1) {					shift1=positionType.substring(positionType.indexOf(":")+1);					positionType=positionType.substring(0,positionType.indexOf(":"));					//if any advanced positioning will be needed (percents or something else) - parser should be added here					//for now we use simple parseInt()					//do we have second parameter?					if (shift1.indexOf(",") !=-1) {						shift2=shift1.substring(shift1.indexOf(",") +1);						shift1=shift1.substring(0,shift1.indexOf(","));						shiftY=parseInt(shift2);						if (isNaN(shiftY)) shiftY=0;					};					shiftX=parseInt(shift1);					if (isNaN(shift1)) shift1=0;				};			};						switch (positionType) {				default:				case "topRight":					promptleftPosition +=  fieldLeft + fieldWidth - 30;					promptTopPosition +=  fieldTop;					break;				case "topLeft":					promptTopPosition +=  fieldTop;					promptleftPosition += fieldLeft; 					break;				case "centerRight":					promptTopPosition = fieldTop+4;					marginTopSize = 0;					promptleftPosition= fieldLeft + field.outerWidth(true)+5;					break;				case "centerLeft":					promptleftPosition = fieldLeft - (promptElmt.width() + 2);					promptTopPosition = fieldTop+4;					marginTopSize = 0;										break;				case "bottomLeft":					promptTopPosition = fieldTop + field.height() + 5;					marginTopSize = 0;					promptleftPosition = fieldLeft;					break;				case "bottomRight":					promptleftPosition = fieldLeft + fieldWidth - 30;					promptTopPosition =  fieldTop +  field.height() + 5;					marginTopSize = 0;			};					//apply adjusments if any			promptleftPosition += shiftX;			promptTopPosition  += shiftY;			return {				"callerTopPosition": promptTopPosition + "px",				"callerleftPosition": promptleftPosition + "px",				"marginTopSize": marginTopSize + "px"			};		},		/**		* Saves the user options and variables in the form.data		*		* @param {jqObject}		*            form - the form where the user option should be saved		* @param {Map}		*            options - the user options		* @return the user options (extended from the defaults)		*/		 _saveOptions: function(form, options) {			 // is there a language localisation ?			 if ($.validationEngineLanguage)			 var allRules = $.validationEngineLanguage.allRules;			 else			 $.error("jQuery.validationEngine rules are not loaded, plz add localization files to the page");			 // --- Internals DO NOT TOUCH or OVERLOAD ---			 // validation rules and i18			 $.validationEngine.defaults.allrules = allRules;			 var userOptions = $.extend(true,{},$.validationEngine.defaults,options);			 form.data('jqv', userOptions);			 return userOptions;		 },		 /**		 * Removes forbidden characters from class name		 * @param {String} className		 */		 _getClassName: function(className) {			 if(className)				 return className.replace(/:/g, "_").replace(/\./g, "_");                 },		/**		* Conditionally required field		*		* @param {jqObject} field		* @param {Array[String]} rules		* @param {int} i rules index		* @param {Map}		* user options		* @return an error string if validation failed		*/		_condRequired: function(field, rules, i, options) {			var idx, dependingField;			for(idx = (i + 1); idx < rules.length; idx++) {				dependingField = jQuery("#" + rules[idx]).first();				/* Use _required for determining wether dependingField has a value.				 * There is logic there for handling all field types, and default value; so we won't replicate that here				 */				if (dependingField.length && methods._required(dependingField, ["required"], 0, options) == undefined) {					/* We now know any of the depending fields has a value,					 * so we can validate this field as per normal required code					 */					return methods._required(field, ["required"], 0, options);				}			}		}        };	 /**	 * Plugin entry point.	 * You may pass an action as a parameter or a list of options.	 * if none, the init and attach methods are being called.	 * Remember: if you pass options, the attached method is NOT called automatically	 *	 * @param {String}	 *            method (optional) action	 */	 $.fn.validationEngine = function(method) {		 var form = $(this);		 if(!form[0]) return form;  // stop here if the form does not exist		 if (typeof(method) == 'string' && method.charAt(0) != '_' && methods[method]) {			 // make sure init is called once			 if(method != "showPrompt" && method != "hide" && method != "hideAll")			 methods.init.apply(form);			 return methods[method].apply(form, Array.prototype.slice.call(arguments, 1));		 } else if (typeof method == 'object' || !method) {			 // default constructor with or without arguments			 methods.init.apply(form, arguments);			 return methods.attach.apply(form);		 } else {			 $.error('Method ' + method + ' does not exist in jQuery.validationEngine');		 }	};	// LEAK GLOBAL OPTIONS	$.validationEngine= {fieldIdCounter: 0,defaults:{		// Name of the event triggering field validation		validationEventTrigger: "blur",		// Automatically scroll viewport to the first error		scroll: true,		// Focus on the first input		focusFirstField:true,		// Opening box position, possible locations are: topLeft,		// topRight, bottomLeft, centerRight, bottomRight		promptPosition: "topRight",		promptType:'',		bindMethod:"bind",		// internal, automatically set to true when it parse a _ajax rule		inlineAjax: false,		// if set to true, the form data is sent asynchronously via ajax to the form.action url (get)		ajaxFormValidation: false,		// The url to send the submit ajax validation (default to action)		ajaxFormValidationURL: false,		// HTTP method used for ajax validation		ajaxFormValidationMethod: 'get',		// Ajax form validation callback method: boolean onComplete(form, status, errors, options)		// retuns false if the form.submit event needs to be canceled.		onAjaxFormComplete: $.noop,		// called right before the ajax call, may return false to cancel		onBeforeAjaxFormValidation: $.noop,		// Stops form from submitting and execute function assiciated with it		onValidationComplete: false,		// Used when you have a form fields too close and the errors messages are on top of other disturbing viewing messages		doNotShowAllErrosOnSubmit: false,		// Object where you store custom messages to override the default error messages		custom_error_messages:{},		// true if you want to vind the input fields		binded: true,		// set to true, when the prompt arrow needs to be displayed		showArrow: true,		// did one of the validation fail ? kept global to stop further ajax validations		isError: false,		// Caches field validation status, typically only bad status are created.		// the array is used during ajax form validation to detect issues early and prevent an expensive submit		ajaxValidCache: {},		// Auto update prompt position after window resize		autoPositionUpdate: false,		InvalidFields: [],		onSuccess: false,		onFailure: false,		// Auto-hide prompt		autoHidePrompt: false,		// Delay before auto-hide		autoHideDelay: 10000,		// Fade out duration while hiding the validations		fadeDuration: 0.3,    // Use Prettify select library    prettySelect: false,    // Custom ID uses prefix    usePrefix: "",    // Custom ID uses suffix    useSuffix: "",    // Only show one message per error prompt    showOneMessage: false	}};	$(function(){$.validationEngine.defaults.promptPosition = methods.isRTL()?'topLeft':"topRight"});})(jQuery);
 |