PageSourceSearch

https://www.navalengineers.org/DesktopModules/DNNGo_xBlog/Resource/js/jquery.validationEngine.js?cdv=565

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

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