2017-02-14 70 views
1

我有一個html表,我通過AJAX使用jQuery dataTables填充。我在頁面上有兩種形式,第一種形式驗證可以正常工作的表格參數。驗證事件偵聽器上的動態錶行

第二個驗證包裹了整個表格,我的目標是使用工具提示創建自定義驗證,除非有另一種方法可以使用提交表單驗證方法來驗證多個輸入[type ='number']和日期選擇器每一行:

input[type=number]事件 - 點擊,KEYUP輸入框的類型=數字

input[NAME=BUYDATE](.hasDatePicker)事件 - onfocusout在

我應該如何觸發提交行的形式?

一個:在其中相同的元件使用的名稱的時間驗證一行= ELEMENT

B:使用所述提交表單驗證方法驗證整個形式?

此表是一個動態訂單項實用

這裏是我的dataTable與樣本行:

<form id="ITEMS"> 
    <table id="table_001" class="xs-small table table-condensed" > 
    <thead> 
    <H5>Program: FRESH INCENTIVE</H5> 
    <H5>Customer: 330-990076-033 (B/C MANISTEE CLARK)</H5> 
    <p><font color="red">Delivery Days: Mon,Thu</font></p> 
    <tr> 
    <th></th> 
    <th class="hidden"> 
    [ 
{ "size" : "lg", 
    "upper_hidden" : [], 
    "lower_hidden" : [1,2,3,4,5,6,7,8,9,10,11,12] 
    }, 
    { "size" : "md", 
    "upper_hidden" : [], 
    "lower_hidden" : [1,2,3,4,5,6,7,8,9,10,11,12] 
    }, 
    { "size" : "sm", 
    "upper_hidden" : [3,4], 
    "lower_hidden" : [1,2,5,6,7,8,9,10,11,12] 
    }, 
    { "size" : "xs", 
    "upper_hidden" : [3,4,5], 
    "lower_hidden" : [1,2,6,7,8,9,10,11,12] 
    } 
    ] 
    </th> 
    <th>Item</th> 
    <th class='cupc'>UPC</th> 
    <th>Pack</th> 
    <th>Size</th> 
    <th>Description</th 
    <th>Mon<br>Qty</th> 
    <th>Tue<br>Qty</th> 
    <th>Wed<br>Qty</th> 
    <th>Thu<br>Qty</th> 
    <th>Fri<br>Qty</th> 
     <th>Sat<br>Qty</th> 
    <th>Start Date</th> 
    </tr> 
    </thead> 
    <tbody> 
    <tr role="row" class="odd"><td class="hidden-lg hidden-md"><span class="row-details row-details-close"><i class="fa fa-plus-square icon-large"></i></span></td><td class=" hidden">place holder</td><td><span class="EmptyRow itno live" title="ITEMNO:1525252" style="padding: 3px;">1525252</span></td><td><span class="UPC" title="UPC:010700807229">010700807229</span></td><td class="hidden-sm hidden-xs"><span class="pack" title="package qty:24">24</span></td><td class="hidden-sm hidden-xs"><span class="size" title="size:CT">CT</span></td><td class="hidden-xs"><span class="descrpt" title="desc:PAYDAY">PAYDAY</span></td><td><span title="Monday:"><input type="number" min="1" max="99" name="QTY" title="Qty must be between 1-99" value="" data-delday="1" data-dow="" class="qty non-day" maxlength="2"></span></td><td><span title="Tuesday:"><input type="number" min="1" max="99" name="QTY" title="Qty must be between 1-99" value="" maxlength="2" class="qty non-day" data-delday="2" data-dow=""></span></td><td><span title="Wednesday:"><input type="number" min="1" max="99" name="QTY" title="Qty must be between 1-99" value="" maxlength="2" class="qty non-day" data-delday="3" data-dow=""></span></td><td><span title="Thursday:"><input type="number" min="1" max="99" name="QTY" title="Qty must be between1-99" value="" maxlength="2" class="qty non-day" data-delday="4" data-dow=""></span></td><td><span title="Friday:"><input type="number" min="1" max="99" name="QTY" title="Qty must be between 1-99" value="" maxlength="2" class="qty delivery-day" data-delday="5" data-dow="5"></span></td><td><span title="Saturday:"><input type="number" min="1" max="99" name="QTY" title="Qty must be between1-99" value="" maxlength="2" class="qty non-day" data-delday="6" data-dow=""></span></td><td><span title="Start date for buying item"><input type="text" size="10" class="dp form-control-inline xs-small hasDatepicker" id="1" value="" name="BUYDATE" data-buydate=""><img class="ui-datepicker-trigger" src="/images/calendar.png" alt="Select a start buying date" title="Select a start buying date"></span></td></tr> 
    </tbody> 
    </table> 
    </form> 

是否可以使用,即使它違背了名字=值的方法典型的DOM準則,你有重複相同的唯一ID /名稱?

我想,如果所有的行強調即使目標是在用戶已集中在排紅色不要緊

注:

每一行的最後一列有他們自己的日期選擇器,如果該行中的任何其他列都有值,則必須提供該行的日期。

隨後,如果提供了日期並且該行的其他輸入字段(012xx)中沒有任何一個具有提供的值,那麼我需要觸發一個錯誤。

基本上,

我有兩種類型的類.RecordRow.EmptyRow識別行。

至少一個input[name='QTY']必須有一個值,如果該行是.EmptyRow,如果一個RecorRow你可能想要刪除所有Qtys。

只有當用戶觸發兩個事件偵聽器之一時,每行的input[name='BUYDATE']都必須輸入有效的日期。

有效期:

enter image description here

enter image description here

無效: enter image description here

enter image description here

這是我迄今爲止

jQuery驗證:

$("input").on("blur keyup", function(){ 
     row.children("td").each(function(){ 
      $(this).children('input').each(function() { 
      if($(this).attr("name") === 'BUYDATE') && $(this).valid()){ 
       //validate tds 
      } 
      }); 
     }); 
    }); 

form.validate({ 
     focusInvalid: false, 
     onkeyup: function(element) { rule!! 
      var element_id = $(element).attr('name'); 
      if (this.settings.rules[element_id]) { 
       if (this.settings.rules[element_id].onkeyup !== false) { 
        $.validator.defaults.onkeyup.apply(this, arguments); 
       } 
      } 
     }, 
     rules: { 
      "BUYDATE": { 
       required: { depends:function(){ 
          //iterate through rows here? 
          //this only validate onn submit 
          //I guess maybe on could trigger submit onkeyup 
          //or blur? 
         } 
       } 
      }, 
      "DLOCN": { 
       required:{ 
       depends: function(){ 
          //iterate through rows here? 
          //this only validate onn submit 
          //I guess maybe on could trigger submit onkeyup 
          //or blur? 
       } 
       } 
      } 
     }, 
     messages: { // custom messages 
      "EVENT": { 
       required: "Select a Program.", 
       HTH_SelectValue: "Select a Program."    
      }, 
      "LOCN": { 
       HTH_SingleLOCN: "A single location must be selected when using this option to load items." 
      }, 
      "DLOCN": { 
       required: "A customer location must be supplied when using this option to load items." 
      } 
     },   
     showErrors: function(errorMap, errorList) { 
      FormError.hide(); 
      // Clean up any tooltips for valid elements 
      $.each(this.validElements(), function (index, element) { 
       element = $(element); 
       NoError_ToolTip(element); 
      }); 
      // Create new tooltips for invalid elements 
      $.each(errorList, function (index, error) { 
       element = $(error.element); 
       message = error.message; 
       Error_ToolTip(element,message); 
       FormError.show(); 
      }); 
     },     
     invalidHandler: function (event, validator) { //display error alert on form submit  
      success.hide(); 
      FormError.show(); 
      $(document).scrollTop($(".form-body:first-of-type").offset().top); 
     }, 
     submitHandler: function (form) { 
      success.show(); 
      FormError.hide(); 
      // Submit1(form,FormError,success); 
     } 

    }); 
} 

最後,

有人會建議用表單包裝每一行並驗證那種方式嗎?似乎如果我這樣做,它會違反DOM準則,因爲我需要使用Id來使用jQuery驗證。我已經看到在單個頁面上使用多個唯一ID,並且在某些情況下它可以工作。

回答

1

我決定使用兩個事件偵聽器來一次驗證一個動態錶行,其中我重置了兩個事件偵聽器上的驗證;

A)上輸入[類型=數]點擊,關於日期選擇器輸入事件的內容KEYUP

&

B),和KEYUP

我使用內聯復位驗證規則即:

$(".element").rules('add',{required: true});

$(".element").rules('remove',"required");在飛行中。

我還在創建新行後動態創建新的$("#id").datepicker()對象。我也用$(this).clone()在處理原始行時創建動態行。我從來沒有想過$.clone() API會有用,但我終於找到了一個有用的例子。

從我的理解克隆的對象不綁定到我認爲依賴於API的原始行的事件偵聽器。我實際上已經證明我用datepicker的嵌套輸入文本克隆了一行。

我最終選擇使用jQuery.remove()函數刪除輸入文本框,然後重新創建它並將其綁定到datepicker API,然後爲其提供一個新ID以使其正確工作。

現在的問題是changeDate事件沒有綁定到新的datepicker對象,我記得我試圖刪除id並添加一個新的id,但元素仍然綁定到從它克隆的原始元素的事件。

例如,日曆在原始元素上彈出或日曆本身不顯示,具體取決於您如何選擇重新初始化克隆行中的嵌套日期選擇器。 (請參閱follow-up question I posted regarding the onchangeDate issue)。

也看出來哪個日期選擇器API你引用因爲有這個功能,如Bootstrap-datepickerjQuery-datepicker這礦是從美創,距離jQuery的日期選擇器API許多API

我將展示樣品如果有人遇到與我相同的問題,也可以使用這些代碼。

注意:我沒有在所有瀏覽器中測試2017年2月23日,所以我會在測試後更新。

這裏是$.rules(), $.datepicker(), and $.clone() API的一些示例代碼段:

這是我如何驗證和處理表中的行,而無需使用$("form").submit()技術。

注:我的形式在我的桌子包裹所以我有一個驗證的聲明,但我不使用form.submit()技術,而我處理的,動態驗證規則我重置和每個事件的觸發設置。

function TableEventHandlers(){ 
    var form = $("#ITEMS"); 
    var FormError = $('.item-failure',form); 
    var FormSuccess = $('.item-success',form); 
    //used to trigger datepicker on calendar selection 
    $(".hasDatepicker").on("changeDate",function(e){ 
     e.stopImmediatePropagation(); 
     $(this).trigger("focusout"); 
     //alert("onchange date" + $(this).val() + e.type); 
    }); 

    //Processes a single qty at a time w/o popout 
    $("#table_001").on("click keyup",".qty",function (e) { 
     e.stopImmediatePropagation(); 
     //reset validators 
     $(".qty").rules('remove','min'); 
     $(".qty").rules('remove','max');  
     $(".qty").rules('remove','required'); 
     $(".dp").rules('remove','required'); 
     $(".dp").rules('remove','UsaDate'); 
     $(".dp").removeClass("error").tooltip("disable").tooltip("hide"); 
     $(".qty").removeClass("error").tooltip("disable").tooltip("hide"); 
     var row = $(this).closest('tr'); 
     flag = true; 
     row.find('.dp').rules('add',{required:true,messages:{required:"Must supply a start buy date."}}); 
     row.find('.dp').rules('add',{UsaDate:true,messages:{UsaDate:"Enter date in mm/dd/yyyy format"}}); 
     hasQtys = false; 
     hadOtherQtys = false; 
     var actualQty = parseInt($(this).val(), 10); 
     var dow = $(this).data("dow"); 
     var qty = $(); 
     var num = 0;    
     var buydate = row.find(".dp"); 
     var delday = ""; 
     var quans = 0; 
     var Error = false;  
     //iterate thru tr check if multiple records 
     row.children("td").each(function(index){ 
      qty = $(this).find(".qty"); 
      if(qty.val() !== undefined){ 
       num = parseInt(qty.val(), 10); 
       //console.log(isNaN(num)+ "index=" + index); 
       if(isNaN(num)) 
        num = 0; 
       if(num > 0){ 
        hasQtys = true; 
        if(quans > 1) 
         hadOtherQtys = true; 
        quans++; 
       } 
       //Min max validation process 
       console.log(num + ">"+ +parseInt(qty.attr("max"),10) + "<"+ parseInt(qty.attr("min"),10) + "not 0 = "+ num); 
       //qty out of range: min or Max attr or != 0? 
       if(num != 0 && (num > parseInt(qty.attr("max"),10) || num < parseInt(qty.attr("min"),10))) 
       { 
        if(num > parseInt(qty.attr("max"),10)){   
         qty.rules('add',{max: parseInt(qty.attr('max')), messages: {max: "Quantity must not be greater than " + qty.attr("max")}}); 
        } 
        else{ 
         qty.rules('add',{min: parseInt(qty.attr('min')), messages: {max: "Quantity must be greater than " + qty.attr("min")}}); 
        } 
         qty.addClass("error").tooltip("enable").tooltip('show'); 
         $('.item-failure').removeClass("hidden").show().html(qty.data("originalTitle")); 
         Error = true; 
       } 
       else 
        qty.removeClass("error").tooltip("disable").tooltip("hide"); 
      }//eof undefined qty 
     }); 
     console.log("has qtys= " + hasQtys + "has hadotherQtys = " + hadOtherQtys); 
     //.EmptyRow all require qtys when empty row 
     if(row.find(".itno").hasClass("EmptyRow") && hasQtys === false) 
     { 
      row.find(".qty").rules('add',{required: true, messages: {required: "Quantity must be entered when the item request date is new"}}); 
      row.find(".qty").addClass("error").tooltip("enable"); 
      Error = true; 
     } 
     else 
     { //.EmptyRow has Qtys or .RecordRow 
      row.find(".qty").rules('remove','required'); 
      //row.find(".qty").removeClass("error").tooltip("disable"); 
     } 
     console.log("buydate valid = " + buydate.valid() + "buydate.val = " + buydate.val()); 
     //new date is valid 
     if(buydate.valid() == false || buydate.val() == ""){ 
      $('.item-failure').removeClass("hidden").show().html("You have some errors. See below."); 
      row.find(".dp").addClass("error").tooltip("enable");  
      Error = true; 
     } 
     if(Error === true) 
      return true; 
     else{ 
      //Qtys met requirements of >= max && <= min or 0  
      buydate.removeClass("error").tooltip("disable"); 
      delday = qty.data("delday"); 
      $('.item-failure').addClass("hidden").hide(); 
      $('.item-success').removeClass("hidden").html("Processing future order request...").show(); 
      ProcessRequest(row,actualQty,delday, buydate.val()); 
     }//eof valid date 
    });//eof qty event listener 

    //Iterates thru the entire row when date changed 
    //NOTE: no popout atm causes erroneous results 
    $(".dp").on("keyup focusout",function (e) { 
     e.stopImmediatePropagation(); 
     //reset validators 
     $(".qty").rules('remove','min'); 
     $(".qty").rules('remove','max');  
     $(".qty").rules('remove','required'); 
     hasQtys = false; 
     hadOtherQtys = false; 
     var row = $(this).closest('tr'); 
     $(this).rules('add',{required:true,messages:{required:"Must supply a start buy date."}}); 
     $(this).rules('add',{UsaDate:true,messages:{UsaDate:"Enter date in mm/dd/yyyy format"}}); 
     var buydate = $(this); 
     var num = 0; 
     var dow = ''; 
     var delday = ''; 
     var quans = 0; 
      flag = true; 
     var qty = $(); 
     var Error = false; 
     //console.log("dp triggered" + e.type); 
     //only check date when manually entered. 
     if(e.type === "keyup" && ($(this).valid() === false || $(this).val() ==="")) 
     { console.log(e.type + $(this).valid()); 
      $(this).addClass("error").tooltip("enable").show(); 
      $('item-failure').removeClass("hidden").html("You have some errors. See below.").show(); 
      Error = true; 
     } 
     //check for qtys in row before processing  
     row.children("td").each(function(index){ 
      qty = $(this).find(".qty"); 
      if(qty.val() !== undefined){ 
       num = parseInt(qty.val(), 10); 
       if(isNaN(num)) 
        num = 0; 
       if(num > 0){ 
        hasQtys = true; 
        if(quans > 1) 
         hadOtherQtys = true; 
        quans++; 
       } 
       //Min max or 0 validation process 
       console.log(num + ">"+ +parseInt(qty.attr("max"),10) + "<"+ parseInt(qty.attr("min"),10) + "not 0 = "+ num); 
       console.log(num > parseInt(qty.attr('max'),10));; 
       //qty out of range: min or Max attr or != 0? 
       if(num != 0 && (num > parseInt(qty.attr("max"),10) || num < parseInt(qty.attr("min"),10))) 
       { 
        if(num > parseInt(qty.attr("max"),10)){   
         qty.rules('add',{max: parseInt(qty.attr('max')), messages: {max: "Quantity must not be greater than " + qty.attr("max")}}); 
        } 
        else{ 
         qty.rules('add',{min: parseInt(qty.attr('min')), messages: {max: "Quantity must be greater than " + qty.attr("min")}}); 
        } 
         qty.addClass("error").tooltip("enable").tooltip('show'); 
         $('.item-failure').removeClass("hidden").show().html(qty.data("originalTitle")); 
        Error = true; 
       } 
      }//eof undefined qty 
     }); 
      //Empty rows require atleast one qty 
      if(row.find(".itno").hasClass("EmptyRow") && hasQtys === false){ 
       row.find(".qty").rules('add',{required: true, messages: {required: "Quantity must be entered when the item request date is new"}}); 
       row.find(".qty").addClass("error").tooltip("enable"); 
       Error = true; 
      } 
      if(Error === true) 
       return true; 
      else{ 
      //Final stage of processing multiple records 
      row.children("td").each(function(){ 
      qty = $(this).find(".qty");  
      if(qty.val() !== undefined){ 
       num = parseInt(qty.val(), 10); 
       if(isNaN(num)) 
        num = 0; 
       //console.log("buydate.valid() = " +buydate.valid()); 
       //console.log(qty.val() + "<="+ qty.attr("max") +qty.val() + ">="+ qty.attr("min")); 
       if(buydate.valid() == "1" && buydate.val() !== "" && ((row.find(".itno").hasClass("EmptyRow") && hasQtys === true) || row.find(".itno").hasClass("RecordRow"))){ 
        $('.item-failure').addClass("hidden").hide(); 
        $('.item-success').removeClass("hidden").html("Processing future order requests...").show(); 
        console.log("processing.."); 
        ProcessRequest(row,num,delday); 
       } 

      }//eof qty.val undefined 
      });//eof td children 
     }//eof error 
    });//eof event datepicker listener 

    form.validate({ 
     focusInvalid: false, // do not focus the last invalid input 
     onkeyup: function(element) { //only allow if 'onkeyup:false' is rule!! 
      var element_id = $(element).attr('NAME'); 
      if (this.settings.rules[element_id]) { 
       if (this.settings.rules[element_id].onkeyup !== false) { 
        $.validator.defaults.onkeyup.apply(this, arguments); 
       } 
      } 
     }, 
     rules: { 
      //dynamic rules worked better in this instance 
     }, 
     messages: { 
      // same with custom messages 
     },   
     showErrors: function(errorMap, errorList) { 
      // Clean up any tooltips for valid elements 
      $.each(this.validElements(), function (index, element) { 
       element = $(element); 
       NoError_ToolTip(element); 
      }); 
      // Create new tooltips for invalid elements 
      $.each(errorList, function (index, error) { 
       element = $(error.element); 
       message = error.message; 
       Error_ToolTip(element,message); 
       FormError.html("You have some errors. Please check below.").show(); 
      }); 
     },     
     invalidHandler: function (event, validator) { //display error alert on form submit  
      FormError.html("You have some errors. Please check below.").show(); 
     }, 
     submitHandler: function (form) { 
      FormSuccess.html("Processing request...").show(); 
     } 

    }); 
    $.validator.addMethod("UsaDate", function(value, element) { 
      return this.optional(element) || /^\b\d{1,2}[\/]\d{1,2}[\/]\d{4}\b/.test(value); 
    }, "Please enter mm/dd/yyyy date format"); 
    } 

這裏是我如何使用$ .clone()API從剛處理的行創建了一個新的空行:

var ProcessRequest = function(tr, count, dow){ 
     var success = $('#table_001_processing').css("color", "green").removeClass("hidden").show().html("Processing request..."); 
     //post vars 
     var recureItemNo = tr.find(".itno").html(); 
     var itemCount = count; 
     var dp = tr.find("[name='BUYDATE']"); 
     var newDate = dp.val(); 
     tempDate = dp.data("date"); 
     //clear all errors 
     tr.children("td").each(function(){ 
      $(".qty").each(function(){ 
       $(this).removeClass("error").tooltip("disable").tooltip("hide"); 
      }); 
     }); 
     //insert new row because we create new row off emptyRow 
     if(tr.find(".itno").hasClass("EmptyRow") && flag == true){ 
      console.log("this was an .EmptyRow"); 
      var randId = (Math.floor(Math.random() * 100 * 100)+1); 
      var $clone = tr.clone(); 
      $clone.insertBefore(tr); 
      //clear inputs 
      $clone.children("td").each(function(){ 
       var $input = $(this).find("input"); 
       $input.val(""); 
      }); 
      //destroy datepicker  
      var dp = $clone.find(".dp"); 
       dp.remove(); 
      //create new DatePicker(dp); 
      var dpId = $('#table_001 tr').length + 1; 
      $clone.find("td:eq(13) span").html("<input name='BUYDATE' class='dp form-control-inline' style='width:95px'; />"); 
      var newDp = $clone.find(".dp").attr("id",dpId); 
      DatePicker(newDp); 

     }else{//update took place which means future distribution no matter what 

     } 
     //getJSON web0572 complete stuff 
     //add-ons become future distributions by defaults 
     if(tr.find(".itno").hasClass("EmptyRow")) 
      tr.find(".itno").removeClass("EmptyRow").addClass("RecordRow").removeClass("live").addClass("future"); 
     if(tempDate > newDate) 
      tr.find(".itno").removeClass("live").addClass("future"); 
     if(tr.find(".itno").hasClass("future")) 
      tr.addClass("pending"); 
     //Call web057s2 add all of this below: 
     console.log("hasqtys ="+hasQtys+"itemno"); 
      //Display successful processing   
      if(hasQtys == true){  
      console.log("processed request add or update"); 
      if(hadOtherQtys == true && tr.find(".itno").hasClass("RecordRow")) 
       success.html("Item #" + recureItemNo + " successfully updated!");   
      else 
       success.html("Item #" + recureItemNo + " successfully added!"); 
      }else{ 
      console.log("processed request deleted row"); 
      tr.remove(); 
      success.html("Item #" + recureItemNo + " for " + tempDate + " successfully removed!"); 
      } 

      setTimeout(function(){ 
      success.addClass("hidden").hide().css("color","green").html("Processing..."); 
      }, 7000); 
      flag = false; 
} 

我發現,關鍵是創造動態的日期選擇器是當你克隆一個對象覆蓋舊的id,或者甚至是克隆對象的元素本身,這個例子可以在ProcessRequest函數裏看到:

NOTE: I ha d與onChangeDate事件監聽器一起玩一些遊戲,以便處理datepicker關閉的行。現在唯一的問題是onChangeDate事件偵聽器未在新克隆的對象上觸發。我試圖解除綁定事件並綁定它,但沒有運氣atm。

var DatePicker = function(that){ 
    if (jQuery().datepicker) { 
    //destroy old datepicker from clone 
    if(that.hasClass('hasDatepicker')){ 
     that.datepicker('remove'); 
    } 
     that.datepicker({ 
     showOn: "button", 
     buttonImage: "/images/calendar.png", 
     buttonImageOnly: true, 
     buttonText: 'Select a start buying date', 
     changeMonth: true, 
     changeYear: true, 
     beforeShow: function() { 
      setTimeout(function(){ 
       $('.ui-datepicker').css('z-index', 100100); 
      }, 0); 
     }, 
     onSelect: function() { 
     $(this).removeClass("error").tooltip("disable").tooltip("hide"); 
     $('.ui-datepicker').css('z-index', -1); 
     setTimeout(function(){ 
      //allows date to catchup 
     },0); 
    }, 
    onClose: function(){ 
     $(this).trigger("changeDate"); 
    }, 
     minDate: '+1', // The min date that can be selected, i.e. 30 days from the 'now' 
     maxDate: '+1y' // The max date that can be selected, i.e. + 1 month, 1 week, and 1 days from 'now' 
     //      HR MIN SEC MILLI 
     //new Date().getTime() + 24 * 60 * 60 * 1000) 
    }).datepicker(); 

    } 
} 

注:我一直在嘗試使用類似的技術,我使用隨機的ID與日期選擇器用於創建dynamic bootstrap popout confirmation dialogs但我有一些錯誤的地方正在採取兩次點擊輸入。如果我修復,我會發布結果。

我有一個datepicker錯誤,其中第一個選擇不註冊可能是因爲它嵌套在一個事件內?在做了一些研究之後,我發現有一個similar issue with angular where user had to select date twice。我在OnClose中設置了一個setTimeout,它似乎可以解決問題。我將對彈出窗口使用相同的方法,看看它是如何發揮作用的。我希望我能幫助別人!


UPDATE: 感謝artemisian,我能夠與動態datepickers解決的問題!關於克隆日期選擇器請參閱this

var DatePicker = function(that){ 
    if (jQuery().datepicker) { 
    //alert(that.attr('id')); 
     that.datepicker({ 
     showOn: "button", 
     buttonImage: "/images/calendar.png", 
     buttonImageOnly: true, 
     buttonText: 'Select a start buying date', 
     changeMonth: true, 
     changeYear: true, 
     beforeShow: function() { 
      setTimeout(function(){ 
       $('.ui-datepicker').css('z-index', 100100); 
      }, 0); 
     }, 
     onSelect: function() { 
     $('.item-failure').addClass("hidden").hide(); 
     $(this).removeClass("error").tooltip("disable").tooltip("hide"); 
     $('.ui-datepicker').css('z-index', -1); 
     setTimeout(function(){ 
      //allows date to catchup 
     },0); 
    }, 
    onClose: function(){ 
     $(this).trigger("changeDate"); 
    }, 
     minDate: '+1', // The min date that can be selected, i.e. 30 days from the 'now' 
     maxDate: '+1y' // The max date that can be selected, i.e. + 1 month, 1 week, and 1 days from 'now' 
     //      HR MIN SEC MILLI 
     //new Date().getTime() + 24 * 60 * 60 * 1000) 
    }).datepicker(); 

    if($(this).hasClass("newDp")){ 
     $(this).bind("changeDate", function(e) { // this is the missing part in my opinion 
      e.stopImmediatePropagation(); 
      $(this).trigger("focusout"); 
      alert("onchange date" + $(this).val()); 
     }); 
    //Dynamic binding on cloned datepickers only 
    $(this).on("focusout",function(){ 
    RowValidation($(this)); 
    }); 
    } 
    } 
} 

那麼我這樣做,所以我不得不重用代碼:

/************ ************************************************** * 包裝功能允許動態綁定 **************************************** ****************************************/

var RowValidation = function(that){ 
     //reset validators 
     $(".qty").rules('remove','min'); 
     $(".qty").rules('remove','max');  
     $(".qty").rules('remove','required'); 
     hasQtys = false; 
     hadOtherQtys = false; 
     var row = that.closest('tr'); 
     that.rules('add',{required:true,messages:{required:"Must supply a start buy date."}}); 
     that.rules('add',{UsaDate:true,messages:{UsaDate:"Enter date in mm/dd/yyyy format"}}); 
     var buydate = that; 
     var num = 0; 
     var dow = ''; 
     var delday = ''; 
     var quans = 0; 
      flag = true; 
     var qty = $(); 
     var Error = false; 
     //console.log("dp triggered" + e.type); 
     //only check date when manually entered. 
     if(e.type === "keyup" && (that.valid() === false || that.val() ==="")) 
     { console.log(e.type + $(that.valid()); 
      that.addClass("error").tooltip("enable").show();  
      $('item-failure').removeClass("hidden").html("You have some errors. See below.").show(); 
      Error = true; 
     } 
     //check for qtys in row before processing  
     row.children("td").each(function(index){ 
      qty = $(this).find(".qty"); 
      if(qty.val() !== undefined){ 
       num = parseInt(qty.val(), 10); 
       if(isNaN(num)) 
        num = 0; 
       if(num > 0){ 
        hasQtys = true; 
        if(quans > 1) 
         hadOtherQtys = true; 
        quans++; 
       } 
       //Min max or 0 validation process 
       console.log(num + ">"+ +parseInt(qty.attr("max"),10) + "<"+ parseInt(qty.attr("min"),10) + "not 0 = "+ num); 
       console.log(num > parseInt(qty.attr('max'),10));; 
       //qty out of range: min or Max attr or != 0? 
       if(num != 0 && (num > parseInt(qty.attr("max"),10) || num < parseInt(qty.attr("min"),10))) 
       { 
        if(num > parseInt(qty.attr("max"),10)){   
         qty.rules('add',{max: parseInt(qty.attr('max')), messages: {max: "Quantity must not be greater than " + qty.attr("max")}}); 
        } 
        else{ 
         qty.rules('add',{min: parseInt(qty.attr('min')), messages: {max: "Quantity must be greater than " + qty.attr("min")}}); 
        } 
         qty.addClass("error").tooltip("enable").tooltip('show'); 
         $('.item-failure').removeClass("hidden").show().html(qty.data("originalTitle")); 
        Error = true; 
       } 
      }//eof undefined qty 
     }); 
      //Empty rows require atleast one qty 
      if(row.find(".itno").hasClass("EmptyRow") && hasQtys === false){ 
       row.find(".qty").rules('add',{required: true, messages: {required: "Quantity must be entered when the item request date is new"}}); 
       row.find(".qty").addClass("error").tooltip("enable"); 
       Error = true; 
      } 
      if(Error === true) 
       return true; 
      else{ 
      //Final stage of processing multiple records 
      row.children("td").each(function(){ 
      qty = $(this).find(".qty");  
      if(qty.val() !== undefined){ 
       num = parseInt(qty.val(), 10); 
       if(isNaN(num)) 
        num = 0; 
       //console.log("buydate.valid() = " +buydate.valid()); 
       //console.log(qty.val() + "<="+ qty.attr("max") +qty.val() + ">="+ qty.attr("min")); 
       if(buydate.valid() == "1" && buydate.val() !== "" && ((row.find(".itno").hasClass("EmptyRow") && hasQtys === true) || row.find(".itno").hasClass("RecordRow"))){ 
        $('.item-failure').addClass("hidden").hide(); 
        $('.item-success').removeClass("hidden").html("Processing future order requests...").show(); 
        console.log("processing.."); 
        ProcessRequest(row,num,delday); 
       } 

      }//eof qty.val undefined 
      });//eof td children 
     }//eof error 

}