2015-09-25 2 views
0

Итак, я построил этот плагин, и, проверяя его, все работало хорошо, пока я наконец не добрался до части плагина onSubmit. Что происходит, так это то, что форма будет отправляться один раз успешно, а затем потом, похоже, удваивает количество раз, которое она подает. Я точно не знаю, как это происходит, поэтому я обращаюсь к вам за помощью.Форма submit отправляется один раз, затем удваивается каждый раз после

Я предоставил демо-версию, как плагин работает с формой и самим плагином. Так как я "не уверен, где это происходит из в плагине я предоставил полноту исходного кода. Дайте мне знать, если есть что-нибудь еще, что требуется для получения помощи.

HTML

<form id='test'> 
    <div class='form-group'> 
     <input type='text' id='data' class='form-control' /> 
    </div> 
    <button type='submit' class='btn btn-default'>Submit</button> 
</form> 

Javascript

$(function(){ 
     $('#test').validator({ 
      controls:{ 
       data : { 
        validate : 'notEmpty' 
       } 
      }, 
      onSubmit : function(){ 
       alert("success"); 

       // destroy the instance 
       $('#test').validator('destroy'); 

       // get the original options 
       var options = $('#test').validator('getSettings'); 

       // re initialize the plugin for the form 
       $('#test').validator(options); 
      } 
     }); 
    }); 

validator.js

(function($){ 
    var _defaults = null; 
    // functions object where the validator functions are stored for use 
    var functions = { 
     notEmpty : function(value){ 
      return value && $.trim(value).length > 0; 
     }, 
     required : function(value){ 
      return value && $.trim(value).length > 0; 
     }, 
     isEmail : function(value){ 
      var check = true; 
      if(value.length) 
       check = /^([^@\s\t\n]+\@[\w\d]+\.[\w]{2,3}(\.[\w]{2})?)$/.test(value); 
      return check; 
     }, 
     isPhoneNumber : function(value){ 
      var check = true; 
      if(value.length) 
       check = /^(\d\-)?\(?\d{3}\)?[\-|\s]?\d{3}[\-|\s]?\d{4}$/.test(value); 
      return check; 
     }, 
     isNumber : function(value){ 
      var check = true; 
      if(value.length) 
       check = /^[+-]?\d+(\.\d+)?$/.test(value); 
      return check; 
     }, 
     isSSN : function(value){ 
      var check = true; 
      if(value.length) 
       check = /^\d{3}\-?\d{2}\-?\d{4}$/.test(value); 
      return check; 
     }, 
     isString : function(value){ 
      var check = true; 
      if(value.length) 
       check = /^\D+$/.test(value); 
      return check; 
     }, 
     isURL : function(value){ 
      var check = true; 
      if(value.length) 
       check = /^([http\:\/\/]+)?([a-zA-Z]+)?\.?[a-zA-Z0-9\-]+\.[a-zA-Z]+$/.test(value); 
      return check; 
     }, 
     isDateTime : function(value, regex){ 
      var check = true; 
      if(regex == null){ 
       return true; 
      } 
      var regexChars = regex.split(""); 
      var pattern = "^"; 
      for(var i = 0; i < regexChars.length; i++){ 
       switch(regexChars[i]){ 
        case "d" : 
        case "j" : 
         pattern = pattern + "(0?[1-9]|[12][0-9]|3[01])"; 
         break; 
        case "D": 
         pattern = pattern + "(Sun|Mon|Tue|Wed|Thu|Fri|Sat)"; 
        case "l" : 
         pattern = pattern + "(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)"; 
         break; 
        case "F" : 
         pattern = pattern + "(January|February|March|April|May|June|July|August|September|October|November|December)"; 
         break; 
        case "M" : 
         pattern = pattern + "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"; 
         break; 
        case "m" : 
        case "n" : 
         pattern = pattern + "(0?[1-9]|1[012])"; 
         break; 
        case "Y" : 
        case "y" : 
         pattern = pattern + "(19|20)?[\\d]+"; 
         break; 
        case "a" : 
        case "A" : 
         pattern = pattern + "([AaPp][Mm])"; 
         break; 
        case "g" : 
        case "G" : 
        case "h" : 
        case "H" : 
         pattern = pattern + "(0?[0-9]|1[012]|2[0123])"; 
         break; 
        case "i" : 
        case "s" : 
         pattern = pattern + "([][0-9])"; 
         break; 
        case "/" : 
         pattern = pattern + "[/]"; 
         break; 
        case ":" : 
         pattern = pattern + "[:]"; 
         break; 
        case "." : 
         pattern = pattern + "[.]"; 
         break; 
        case " " : 
         pattern = pattern + "[ ]"; 
         break; 
        case "," : 
         pattern = pattern + "[,]"; 
         break; 
        case "-" : 
         pattern = pattern + "[-]"; 
         break; 
       } 
      } 
      pattern = pattern+"$"; 

      pattern = new RegExp(pattern, 'i'); 

      if(value.length) 
       check = pattern.test(value); 
      return check; 
     }, 
     groupNotEmpty : function(value){ 
      return value.length > 0; 
     }, 
     isRoutingNumber : function(value){ 
      //run through each digit and calculate the total 
      var n = 0; 
      for(var i = 0; i < value.length; i += 3){ 
       n += parseInt(value.charAt(i), 10)*3 + parseInt(value.charAt(i+1), 10)*7 + parseInt(value.charAt(i+2), 10); 
      } 
      //if the resulting sum is an even multiple of ten (but not zero), the aba routing number is good 
      if(n != 0 && n % 10 == 0){ 
       return true; 
      }else{ 
       return false; 
      } 
     }, 
     isMacAddress : function(value){ 
      var check = true; 
      if(value.length){ 
       check = /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value); 
      } 
      return check; 
     }, 
     isIPAddress : function(value){ 
      var check = true; 
      if(value.length){ 
       check = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(value); 
      } 
      return check; 
     }, 
     validPassword : function(value, selector){ 
      var form = this.$form; 
      var that = this; 
      var check = false; 
      var strength = 0; 

      if(value.length >= 1){ 
       strength = 4; 
      } 
      // password mixins 
      var passwordChars = value.split(''); 
      var count = 0; // keep track of the characters 
      for(p in passwordChars){ 
       count++; 
       if(count < 8){ 
        strength += 5; 
       }else if(count >= 8 && count < 20){ 
        strength += 3; 
       }else if(count >= 20){ 
        strength += 2; 
       } 
       if(/[0-9]/.test(passwordChars[p])){ 
        strength += 3; 
       } 
       if(/[a-z]/.test(passwordChars[p])){ 
        strength += 1; 
       } 
       if(/[A-Z]/.test(passwordChars[p])){ 
        strength += 2; 
       } 
       if(/[[email protected]#]/.test(passwordChars[p])){ 
        strength += 4; 
       } 

      } 
      var progressBarHolder = $(form).find(selector).closest('.form-group'); 
      var progressBar = $(progressBarHolder).find('.progress-bar'); 
      var progressBarValue = strength; 
      if(strength < 50){ 
       $(progressBar).css({ 
        'width' : progressBarValue+'%', 
        'background-color' : '#D9534F' 
       }); 
       $(progressBar).html(progressBarValue+'%'); 
      }else if(strength >= 50 && strength < 80){ 
       $(progressBar).css({ 
        'width' : progressBarValue+'%', 
        'background-color' : '#F0AD4E' 
       }); 
       $(progressBar).html(progressBarValue+'%'); 
      }else if(strength >= 80 && strength <= 100){ 
       $(progressBar).css({ 
        'width' : progressBarValue+'%', 
        'background-color' : '#5CB85C' 
       }); 
       $(progressBar).html(progressBarValue+'%'); 
      }else if(strength > 100){ 
       $(progressBar).css({ 
        'width' : '100%', 
        'background-color' : '#5CB85C' 
       }); 
       $(progressBar).html('100%'); 
      } 
      if(strength >= 6){ 
       check = true; 
      } 
      return check; 
     }, 
     equalTo : function(value, selector){ 
      var form = this.$form; 
      var check = false; 
      var checkValue = $(form).find(selector).val(); 
      if(value.length){ 
       if(value === checkValue){ 
        check = true; 
       } 
      } 
      return check; 
     }, 
     isCreditCard : function(value){ 
      var that = this; 
      var check = false; 
      var value = value.replace(/[ -]/g, ''); 
      var card_types = [ 
       { 
        name : 'amex', 
        pattern: /^3[47]/, 
        valid_length: [15] 
       }, { 
        //diners_club_carte_blanche 
        name: 'dccb', 
        pattern: /^30[0-5]/, 
        valid_length: [14] 
       }, { 
        //diners_club_international 
        name: 'dci', 
        pattern: /^36/, 
        valid_length: [14] 
       }, { 
        name: 'jcb', 
        pattern: /^35(2[89]|[3-8][0-9])/, 
        valid_length: [16] 
       }, { 
        name: 'laser', 
        pattern: /^(6304|670[69]|6771)/, 
        valid_length: [16, 17, 18, 19] 
       }, { 
        //visa_electron 
        name: 'electron', 
        pattern: /^(4026|417500|4508|4844|491(3|7))/, 
        valid_length: [16] 
       }, { 
        name: 'visa', 
        pattern: /^4/, 
        valid_length: [16] 
       }, { 
        //mastercard 
        name: 'mc', 
        pattern: /^5[1-5]/, 
        valid_length: [16] 
       }, { 
        name: 'maestro', 
        pattern: /^(5018|5020|5038|6304|6759|676[1-3])/, 
        valid_length: [12, 13, 14, 15, 16, 17, 18, 19] 
       }, { 
        name: 'discover', 
        pattern: /^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)/, 
        valid_length: [16] 
       } 
      ]; 

      if(value.length){ 
       var exists = false; 
       var matches = false; 
       var validlength = false; 
       var validLuhn = false; 
       var cardname = ""; 
       that.setCreditCardImage(cardname); 
       for(var name in card_types){ 
        if(value.match(card_types[name].pattern)){ 
         matches = true; 
        } 
        if(card_types[name].valid_length.indexOf(value.length) > -1){ 
         validlength = true; 
        } 
        if(matches && validlength){ 
         cardname = card_types[name].name.toLowerCase(); 
         break; 
        } 
       } 
       if(matches && validlength){ 
        var digit, n, sum, j, len, ref1; 
        sum = 0; 
        ref1 = value.split('').reverse(); 
        for(n = j = 0, len = ref1.length; j < len; n = ++j){ 
         digit = ref1[n]; 
         digit = +digit; 
         if(n % 2){ 
          digit *= 2; 
          if(digit < 10){ 
           sum += digit; 
          }else{ 
           sum += digit - 9; 
          } 
         }else{ 
          sum += digit; 
         } 
        } 
        if(sum % 10 === 0){ 
         validLuhn = true; 
        }   
       }else{ 
        return check; 
       } 
       if(matches && validlength && validLuhn){ 
        check = true; 
        that.setCreditCardImage(cardname); 
        return check; 
       }else{ 
        that.setCreditCardImage(); 
        return check; 
       } 
      }else{ 
       check = true; 
       return check; 
       that.setCreditCardImage(); 
      } 

     }, 
     isZipCode : function(value){ 
      var check = true; 
      if(value.length){ 
       check = /^\d{5}(?:[-\s]\d{4})?$/.test(value); 
      } 
      return check; 
     }, 
     isDependent : function(value, selector){ 
      var check = true; 
      if(selector.length){ 
       if(selector.substring(0,1) === '_'){ 
        selector = "[data-validator*=isDependent"+selector+"]"; 
       } 
       if(!this.notEmpty(value)){ 
        form.find(selector).each(function(){ 
         if($(this).val() !== ''){ 
          check = false; 
         } 
        }); 
       } 
      } 
      return check; 
     }, 
     testRegex : function(value, regex){ 
      var check = true; 
      var caret = regex.substring(0); 
      var dollar = regex.substring(regex.length-1); 
      if(caret != "^") 
       regex = "^"+regex; 
      if(dollar != "$") 
       regex = regex+'$'; 
      if(value.length && regex.length){ 
       var pattern = new RegExp(regex, 'i'); 
       check = pattern.test(value); 
      } 
      return check; 
     } 
    }; 
    var selectors = []; 
    // private function that sets the form control data-validator values 
    var setControlData = function(selector, options){ 
     var validate = options.validate; 
     var validations = ""; 
     if(Array.isArray(validate)){ 
      validations = validate.join("|"); 
     }else{ 
      validations = validate; 
     } 
     if(validations.indexOf('isDateTime') > -1 && typeof(options.dateFormat) != 'undefined' && typeof(options.dateFormat) == 'string'){ 
      validations = validations.replace(/isDateTime/g, 'isDateTime'+options.dateFormat); 
     } 
     if(validations.indexOf('equalTo') > -1 && typeof(options.equalTo) != 'undefined' && typeof(options.equalTo) == 'string'){ 
      validations = validations.replace(/equalTo/g, 'equalTo'+options.equalTo); 
     } 
     if(validations.indexOf('testRegex') > -1 && typeof(options.regex) != 'undefined' && typeof(options.regex) == 'string'){ 
      validations = validations.replace(/testRegex/g, 'testRegex'+options.regex); 
     } 
     $(selector).data('validator', validations); 
    }; 

    // main function that validates the form itself 
    var validator = function(selector){ 
      var rVal = true; 
      var element = selector; 
      var errors = 0; 
      //check if there is a validator option for the specific input and that it has a value to it 
      if($(element).data('validator')){ 

       // get the element type and split the pipe separated values into an array 
       var value = null; 
       var type = $(element).attr('type'); 
       var formGroup = null; 
       if(type != "radio" && type != "checkbox"){ 
        formGroup = $(element).closest('.form-group'); 
        value = $(element).val(); 
       }else{ 
        formGroup = $(element).closest('.form-group'); 
        value = []; 
        $(formGroup).find('.radio, .checkbox, .radio-inline, .checkbox-inline').each(function(){ 
         $(":checked", this).each(function(){ 
          value.push($(this).val()); 
         }); 
        }); 
       } 

       // check the .data('validator') string to account for interior pipes that may be used with regexes or selectors 
       var validations = $(element).data('validator'); 
       validations = validations.replace(/\|\=/g, '%='); 
       var holding = []; 
       if(validations.indexOf('testRegex') > -1){ 
        var hold = validations.substring(validations.indexOf('testRegex'), validations.lastIndexOf('/')+1); 
        holding.push(hold); 
        validations = validations.replace(hold, ''); 
       } 
       validations = validations.replace("||", "|"); 
       validations = validations.split('|'); 
       validations = validations.concat(holding); 
       for(var x in validations){ 
        validations[x] = validations[x].replace('%=', '|='); 
       } 
       validations = validations.filter(function(n){return n != undefined && n != ""}); 
       for(var i = 0; i < validations.length; i++){ 
        if(validations[i].indexOf('validPassword') !== -1){ 
         var selector = validations[i].replace('validPassword', ''); 
         !functions['validPassword'](value, selector) ? errors++ : null; 
        }else if(validations[i].indexOf('isDateTime') !== -1){ 
         var regex = validations[i].replace('isDateTime', ''); 
         !functions['isDateTime'](value, regex) ? errors++ : null; 
        }else if(validations[i].indexOf('equalTo') !== -1){ 
         var selector = validations[i].replace('equalTo', ''); 
         !functions['equalTo'](value, selector) ? errors++ : null; 
        }else if(validations[i].indexOf('isDependent') !== -1){ 
         var selector = validations[i].replace('isDependent', ''); 
         !functions['isDependent'](value, selector) ? errors++ : null; 
        }else if(validations[i].indexOf('testRegex') !== -1){ 
         var regex = validations[i].replace('testRegex', ''); 
         var regex = regex.substring(regex.indexOf('/')+1, regex.lastIndexOf('/')); 
         !functions['testRegex'](value, regex) ? errors++ : null; 
        }else{ 
         !functions[validations[i]](value) ? errors++ : null; 
        } 
       } 
       if(errors > 0){ 
        $(formGroup).addClass('has-error'); 
       }else{ 
        $(formGroup).removeClass('has-error'); 
       } 
       if(errors > 0) rVal = false; 
      }else{ 
       formGroup = $(element).closest('.form-group'); 
       if(errors > 0){ 
        $(formGroup).addClass('has-error'); 
       }else{ 
        $(formGroup).removeClass('has-error'); 
       } 
      } 

      return rVal; 
    }; 
    // object literal for the methods 
    var methods = { 
     // defining the individual methods inside of the literal 
     init : function(options){ 

      // Repeat this process over each element in the selector 
      return this.each(function(){ 
       var $this = $(this); 
       var settings = options; 
       _defaults = options; 
       console.log(settings); 
       // validation to make sure at least the bare minimum is supplied 
       if(typeof(settings) == 'undefined'){ 
        console.log("No options were supplied for this plugin. 'selectors' and 'onSubmit' are required. Please see documentation for assistance"); 
        return false; 
       }else if(typeof(settings.controls) != 'object'){ 
        console.log("'selectors' must be an object"); 
        return false; 
       }else if(typeof(settings.onSubmit) != 'function'){ 
        console.log("'onSubmit' is a callback function"); 
        return false; 
       } 

       // if nothing else was wrong proceed to run the rest of the program here 
       var controls = settings.controls; 
       var bindInput = typeof settings.bindInput != 'undefined' && settings.bindInput != false ? true : false; 
       var showErrorMessage = typeof settings.showErrorMessage != 'undefined' && settings.showErrorMessage != false ? true : false; 

       for(var control in controls){ 
        if(typeof controls[control] != 'object'){ 
         console.log("controls."+control+" must be an object. Skipping this element"); 
         continue; 
        }else if(typeof controls[control].validate == 'undefined'){ 
         console.log("controls."+control+".validate must be defined"); 
         continue; 
        } 
        $($this).find('input, textarea, select').each(function(){ 
         if($(this).is('#'+control)){ 
          setControlData('#'+control, controls[control]); 
          selectors.push('#'+control);  
         }else if($(this).hasClass(control)){ 
          setControlData('.'+control, controls[control]); 
          selectors.push('.'+control); 
         } 
        }); 
       } 
       if(bindInput){ 
        $($this).find('input, textarea, select').on('change keyup click select focus', function(){ 
         for(var s in selectors){ 
          validator(selectors[s]); 
         } 
        }); 
       } 
       if(showErrorMessage){ 
        $($this).prepend("<section id='errorAlert' class='form-group col-xs-12 hidden'><div class='alert alert-danger' ></div></section>"); 
       } 
       // handle the form submission 
       $($this).submit(function(e){ 
        e.preventDefault(); 
        var errors = ""; 
        var rVal = true; 
        for(selector in selectors){ 
         if(!validator(selectors[selector])){ 
          rVal = false; 
          if(showErrorMessage){ 
           var pos = selectors.indexOf(selector); 
           var control = selectors[pos].replace(/[.#]/g, ''); 
           if(typeof controls[control].errorMessage != "undefined" && typeof controls[control].errorMessage == 'string'){ 
            errors += "&bull; "+controls[control].errorMessage+"<br>"; 
           } 
          } 
         } 
        } 
        if(rVal){ 
         if(showErrorMessage){ 
          $('#errorAlert').addClass('hidden'); 
         } 
         settings.onSubmit(); 
        }else{ 
         if(showErrorMessage){ 
          $('#errorAlert').removeClass('hidden'); 
          $('#errorAlert > div').html(errors); 
          $('html, body').animate({ 
           scrollTop : $('#errorAlert').offset().top 
          }, 1000); 
         } 
        } 
       }); 
      }); 
     }, 
     checkControl : function(control, options){ 
      return this.each(function(){ 
       setControlData(control, options); 
       validator(control); 
       $(control).on('change keyup click select focus', function(){ 
         validator(control); 
       }); 
      }); 
     }, 
     clearControl : function(control){ 
      return this.each(function(){ 
       $(control).removeData('validator'); 
       $(control).off('change keyup click select focus'); 
       validator(control);    
      }); 
     }, 
     getSettings : function(){ 
      return _defaults; 
     }, 
     destroy : function(){ 
      return this.each(function(){ 
       $(this).find('input, select, textarea').each(function(){ 
        $(this).data('validator', ''); 
        validator($(this)); 
        $(this).removeData('validator'); 

       }); 
      }); 
     } 
    } 

    // the engine 
    $.fn.validator = function(){ 

     // get the first argument passed if any 
     var method = arguments[0]; 
     if(methods[method]){ 
      method = methods[method]; 
      arguments = Array.prototype.slice.call(arguments, 1); 
     // if there was no argument or the argument is the default argument object then proceed to initialize 
     }else if(typeof(method) == 'object' || !method){ 
      method = methods.init; 
     }else { 
      console.log("Method "+ method + " does not exist for this plugin"); 
      return this; 
     } 

     // return the result that is wanted based on what was passed in the initial arguments 
     return method.apply(this, arguments); 
    } 
})(jQuery); 
+0

Ваш метод «уничтожить», похоже, не удаляет события. –

+0

объясните, пожалуйста, пожалуйста? –

+0

Вы связываете события каждый раз, когда вы вызываете .init, и делаете это каждый раз, когда отправляете. но вы никогда не удаляете упомянутые события, поэтому событие отправки привязывается 1 раз, затем 2 раза, затем 4, 8 и т. д. –

ответ

1

Уничтожая и повторно инициализируя плагин каждый раз, вы полагаетесь на плагин, который правильно отвязывает все обработчики событий, и в этом случае он не выглядит.

Возможно, было бы проще просто предоставить плагину метод, который сбрасывает данные и значения на входах, тем самым давая вам новую форму без необходимости перезапускать.

+0

еще раз спасибо !!! –

Смежные вопросы