PageSourceSearch

https://www.wiggensbach.de/DesktopModules/DNNGo_xNews/Resource/js/jquery.validationEngine.js?cdv=1062

js wiggensbach.de collected 2026-10-02 21:23:49 UTC 92,013 bytes, 2,066 lines download raw bytes

1/*
2* Inline Form Validation Engine 2.6.2, 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    "use strict";
16
17    var methods = {
18
19        /**
20        * Kind of the constructor, called before any action
21        * @param {Map} user options
22        */
23        init: function (options) {
24
25            var form = this;
26            if (!form.data('jqv') || form.data('jqv') == null) {
27                options = methods._saveOptions(form, options);
28                // bind all formError elements to close on click
29                $(document).on("click", ".formError", function () {
30                    $(this).fadeOut(150, function () {
31                        // remove prompt once invisible
32                        $(this).parent('.formErrorOuter').remove();
33                        $(this).remove();
34                    });
35                });
36            }
37            return this;
38        },
39        /**
40        * Attachs jQuery.validationEngine to form.submit and field.blur events
41        * Takes an optional params: a list of options
42        * ie. jQuery("#formID1").validationEngine('attach', {promptPosition : "centerRight"});
43        */
44        attach: function (userOptions) {
45
46            var form = this;
47            var options;
48
49            if (userOptions)
50                options = methods._saveOptions(form, userOptions);
51            else
52                options = form.data('jqv');
53
54            options.validateAttribute = (form.find("[data-validation-engine*=validate]").length) ? "data-validation-engine" : "class";
55            if (options.binded) {
56
57                // delegate fields
58                form.on(options.validationEventTrigger, "[" + options.validateAttribute + "*=validate]:not([type=checkbox]):not([type=radio]):not(.datepicker)", methods._onFieldEvent);
59                form.on("click", "[" + options.validateAttribute + "*=validate][type=checkbox],[" + options.validateAttribute + "*=validate][type=radio]", methods._onFieldEvent);
60                form.on(options.validationEventTrigger, "[" + options.validateAttribute + "*=validate][class*=datepicker]", { "delay": 300 }, methods._onFieldEvent);
61            }
62            if (options.autoPositionUpdate) {
63                $(window).bind("resize", {
64                    "noAnimation": true,
65                    "formElem": form
66                }, methods.updatePromptsPosition);
67            }
68            form.on("click", "a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick);
69            form.removeData('jqv_submitButton');
70
71            // bind form.submit
72            form.on("submit", methods._onSubmitEvent);
73            return this;
74        },
75        /**
76        * Unregisters any bindings that may point to jQuery.validaitonEngine
77        */
78        detach: function () {
79
80            var form = this;
81            var options = form.data('jqv');
82
83            // unbind fields
84            form.find("[" + options.validateAttribute + "*=validate]").not("[type=checkbox]").off(options.validationEventTrigger, methods._onFieldEvent);
85            form.find("[" + options.validateAttribute + "*=validate][type=checkbox],[class*=validate][type=radio]").off("click", methods._onFieldEvent);
86
87            // unbind form.submit
88            form.off("submit", methods._onSubmitEvent);
89            form.removeData('jqv');
90
91            form.off("click", "a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick);
92            form.removeData('jqv_submitButton');
93
94            if (options.autoPositionUpdate)
95                $(window).off("resize", methods.updatePromptsPosition);
96
97            return this;
98        },
99        /**
100        * Validates either a form or a list of fields, shows prompts accordingly.
101        * Note: There is no ajax form validation with this method, only field ajax validation are evaluated
102        *
103        * @return true if the form validates, false if it fails
104        */
105        validate: function () {
106
107            var element = $(this);
108            var valid = null;
109
110            if (element.is("form") || element.hasClass("validationEngineContainer")) {
111
112                if (element.hasClass('validating')) {
113
114                    // form is already validating.
115                    // Should abort old validation and start new one. I don't know how to implement it.
116                    return false;
117                } else {
118                    element.addClass('validating');
119                    var options = element.data('jqv');
120                    var valid = methods._validateFields(this);
121
122                    // If the form doesn't validate, clear the 'validating' class before the user has a chance to submit again
123                    setTimeout(function () {
124                        element.removeClass('validating');
125                    }, 100);
126                    if (valid && options.onSuccess) {
127                        options.onSuccess();
128                    } else if (!valid && options.onFailure) {
129                        options.onFailure();
130                    }
131                }
132            } else if (element.is('form') || element.hasClass('validationEngineContainer')) {
133                element.removeClass('validating');
134            } else {
135                // field validation
136                var form = element.closest('form, .validationEngineContainer'),
137					options = (form.data('jqv')) ? form.data('jqv') : $.validationEngine.defaults,
138					valid = methods._validateField(element, options);
139                if (valid && options.onFieldSuccess)
140                    options.onFieldSuccess();
141                else if (options.onFieldFailure && options.InvalidFields.length > 0) {
142                    options.onFieldFailure();
143                }
144            }
145            if (options.onValidationComplete) {
146                // !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing
147                return !!options.onValidationComplete(form, valid);
148            }
149            return valid;
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;
158                var noAnimation = event.data.noAnimation;
159            }
160            else
161                var form = $(this.closest('form, .validationEngineContainer'));
162
163            var options = form.data('jqv');
164            // No option, take default one
165            form.find('[' + options.validateAttribute + '*=validate]').not(":disabled").each(function () {
166                var field = $(this);
167                if (options.prettySelect && field.is(":hidden"))
168                    field = form.find("#" + options.usePrefix + field.attr('id') + options.useSuffix);
169                var prompt = methods._getPrompt(field);
170                var promptText = $(prompt).find(".formErrorContent").html();
171
172                if (prompt)
173                    methods._updatePrompt(field, $(prompt), promptText, undefined, false, options, noAnimation);
174            });
175            return this;
176        },
177        /**
178        * Displays a prompt on a element.
179        * Note that the element needs an id!
180        *
181        * @param {String} promptText html text to display type
182        * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
183        * @param {String} possible values topLeft, topRight, bottomLeft, centerRight, bottomRight
184        */
185        showPrompt: function (promptText, type, promptPosition, showArrow) {
186            var form = this.closest('form, .validationEngineContainer');
187            var options = form.data('jqv');
188            // No option, take default one
189            if (!options)
190                options = methods._saveOptions(this, options);
191            if (promptPosition)
192                options.promptPosition = promptPosition;
193            options.showArrow = showArrow == true;
194
195            methods._showPrompt(this, promptText, type, false, options);
196            return this;
197        },
198        /**
199        * Closes form error prompts, CAN be invidual
200        */
201        hide: function () {
202            var form = $(this).closest('form, .validationEngineContainer');
203            var options = form.data('jqv');
204            var fadeDuration = (options && options.fadeDuration) ? options.fadeDuration : 0.3;
205            var closingtag;
206
207            if ($(this).is("form") || $(this).hasClass("validationEngineContainer")) {
208                closingtag = "parentForm" + methods._getClassName($(this).attr("id"));
209            } else {
210                closingtag = methods._getClassName($(this).attr("id")) + "formError";
211            }
212            $('.' + closingtag).fadeTo(fadeDuration, 0.3, function () {
213                $(this).parent('.formErrorOuter').remove();
214                $(this).remove();
215            });
216            return this;
217        },
218        /**
219        * Closes all error prompts on the page
220        */
221        hideAll: function () {
222
223            var form = this;
224            var options = form.data('jqv');
225            var duration = options ? options.fadeDuration : 300;
226            $('.formError').fadeTo(duration, 300, function () {
227                $(this).parent('.formErrorOuter').remove();
228                $(this).remove();
229            });
230            return this;
231        },
232        /**
233        * Typically called when user exists a field using tab or a mouse click, triggers a field
234        * validation
235        */
236        _onFieldEvent: function (event) {
237            var field = $(this);
238            var form = field.closest('form, .validationEngineContainer');
239            var options = form.data('jqv');
240            options.eventTrigger = "field";
241            // validate the current field
242            window.setTimeout(function () {
243                methods._validateField(field, options);
244                if (options.InvalidFields.length == 0 && options.onFieldSuccess) {
245                    options.onFieldSuccess();
246                } else if (options.InvalidFields.length > 0 && options.onFieldFailure) {
247                    options.onFieldFailure();
248                }
249            }, (event.data) ? event.data.delay : 0);
250
251        },
252        /**
253        * Called when the form is submited, shows prompts accordingly
254        *
255        * @param {jqObject}
256        *            form
257        * @return false if form submission needs to be cancelled
258        */
259        _onSubmitEvent: function () {
260            var form = $(this);
261            var options = form.data('jqv');
262
263            //check if it is trigger from skipped button
264            if (form.data("jqv_submitButton")) {
265                var submitButton = $("#" + form.data("jqv_submitButton"));
266                if (submitButton) {
267                    if (submitButton.length > 0) {
268                        if (submitButton.hasClass("validate-skip") || submitButton.attr("data-validation-engine-skip") == "true")
269                            return true;
270                    }
271                }
272            }
273
274            options.eventTrigger = "submit";
275
276            // validate each field 
277            // (- skip field ajax validation, not necessary IF we will perform an ajax form validation)
278            var r = methods._validateFields(form);
279
280            if (r && options.ajaxFormValidation) {
281                methods._validateFormWithAjax(form, options);
282                // cancel form auto-submission - process with async call onAjaxFormComplete
283                return false;
284            }
285
286            if (options.onValidationComplete) {
287                // !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing
288                return !!options.onValidationComplete(form, r);
289            }
290            return r;
291        },
292        /**
293        * Return true if the ajax field validations passed so far
294        * @param {Object} options
295        * @return true, is all ajax validation passed so far (remember aja
295x is async)
296        */
297        _checkAjaxStatus: function (options) {
298            var status = true;
299            $.each(options.ajaxValidCache, function (key, value) {
300                if (!value) {
301                    status = false;
302                    // break the each
303                    return false;
304                }
305            });
306            return status;
307        },
308
309        /**
310        * Return true if the ajax field is validated
311        * @param {String} fieldid
312        * @param {Object} options
313        * @return true, if validation passed, false if false or doesn't exist
314        */
315        _checkAjaxFieldStatus: function (fieldid, options) {
316            return options.ajaxValidCache[fieldid] == true;
317        },
318        /**
319        * Validates form fields, shows prompts accordingly
320        *
321        * @param {jqObject}
322        *            form
323        * @param {skipAjaxFieldValidation}
324        *            boolean - when set to true, ajax field validation is skipped, typically used when the submit button is clicked
325        *
326        * @return true if form is valid, false if not, undefined if ajax form validation is done
327        */
328        _validateFields: function (form) {
329            var options = form.data('jqv');
330
331            // this variable is set to true if an error is found
332            var errorFound = false;
333
334            // Trigger hook, start validation
335            form.trigger("jqv.form.validating");
336            // first, evaluate status of non ajax fields
337            var first_err = null;
338            form.find('[' + options.validateAttribute + '*=validate]').not(":disabled").each(function () {
339                var field = $(this);
340                var names = [];
341                if ($.inArray(field.attr('name'), names) < 0) {
342                    errorFound |= methods._validateField(field, options);
343                    if (errorFound && first_err == null)
344                        if (field.is(":hidden") && options.prettySelect)
345                            first_err = field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix);
346                        else {
347
348                            //Check if we need to adjust what element to show the prompt on
349                            //and and such scroll to instead
350                            if (field.data('jqv-prompt-at') instanceof jQuery) {
351                                field = field.data('jqv-prompt-at');
352                            } else if (field.data('jqv-prompt-at')) {
353                                field = $(field.data('jqv-prompt-at'));
354                            }
355                            first_err = field;
356                        }
357                    if (options.doNotShowAllErrosOnSubmit)
358                        return false;
359                    names.push(field.attr('name'));
360
361                    //if option set, stop checking validation rules after one error is found
362                    if (options.showOneMessage == true && errorFound) {
363                        return false;
364                    }
365                }
366            });
367
368            // second, check to see if all ajax calls completed ok
369            // errorFound |= !methods._checkAjaxStatus(options);
370
371            // third, check status and scroll the container accordingly
372            form.trigger("jqv.form.result", [errorFound]);
373
374            if (errorFound) {
375                if (options.scroll) {
376                    var destination = first_err.offset().top;
377                    var fixleft = first_err.offset().left;
378
379                    //prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)
380                    var positionType = options.promptPosition;
381                    if (typeof (positionType) == 'string' && positionType.indexOf(":") != -1)
382                        positionType = positionType.substring(0, positionType.indexOf(":"));
383
384                    if (positionType != "bottomRight" && positionType != "bottomLeft") {
385                        var prompt_err = methods._getPrompt(first_err);
386                        if (prompt_err) {
387                            destination = prompt_err.offset().top;
388                        }
389                    }
390
391                    // Offset the amount the page scrolls by an amount in px to accomodate fixed elements at top of page
392                    if (options.scrollOffset) {
393                        destination -= options.scrollOffset;
394                    }
395
396                    // get the position of the first error, there should be at least one, no need to check this
397                    //var destination = form.find(".formError:not('.greenPopup'):first").offset().top;
398                    if (options.isOverflown) {
399                        var overflowDIV = $(options.overflownDIV);
400                        if (!overflowDIV.length) return false;
401                        var scrollContainerScroll = overflowDIV.scrollTop();
402                        var scrollContainerPos = -parseInt(overflowDIV.offset().top);
403
404                        destination += scrollContainerScroll + scrollContainerPos - 5;
405                        var scrollContainer = $(options.overflownDIV + ":not(:animated)");
406
407                        scrollContainer.animate({ scrollTop: destination }, 1100, function () {
408                            if (options.focusFirstField) first_err.focus();
409                        });
410
411                    } else {
412                        $("html, body").animate({
413                            scrollTop: destination
414                        }, 1100, function () {
415                            if (options.focusFirstField) first_err.focus();
416                        });
417                        $("html, body").animate({ scrollLeft: fixleft }, 1100)
418                    }
419
420                } else if (options.focusFirstField)
421                    first_err.focus();
422                return false;
423            }
424            return true;
425        },
426        /**
427        * This method is called to perform an ajax form validation.
428        * During this process all the (field, value) pairs are sent to the server which returns a list of invalid fields or true
429        *
430        * @param {jqObject} form
431        * @param {Map} options
432        */
433        _validateFormWithAjax: function (form, options) {
434
435            var data = form.serialize();
436            var type = (options.ajaxFormValidationMethod) ? options.ajaxFormValidationMethod : "GET";
437            var url = (options.ajaxFormValidationURL) ? options.ajaxFormValidationURL : form.attr("action");
438            var dataType = (options.dataType) ? options.dataType : "json";
439            $.ajax({
440                type: type,
441                url: url,
442                cache: false,
443                dataType: dataType,
444                data: data,
445                form: form,
446                methods: methods,
447                options: options,
448                beforeSend: function () {
449                    return options.onBeforeAjaxFormValidation(form, options);
450                },
451                error: function (data, transport) {
452                    methods._ajaxError(data, transport);
453                },
454                success: function (json) {
455                    if ((dataType == "json") && (json !== true)) {
456                        // getting to this case doesn't necessary means that the form is invalid
457                        // the server may return green or closing prompt actions
458                        // this flag helps figuring it out
459                        var errorInForm = false;
460                        for (var i = 0; i < json.length; i++) {
461                            var value = json[i];
462
463                            var errorFieldId = value[0];
464                            var errorField = $($("#" + errorFieldId)[0]);
465
466                            // make sure we found the element
467                            if (errorField.length == 1) {
468
469                                // promptText or selector
470                                var msg = value[2];
471                                // if the field is valid
472                                if (value[1] == true) {
473
474                                    if (msg == "" || !msg) {
475                                        // if for some reason, status==true and error="", just close the prompt
476                                        methods._closePrompt(errorField);
477                                    } else {
478                                        // the field is valid, but we are displaying a green prompt
479                                        if (options.allrules[msg]) {
480                                            var txt = options.allrules[msg].alertTextOk;
481                                            if (txt)
482                                                msg = txt;
483                                        }
484                                        if (options.showPrompts) methods._showPrompt(errorField, msg, "pass", false, options, true);
485                                    }
486                                } else {
487                                    // the field is invalid, show the red error prompt
488                                    errorInForm |= true;
489                                    if (options.allrules[msg]) {
490                                        var txt = options.allrules[msg].alertText;
491                                        if (txt)
492                                            msg = txt;
493                                    }
494                                    if (options.showPrompts) methods._showPrompt(errorField, msg, "", false, options, true);
495                                }
496                            }
497                        }
498                        options.onAjaxFormComplete(!errorInForm, form, json, options);
499                    } else
500                        options.onAjaxFormComplete(true, form, json, options);
501
502                }
503            });
504
505        },
506        /**
507        * Validates field, shows prompts accordingly
508        *
509        * @param {jqObject}
510        *            field
511        * @param {Array[String]}
512        *            field's validation rules
513        * @param {Map}
514        *            user options
515        * @return false if field is valid (It is inversed for *fields*, it return false on validate and true on errors.)
516        */
517        _validateField: function (field, options, skipAjaxValidation) {
518            if (!field.attr("id")) {
519                field.attr("id", "form-validation-field-" + $.validationEngine.fieldIdCounter);
520                ++$.validationEngine.fieldIdCounter;
521            }
522
523            if (!options.validateNonVisibleFields && (field.is(":hidden") && !options.prettySelect || field.parent().is(":hidden")))
524                return false;
525
526            var rulesParsing = field.attr(options.validateAttribute);
527            var getRules = /validate\[(.*)\]/.exec(rulesParsing);
528
529            if (!getRules)
530                return false;
531            var str = getRules[1];
532            var rules = str.split(/\[|,|\]/);
533
534            // true if we ran the ajax validation, tells the logic to stop messing with prompts
535            var isAjaxValidator = false;
536            var fieldName = field.attr("name");
537            var promptText = "";
538            var promptType = "";
539            var required = false;
540            var limitErrors = false;
541            options.isError = false;
542            options.showArrow = true;
543
544            // If the programmer wants to limit the amount of error messages per field,
545            if (options.maxErrorsPerField > 0) {
546                limitErrors = true;
547            }
548
549            var form = $(field.closest("form, .validationEngineContainer"));
550            // Fix for adding spaces in the rules
551            for (var i = 0; i < rules.length; i++) {
552                rules[i] = rules[i].replace(" ", "");
553                // Remove any parsing errors
554                if (rules[i] === '') {
555                    delete rules[i];
556                }
557            }
558
559            for (var i = 0, field_errors = 0; i < rules.length; i++) {
560
561                // If we are limiting errors, and have hit the max, break
562                if (limitErrors && field_errors >= options.maxErrorsPerField) {
563                    // If we haven't hit a required yet, check to see if there is one in the validation rules for this
564                    // field and that it's index is greater or equal to our current index
565                    if (!required) {
566                        var have_required = $.inArray('required', rules);
567                        required = (have_required != -1 && have_required >= i);
568                    }
569                    break;
570                }
571
572
573                var errorMsg = undefined;
574                switch (rules[i]) {
575
576                    case "required":
577                        required = true;
578                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._required);
579                        break;
580                    case "custom":
581                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._custom);
582                        break;
583                    case "groupRequired":
584                        // Check is its the first of group, if not, reload validation with first field
585                        // AND continue normal validation on present field
586                        var classGroup = "[" + options.validateAttribute + "*=" + rules[i + 1] + "]";
587                        var firstOfGroup = form.find(classGroup).eq(0);
588                        if (firstOfGroup[0] != field[0]) {
589
590                            methods._validateField(firstOfGroup, options, skipAjaxValidation);
591                            options.showArrow = true;
592
593                        }
594                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._groupRequired);
595                        if (errorMsg) required = true;
596                        options.showArrow = false;
597                        break;
598                    case "ajax":
599                        // AJAX defaults to returning it's loading message
600                        errorMsg = methods._ajax(field, rules, i, options);
601                        if (errorMsg) {
602                            promptType = "load";
603                        }
604                        break;
605                    case "minSize":
606                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minSize);
607                        break;
608                    case "maxSize":
609                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxSize);
610                        break;
611                    case "min":
612                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._min);
613                        break;
614                    case "max":
615                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._max);
616                        break;
617                    case "past":
618                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._past);
619                        break;
620                    case "future":
621                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._future);
622                        break;
623                    case "dateRange":
624                        var classGroup = "[" + options.validateAttribute + "*=" 
624+ rules[i + 1] + "]";
625                        options.firstOfGroup = form.find(classGroup).eq(0);
626                        options.secondOfGroup = form.find(classGroup).eq(1);
627
628                        //if one entry out of the pair has value then proceed to run through validation
629                        if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {
630                            errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._dateRange);
631                        }
632                        if (errorMsg) required = true;
633                        options.showArrow = false;
634                        break;
635
636                    case "dateTimeRange":
637                        var classGroup = "[" + options.validateAttribute + "*=" + rules[i + 1] + "]";
638                        options.firstOfGroup = form.find(classGroup).eq(0);
639                        options.secondOfGroup = form.find(classGroup).eq(1);
640
641                        //if one entry out of the pair has value then proceed to run through validation
642                        if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {
643                            errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._dateTimeRange);
644                        }
645                        if (errorMsg) required = true;
646                        options.showArrow = false;
647                        break;
648                    case "maxCheckbox":
649                        field = $(form.find("input[name='" + fieldName + "']"));
650                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxCheckbox);
651                        break;
652                    case "minCheckbox":
653                        field = $(form.find("input[name='" + fieldName + "']"));
654                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minCheckbox);
655                        break;
656                    case "equals":
657                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._equals);
658                        break;
659                    case "funcCall":
660                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._funcCall);
661                        break;
662                    case "creditCard":
663                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._creditCard);
664                        break;
665                    case "condRequired":
666                        errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._condRequired);
667                        if (errorMsg !== undefined) {
668                            required = true;
669                        }
670                        break;
671
672                    default:
673                }
674
675                var end_validation = false;
676
677                // If we were passed back an message object, check what the status was to determine what to do
678                if (typeof errorMsg == "object") {
679                    switch (errorMsg.status) {
680                        case "_break":
681                            end_validation = true;
682                            break;
683                        // If we have an error message, set errorMsg to the error message       
684                        case "_error":
685                            errorMsg = errorMsg.message;
686                            break;
687                        // If we want to throw an error, but not show a prompt, return early with true       
688                        case "_error_no_prompt":
689                            return true;
690                            break;
691                        // Anything else we continue on       
692                        default:
693                            break;
694                    }
695                }
696
697                // If it has been specified that validation should end now, break
698                if (end_validation) {
699                    break;
700                }
701
702                // If we have a string, that means that we have an error, so add it to the error message.
703                if (typeof errorMsg == 'string') {
704                    promptText += errorMsg + "<br/>";
705                    options.isError = true;
706                    field_errors++;
707                }
708            }
709            // If the rules required is not added, an empty field is not val
709idated
710            if (!required && !(field.val()) && field.val().length < 1) options.isError = false;
711
712            // Hack for radio/checkbox group button, the validation go into the
713            // first radio/checkbox of the group
714            var fieldType = field.prop("type");
715            var positionType = field.data("promptPosition") || options.promptPosition;
716
717            if ((fieldType == "radio" || fieldType == "checkbox") && form.find("input[name='" + fieldName + "']").size() > 1) {
718                if (positionType === 'inline') {
719                    field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:last"));
720                } else {
721                    field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:first"));
722                }
723                options.showArrow = false;
724            }
725
726            if (field.is(":hidden") && options.prettySelect) {
727                field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix);
728            }
729
730            if (options.isError && options.showPrompts) {
731                methods._showPrompt(field, promptText, promptType, false, options);
732            } else {
733                if (!isAjaxValidator) methods._closePrompt(field);
734            }
735
736            if (!isAjaxValidator) {
737                field.trigger("jqv.field.result", [field, options.isError, promptText]);
738            }
739
740            /* Record error */
741            var errindex = $.inArray(field[0], options.InvalidFields);
742            if (errindex == -1) {
743                if (options.isError)
744                    options.InvalidFields.push(field[0]);
745            } else if (!options.isError) {
746                options.InvalidFields.splice(errindex, 1);
747            }
748
749            methods._handleStatusCssClasses(field, options);
750
751            /* run callback function for each field */
752            if (options.isError && options.onFieldFailure)
753                options.onFieldFailure(field);
754
755            if (!options.isError && options.onFieldSuccess)
756                options.onFieldSuccess(field);
757
758            return options.isError;
759        },
760        /**
761        * Handling css classes of fields indicating result of validation 
762        *
763        * @param {jqObject}
764        *            field
765        * @param {Array[String]}
766        *            field's validation rules            
767        * @private
768        */
769        _handleStatusCssClasses: function (field, options) {
770            /* remove all classes */
771            if (options.addSuccessCssClassToField)
772                field.removeClass(options.addSuccessCssClassToField);
773
774            if (options.addFailureCssClassToField)
775                field.removeClass(options.addFailureCssClassToField);
776
777            /* Add classes */
778            if (options.addSuccessCssClassToField && !options.isError)
779                field.addClass(options.addSuccessCssClassToField);
780
781            if (options.addFailureCssClassToField && options.isError)
782                field.addClass(options.addFailureCssClassToField);
783        },
784
785        /********************
786        * _getErrorMessage
787        *
788        * @param form
789        * @param field
790        * @param rule
791        * @param rules
792        * @param i
793        * @param options
794        * @param originalValidationMethod
795        * @return {*}
796        * @private
797        */
798        _getErrorMessage: function (form, field, rule, rules, i, options, originalValidationMethod) {
799            // If we are using the custon validation type, build the index for the rule.
800            // Otherwise if we are doing a function call, make the call and return the object
801            // that is passed back.
802            var rule_index = jQuery.inArray(rule, rules);
803            if (rule === "custom" || rule === "funcCall") {
804                var custom_validation_type = rules[rule_index + 1];
805                rule = rule + "[" + custom_validation_type + "]";
806                // Delete the rule from the rules array so that it doesn't try to call the
807                // same rule over again
808                delete (rules[rule_index]);
809            }
810            // Change the rule to the composite rule, if it was different from the original
811            var alteredRule = rule;
812
813
814            var element_classes = (field.attr("data-validation-engine")) ? field.attr("data-validation-engine") : field.attr("class");
815            var element_classes_array = element_classes.split(" ");
816
817            // Call the original validation method. If we are dealing with dates or checkboxes, also pass the form
818            var errorMsg;
819            if (rule == "future" || rule == "past" || rule == "maxCheckbox" || rule == "minCheckbox") {
820                errorMsg = originalValidationMethod(form, field, rules, i, options);
821            } else {
822                errorMsg = originalValidationMethod(field, rules, i, options);
823            }
824
825            // If the original validation method returned an error and we have a custom error message,
826            // return the custom message instead. Otherwise return the original error message.
827            if (errorMsg != undefined) {
828                var custom_message = methods._getCustomErrorMessage($(field), element_classes_array, alteredRule, options);
829                if (custom_message) errorMsg = custom_message;
830            }
831            return errorMsg;
832
833        },
834        _getCustomErrorMessage: function (field, classes, rule, options) {
835            var custom_message = false;
836            var validityProp = /^custom\[.*\]$/.test(rule) ? methods._validityProp["custom"] : methods._validityProp[rule];
837            // If there is a validityProp for this rule, check to see if the field has an attribute for it
838            if (validityProp != undefined) {
839                custom_message = field.attr("data-errormessage-" + validityProp);
840                // If there was an error message for it, return the message
841                if (custom_message != undefined)
842                    return custom_message;
843            }
844            custom_message = field.attr("data-errormessage");
845            // If there is an inline custom error message, return it
846            if (custom_message != undefined)
847                return custom_message;
848            var id = '#' + field.attr("id");
849            // If we have custom messages for the element's id, get the message for the rule from the id.
850            // Otherwise, if we have custom messages for the element's classes, use the first class message we find instead.
851            if (typeof options.custom_error_messages[id] != "undefined" &&
852				typeof options.custom_error_messages[id][rule] != "undefined") {
853                custom_message = options.custom_error_messages[id][rule]['message'];
854            } else if (classes.length > 0) {
855                for (var i = 0; i < classes.length && classes.length > 0; i++) {
856                    var element_class = "." + classes[i];
857                    if (typeof options.custom_error_messages[element_class] != "undefined" &&
858						typeof options.custom_error_messages[element_class][rule] != "undefined") {
859                        custom_message = options.custom_error_messages[element_class][rule]['message'];
860                        break;
861                    }
862                }
863            }
864            if (!custom_message &&
865				typeof options.custom_error_messages[rule] != "undefined" &&
866				typeof options.custom_error_messages[rule]['message'] != "undefined") {
867                custom_message = options.custom_error_messages[rule]['message'];
868            }
869            return custom_message;
870        },
871        _validityProp: {
872            "required": "value-missing",
873            "custom": "custom-error",
874            "groupRequired": "value-missing",
875            "ajax": "custom-error",
876            "minSize": "range-underflow",
877            "maxSize": "range-overflow",
878            "min": "range-underflow",
879            "max": "range-overflow",
880            "past": "type-mismatch",
881            "future": "type-mismatch",
882            "dateRange": "type-mismatch",
883            "dateTimeRange": "type-mismatch",
884            "maxCheckbox": "range-overflow",
885            "minCheckbox": "range-underflow",
886            "equals": "pattern-mismatch",
887            "funcCall": "custom-error",
888            "creditCard": "pattern-mismatch",
889            "condRequired": "value-missing"
890        },
891        /**
892        * Required validation
893        *
894        * @param {jqObject} field
895        * @param {Array[String]} rules
896        * @param {int} i rules index
897        * @param {Map}
898        *            user options
899        * @param {bool} condRequired flag when method is used for internal purpose in condRequired check
900        * @return an error string if validation failed
901        */
902        _required: function (field, rules, i, options, condRequired) {
903            switch (field.prop("type")) {
904                case "text":
905                case "password":
906                case "textarea":
907                case "file":
908                case "select-one":
909                case "select-multiple":
910                default:
911                    var field_val = $.trim(field.val());
912                    var dv_placeholder = $.trim(field.attr("data-validation-placeholder"));
913                    var placeholder = $.trim(field.attr("placeholder"));
914                    if (
915						   (!field_val)
916						|| (dv_placeholder && field_val == dv_placeholder)
917						|| (placeholder && field_val == placeholder)
918					) {
919                        return options.allrules[rules[i]].alertText;
920                    }
921                    break;
922                case "radio":
923                case "checkbox":
924                    // new validation style to only check dependent field
925                    if (condRequired) {
926                        if (!field.attr('checked')) {
927                            return options.allrules[rules[i]].alertTextCheckboxMultiple;
928                        }
929                        break;
930                    }
931                    // old validation style
932                    var form = field.closest("form, .validationEngineContainer");
933                    var name = field.attr("name");
934                    if (form.find("input[name='" + name + "']:checked").size() == 0) {
935                        if (form.find("input[name='" + name + "']:visible").size() == 1)
936                            return options.allrules[rules[i]].alertTextCheckboxe;
937                        else
938                            return options.allrules[rules[i]].alertTextCheckboxMultiple;
939                    }
940                    break;
941            }
942        },
943        /**
944        * Validate that 1 from the group field is required
945        *
946        * @param {jqObject} field
947        * @param {Array[String]} rules
948        * @param {int} i rules index
949        * @param {Map}
950        *            user options
951        * @return an error string if validation failed
952        */
953        _groupRequired: function (field, rules, i, options) {
954            var classGroup = "[" + options.validateAttribute + "*=" 
954+ rules[i + 1] + "]";
955            var isValid = false;
956            // Check all fields from the group
957            field.closest("form, .validationEngineContainer").find(classGroup).each(function () {
958                if (!methods._required($(this), rules, i, options)) {
959                    isValid = true;
960                    return false;
961                }
962            });
963
964            if (!isValid) {
965                return options.allrules[rules[i]].alertText;
966            }
967        },
968        /**
969        * Validate rules
970        *
971        * @param {jqObject} field
972        * @param {Array[String]} rules
973        * @param {int} i rules index
974        * @param {Map}
975        *            user options
976        * @return an error string if validation failed
977        */
978        _custom: function (field, rules, i, options) {
979            var customRule = rules[i + 1];
980            var rule = options.allrules[customRule];
981            var fn;
982            if (!rule) {
983                alert("jqv:custom rule not found - " + customRule);
984                return;
985            }
986
987            if (rule["regex"]) {
988                var ex = rule.regex;
989                if (!ex) {
990                    alert("jqv:custom regex not found - " + customRule);
991                    return;
992                }
993                var pattern = new RegExp(ex);
994
995                if (!pattern.test(field.val())) return options.allrules[customRule].alertText;
996
997            } else if (rule["func"]) {
998                fn = rule["func"];
999
1000                if (typeof (fn) !== "function") {
1001                    alert("jqv:custom parameter 'function' is no function - " + customRule);
1002                    return;
1003                }
1004
1005                if (!fn(field, rules, i, options))
1006                    return options.allrules[customRule].alertText;
1007            } else {
1008                alert("jqv:custom type not allowed " + customRule);
1009                return;
1010            }
1011        },
1012        /**
1013        * Validate custom function outside of the engine scope
1014        *
1015        * @param {jqObject} field
1016        * @param {Array[String]} rules
1017        * @param {int} i rules index
1018        * @param {Map}
1019        *            user options
1020        * @return an error string if validation failed
1021        */
1022        _funcCall: function (field, rules, i, options) {
1023            var functionName = rules[i + 1];
1024            var fn;
1025            if (functionName.indexOf('.') > -1) {
1026                var namespaces = functionName.split('.');
1027                var scope = window;
1028                while (namespaces.length) {
1029                    scope = scope[namespaces.shift()];
1030                }
1031                fn = scope;
1032            }
1033            else
1034                fn = window[functionName] || options.customFunctions[functionName];
1035            if (typeof (fn) == 'function')
1036                return fn(field, rules, i, options);
1037
1038        },
1039        /**
1040        * Field match
1041        *
1042        * @param {jqObject} field
1043        * @param {Array[String]} rules
1044        * @param {int} i rules index
1045        * @param {Map}
1046        *            user options
1047        * @return an error string if validation failed
1048        */
1049        _equals: function (field, rules, i, options) {
1050            var equalsField = rules[i + 1];
1051
1052            if (field.val() != $("#" + equalsField).val())
1053                return options.allrules.equals.alertText;
1054        },
1055        /**
1056        * Check the maximum size (in characters)
1057        *
1058        * @param {jqObject} field
1059        * @param {Array[String]} rules
1060        * @param {int} i rules index
1061        * @param {Map}
1062        *            user options
1063        * @return an error string if validation failed
1064        */
1065        _maxSize: function (field, rules, i, options) {
1066            var max = rules[i + 1];
1067            var len = field.val().length;
1068
1069            if (len > max) {
1070                var rule = options.allrules.maxSize;
1071                return rule.alertText + max + rule.alertText2;
1072            }
1073        },
1074        /**
1075        * Check the minimum size (in characters)
1076        *
1077        * @param {jqObject} field
1078        * @param {Array[String]} rules
1079        * @param {int} i rules index
1080        * @param {Map}
1081        *            user options
1082        * @return an error string if validation failed
1083        */
1084        _minSize: function (field, rules, i, options) {
1085            var min = rules[i + 1];
1086            var len = field.val().length;
1087
1088            if (len < min) {
1089                var rule = options.allrules.minSize;
1090                return rule.alertText + min + rule.alertText2;
1091            }
1092        },
1093        /**
1094        * Check number minimum value
1095        *
1096        * @param {jqObject} field
1097        * @param {Array[String]} rules
1098        * @param {int} i rules index
1099        * @param {Map}
1100        *            user options
1101        * @return an error string if validation failed
1102        */
1103        _min: function (field, rules, i, options) {
1104            var min = parseFloat(rules[i + 1]);
1105            var len = parseFloat(field.val());
1106
1107            if (len < min) {
1108                var rule = options.allrules.min;
1109                if (rule.alertText2) return rule.alertText + min + rule.alertText2;
1110                return rule.alertText + min;
1111            }
1112        },
1113        /**
1114        * Check number maximum value
1115        *
1116        * @param {jqObject} field
1117        * @param {Array[String]} rules
1118        * @param {int} i rules index
1119        * @param {Map}
1120        *            user options
1121        * @return an error string if validation failed
1122        */
1123        _max: function (field, rules, i, options) {
1124            var max = parseFloat(rules[i + 1]);
1125            var len = parseFloat(field.val());
1126
1127            if (len > max) {
1128                var rule = options.allrules.max;
1129                if (rule.alertText2) return rule.alertText + max + rule.alertText2;
1130                //orefalo: to review, also do the translations
1131                return rule.alertText + max;
1132            }
1133        },
1134        /**
1135        * Checks date is in the past
1136        *
1137        * @param {jqObject} field
1138        * @param {Array[String]} rules
1139        * @param {int} i rules index
1140        * @param {Map}
1141        *            user options
1142        * @return an error string if validation failed
1143        */
1144        _past: function (form, field, rules, i, options) {
1145
1146            var p = rules[i + 1];
1147            var fieldAlt = $(form.find("input[name='" + p.replace(/^#+/, '') + "']"));
1148            var pdate;
1149
1150            if (p.toLowerCase() == "now") {
1151                pdate = new Date();
1152            } else if (undefined != fieldAlt.val()) {
1153                if (fieldAlt.is(":disabled"))
1154                    return;
1155                pdate = methods._parseDate(fieldAlt.val());
1156            } else {
1157                pdate = methods._parseDate(p);
1158            }
1159            var vdate = methods._parseDate(field.val());
1160
1161            if (vdate > pdate) {
1162                var rule = options.allrules.past;
1163                if (rule.alertText2) return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
1164                return rule.alertText + methods._dateToString(pdate);
1165            }
1166        },
1167        /**
1168        * Checks date is in the future
1169        *
1170        * @param {jqObject} field
1171        * @param {Array[String]} rules
1172        * @param {int} i rules index
1173        * @param {Map}
1174        *            user options
1175        * @return an error string if validation failed
1176        */
1177        _future: function (form, field, rules, i, options) {
1178
1179            var p = rules[i + 1];
1180            var fieldAlt = $(form.find("input[name='" + p.replace(/^#+/, '') + "']"));
1181            var pdate;
1182
1183            if (p.toLowerCase() == "now") {
1184                pdate = new Date();
1185            } else if (undefined != fieldAlt.val()) {
1186                if (fieldAlt.is(":disabled"))
1187                    return;
1188                pdate = methods._parseDate(fieldAlt.val());
1189            } else {
1190                pdate = methods._parseDate(p);
1191            }
1192            var vdate = methods._parseDate(field.val());
1193
1194            if (vdate < pdate) {
1195                var rule = options.allrules.future;
1196                if (rule.alertText2)
1197                    return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
1198                return rule.alertText + methods._dateToString(pdate);
1199            }
1200        },
1201        /**
1202        * Checks if valid date
1203        *
1204        * @param {string} date string
1205        * @return a bool based on determination of valid date
1206        */
1207        _isDate: function (value) {
1208            var dateRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$|^(?:(?:(?
1208: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]))$/);
1209            return dateRegEx.test(value);
1210        },
1211        /**
1212        * Checks if valid date time
1213        *
1214        * @param {string} date string
1215        * @return a bool based on determination of valid date time
1216        */
1217        _isDateTime: function (value) {
1218            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})$/);
1219            return dateTimeRegEx.test(value);
1220        },
1221        //Checks if the start date is before the end date
1222        //returns true if end is later than start
1223        _dateCompare: function (start, end) {
1224            return (new Date(start.toString()) < new Date(end.toString()));
1225        },
1226        /**
1227        * Checks date range
1228        *
1229        * @param {jqObject} first field name
1230        * @param {jqObject} second field name
1231        * @return an error string if validation failed
1232        */
1233        _dateRange: function (field, rules, i, options) {
1234            //are not both populated
1235            if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {
1236                return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1237            }
1238
1239            //are not both dates
1240            if (!methods._isDate(options.firstOfGroup[0].value) || !methods._isDate(options.secondOfGroup[0].value)) {
1241                return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1242            }
1243
1244            //are both dates but range is off
1245            if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {
1246                return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1247            }
1248        },
1249        /**
1250        * Checks date time range
1251        *
1252        * @param {jqObject} first field name
1253        * @param {jqObject} second field name
1254        * @return an error string if validation failed
1255        */
1256        _dateTimeRange: function (field, rules, i, options) {
1257            //are not both populated
1258            if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {
1259                return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1260            }
1261            //are not both dates
1262            if (!methods._isDateTime(options.firstOfGroup[0].value) || !methods._isDateTime(options.secondOfGroup[0].value)) {
1263                return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1264            }
1265            //are both dates but range is off
1266            if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {
1267                return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
1268            }
1269        },
1270        /**
1271        * Max number of checkbox selected
1272        *
1273        * @param {jqObject} field
1274        * @param {Array[String]} rules
1275        * @param {int} i rules index
1276        * @param {Map}
1277        *            user options
1278        * @return an error string if validation failed
1279        */
1280        _maxCheckbox: function (form, field, rules, i, options) {
1281
1282            var nbCheck = rules[i + 1];
1283            var groupname = field.attr("name");
1284            var groupSize = form.find("input[name='" + groupname + "']:checked").size();
1285            if (groupSize > nbCheck) {
1286                options.showArrow = false;
1287                if (options.allrules.maxCheckbox.alertText2)
1288                    return options.allrules.maxCheckbox.alertText + " " + nbCheck + " " + options.allrules.maxCheckbox.alertText2;
1289                return options.allrules.maxCheckbox.alertText;
1290            }
1291        },
1292        /**
1293        * Min number of checkbox selected
1294        *
1295        * @param {jqObject} field
1296        * @param {Array[String]} rules
1297        * @param {int} i rules index
1298        * @param {Map}
1299        *            user options
1300        * @return an error string if validation failed
1301        */
1302        _minCheckbox: function (form, field, rules, i, options) {
1303
1304            var nbCheck = rules[i + 1];
1305            var groupname = field.attr("name");
1306            var groupSize = form.find("input[name='" + groupname + "']:checked").size();
1307            if (groupSize < nbCheck) {
1308                options.showArrow = false;
1309                return options.allrules.minCheckbox.alertText + " " + nbCheck + " " + options.allrules.minCheckbox.alertText2;
1310            }
1311        },
1312        /**
1313        * Checks that it is a valid credit card number according to the
1314        * Luhn checksum algorithm.
1315        *
1316        * @param {jqObject} field
1317        * @param {Array[String]} rules
1318        * @param {int} i rules index
1319        * @param {Map}
1320        *            user options
1321        * @return an error string if validation failed
1322        */
1323        _creditCard: function (field, rules, i, options) {
1324            //spaces and dashes may be valid characters, but must be stripped to calculate the checksum.
1325            var valid = false, cardNumber = field.val().replace(/ +/g, '').replace(/-+/g, '');
1326
1327            var numDigits = cardNumber.length;
1328            if (numDigits >= 14 && numDigits <= 16 && parseInt(cardNumber) > 0) {
1329
1330                var sum = 0, i = numDigits - 1, pos = 1, digit, luhn = new String();
1331                do {
1332                    digit = parseInt(cardNumber.charAt(i));
1333                    luhn += (pos++ % 2 == 0) ? digit * 2 : digit;
1334                } while (--i >= 0)
1335
1336                for (i = 0; i < luhn.length; i++) {
1337                    sum += parseInt(luhn.charAt(i));
1338                }
1339                valid = sum % 10 == 0;
1340            }
1341            if (!valid) return options.allrules.creditCard.alertText;
1342        },
1343        /**
1344        * Ajax field validation
1345        *
1346        * @param {jqObject} field
1347        * @param {Array[String]} rules
1348        * @param {int} i rules index
1349        * @param {Map}
1350        *            user options
1351        * @return nothing! the ajax validator handles the prompts itself
1352        */
1353        _ajax: function (field, rules, i, options) {
1354
1355            var errorSelector = rules[i + 1];
1356            var rule = options.allrules[errorSelector];
1357            var extraData = rule.extraData;
1358            var extraDataDynamic = rule.extraDataDynamic;
1359            var data = {
1360                "fieldId": field.attr("id"),
1361                "fieldValue": field.val()
1362            };
1363
1364            if (typeof extraData === "object") {
1365                $.extend(data, extraData);
1366            } else if (typeof extraData === "string") {
1367                var tempData = extraData.split("&");
1368                for (var i = 0; i < tempData.length; i++) {
1369                    var values = tempData[i].split("=");
1370                    if (values[0] && values[0]) {
1371                        data[values[0]] = values[1];
1372                    }
1373                }
1374            }
1375
1376            if (extraDataDynamic) {
1377                var tmpData = [];
1378                var domIds = String(extraDataDynamic).split(",");
1379                for (var i = 0; i < domIds.length; i++) {
1380                    var id = domIds[i];
1381                    if ($(id).length) {
1382                        var inputValue = field.closest("form, .validationEngineContainer").find(id).val();
1383                        var keyValue = id.replace('#', '') + '=' + escape(inputValue);
1384                        data[id.replace('#', '')] = inputValue;
1385                    }
1386                }
1387            }
1388
1389            // If a field change event triggered this we want to clear the cache for this ID
1390            if (options.eventTrigger == "field") {
1391                delete (options.ajaxValidCache[field.attr("id")]);
1392            }
1393
1394            // If there is an error or if the the field is already validated, do not re-execute AJAX
1395            if (!options.isError && !methods._checkAjaxFieldStatus(field.attr("id"), options)) {
1396                $.ajax({
1397                    type: options.ajaxFormValidationMethod,
1398                    url: rule.url,
1399                    cache: false,
1400                    dataType: "json",
1401                    data: data,
1402                    field: field,
1403                    rule: rule,
1404                    methods: methods,
1405                    options: options,
1406                    beforeSend: function () { },
1407                    error: function (data, transport) {
1408                        methods._ajaxError(data, transport);
1409                    },
1410                    success: function (json) {
1411
1412                        // asynchronously called on success, data is the json answer from the server
1413                        var errorFieldId = json[0];
1414                        //var errorField = $($("#" + errorFieldId)[0]);
1415                        var errorField = $("#" + errorFieldId).eq(0);
1416
1417                        // make sure we found the element
1418                        if (errorField.length == 1) {
1419                            var status = json[1];
1420                            // read the optional msg from the server
1421                            var msg = json[2];
1422                            if (!status) {
1423                                // Houston we got a problem - display an red prompt
1424                                options.ajaxValidCache[errorFieldId] = false;
1425                                options.isError = true;
1426
1427                                // resolve the msg prompt
1428                                if (msg) {
1429                                    if (options.allrules[msg]) {
1430                                        var txt = options.allrules[msg].alertText;
1431                                        if (txt) {
1432                                            msg = txt;
1433                                        }
1434                                    }
1435                                }
1436                                else
1437                                    msg = rule.alertText;
1438
1439                                if (options.showPrompts) methods._showPrompt(errorField, msg, "", true, options);
1440                            } else {
1441                                options.ajaxValidCache[errorFieldId] = true;
1442
1443                                // resolves the msg prompt
1444                                if (msg) {
1445                                    if (options.allrules[msg]) {
1446                                        var txt = options.allrules[msg].alertTextOk;
1447                                        if (txt) {
1448                                            msg = txt;
1449                                        }
1450                                    }
1451                                }
1452                                else
1453                                    msg = rule.alertTextOk;
1454
1455                                if (options.showPrompts) {
1456                                    // see if we should display a green prompt
1457                                    if (msg)
1458                                        methods._showPrompt(errorField, msg, "pass", true, options);
1459                                    else
1460                                        methods._closePrompt(errorField);
1461                                }
1462
1463                                // If a submit form triggered this, we want to re-submit the form
1464                                if (options.eventTrigger == "submit")
1465                                    field.closest("form").submit();
1466                            }
1467                        }
1468                        errorField.trigger("jqv.field.result", [errorField, options.isError, msg]);
1469                    }
1470                });
1471
1472                return rule.alertTextLoad;
1473            }
1474        },
1475        /**
1476        * Common method to handle ajax errors
1477        *
1478        * @param {Object} data
1479        * @param {Object} transport
1480        */
1481        _ajaxError: function (data, transport) {
1482            if (data.status == 0 && transport == null)
1483                alert("The page is not served from a server! ajax call failed");
1484            else if (typeof console != "undefined")
1485                console.log("Ajax error: " + data.status + " " + transport);
1486        },
1487        /**
1488        * date -> string
1489        *
1490        * @param {Object} date
1491        */
1492        _dateToString: function (date) {
1493            return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
1494        },
1495        /**
1496        * Parses an ISO date
1497        * @param {String} d
1498        */
1499        _parseDate: function (d) {
1500
1501            var dateParts = d.split("-");
1502            if (dateParts == d)
1503                dateParts = d.split("/");
1504            if (dateParts == d) {
1505                dateParts = d.split(".");
1506                return new Date(dateParts[2], (dateParts[1] - 1), dateParts[0]);
1507            }
1508            return new Date(dateParts[0], (dateParts[1] - 1), dateParts[2]);
1509        },
1510        /**
1511        * Builds or updates a prompt with the given information
1512        *
1513        * @param {jqObject} field
1514        * @param {String} promptText html text to display type
1515        * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
1516        * @param {boolean} ajaxed - use to mark fields than being validated with ajax
1517        * @param {Map} options user options
1518        */
1519        _showPrompt: function (field, promptText, type, ajaxed, options, ajaxform) {
1520            //Check if we need to adjust what element to show the prompt on
1521            if (field.data('jqv-prompt-at') instanceof jQuery) {
1522                field = field.data('jqv-prompt-at');
1523            } else if (field.data('jqv-prompt-at')) {
1524                field = $(field.data('jqv-prompt-at'));
1525            }
1526
1527            var prompt = methods._getPrompt(field);
1528            // The ajax submit errors are not see has an error in the form,
1529            // When the form errors are returned, the engine see 2 bubbles, but those are ebing closed by the engine at the same time
1530            // Because no error was found befor submitting
1531            if (ajaxform) prompt = false;
1532            // Check that there is indded text
1533            if ($.trim(promptText)) {
1534                if (prompt)
1535                    methods._updatePrompt(field, prompt, promptText, type, ajaxed, options);
1536                else
1537                    methods._buildPrompt(field, promptText, type, ajaxed, options);
1538            }
1539        },
1540        /**
1541        * Builds and shades a prompt for the given field.
1542        *
1543        * @param {jqObject} field
1544        * @param {String} promptText html text to display type
1545        * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
1546        * @param {boolean} ajaxed - use to mark fields than being validated with ajax
1547        * @param {Map} options user options
1548        */
1549        _buildPrompt: function (field, promptText, type, ajaxed, options) {
1550
1551            // create the prompt
1552            var prompt = $('<div>');
1553            prompt.addClass(methods._getClassName(field.attr("id")) + "formError");
1554            // add a class name to identify the parent form of the prompt
1555            prompt.addClass("parentForm" + methods._getClassName(field.closest('form, .validationEngineContainer').attr("id")));
1556            prompt.addClass("formError");
1557
1558            switch (type) {
1559                case "pass":
1560                    prompt.addClass("greenPopup");
1561                    break;
1562                case "load":
1563                    prompt.addClass("blackPopup");
1564                    break;
1565                default:
1566                    /* it has error  */
1567                    //alert("unknown popup type:"+type);
1568            }
1569            if (ajaxed)
1570                prompt.addClass("ajaxed");
1571
1572            // create the prompt content
1573            var promptContent = $('<div>').addClass("formErrorContent").html(promptText).appendTo(prompt);
1574
1575            // determine position type
1576            var positionType = field.data("promptPosition") || options.promptPosition;
1577
1578            // create the css arrow pointing at the field
1579            // note that there is no triangle on max-checkbox and radio
1580            if (options.showArrow) {
1581                var arrow = $('<div>').addClass("formErrorArrow");
1582
1583                //prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)
1584                if (typeof (positionType) == 'string') {
1585                    var pos = positionType.indexOf(":");
1586                    if (pos != -1)
1587                        positionType = positionType.substring(0, pos);
1588                }
1589
1590                switch (positionType) {
1591                    case "bottomLeft":
1592                    case "bottomRight":
1593                        prompt.find(".formErrorContent").before(arrow);
1594                        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>');
1595                        break;
1596                    case "topLeft":
1597                    case "topRight":
1598                        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>');
1599                        prompt.append(arrow);
1600                        break;
1601                }
1602            }
1603            // Add custom prompt class
1604            if (options.addPromptClass)
1605                prompt.addClass(options.addPromptClass);
1606
1607            // Add custom prompt class defined in element
1608            var requiredOverride = field.attr('data-required-class');
1609            if (requiredOverride !== undefined) {
1610                prompt.addClass(requiredOverride);
1611            } else {
1612                if (options.prettySelect) {
1613                    if ($('#' + field.attr('id')).next().is('select')) {
1614                        var prettyOverrideClass = $('#' + field.attr('id').substr(options.usePrefix.length).substring(options.useSuffix.length)).attr('data-required-class');
1615                        if (prettyOverrideClass !== undefined) {
1616                            prompt.addClass(prettyOverrideClass);
1617                        }
1618                    }
1619                }
1620            }
1621
1622            prompt.css({
1623                "opacity": 0
1624            });
1625            if (positionType === 'inline') {
1626                prompt.addClass("inline");
1627                if (typeof field.attr('data-prompt-target') !== 'undefined' && $('#' + field.attr('data-prompt-target')).length > 0) {
1628                    prompt.appendTo($('#' + field.attr('data-prompt-target')));
1629                } else {
1630                    field.after(prompt);
1631                }
1632            } else {
1633                field.before(prompt);
1634            }
1635
1636            var pos = methods._calculatePosition(field, prompt, options);
1637            prompt.css({
1638                'position': positionType === 'inline' ? 'relative' : 'absolute',
1639                "top": pos.callerTopPosition,
1640                "left": pos.callerleftPosition,
1641                "marginTop": pos.marginTopSize,
1642                "opacity": 0
1643            }).data("callerField", field);
1644
1645
1646            if (options.autoHidePrompt) {
1647                setTimeout(function () {
1648                    prompt.animate({
1649                        "opacity": 0
1650                    }, function () {
1651                        prompt.closest('.formErrorOuter').remove();
1652                        prompt.remove();
1653                    });
1654                }, options.autoHideDelay);
1655            }
1656            return prompt.animate({
1657                "opacity": 0.87
1658            });
1659        },
1660        /**
1661        * Updates the prompt text field - the field for which the prompt
1662        * @param {jqObject} field
1663        * @param {String} promptText html text to display type
1664        * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
1665        * @param {boolean} ajaxed - use to mark fields than being validated with ajax
1666        * @param {Map} options user options
1667        */
1668        _updatePrompt: function (field, prompt, promptText, type, ajaxed, options, noAnimation) {
1669
1670            if (prompt) {
1671                if (typeof type !== "undefined") {
1672                    if (type == "pass")
1673                        prompt.addClass("greenPopup");
1674                    else
1675                        prompt.removeClass("greenPopup");
1676
1677                    if (type == "load")
1678                        prompt.addClass("blackPopup");
1679                    else
1680                        prompt.removeClass("blackPopup");
1681                }
1682                if (ajaxed)
1683                    prompt.addClass("ajaxed");
1684                else
1685                    prompt.removeClass("ajaxed");
1686
1687                prompt.find(".formErrorContent").html(promptText);
1688
1689                var pos = methods._calculatePosition(field, prompt, options);
1690                var css = { "top": pos.callerTopPosition,
1691                    "left": pos.callerleftPosition,
1692                    "marginTop": pos.marginTopSize
1693                };
1694
1695                if (noAnimation)
1696                    prompt.css(css);
1697                else
1698                    prompt.animate(css);
1699            }
1700        },
1701        /**
1702        * Closes the prompt associated with the given field
1703        *
1704        * @param {jqObject}
1705        *            field
1706        */
1707        _closePrompt: function (field) {
1708            var prompt = methods._getPrompt(field);
1709            if (prompt)
1710                prompt.fadeTo("fast", 0, function () {
1711                    prompt.parent('.formErrorOuter').remove();
1712                    prompt.remove();
1713                });
1714        },
1715        closePrompt: function (field) {
1716            return methods._closePrompt(field);
1717        },
1718        /**
1719        * Returns the error prompt matching the field if any
1720        *
1721        * @param {jqObject}
1722        *            field
1723        * @return undefined or the error prompt (jqObject)
1724        */
1725        _getPrompt: function (field) {
1726            var formId = $(field).closest('form, .validationEngineContainer').attr('id');
1727            var className = methods._getClassName(field.attr("id")) + "formError";
1728            var match = $("." + methods._escapeExpression(className) + '.parentForm' + methods._getClassName(formId))[0];
1729            if (match)
1730                return $(match);
1731        },
1732        /**
1733        * Returns the escapade classname
1734        *
1735        * @param {selector}
1736        *            className
1737        */
1738        _escapeExpression: function (selector) {
1739            return selector.replace(/([#;&,\.\+\*\~':"\!\^$\[\]\(\)=>\|])/g, "\\$1");
1740        },
1741        /**
1742        * returns true if we are in a RTLed document
1743        *
1744        * @param {jqObject} field
1745        */
1746        isRTL: function (field) {
1747            var $document = $(document);
1748            var $body = $('body');
1749            var rtl =
1750				(field && field.hasClass('rtl')) ||
1751				(field && (field.attr('dir') || '').toLowerCase() === 'rtl') ||
1752				$document.hasClass('rtl') ||
1753				($document.attr('dir') || '').toLowerCase() === 'rtl' ||
1754				$body.hasClass('rtl') ||
1755				($body.attr('dir') || '').toLowerCase() === 'rtl';
1756            return Boolean(rtl);
1757        },
1758        /**
1759        * Calculates prompt position
1760        *
1761        * @param {jqObject}
1762        *            field
1763        * @param {jqObject}
1764        *            the prompt
1765        * @param {Map}
1766        *            options
1767        * @retu
1767rn positions
1768        */
1769        _calculatePosition: function (field, promptElmt, options) {
1770
1771            var promptTopPosition, promptleftPosition, marginTopSize;
1772            var fieldWidth = field.width();
1773            var fieldLeft = field.position().left;
1774            var fieldTop = field.position().top;
1775            var fieldHeight = field.height();
1776            var promptHeight = promptElmt.height();
1777
1778
1779            // is the form contained in an overflown container?
1780            promptTopPosition = promptleftPosition = 0;
1781            // compensation for the arrow
1782            marginTopSize = -promptHeight;
1783
1784
1785            //prompt positioning adjustment support
1786            //now you can adjust prompt position
1787            //usage: positionType:Xshift,Yshift
1788            //for example:
1789            //   bottomLeft:+20 means bottomLeft position shifted by 20 pixels right horizontally
1790            //   topRight:20, -15 means topRight position shifted by 20 pixels to right and 15 pixels to top
1791            //You can use +pixels, - pixels. If no sign is provided than + is default.
1792            var positionType = field.data("promptPosition") || options.promptPosition;
1793            var shift1 = "";
1794            var shift2 = "";
1795            var shiftX = 0;
1796            var shiftY = 0;
1797            if (typeof (positionType) == 'string') {
1798                //do we have any position adjustments ?
1799                if (positionType.indexOf(":") != -1) {
1800                    shift1 = positionType.substring(positionType.indexOf(":") + 1);
1801                    positionType = positionType.substring(0, positionType.indexOf(":"));
1802
1803                    //if any advanced positioning will be needed (percents or something else) - parser should be added here
1804                    //for now we use simple parseInt()
1805
1806                    //do we have second parameter?
1807                    if (shift1.indexOf(",") != -1) {
1808                        shift2 = shift1.substring(shift1.indexOf(",") + 1);
1809                        shift1 = shift1.substring(0, shift1.indexOf(","));
1810                        shiftY = parseInt(shift2);
1811                        if (isNaN(shiftY)) shiftY = 0;
1812                    };
1813
1814                    shiftX = parseInt(shift1);
1815                    if (isNaN(shift1)) shift1 = 0;
1816
1817                };
1818            };
1819
1820
1821            switch (positionType) {
1822                default:
1823                case "topRight":
1824                    promptleftPosition += fieldLeft + fieldWidth - 30;
1825                    promptTopPosition += fieldTop;
1826                    break;
1827
1828                case "topLeft":
1829                    promptTopPosition += fieldTop;
1830                    promptleftPosition += fieldLeft;
1831                    break;
1832
1833                case "centerRight":
1834                    promptTopPosition = fieldTop + 4;
1835                    marginTopSize = 0;
1836                    promptleftPosition = fieldLeft + field.outerWidth(true) + 5;
1837                    break;
1838                case "centerLeft":
1839                    promptleftPosition = fieldLeft - (promptElmt.width() + 2);
1840                    promptTopPosition = fieldTop + 4;
1841                    marginTopSize = 0;
1842
1843                    break;
1844
1845                case "bottomLeft":
1846                    promptTopPosition = fieldTop + field.height() + 5;
1847                    marginTopSize = 0;
1848                    promptleftPosition = fieldLeft;
1849                    break;
1850                case "bottomRight":
1851                    promptleftPosition = fieldLeft + fieldWidth - 30;
1852                    promptTopPosition = fieldTop + field.height() + 5;
1853                    marginTopSize = 0;
1854                    break;
1855                case "inline":
1856                    promptleftPosition = 0;
1857                    promptTopPosition = 0;
1858                    marginTopSize = 0;
1859            };
1860
1861
1862
1863            //apply adjusments if any
1864            promptleftPosition += shiftX;
1865            promptTopPosition += shiftY;
1866
1867            return {
1868                "callerTopPosition": promptTopPosition + "px",
1869                "callerleftPosition": promptleftPosition + "px",
1870                "marginTopSize": marginTopSize + "px"
1871            };
1872        },
1873        /**
1874        * Saves the user options and variables in the form.data
1875        *
1876        * @param {jqObject}
1877        *            form - the form where the user option should be saved
1878        * @param {Map}
1879        *            options - the user options
1880        * @return the user options (extended from the defaults)
1881        */
1882        _saveOptions: function (form, options) {
1883
1884            // is there a language localisation ?
1885            if ($.validationEngineLanguage)
1886                var allRules = $.validationEngineLanguage.allRules;
1887            else
1888                $.error("jQuery.validationEngine rules are not loaded, plz add localization files to the page");
1889            // --- Internals DO NOT TOUCH or OVERLOAD ---
1890            // validation rules and i18
1891            $.validationEngine.defaults.allrules = allRules;
1892
1893            var userOptions = $.extend(true, {}, $.validationEngine.defaults, options);
1894
1895            form.data('jqv', userOptions);
1896            return userOptions;
1897        },
1898
1899        /**
1900        * Removes forbidden characters from class name
1901        * @param {String} className
1902        */
1903        _getClassName: function (className) {
1904            if (className)
1905                return className.replace(/:/g, "_").replace(/\./g, "_");
1906        },
1907        /**
1908        * Escape special character for jQuery selector
1909        * http://totaldev.com/content/escaping-characters-get-valid-jquery-id
1910        * @param {String} selector
1911        */
1912        _jqSelector: function (str) {
1913            return str.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
1914        },
1915        /**
1916        * Conditionally required field
1917        *
1918        * @param {jqObject} field
1919        * @param {Array[String]} rules
1920        * @param {int} i rules index
1921        * @param {Map}
1922        * user options
1923        * @return an error string if validation failed
1924        */
1925        _condRequired: function (field, rules, i, options) {
1926            var idx, dependingField;
1927
1928            for (idx = (i + 1); idx < rules.length; idx++) {
1929                dependingField = jQuery("#" + rules[idx]).first();
1930
1931                /* Use _required for determining wether dependingField has a value.
1932                * There is logic there for handling all field types, and default value; so we won't replicate that here
1933                * Indicate this special use by setting the last parameter to true so we only validate the dependingField on chackboxes and radio buttons (#462)
1934                */
1935                if (dependingField.length && methods._required(dependingField, ["required"], 0, options, true) == undefined) {
1936                    /* We now know any of the depending fields has a value,
1937                    * so we can validate this field as per normal required code
1938                    */
1939                    return methods._required(field, ["required"], 0, options);
1940                }
1941            }
1942        },
1943
1944        _submitButtonClick: function (event) {
1945            var button = $(this);
1946            var form = button.closest('form, .validationEngineContainer');
1947            form.data("jqv_submitButton", button.attr("id"));
1948        }
1949    };
1950
1951    /**
1952    * Plugin entry point.
1953    * You may pass an action as a parameter or a list of options.
1954    * if none, the init and attach methods are being called.
1955    * Remember: if you pass options, the attached method is NOT called automatically
1956    *
1957    * @param {String}
1958    *            method (optional) action
1959    */
1960    $.fn.validationEngine = function (method) {
1961
1962        var form = $(this);
1963        if (!form[0]) return form;  // stop here if the form does not exist
1964
1965        if (typeof (method) == 'string' && method.charAt(0) != '_' && methods[method]) {
1966
1967            // make sure init is called once
1968            if (method != "showPrompt" && method != "hide" && method != "hideAll")
1969                methods.init.apply(form);
1970
1971            return methods[method].apply(form, Array.prototype.slice.call(arguments, 1));
1972        } else if (typeof method == 'object' || !method) {
1973
1974            // default constructor with or without arguments
1975            methods.init.apply(form, arguments);
1976            return methods.attach.apply(form);
1977        } else {
1978            $.error('Method ' + method + ' does not exist in jQuery.validationEngine');
1979        }
1980    };
1981
1982
1983
1984    // LEAK GLOBAL OPTIONS
1985    $.validationEngine = { fieldIdCounter: 0, defaults: {
1986
1987        // Name of the event triggering field validation
1988        validationEventTrigger: "blur",
1989        // Automatically scroll viewport to the first error
1990        scroll: true,
1991        // Focus on the first input
1992        focusFirstField: true,
1993        // Show prompts, set to false to disable prompts
1994        showPrompts: true,
1995        // Should we attempt to validate non-visible input fields contained in the form? (Useful in cases of tabbed containers, e.g. jQuery-UI tabs)
1996        validateNonVisibleFields: false,
1997        // Opening box position, possible locations are: topLeft,
1998        // topRight, bottomLeft, centerRight, bottomRight, inline
1999        // inline gets inserted after the validated field or into an element specified in data-prompt-target
2000        promptPosition: "topRight",
2001        bindMethod: "bind",
2002        // internal, automatically set to true when it parse a _ajax rule
2003        inlineAjax: false,
2004        // if set to true, the form data is sent asynchronously via ajax to the form.action url (get)
2005        ajaxFormValidation: false,
2006        // The url to send the submit ajax validation (default to action)
2007        ajaxFormValidationURL: false,
2008        // HTTP method used for ajax validation
2009        ajaxFormValidationMethod: 'get',
2010        // Ajax form validation callback method: boolean onComplete(form, status, errors, options)
2011        // retuns false if the form.submit event needs to be canceled.
2012        onAjaxFormComplete: $.noop,
2013        // called right before the ajax call, may return false to cancel
2014        onBeforeAjaxFormValidation: $.noop,
2015        // Stops form from submitting and execute function assiciated with it
2016        onValidationComplete: false,
2017
2018        // Used when you have a form fields too close and the errors messages are on top of other disturbing viewing messages
2019        doNotShowAllErrosOnSubmit: false,
2020        // Object where you store custom messages to override the default error messages
2021        custom_error_messages: {},
2022        // true if you want to vind the input fields
2023        binded: true,
2024        // set to true, when the prompt arrow needs to be displayed
2025        showArrow: true,
2026        // did one of the validation fail ? kept global to stop further ajax validations
2027        isError: false,
2028        // Limit how many displayed errors a field can have
2029        maxErrorsPerField: false,
2030
2031        // Caches field validation status, typically only bad status are created.
2032        // the array is used during ajax form validation to detect issues early and prevent an expensive submit
2033        ajaxValidCache: {},
2034        // Auto update prompt position after window resize
2035        autoPositionUpdate: false,
2036
2037        InvalidFields: [],
2038        onFieldSuccess: false,
2039        onFieldFailure: false,
2040        onSuccess: false,
2041        onFailure: false,
2042        validateAttribute: "class",
2043        addSuccessCssClassToField: "",
2044        addFailureCssClassToField: "",
2045
2046        // Auto-hide prompt
2047        autoHidePrompt: false,
2048        // Delay before auto-hide
2049        autoHideDelay: 10000,
2050        // Fade out duration while hiding the validations
2051        fadeDuration: 0.3,
2052        // Use Prettify select library
2053        prettySelect: false,
2054        // Add css class on prompt
2055        addPromptClass: "",
2056        // Custom ID uses prefix
2057        usePrefix: "",
2058        // Custom ID uses suffix
2059        useSuffix: "",
2060        // Only show one message per error prompt
2061        showOneMessage: false
2062    }
2063    };
2064    $(function () { $.validationEngine.defaults.promptPosition = methods.isRTL() ? 'topLeft' : "topRight" });
2065})(jQuery);
2066

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.