PageSourceSearch

https://www.wikitimbres.fr/public/assets/js/jquery.validationEngine.js

js wikitimbres.fr collected 2026-10-02 10:26:56 UTC 61,024 bytes, 1,527 lines download raw bytes

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