2054 lines
		
	
	
		
			70 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
		
			
		
	
	
			2054 lines
		
	
	
		
			70 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
|  | /* | ||
|  |  * Inline Form Validation Engine 2.6.2, 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
 | ||
|  | 				$(document).on("click", ".formError", 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) { | ||
|  | 
 | ||
|  | 			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) { | ||
|  | 
 | ||
|  | 				// delegate fields
 | ||
|  | 				form.on(options.validationEventTrigger, "["+options.validateAttribute+"*=validate]:not([type=checkbox]):not([type=radio]):not(.datepicker)", methods._onFieldEvent); | ||
|  | 				form.on("click", "["+options.validateAttribute+"*=validate][type=checkbox],["+options.validateAttribute+"*=validate][type=radio]", methods._onFieldEvent); | ||
|  | 				form.on(options.validationEventTrigger,"["+options.validateAttribute+"*=validate][class*=datepicker]", {"delay": 300}, methods._onFieldEvent); | ||
|  | 			} | ||
|  | 			if (options.autoPositionUpdate) { | ||
|  | 				$(window).bind("resize", { | ||
|  | 					"noAnimation": true, | ||
|  | 					"formElem": form | ||
|  | 				}, methods.updatePromptsPosition); | ||
|  | 			} | ||
|  | 			form.on("click","a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick); | ||
|  | 			form.removeData('jqv_submitButton'); | ||
|  | 
 | ||
|  | 			// bind form.submit
 | ||
|  | 			//form.on("submit", methods._onSubmitEvent);
 | ||
|  | 			return this; | ||
|  | 		}, | ||
|  | 		/** | ||
|  | 		* Unregisters any bindings that may point to jQuery.validaitonEngine | ||
|  | 		*/ | ||
|  | 		detach: function() { | ||
|  | 
 | ||
|  | 			var form = this; | ||
|  | 			var options = form.data('jqv'); | ||
|  | 
 | ||
|  | 			// unbind fields
 | ||
|  | 			form.find("["+options.validateAttribute+"*=validate]").not("[type=checkbox]").off(options.validationEventTrigger, methods._onFieldEvent); | ||
|  | 			form.find("["+options.validateAttribute+"*=validate][type=checkbox],[class*=validate][type=radio]").off("click", methods._onFieldEvent); | ||
|  | 
 | ||
|  | 			// unbind form.submit
 | ||
|  | 			form.off("submit", methods.onAjaxFormComplete); | ||
|  | 
 | ||
|  | 			// unbind form.submit
 | ||
|  | 			form.off("submit", methods.onAjaxFormComplete); | ||
|  | 			form.removeData('jqv'); | ||
|  |              | ||
|  | 			form.off("click", "a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick); | ||
|  | 			form.removeData('jqv_submitButton'); | ||
|  | 
 | ||
|  | 			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() { | ||
|  | 			var element = $(this); | ||
|  | 			var valid = null; | ||
|  | 
 | ||
|  | 			if (element.is("form") || element.hasClass("validationEngineContainer")) { | ||
|  | 				if (element.hasClass('validating')) { | ||
|  | 					// form is already validating.
 | ||
|  | 					// Should abort old validation and start new one. I don't know how to implement it.
 | ||
|  | 					return false; | ||
|  | 				} else {				 | ||
|  | 					element.addClass('validating'); | ||
|  | 					var options = element.data('jqv'); | ||
|  | 					var valid = methods._validateFields(this); | ||
|  | 
 | ||
|  | 					// If the form doesn't validate, clear the 'validating' class before the user has a chance to submit again
 | ||
|  | 					setTimeout(function(){ | ||
|  | 						element.removeClass('validating'); | ||
|  | 					}, 100); | ||
|  | 					if (valid && options.onSuccess) { | ||
|  | 						options.onSuccess(); | ||
|  | 					} else if (!valid && options.onFailure) { | ||
|  | 						options.onFailure(); | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} else if (element.is('form') || element.hasClass('validationEngineContainer')) { | ||
|  | 				element.removeClass('validating'); | ||
|  | 			} else { | ||
|  | 				// field validation
 | ||
|  | 				var form = element.closest('form, .validationEngineContainer'), | ||
|  | 					options = (form.data('jqv')) ? form.data('jqv') : $.validationEngine.defaults, | ||
|  | 					valid = methods._validateField(element, options); | ||
|  | 
 | ||
|  | 				if (valid && options.onFieldSuccess) | ||
|  | 					options.onFieldSuccess(); | ||
|  | 				else if (options.onFieldFailure && options.InvalidFields.length > 0) { | ||
|  | 					options.onFieldFailure(); | ||
|  | 				} | ||
|  | 			} | ||
|  | 			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, valid); | ||
|  | 			} | ||
|  | 			return valid; | ||
|  | 		}, | ||
|  | 		/** | ||
|  | 		*  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, .validationEngineContainer')); | ||
|  | 
 | ||
|  | 			var options = form.data('jqv'); | ||
|  | 			// No option, take default one
 | ||
|  | 			form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each(function(){ | ||
|  | 				var field = $(this); | ||
|  | 				if (options.prettySelect && field.is(":hidden")) | ||
|  | 				  field = form.find("#" + options.usePrefix + field.attr('id') + options.useSuffix); | ||
|  | 				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, .validationEngineContainer'); | ||
|  | 			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, .validationEngineContainer'); | ||
|  | 			 var options = form.data('jqv'); | ||
|  | 			 var fadeDuration = (options && options.fadeDuration) ? options.fadeDuration : 0.3; | ||
|  | 			 var closingtag; | ||
|  | 			  | ||
|  | 			 if($(this).is("form") || $(this).hasClass("validationEngineContainer")) { | ||
|  | 				 closingtag = "parentForm"+methods._getClassName($(this).attr("id")); | ||
|  | 			 } else { | ||
|  | 				 closingtag = methods._getClassName($(this).attr("id")) +"formError"; | ||
|  | 			 } | ||
|  | 			 $('.'+closingtag).fadeTo(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:300; | ||
|  | 			 $('.formError').fadeTo(duration, 300, 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, .validationEngineContainer'); | ||
|  | 			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.onFieldSuccess) { | ||
|  | 					options.onFieldSuccess(); | ||
|  | 				} else if (options.InvalidFields.length > 0 && options.onFieldFailure) { | ||
|  | 					options.onFieldFailure(); | ||
|  | 				} | ||
|  | 			}, (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'); | ||
|  | 			 | ||
|  | 			//check if it is trigger from skipped button
 | ||
|  | 			if (form.data("jqv_submitButton")){ | ||
|  | 				var submitButton = $("#" + form.data("jqv_submitButton")); | ||
|  | 				if (submitButton){ | ||
|  | 					if (submitButton.length > 0){ | ||
|  | 						if (submitButton.hasClass("validate-skip") || submitButton.attr("data-validation-engine-skip") == "true") | ||
|  | 							return true; | ||
|  | 					} | ||
|  | 				} | ||
|  | 			} | ||
|  | 
 | ||
|  | 			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 + methods._jqSelector(field.attr('id')) + options.useSuffix); | ||
|  | 									else | ||
|  | 										 first_err=field; | ||
|  | 					if (options.doNotShowAllErrosOnSubmit) | ||
|  | 						return false; | ||
|  | 					names.push(field.attr('name')); | ||
|  | 
 | ||
|  | 					//if option set, stop checking validation rules after one error is found
 | ||
|  | 					if(options.showOneMessage == true && errorFound){ | ||
|  | 						return false; | ||
|  | 					} | ||
|  | 				} | ||
|  | 			}); | ||
|  | 
 | ||
|  | 			// 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); | ||
|  | 						if (prompt_err) { | ||
|  | 							destination=prompt_err.offset().top; | ||
|  | 						} | ||
|  | 					} | ||
|  | 					 | ||
|  | 					// Offset the amount the page scrolls by an amount in px to accomodate fixed elements at top of page
 | ||
|  | 					if (options.scrollOffset) { | ||
|  | 						destination -= options.scrollOffset; | ||
|  | 					} | ||
|  | 
 | ||
|  | 					// 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, body").animate({ | ||
|  | 							scrollTop: destination | ||
|  | 						}, 1100, function(){ | ||
|  | 							if(options.focusFirstField) first_err.focus(); | ||
|  | 						}); | ||
|  | 						$("html, body").animate({scrollLeft: fixleft},1100) | ||
|  | 					} | ||
|  | 
 | ||
|  | 				} 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.ajaxFormValidationMethod) ? options.ajaxFormValidationMethod : "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 ((dataType == "json") && (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; | ||
|  | 										} | ||
|  | 										if (options.showPrompts) 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; | ||
|  | 									} | ||
|  | 									if(options.showPrompts) methods._showPrompt(errorField, msg, "", false, options, true); | ||
|  | 								} | ||
|  | 							} | ||
|  | 						} | ||
|  | 						options.onAjaxFormComplete(!errorInForm, form, json, options); | ||
|  | 					} else | ||
|  | 						options.onAjaxFormComplete(true, form, json, 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 (!options.validateNonVisibleFields && (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; | ||
|  | 			var limitErrors = false; | ||
|  | 			options.isError = false; | ||
|  | 			options.showArrow = true; | ||
|  | 			 | ||
|  | 			// If the programmer wants to limit the amount of error messages per field,
 | ||
|  | 			if (options.maxErrorsPerField > 0) { | ||
|  | 				limitErrors = true; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			var form = $(field.closest("form, .validationEngineContainer")); | ||
|  | 			// Fix for adding spaces in the rules
 | ||
|  | 			for (var i = 0; i < rules.length; i++) { | ||
|  | 				rules[i] = rules[i].replace(" ", ""); | ||
|  | 				// Remove any parsing errors
 | ||
|  | 				if (rules[i] === '') { | ||
|  | 					delete rules[i]; | ||
|  | 				} | ||
|  | 			} | ||
|  | 
 | ||
|  | 			for (var i = 0, field_errors = 0; i < rules.length; i++) { | ||
|  | 				 | ||
|  | 				// If we are limiting errors, and have hit the max, break
 | ||
|  | 				if (limitErrors && field_errors >= options.maxErrorsPerField) { | ||
|  | 					// If we haven't hit a required yet, check to see if there is one in the validation rules for this
 | ||
|  | 					// field and that it's index is greater or equal to our current index
 | ||
|  | 					if (!required) { | ||
|  | 						var have_required = $.inArray('required', rules); | ||
|  | 						required = (have_required != -1 &&  have_required >= i); | ||
|  | 					} | ||
|  | 					break; | ||
|  | 				} | ||
|  | 				 | ||
|  | 				 | ||
|  | 				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; | ||
|  | 
 | ||
|  | 						} | ||
|  | 						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: | ||
|  | 				} | ||
|  | 				 | ||
|  | 				var end_validation = false; | ||
|  | 				 | ||
|  | 				// If we were passed back an message object, check what the status was to determine what to do
 | ||
|  | 				if (typeof errorMsg == "object") { | ||
|  | 					switch (errorMsg.status) { | ||
|  | 						case "_break": | ||
|  | 							end_validation = true; | ||
|  | 							break; | ||
|  | 						// If we have an error message, set errorMsg to the error message
 | ||
|  | 						case "_error": | ||
|  | 							errorMsg = errorMsg.message; | ||
|  | 							break; | ||
|  | 						// If we want to throw an error, but not show a prompt, return early with true
 | ||
|  | 						case "_error_no_prompt": | ||
|  | 							return true; | ||
|  | 							break; | ||
|  | 						// Anything else we continue on
 | ||
|  | 						default: | ||
|  | 							break; | ||
|  | 					} | ||
|  | 				} | ||
|  | 				 | ||
|  | 				// If it has been specified that validation should end now, break
 | ||
|  | 				if (end_validation) { | ||
|  | 					break; | ||
|  | 				} | ||
|  | 				 | ||
|  | 				// If we have a string, that means that we have an error, so add it to the error message.
 | ||
|  | 				if (typeof errorMsg == 'string') { | ||
|  | 					promptText += errorMsg + "<br/>"; | ||
|  | 					options.isError = true; | ||
|  | 					field_errors++; | ||
|  | 				}	 | ||
|  | 			} | ||
|  | 			// If the rules required is not added, an empty field is not validated
 | ||
|  | 			if(!required && !(field.val()) && 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"); | ||
|  | 			var positionType=field.data("promptPosition") || options.promptPosition; | ||
|  | 
 | ||
|  | 			if ((fieldType == "radio" || fieldType == "checkbox") && form.find("input[name='" + fieldName + "']").size() > 1) { | ||
|  | 				if(positionType === 'inline') { | ||
|  | 					field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:last")); | ||
|  | 				} else { | ||
|  | 				field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:first")); | ||
|  | 				} | ||
|  | 				options.showArrow = false; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			if(field.is(":hidden") && options.prettySelect) { | ||
|  | 				field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			if (options.isError && options.showPrompts){ | ||
|  | 				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); | ||
|  | 			} | ||
|  | 				 | ||
|  | 			methods._handleStatusCssClasses(field, options); | ||
|  | 	 | ||
|  | 			/* run callback function for each field */ | ||
|  | 			if (options.isError && options.onFieldFailure) | ||
|  | 				options.onFieldFailure(field); | ||
|  | 
 | ||
|  | 			if (!options.isError && options.onFieldSuccess) | ||
|  | 				options.onFieldSuccess(field); | ||
|  | 
 | ||
|  | 			return options.isError; | ||
|  | 		}, | ||
|  | 		/** | ||
|  | 		* Handling css classes of fields indicating result of validation  | ||
|  | 		* | ||
|  | 		* @param {jqObject} | ||
|  | 		*            field | ||
|  | 		* @param {Array[String]} | ||
|  | 		*            field's validation rules             | ||
|  | 		* @private | ||
|  | 		*/ | ||
|  | 		_handleStatusCssClasses: function(field, options) { | ||
|  | 			/* remove all classes */ | ||
|  | 			if(options.addSuccessCssClassToField) | ||
|  | 				field.removeClass(options.addSuccessCssClassToField); | ||
|  | 			 | ||
|  | 			if(options.addFailureCssClassToField) | ||
|  | 				field.removeClass(options.addFailureCssClassToField); | ||
|  | 			 | ||
|  | 			/* Add classes */ | ||
|  | 			if (options.addSuccessCssClassToField && !options.isError) | ||
|  | 				field.addClass(options.addSuccessCssClassToField); | ||
|  | 			 | ||
|  | 			if (options.addFailureCssClassToField && options.isError) | ||
|  | 				field.addClass(options.addFailureCssClassToField);		 | ||
|  | 		}, | ||
|  | 		 | ||
|  | 		 /******************** | ||
|  | 		  * _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 rule_index = jQuery.inArray(rule, rules); | ||
|  | 			 if (rule === "custom" || rule === "funcCall") { | ||
|  | 				 var custom_validation_type = rules[rule_index + 1]; | ||
|  | 				 rule = rule + "[" + custom_validation_type + "]"; | ||
|  | 				 // Delete the rule from the rules array so that it doesn't try to call the
 | ||
|  | 			    // same rule over again
 | ||
|  | 			    delete(rules[rule_index]); | ||
|  | 			 } | ||
|  | 			 // Change the rule to the composite rule, if it was different from the original
 | ||
|  | 			 var alteredRule = rule; | ||
|  | 
 | ||
|  | 
 | ||
|  | 			 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 or checkboxes, 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, alteredRule, options); | ||
|  | 				 if (custom_message) errorMsg = custom_message; | ||
|  | 			 } | ||
|  | 			 return errorMsg; | ||
|  | 
 | ||
|  | 		 }, | ||
|  | 		 _getCustomErrorMessage:function (field, classes, rule, options) { | ||
|  | 			var custom_message = false; | ||
|  | 			var validityProp = methods._validityProp[rule]; | ||
|  | 			 // If there is a validityProp for this rule, check to see if the field has an attribute for it
 | ||
|  | 			if (validityProp != undefined) { | ||
|  | 				custom_message = field.attr("data-errormessage-"+validityProp); | ||
|  | 				// If there was an error message for it, return the message
 | ||
|  | 				if (custom_message != undefined)  | ||
|  | 					return custom_message; | ||
|  | 			} | ||
|  | 			custom_message = field.attr("data-errormessage"); | ||
|  | 			 // If there is an inline custom error message, return it
 | ||
|  | 			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 | ||
|  | 		* @param {bool} condRequired flag when method is used for internal purpose in condRequired check | ||
|  | 		* @return an error string if validation failed | ||
|  | 		*/ | ||
|  | 		_required: function(field, rules, i, options, condRequired) { | ||
|  | 			switch (field.prop("type")) { | ||
|  | 				case "text": | ||
|  | 				case "password": | ||
|  | 				case "textarea": | ||
|  | 				case "file": | ||
|  | 				case "select-one": | ||
|  | 				case "select-multiple": | ||
|  | 				default: | ||
|  | 					var field_val      = $.trim( field.val()                               ); | ||
|  | 					var dv_placeholder = $.trim( field.attr("data-validation-placeholder") ); | ||
|  | 					var placeholder    = $.trim( field.attr("placeholder")                 ); | ||
|  | 					if ( | ||
|  | 						   ( !field_val                                    ) | ||
|  | 						|| ( dv_placeholder && field_val == dv_placeholder ) | ||
|  | 						|| ( placeholder    && field_val == placeholder    ) | ||
|  | 					) { | ||
|  | 						return options.allrules[rules[i]].alertText; | ||
|  | 					} | ||
|  | 					break; | ||
|  | 				case "radio": | ||
|  | 				case "checkbox": | ||
|  | 					// new validation style to only check dependent field
 | ||
|  | 					if (condRequired) { | ||
|  | 						if (!field.attr('checked')) { | ||
|  | 							return options.allrules[rules[i]].alertTextCheckboxMultiple; | ||
|  | 						} | ||
|  | 						break; | ||
|  | 					} | ||
|  | 					// old validation style
 | ||
|  | 					var form = field.closest("form, .validationEngineContainer"); | ||
|  | 					var name = field.attr("name"); | ||
|  | 					if (form.find("input[name='" + name + "']:checked").size() == 0) { | ||
|  | 						if (form.find("input[name='" + name + "']:visible").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, .validationEngineContainer").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; | ||
|  | 			} | ||
|  | 		}, | ||
|  | 		/** | ||
|  | 		* 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; | ||
|  | 			} | ||
|  | 		}, | ||
|  | 		/** | ||
|  | 		* 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, .validationEngineContainer").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 = $("#"+ errorFieldId).eq(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; | ||
|  | 
 | ||
|  | 								 if (options.showPrompts) 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; | ||
|  | 
 | ||
|  | 								 if (options.showPrompts) { | ||
|  | 									 // 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("/"); | ||
|  | 			if(dateParts==d) { | ||
|  | 				dateParts = d.split("."); | ||
|  | 				return new Date(dateParts[2], (dateParts[1] - 1), dateParts[0]); | ||
|  | 			} | ||
|  | 			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; | ||
|  | 			 // Check that there is indded text
 | ||
|  | 			 if($.trim(promptText)){  | ||
|  | 				 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.closest('form, .validationEngineContainer').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); | ||
|  | 
 | ||
|  | 			// determine position type
 | ||
|  | 			var positionType=field.data("promptPosition") || options.promptPosition; | ||
|  | 
 | ||
|  | 			// 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)
 | ||
|  | 				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; | ||
|  | 				} | ||
|  | 			} | ||
|  | 			// Add custom prompt class
 | ||
|  | 			if (options.addPromptClass) | ||
|  | 				prompt.addClass(options.addPromptClass); | ||
|  | 
 | ||
|  |             // Add custom prompt class defined in element
 | ||
|  |             var requiredOverride = field.attr('data-required-class'); | ||
|  |             if(requiredOverride !== undefined) { | ||
|  |                 prompt.addClass(requiredOverride); | ||
|  |             } else { | ||
|  |                 if(options.prettySelect) { | ||
|  |                     if($('#' + field.attr('id')).next().is('select')) { | ||
|  |                         var prettyOverrideClass = $('#' + field.attr('id').substr(options.usePrefix.length).substring(options.useSuffix.length)).attr('data-required-class'); | ||
|  |                         if(prettyOverrideClass !== undefined) { | ||
|  |                             prompt.addClass(prettyOverrideClass); | ||
|  |                         } | ||
|  |                     } | ||
|  |                 } | ||
|  |             } | ||
|  | 
 | ||
|  | 			prompt.css({ | ||
|  | 				"opacity": 0 | ||
|  | 			}); | ||
|  | 			if(positionType === 'inline') { | ||
|  | 				prompt.addClass("inline"); | ||
|  | 				if(typeof field.attr('data-prompt-target') !== 'undefined' && $('#'+field.attr('data-prompt-target')).length > 0) { | ||
|  | 					prompt.appendTo($('#'+field.attr('data-prompt-target'))); | ||
|  | 				} else { | ||
|  | 					field.after(prompt); | ||
|  | 				} | ||
|  | 			} else { | ||
|  | 				field.before(prompt);				 | ||
|  | 			} | ||
|  | 			 | ||
|  | 			var pos = methods._calculatePosition(field, prompt, options); | ||
|  | 			prompt.css({ | ||
|  | 				'position': positionType === 'inline' ? 'relative' : 'absolute', | ||
|  | 				"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, .validationEngineContainer').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; | ||
|  | 					break; | ||
|  | 				case "inline": | ||
|  | 					promptleftPosition = 0; | ||
|  | 					promptTopPosition = 0; | ||
|  | 					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, "_"); | ||
|  | 					  }, | ||
|  | 		/** | ||
|  | 		 * Escape special character for jQuery selector | ||
|  | 		 * http://totaldev.com/content/escaping-characters-get-valid-jquery-id
 | ||
|  | 		 * @param {String} selector | ||
|  | 		 */ | ||
|  | 		 _jqSelector: function(str){ | ||
|  | 			return str.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1'); | ||
|  | 		}, | ||
|  | 		/** | ||
|  | 		* 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 | ||
|  | 				 * Indicate this special use by setting the last parameter to true so we only validate the dependingField on chackboxes and radio buttons (#462) | ||
|  | 				 */ | ||
|  | 				if (dependingField.length && methods._required(dependingField, ["required"], 0, options, true) == 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); | ||
|  | 				} | ||
|  | 			} | ||
|  | 		}, | ||
|  | 
 | ||
|  | 	    _submitButtonClick: function(event) { | ||
|  | 	        var button = $(this); | ||
|  | 	        var form = button.closest('form, .validationEngineContainer'); | ||
|  | 	        form.data("jqv_submitButton", button.attr("id")); | ||
|  | 	    } | ||
|  | 		  }; | ||
|  | 
 | ||
|  | 	 /** | ||
|  | 	 * 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, | ||
|  | 		// Show prompts, set to false to disable prompts
 | ||
|  | 		showPrompts: true, | ||
|  |        // Should we attempt to validate non-visible input fields contained in the form? (Useful in cases of tabbed containers, e.g. jQuery-UI tabs)
 | ||
|  |        validateNonVisibleFields: false, | ||
|  | 		// Opening box position, possible locations are: topLeft,
 | ||
|  | 		// topRight, bottomLeft, centerRight, bottomRight, inline
 | ||
|  | 		// inline gets inserted after the validated field or into an element specified in data-prompt-target
 | ||
|  | 		promptPosition: "topRight", | ||
|  | 		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, | ||
|  | 		// Limit how many displayed errors a field can have
 | ||
|  | 		maxErrorsPerField: 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: [], | ||
|  | 		onFieldSuccess: false, | ||
|  | 		onFieldFailure: false, | ||
|  | 		onSuccess: false, | ||
|  | 		onFailure: false, | ||
|  | 		validateAttribute: "class", | ||
|  | 		addSuccessCssClassToField: "", | ||
|  | 		addFailureCssClassToField: "", | ||
|  | 		 | ||
|  | 		// 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, | ||
|  | 	 // Add css class on prompt
 | ||
|  | 	 addPromptClass : "", | ||
|  | 	 // 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); | ||
|  | 
 | ||
|  | 
 |