PageSourceSearch

https://www.e-nformation.ro/wp-content/plugins/wp-eMember/js/jquery.validationEngine.js

js e-nformation.ro collected 2026-09-24 10:36:50 UTC 48,037 bytes, 1,199 lines download raw bytes

1/*
2 * Inline Form Validation Engine 2.1, jQuery plugin
3 *
4 * Copyright(c) 2010, Cedric Dugas
5 * http://www.position-absolute.com
6 *
7 * 2.0 Rewrite by Olivier Refalo
8 * http://www.crionics.com
9 *
10 * Form validation engine allowing custom regex rules to be added.
11 * Licensed under the MIT License
12 */
13(function($) {
14
15    var methods = {
16        /**
17         * Kind of the constructor, called before any action
18         * @param {Map} user options
19         */
20        init: function(options) {
21            var form = this;
22            if (!form.data('jqv') || form.data('jqv') == null) {
23                methods._saveOptions(form, options);
24
25                // bind all formError elements to close on click
26                $(".formError").live("click", function() {
27                    $(this).fadeOut(150, function() {
28
29                        // remove prompt once invisible
30                        $(this).remove();
31                    });
32                });
33            }
34        },
35        /**
36         * Attachs jQuery.validationEngine to form.submit and field.blur events
37         * Takes an optional params: a list of options
38         * ie. jQuery("#formID1").validationEngine('attach', {promptPosition : "centerRight"});
39         */
40        attach: function(userOptions) {
41            var form = this;
42            var options;
43
44            if (userOptions)
45                options = methods._saveOptions(form, userOptions);
46            else
47                options = form.data('jqv');
48
49            if (!options.binded) {
50                if (options.bindMethod == "bind") {
51                    // bind fields
52                    form.find("[class*=validate]:not([type=checkbox])").bind(options.validationEventTrigger, methods._onFieldEvent);
53                    form.find("[class*=validate][type=checkbox]").bind("click", methods._onFieldEvent);
54
55                    // bind form.submit
56                    form.bind("submit", methods._onSubmitEvent);
57                } else if (options.bindMethod == "live") {
58                    // bind fields with LIVE (for persistant state)
59                    form.find("[class*=validate]:not([type=checkbox])").live(options.validationEventTrigger, methods._onFieldEvent);
60                    form.find("[class*=validate][type=checkbox]").live("click", methods._onFieldEvent);
61
62                    // bind form.submit
63                    form.live("submit", methods._onSubmitEvent);
64                }
65
66                options.binded = true;
67            }
68
69        },
70        /**
71         * Unregisters any bindings that may point to jQuery.validaitonEngine
72         */
73        detach: function() {
74            var form = this;
75            var options = form.data('jqv');
76            if (options.binded) {
77
78                // unbind fields
79                form.find("[class*=validate]").not("[type=checkbox]").unbind(options.validationEventTrigger, methods._onFieldEvent);
80                form.find("[class*=validate][type=checkbox]").unbind("click", methods._onFieldEvent);
81                // unbind form.submit
82                form.unbind("submit", methods.onAjaxFormComplete);
83
84
85                // unbind live fields (kill)
86                form.find("[class*=validate]").not("[type=checkbox]").die(options.validationEventTrigger, methods._onFieldEvent);
87                form.find("[class*=validate][type=checkbox]").die("click", methods._onFieldEvent);
88                // unbind form.submit
89                form.die("submit", methods.onAjaxFormComplete);
90
91                form.removeData('jqv');
92            }
93        },
94        /**
95         * Validates the form fields, shows prompts accordingly.
96         * Note: There is no ajax form validation with this method, only field ajax validation are evaluated
97         *
98         * @return true if the form validates, false if it fails
99         */
100        validate: function() {
101            return methods._validateFields(this);
102        },
103        /**
104         * Validates one field, shows prompt accordingly.
105         * Note: There is no ajax form validation with this method, only field ajax validation are evaluated
106         *
107         * @return true if the form validates, false if it fails
108         */
109        validateField: function(el) {
110            var options = $(this).data('jqv');
111            return methods._validateField($(el), options);
112        },
113        /**
114         * Validates the form fields, shows prompts accordingly.
115         * Note: this methods performs fields and form ajax validations(if setup)
116         *
117         * @return true if the form validates, false if it fails, undefined if ajax is used for form validation
118         */
119        validateform: function() {
120            return methods._onSubmitEvent.call(this);
121        },
122        /**
123         * Displays a prompt on a element.
124         * Note that the element needs an id!
125         *
126         * @param {String} promptText html text to display type
127         * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
128         * @param {String} possible values topLeft, topRight, bottomLeft, centerRight, bottomRight
129         */
130        showPrompt: function(promptText, type, promptPosition, showArrow) {
131
132            var form = this.closest('form');
133            var options = form.data('jqv');
134            // No option, take default one
135            if (!options)
136                options = methods._saveOptions(this, options);
137            if (promptPosition)
138                options.promptPosition = promptPosition;
139            options.showArrow = showArrow == true;
140
141            methods._showPrompt(this, promptText, type, false, options);
142        },
143        /**
144         * Closes all error prompts on the page
145         */
146        hidePrompt: function() {
147            var promptClass = "." + methods._getClassName($(this).attr("id")) + "formError"
148            $(promptClass).fadeTo("fast", 0.3, function() {
149                $(this).remove();
150            });
151        },
152        /**
153         * Closes form error prompts, CAN be invidual
154         */
155        hide: function() {
156            if ($(this).is("form")) {
157                var closingtag = "parentForm" + $(this).attr('id');
158            } else {
159
160                var closingtag = $(this).attr('id') + "formError"
161            }
162            $('.' + closingtag).fadeTo("fast", 0.3, function() {
163                $(this).remove();
164            });
165        },
166        /**
167         * Closes all error prompts on the page
168         */
169        hideAll: function() {
170            $('.formError').fadeTo("fast", 0.3, function() {
171                $(this).remove();
172            });
173        },
174        /**
175         * Typically called when user exists a field using tab or a mouse click, triggers a field
176         * validation
177         */
178        _onFieldEvent: function() {
179            var field = $(this);
180            var form = field.closest('form');
181            var options = form.data('jqv');
182            // validate the current field
183            methods._validateField(field, options);
184        },
185        /**
186         * Called when the form is submited, shows prompts accordingly
187         *
188         * @param {jqObject}
189         *            form
190         * @return false if form submission needs to be cancelled
191         */
192        _onSubmitEvent: function() {
193            var form = $(this);
194            var options = form.data('jqv');
195
196            // validate each field (- skip field ajax validation, no necessary since we will perform an ajax form validation)
197            var r = methods._validateFields(form, true);
198
199            if (r && options.ajaxFormValidation) {
200                methods._validateFormWithAjax(form, options);
201                return false;
202            }
203
204            if (options.onValidationComplete) {
205                options.onValidationComplete(form, r);
206                return false;
207            }
208            return r;
209        },
210        /**
211         * Return true if the ajax field validations passed so far
212         * @param {Object} options
213         * @return true, is all ajax validation passed so far (remember aja
213x is async)
214         */
215        _checkAjaxStatus: function(options) {
216            var status = true;
217            $.each(options.ajaxValidCache, function(key, value) {
218                if (!value) {
219                    status = false;
220                    // break the each
221                    return false;
222                }
223            });
224            return status;
225        },
226        /**
227         * Validates form fields, shows prompts accordingly
228         *
229         * @param {jqObject}
230         *            form
231         * @param {skipAjaxFieldValidation}
232         *            boolean - when set to true, ajax field validation is skipped, typically used when the submit button is clicked
233         *
234         * @return true if form is valid, false if not, undefined if ajax form validation is done
235         */
236        _validateFields: function(form, skipAjaxValidation) {
237            var options = form.data('jqv');
238
239            // this variable is set to true if an error is found
240            var errorFound = false;
241
242            // Trigger hook, start validation
243            form.trigger("jqv.form.validating")
244            // first, evaluate status of non ajax fields
245            form.find('[class*=validate]').not(':hidden').each(function() {
246                var field = $(this);
247                errorFound |= methods._validateField(field, options, skipAjaxValidation);
248            });
249            // second, check to see if all ajax calls completed ok
250            // errorFound |= !methods._checkAjaxStatus(options);
251
252            // thrird, check status and scroll the container accordingly
253            form.trigger("jqv.form.result", [errorFound])
254
255            if (errorFound) {
256
257                if (options.scroll) {
258
259                    // get the position of the first error, there should be at least one, no need to check this
260                    //var destination = form.find(".formError:not('.greenPopup'):first").offset().top;
261
262                    // look for the visually top prompt
263                    var destination = Number.MAX_VALUE;
264
265                    var lst = $(".formError:not('.greenPopup')");
266                    for (var i = 0; i < lst.length; i++) {
267                        var d = $(lst[i]).offset().top;
268                        if (d < destination)
269                            destination = d;
270                    }
271
272                    if (!options.isOverflown)
273                        $("html:not(:animated),body:not(:animated)").animate({
274                            scrollTop: destination
275                        }, 1100);
276                    else {
277                        var overflowDIV = $(options.overflownDIV);
278                        var scrollContainerScroll = overflowDIV.scrollTop();
279                        var scrollContainerPos = -parseInt(overflowDIV.offset().top);
280
281                        destination += scrollContainerScroll + scrollContainerPos - 5;
282                        var scrollContainer = $(options.overflownDIV + ":not(:animated)");
283
284                        scrollContainer.animate({
285                            scrollTop: destination
286                        }, 1100);
287                    }
288                }
289                return false;
290            }
291            return true;
292        },
293        /**
294         * This method is called to perform an ajax form validation.
295         * During this process all the (field, value) pairs are sent to the server which returns a list of invalid fields or true
296         *
297         * @param {jqObject} form
298         * @param {Map} options
299         */
300        _validateFormWithAjax: function(form, options) {
301
302            var data = form.serialize();
303            var url = (options.ajaxFormValidationURL) ? options.ajaxFormValidationURL : form.attr("action");
304            $.ajax({
305                type: "GET",
306                url: url,
307                cache: false,
308                dataType: "json",
309                data: data,
310                form: form,
311                methods: methods,
312                options: options,
313                beforeSend: function() {
314                    return options.onBeforeAjaxFormValidation(form, options);
315                },
316                error: function(data, transport) {
317                    methods._ajaxError(data, transport);
318                },
319                success: function(json) {
320
321                    if (json !== true) {
322
323                        // getting to this case doesn't necessary means that the form is invali
323d
324                        // the server may return green or closing prompt actions
325                        // this flag helps figuring it out
326                        var errorInForm = false;
327                        for (var i = 0; i < json.length; i++) {
328                            var value = json[i];
329
330                            var errorFieldId = value[0];
331                            var errorField = $($("#" + errorFieldId)[0]);
332
333                            // make sure we found the element
334                            if (errorField.length == 1) {
335
336                                // promptText or selector
337                                var msg = value[2];
338                                // if the field is valid
339                                if (value[1] == true) {
340
341                                    if (msg == "" || !msg) {
342                                        // if for some reason, status==true and error="", just close the prompt
343                                        methods._closePrompt(errorField);
344                                    } else {
345                                        // the field is valid, but we are displaying a green prompt
346                                        if (options.allrules[msg]) {
347                                            var txt = options.allrules[msg].alertTextOk;
348                                            if (txt)
349                                                msg = txt;
350                                        }
351                                        methods._showPrompt(errorField, msg, "pass", false, options, true);
352                                    }
353
354                                } else {
355                                    // the field is invalid, show the red error prompt
356                                    errorInForm |= true;
357                                    if (options.allrules[msg]) {
358                                        var txt = options.allrules[msg].alertText;
359                                        if (txt)
360                                            msg = txt;
361                                    }
362                                    methods._showPrompt(errorField, msg, "", false, options, true);
363                                }
364                            }
365                        }
366                        options.onAjaxFormComplete(!errorInForm, form, json, options);
367                    } else
368                        options.onAjaxFormComplete(true, form, "", options);
369                }
370            });
371
372        },
373        /**
374         * Validates field, shows prompts accordingly
375         *
376         * @param {jqObject}
377         *            field
378         * @param {Array[String]}
379         *            field's validation rules
380         * @param {Map}
381         *            user options
382         * @return true if field is valid
383         */
384        _validateField: function(field, options, skipAjaxValidation) {
385            if (!field.attr("id"))
386                $.error("jQueryValidate: an ID attribute is required for this field: " + field.attr("name") + " class:" +
387                        field.attr("class"));
388
389            var rulesParsing = field.attr('class');
390            var getRules = /validate\[(.*)\]/.exec(rulesParsing);
391            if (!getRules)
392                return false;
393            var str = getRules[1];
394            var rules = str.split(/\[|,|\]/);
395
396            // true if we ran the ajax validation, tells the logic to stop messing with prompts
397            var isAjaxValidator = false;
398            var fieldName = field.attr("name");
399            var promptText = "";
400            var required = false;
401            var equals = true;
402            options.isError = false;
403            options.showArrow = true;
404            optional = false;
405
406            for (var i = 0; i < rules.length; i++) {
407
408                var errorMsg = undefined;
409                switch (rules[i]) {
410
411                    case "optional":
412                        optional = true;
413                        break;
414                    case "required":
415                        required = true;
416                        errorMsg = methods._required(field, rules, i, options);
417                        break;
418                    case "custom":
419                        errorMsg = methods._customRegex(field, rules, i, options);
420                        break;
421                    case "ajax":
422                        // ajax has its own prompts handling technique
423                        if (!skipAjaxValidation) {
424                            methods._ajax(field, rules, i, options);
425                            isAjaxValidator = true;
426                        }
427                        break;
428                    case "minSize":
429                        errorMsg = methods._minSize(field, rules, i, options);
430                        break;
431                    case "maxSize":
432                        errorMsg = methods._maxSize(field, rules, i, options);
433                        break;
434                    case "min":
435                        errorMsg = methods._min(field, rules, i, options);
436                        break;
437                    case "max":
438                        errorMsg = methods._max(field, rules, i, options);
439                        break;
440                    case "past":
441                        errorMsg = methods._past(field, rules, i, options);
442                        break;
443                    case "future":
444                        errorMsg = methods._future(field, rules, i, options);
445                        break;
446                    case "maxCheckbox":
447                        errorMsg = methods._maxCheckbox(field, rules, i, options);
448                        field = $($("input[name='" + fieldName + "']"));
449                        break;
450                    case "minCheckbox":
451                        errorMsg = methods._minCheckbox(field, rules, i, options);
452                        field = $($("input[name='" + fieldName + "']"));
453                        break;
454                    case "equals":
455                        errorMsg = methods._equals(field, rules, i, options);
456                        if (errorMsg !== undefined)
457                            equals = false;
458                        break;
459                    case "funcCall":
460                        errorMsg = methods._funcCall(field, rules, i, options);
461                        break;
462
463                    default:
464                        //$.error("jQueryValidator rule not found"+rules[i]);
465                }
466
467                if (errorMsg !== undefined) {
468                    promptText += errorMsg + "<br/>";
469                    options.isError = true;
470
471                }
472
473            }
474            // If the rules required is not added, an empty field is not validated
475            if (!required) {
476                if (field.val() == "")
477                    options.isError = false;
478            }
479            // Hack for radio/checkbox group button, the validation go into the
480            // first radio/checkbox of the group
481            var fieldType = field.attr("type");
482
483            if ((fieldType == "radio" || fieldType == "checkbox") && $("input[name='" + fieldName + "']").size() > 1) {
484                field = $($("input[name='" + fieldName + "'][type!=hidden]:first"));
485                options.showArrow = false;
486            }
487
488            if (options.isError || !equals) {
489
490                methods._showPrompt(field, promptText, "", false, options);
491            } else {
492                if (!isAjaxValidator)
493                    methods._closePrompt(field);
494            }
495            field.closest('form').trigger("jqv.field.error", [field, options.isError, promptText])
496            return options.isError || (!equals);
497        },
498        /**
499         * Required validation
500         *
501         * @param {jqObject} field
502         * @param {Array[String]} rules
503         * @param {int} i rules index
504         * @param {Map}
505         *            user options
506         * @return an error string if validation failed
507         */
508        _required: function(field, rules, i, options) {
509            switch (field.attr("type")) {
510                case "text":
511                case "password":
512                case "textarea":
513                case "file":
514                default:
515                    if (!field.val())
516                        return options.allrules[rules[i]].alertText;
517                    break;
518                case "radio":
519                case "checkbox":
520                    var name = field.attr("name");
521                    if ($("input[name='" + name + "']:checked").size() == 0) {
522
523                        if ($("input[name='" + name + "']").size() == 1)
524                            return options.allrules[rules[i]].alertTextCheckboxe;
525                        else
526                            return options.allrules[rules[i]].alertTextCheckboxMultiple;
527                    }
528                    break;
529                    // required for <select>
530                case "select-one":
531                    // added by [email protected] for select boxes, Thank y
531ou
532                    if (!field.val())
533                        return options.allrules[rules[i]].alertText;
534                    break;
535                case "select-multiple":
536                    // added by [email protected] for select boxes, Thank you
537                    if (!field.find("option:selected").val())
538                        return options.allrules[rules[i]].alertText;
539                    break;
540            }
541        },
542        /**
543         * Validate Regex rules
544         *
545         * @param {jqObject} field
546         * @param {Array[String]} rules
547         * @param {int} i rules index
548         * @param {Map}
549         *            user options
550         * @return an error string if validation failed
551         */
552        _customRegex: function(field, rules, i, options) {
553            var customRule = rules[i + 1];
554            var rule = options.allrules[customRule];
555            if (!rule) {
556                alert("jqv:custom rule not found " + customRule);
557                return;
558            }
559
560            var ex = rule.regex;
561            if (!ex) {
562                alert("jqv:custom regex not found " + customRule);
563                return;
564            }
565            var pattern = new RegExp(ex);
566
567            if (!pattern.test(field.attr('value')))
568                return options.allrules[customRule].alertText;
569        },
570        /**
571         * Validate custom function outside of the engine scope
572         *
573         * @param {jqObject} field
574         * @param {Array[String]} rules
575         * @param {int} i rules index
576         * @param {Map}
577         *            user options
578         * @return an error string if validation failed
579         */
580        _funcCall: function(field, rules, i, options) {
581            var functionName = rules[i + 1];
582            var fn = window[functionName];
583            if (typeof (fn) == 'function')
584                return fn(field, rules, i, options);
585
586        },
587        /**
588         * Field match
589         *
590         * @param {jqObject} field
591         * @param {Array[String]} rules
592         * @param {int} i rules index
593         * @param {Map}
594         *            user options
595         * @return an error string if validation failed
596         */
597        _equals: function(field, rules, i, options) {
598            var equalsField = rules[i + 1];
599
600            if (field.attr('value') != $("#" + equalsField).attr('value')) {
601                field.css('border', '1px solid red');
602                $("#" + equalsField).css('border', '1px solid red');
603                return options.allrules.equals.alertText;
604            }
605            else {
606                field.css('border', '');
607                $("#" + equalsField).css('border', '');
608            }
609
610        },
611        /**
612         * Check the maximum size (in characters)
613         *
614         * @param {jqObject} field
615         * @param {Array[String]} rules
616         * @param {int} i rules index
617         * @param {Map}
618         *            user options
619         * @return an error string if validation failed
620         */
621        _maxSize: function(field, rules, i, options) {
622            var max = rules[i + 1];
623            var len = field.attr('value').length;
624
625            if (len > max) {
626                var rule = options.allrules.maxSize;
627                return rule.alertText + max + rule.alertText2;
628            }
629        },
630        /**
631         * Check the minimum size (in characters)
632         *
633         * @param {jqObject} field
634         * @param {Array[String]} rules
635         * @param {int} i rules index
636         * @param {Map}
637         *            user options
638         * @return an error string if validation failed
639         */
640        _minSize: function(field, rules, i, options) {
641            var min = rules[i + 1];
642            var len = field.attr('value').length;
643
644            if (len < min) {
645                var rule = options.allrules.minSize;
646                return rule.alertText + min + rule.alertText2;
647            }
648        },
649        /**
650         * Check number minimum value
651         *
652         * @param {jqObject} field
653         * @param {Array[String]} rules
654         * @param {int} i rules index
655         * @param {Map}
656         *            user options
657         * @return an error string if validation failed
658         */
659        _min: function(field, rules, i, options) {
660            var min = parseFloat(rules[i + 1]);
661            var len = parseFloat(field.attr('value'));
662
663            if (len < min) {
664                var rule = options.allrules.min;
665                if (rule.alertText2)
666                    return rule.alertText + min + rule.alertText2;
667                return rule.alertText + min;
668            }
669        },
670        /**
671         * Check number maximum value
672         *
673         * @param {jqObject} field
674         * @param {Array[String]} rules
675         * @param {int} i rules index
676         * @param {Map}
677         *            user options
678         * @return an error string if validation failed
679         */
680        _max: function(field, rules, i, options) {
681            var max = parseFloat(rules[i + 1]);
682            var len = parseFloat(field.attr('value'));
683
684            if (len > max) {
685                var rule = options.allrules.max;
686                if (rule.alertText2)
687                    return rule.alertText + max + rule.alertText2;
688                //orefalo: to review, also do the translations
689                return rule.alertText + max;
690            }
691        },
692        /**
693         * Checks date is in the past
694         *
695         * @param {jqObject} field
696         * @param {Array[String]} rules
697         * @param {int} i rules index
698         * @param {Map}
699         *            user options
700         * @return an error string if validation failed
701         */
702        _past: function(field, rules, i, options) {
703
704            var p = rules[i + 1];
705            var pdate = (p.toLowerCase() == "now") ? new Date() : methods._parseDate(p);
706            var vdate = methods._parseDate(field.attr('value'));
707
708            if (vdate > pdate) {
709                var rule = options.allrules.past;
710                if (rule.alertText2)
711                    return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
712                return rule.alertText + methods._dateToString(pdate);
713            }
714        },
715        /**
716         * Checks date is in the past
717         *
718         * @param {jqObject} field
719         * @param {Array[String]} rules
720         * @param {int} i rules index
721         * @param {Map}
722         *            user options
723         * @return an error string if validation failed
724         */
725        _future: function(field, rules, i, options) {
726
727            var p = rules[i + 1];
728            var pdate = (p.toLowerCase() == "now") ? new Date() : methods._parseDate(p);
729            var vdate = methods._parseDate(field.attr('value'));
730
731            if (vdate < pdate) {
732                var rule = options.allrules.future;
733                if (rule.alertText2)
734                    return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
735                return rule.alertText + methods._dateToString(pdate);
736            }
737        },
738        /**
739         * Max number of checkbox selected
740         *
741         * @param {jqObject} field
742         * @param {Array[String]} rules
743         * @param {int} i rules index
744         * @param {Map}
745         *            user options
746         * @return an error string if validation failed
747         */
748        _maxCheckbox: function(field, rules, i, options) {
749
750            var nbCheck = rules[i + 1];
751            var groupname = field.attr("name");
752            var groupSize = $("input[name='" + groupname + "']:checked").size();
753            if (groupSize > nbCheck) {
754                options.showArrow = false;
755                return options.allrules.maxCheckbox.alertText;
756            }
757        },
758        /**
759         * Min number of checkbox selected
760         *
761         * @param {jqObject} field
762         * @param {Array[String]} rules
763         * @param {int} i rules index
764         * @param {Map}
765         *            user options
766         * @return an error string if validation failed
767         */
768        _minCheckbox: function(field, rules, i, options) {
769
770            var nbCheck = rules[i + 1];
771            var groupname = field.attr("name");
772            var groupSize = $("input[name='" + groupname + "']:checked").size();
773            if (groupSize < nbCheck) {
774                options.showArrow = false;
775                return options.allrules.minCheckbox.alertText + " " + nbCheck + " " +
776                        options.allrules.minCheckbox.alertText2;
777            }
778        },
779        /**
780         * Ajax field validation
781         *
782         * @param {jqObject} field
783         * @param {Array[String]} rules
784         * @param {int} i rules index
785         * @param {Map}
786         *            user options
787         * @return nothing! the ajax validator handles the prompts itself
788         */
789        _ajax: function(field, rules, i, options) {
790
791
792            var errorSelector = rules[i + 1];
793            var rule = options.allrules[errorSelector];
794            var extraData = rule.extraData;
795
796            if (!extraData)
797                extraData = "";
798
799            if (!options.isError) {
800                $.ajax({
801                    type: "GET",
802                    url: rule.url,
803                    cache: false,
804                    dataType: "json",
805                    data: "fieldId=" + field.attr("id") + "&fieldValue=" + field.attr("value") + "&extraData=" + extraData,
806                    field: field,
807                    rule: rule,
808                    methods: methods,
809                    options: options,
810                    beforeSend: function() {
811                        // build the loading prompt
812                        var loadingText = rule.alertTextLoad;
813                        if (loadingText)
814                            methods._showPrompt(field, loadingText, "load", true, options);
815                    },
816                    error: function(data, transport) {
817                        methods._ajaxError(data, transport);
818                    },
819                    success: function(json) {
820
821                        // asynchronously called on success, data is the json answer from the server
822                        var errorFieldId = json[0];
823                        var errorField = $($("#" + errorFieldId)[0]);
824                        // make sure we found the element
825                        if (errorField.length == 1) {
826                            var status = json[1];
827                            if (!status) {
828                                // Houston we got a problem
829                                options.ajaxValidCache[errorFieldId] = false;
830                                options.isError = true;
831                                var promptText = rule.alertText;
832                                methods._showPrompt(errorField, promptText, "", true, options);
833                            } else {
834                                if (options.ajaxValidCache[errorFieldId] !== undefined)
835                                    options.ajaxValidCache[errorFieldId] = true;
836
837                                // see if we should display a green prompt
838                                var alertTextOk = rule.alertTextOk;
839                                if (alertTextOk)
840                                    methods._showPrompt(errorField, alertTextOk, "pass", true, options);
841                                else
842                                    methods._closePrompt(errorField);
843                            }
844                        }
845                    }
846                });
847            }
848        },
849        /**
850         * Common method to handle ajax errors
851         *
852         * @param {Object} data
853         * @param {Object} transport
854         */
855        _ajaxError: function(data, transport) {
856            if (data.status == 0 && transport == null)
857                alert("The page is not served from a server! ajax call failed");
858            else if (typeof console != "undefined")
859                console.log("Ajax error: " + data.status + " " + transport);
860        },
861        /**
862         * date -> string
863         *
864         * @param {Object} date
865         */
866        _dateToString: function(date) {
867
868            return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
869        },
870        /**
871         * Parses an ISO date
872         * @param {String} d
873         */
874        _parseDate: function(d) {
875
876            var dateParts = d.split("-");
877            if (dateParts !== d)
878                dateParts = d.split("/");
879            return new Date(dateParts[0], (dateParts[1] - 1), dateParts[2]);
880        },
881        /**
882         * Builds or updates a prompt with the given information
883         *
884         * @param {jqObject} field
885         * @param {String} promptText html text to display type
886         * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
887         * @param {boolean} ajaxed - use to mark fields than being validated with ajax
888         * @param {Map} options user options
889         */
890        _showPrompt: function(field, promptText, type, ajaxed, options, ajaxform) {
891            var prompt = methods._getPrompt(field);
892            // The ajax submit errors are not see has an error in the form,
893            // When the form errors are returned, the engine see 2 bubbles, but those are ebing closed by the engine at the same time
894            // Because no error was found befor submitting
895            if (ajaxform)
896                prompt = false;
897            if (prompt)
898                methods._updatePrompt(field, prompt, promptText, type, ajaxed, options);
899            else
900                methods._buildPrompt(field, promptText, type, ajaxed, options);
901        },
902        /**
903         * Builds and shades a prompt for the given field.
904         *
905         * @param {jqObject} field
906         * @param {String} promptText html text to display type
907         * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
908         * @param {boolean} ajaxed - use to mark fields than being validated with ajax
909         * @param {Map} options user options
910         */
911        _buildPrompt: function(field, promptText, type, ajaxed, options) {
912
913            // create the prompt
914            var prompt = $('<div>');
915            prompt.addClass(methods._getClassName(field.attr("id")) + "formError");
916            // add a class name to identify the parent form of the prompt
917            if (field.is(":input"))
918                prompt.addClass("parentForm" + methods._getClassName(field.parents('form').attr("id")));
919            prompt.addClass("formError");
920
921            switch (type) {
922                case "pass":
923                    prompt.addClass("greenPopup");
924                    break;
925                case "load":
926                    prompt.addClass("blackPopup");
927            }
928            if (ajaxed)
929                prompt.addClass("ajaxed");
930
931            // create the prompt content
932            var promptContent = $('<div>').addClass("formErrorContent").html(promptText).appendTo(prompt);
933            // create the css arrow pointing at the field
934            // note that there is no triangle on max-checkbox and radio
935            if (options.showArrow) {
936                var arrow = $('<div>').addClass("formErrorArrow");
937
938                switch (options.promptPosition) {
939                    case "bottomLeft":
940                    case "bottomRight":
941                        prompt.find(".formErrorContent").before(arrow);
942                        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>');
943                        break;
944                    case "topLeft":
945                    case "topRight":
946                        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>');
947                        prompt.append(arrow);
948                        break;
949                }
950            }
951
952            //Cedric: Needed if a container is in position:relative
953            // insert prompt in the form or in the overflown container?
954            if (options.isOverflown)
955                field.before(prompt);
956            else
957                $("body").append(prompt);
958
959            var pos = methods._calculatePosition(field, prompt, options);
960            prompt.css({
961                "top": pos.callerTopPosition,
962                "left": pos.callerleftPosition,
963                "marginTop": pos.marginTopSize,
964                "opacity": 0
965            });
966
967            return prompt.animate({
968                "opacity": 0.87
969            });
970
971        },
972        /**
973         * Updates the prompt text field - the field for which the prompt
974         * @param {jqObject} field
975         * @param {String} promptText html text to display type
976         * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
977         * @param {boolean} ajaxed - use to mark fields than being validated with ajax
978         * @param {Map} options user options
979         */
980        _updatePrompt: function(field, prompt, promptText, type, ajaxed, options) {
981
982            if (prompt) {
983                if (type == "pass")
984                    prompt.addClass("greenPopup");
985                else
986                    prompt.removeClass("greenPopup");
987
988                if (type == "load")
989                    prompt.addClass("blackPopup");
990                else
991                    prompt.removeClass("blackPopup");
992
993                if (ajaxed)
994                    prompt.addClass("ajaxed");
995                else
996                    prompt.removeClass("ajaxed");
997
998                prompt.find(".formErrorContent").html(promptText);
999
1000                var pos = methods._calculatePosition(field, prompt, options);
1001                prompt.animate({
1002                    "top": pos.callerTopPosition,
1003                    "marginTop": pos.marginTopSize
1004                });
1005            }
1006        },
1007        /**
1008         * Closes the prompt associated with the given field
1009         *
1010         * @param {jqObject}
1011         *            field
1012         */
1013        _closePrompt: function(field) {
1014
1015            var prompt = methods._getPrompt(field);
1016            if (prompt)
1017                prompt.fadeTo("fast", 0, function() {
1018                    prompt.remove();
1019                });
1020        },
1021        closePrompt: function(field) {
1022            return methods._closePrompt(field);
1023        },
1024        /**
1025         * Returns the error prompt matching the field if any
1026         *
1027         * @param {jqObject}
1028         *            field
1029         * @return undefined or the error prompt (jqObject)
1030         */
1031        _getPrompt: function(field) {
1032
1033            var className = "." + methods._getClassName(field.attr("id")) + "formError";
1034            var match = $(className)[0];
1035            if (match)
1036                return $(match);
1037        },
1038        /**
1039         * Calculates prompt position
1040         *
1041         * @param {jqObject}
1042         *            field
1043         * @param {jqObject}
1044         *            the prompt
1045         * @param {Map}
1046         *            options
1047         * @return positions
1048         */
1049        _calculatePosition: function(field, promptElmt, options) {
1050
1051            var promptTopPosition, promptleftPosition, marginTopSize;
1052            var fieldWidth = field.width();
1053            var promptHeight = promptElmt.height();
1054
1055            var overflow = options.isOverflown;
1056            if (overflow) {
1057                // is the form contained in an overflown container?
1058                promptTopPosition = promptleftPosition = 0;
1059                // compensation for the arrow
1060                marginTopSize = -promptHeight;
1061            } else {
1062                var offset = field.offset();
1063                promptTopPosition = offset.top;
1064                promptleftPosition = offset.left;
1065                marginTopSize = 0;
1066            }
1067
1068            switch (options.promptPosition) {
1069
1070                default:
1071                case "topRight":
1072                    if (overflow)
1073                        // Is the form contained in an overflown container?
1074                        promptleftPosition += fieldWidth - 30;
1075                    else {
1076                        promptleftPosition += fieldWidth - 30;
1077                        promptTopPosition += -promptHeight;
1078                    }
1079                    break;
1080                case "topLeft":
1081                    promptTopPosition += -promptHeight - 10;
1082                    break;
1083                case "centerRight":
1084                    promptleftPosition += fieldWidth + 13;
1085                    break;
1086                case "bottomLeft":
1087                    promptTopPosition = promptTopPosition + field.height() + 15;
1088                    break;
1089                case "bottomRight":
1090                    promptleftPosition += fieldWidth - 30;
1091                    promptTopPosition += field.height() + 5;
1092            }
1093
1094            return {
1095                "callerTopPosition": promptTopPosition + "px",
1096                "callerleftPosition": promptleftPosition + "px",
1097                "marginTopSize": marginTopSize + "px"
1098            };
1099        },
1100        /**
1101         * Saves the user options and variables in the form.data
1102         *
1103         * @param {jqObject}
1104         *            form - the form where the user option should be saved
1105         * @param {Map}
1106         *            options - the user options
1107         * @return the user options (extended from the defaults)
1108         */
1109        _saveOptions: function(form, options) {
1110
1111            // is there a language localisation ?
1112            if ($.validationEngineLanguage)
1113                var allRules = $.validationEngineLanguage.allRules;
1114            else
1115                $.error("jQuery.validationEngine rules are not loaded, plz add localization files to the page");
1116
1117            var userOptions = $.extend({
1118                // Name of the event triggering field validation
1119                validationEventTrigger: "blur",
1120                // Automatically scroll viewport to the first error
1121                scroll: true,
1122                // Opening box position, possible locations are: topLeft,
1123                // topRight, bottomLeft, centerRight, bottomRight
1124                promptPosition: "topRight",
1125                bindMethod: "bind",
1126                // internal, automatically set to true when it parse a _ajax rule
1127                inlineAjax: false,
1128                // if set to true, the form data is sent asynchronously via ajax to the form.action url (get)
1129                ajaxFormValidation: false,
1130                // Ajax form validation callback method: boolean onComplete(form, status, errors, options)
1131                // retuns false if the form.submit event needs to be canceled.
1132                ajaxFormValidationURL: false,
1133                // The url to send the submit ajax validation (default to action)
1134                onAjaxFormComplete: $.noop,
1135                // called right before the ajax call, may return false to cancel
1136                onBeforeAjaxFormValidation: $.noop,
1137                // Stops form from submitting and execute function assiciated with it
1138                onValidationComplete: false,
1139                // Used when the form is displayed within a scrolling DIV
1140                isOverflown: false,
1141                overflownDIV: "",
1142                // --- Internals DO NOT TOUCH or OVERLOAD ---
1143                // validation rules and i18
1144                allrules: allRules,
1145                // true when form and fields are binded
1146                binded: false,
1147                // set to true, when the prompt arrow needs to be displayed
1148                showArrow: true,
1149                // did one of the validation fail ? kept global to stop further ajax validations
1150                isError: false,
1151                // Caches field validation status, typically only bad status are created.
1152                // the array is used during ajax form validation to detect issues early and prevent an expensive submit
1153                ajaxValidCache: {}
1154
1155            }, options);
1156
1157            form.data('jqv', userOptions);
1158            return userOptions;
1159        },
1160        /**
1161         * Removes forbidden characters from class name
1162         * @param {String} className
1163         */
1164        _getClassName: function(className) {
1165            return className.replace(":", "_").replace(".", "_");
1166        }
1167    };
1168
1169    /**
1170     * Plugin entry point.
1171     * You may pass an action as a parameter or a list of options.
1172     * if none, the init and attach methods are being called.
1173     * Remember: if you pass options, the attached method is NOT called automatically
1174     *
1175     * @param {String}
1176     *            method (optional) action
1177     */
1178    $.fn.validationEngine = function(method) {
1179
1180        var form = $(this);
1181        if (!form[0])
1182            return false;  // stop here if the form does not exist
1183
1184        if (typeof (method) == 'string' && method.charAt(0) != '_' && methods[method]) {
1185
1186            // make sure init is called once
1187            if (method != "showPrompt" && method != "hidePrompt" && method != "hide" && method != "hideAll")
1188                methods.init.apply(form);
1189
1190            return methods[method].apply(form, Array.prototype.slice.call(arguments, 1));
1191        } else if (typeof method == 'object' || !method) {
1192            // default constructor with or without arguments
1193            methods.init.apply(form, arguments);
1194            return methods.attach.apply(form);
1195        } else {
1196            $.error('Method ' + method + ' does not exist in jQuery.validationEngine');
1197        }
1198    };
1199})(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.