PageSourceSearch

http://multtherapy.ru/js/jquery.validationEngine.js

js multtherapy.ru collected 2026-10-04 16:55:02 UTC 68,302 bytes, 1,673 lines download raw bytes

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

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