Advertisement
Guest User

jquerry validation engine

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