2017-02-14 3 views
1

J'ai une table html que je remplis via AJAX en utilisant jQuery dataTables. J'ai deux formes sur la page le premier formulaire valide les paramètres de la table qui fonctionne bien. La seconde validation entoure la table entière et mon but est de créer une validation personnalisée à l'aide des info-bulles à moins que je puisse utiliser l'approche de validation de formulaire de validation pour valider plusieurs entrées [type = 'number'] et une datepicker dans chaque ligne:Valider les lignes de table dynamiques sur les écouteurs d'événements

input[type=number] événements - cliquez, keyUp le champ input type = nombre

événement input[NAME=BUYDATE] (.hasDatePicker) - onfocusout

Comment dois-je déclencher la présentation des lignes dans une forme?

A: valider une rangée à la fois, où des éléments semblables utiliser le nom = ELEMENT

ou

B: valider la forme entière en utilisant la méthode de soumettre le formulaire de validation?

Ce tableau est un des éléments de commande dynamique utilitaire

Voici mon dataTable avec une ligne d'échantillon:

<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> 

Est-il possible d'utiliser le nom = approche de la valeur, même si elle va à l'encontre les directives DOM typiques où vous avez des ID/noms uniques identiques?

Je suppose que cela n'a pas d'importance si toutes les lignes mettent en évidence en rouge, même si la cible est la ligne dans laquelle l'utilisateur a le focus dans

NOTE:.

dernière colonne de chaque ligne ont leur propre datepicker et si l'une des autres colonnes de cette ligne a une valeur, la date de cette ligne doit être fournie.

Par la suite, si la date est fournie et qu'aucun autre champ d'entrée de la ligne ([name='QTY']) de cette ligne n'a de valeur fournie, j'ai besoin d'une erreur à déclencher.

Fondamentalement,

J'ai deux types de lignes identifiées par les classes .RecordRow et .EmptyRow.

Au moins un input[name='QTY'] doit avoir une valeur si la ligne est un .EmptyRow et si un RecorRow, vous souhaiterez peut-être supprimer tous les Qtys.

La date input[name='BUYDATE'] de chaque ligne doit avoir une date valide entrée uniquement lorsque l'utilisateur déclenche l'un des deux écouteurs d'événement.

Valid:

enter image description here

ET

enter image description here

non valide: enter image description here

ET

enter image description here

C'est ce que j'ai jusqu'à présent

jQuery Validation:

$("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); 
     } 

    }); 
} 

Enfin,

Est-ce que quelqu'un suggérerait d'emballer chaque rangée avec un formulaire et de valider de cette façon? On dirait que si je l'avais fait, cela irait à l'encontre des directives DOM car j'ai besoin d'utiliser Id pour utiliser jQuery Validate. J'ai vu l'utilisation de plusieurs ID uniques sur une seule page et cela peut fonctionner dans certaines circonstances.

Répondre

1

J'ai décidé de valider les lignes de table dynamiques une à la fois en utilisant deux écouteurs d'événements où j'ai réinitialisé la validation sur deux écouteurs d'événements;

A) sur l'entrée [type = nombre] clique, keyUp

&

B) sur la focusout d'entrée datepicker et keyUp

réinitialiser les valideurs en utilisant la ligne règles ie:

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

$(".element").rules('remove',"required"); à la volée.

Je crée également de nouveaux objets $("#id").datepicker() dynamiquement après la création des nouvelles lignes.

J'ai également utilisé $(this).clone() pour créer des lignes dynamiques lors du traitement de la ligne d'origine. Je n'ai jamais pensé que le $.clone() API serait utile mais j'ai finalement trouvé un exemple où cela devient utile. D'après ce que je comprends, les objets clonés ne sont pas liés aux écouteurs d'événement de la ligne d'origine, ce qui selon moi dépend de l'API. J'ai réellement la preuve où je clone une rangée avec un texte d'entrée imbriqué d'un Dateur de date. J'ai finalement choisi de supprimer la zone de texte d'entrée en utilisant la fonction jQuery.remove() puis de la recréer et de la lier à l'API datepicker, puis lui ai donné un nouvel identifiant afin de le faire fonctionner correctement.Le problème est maintenant que l'événement changeDate ne lie pas le nouvel objet datepicker et je me souviens avoir tenté de supprimer l'identifiant et d'ajouter un nouvel identifiant mais l'élément était toujours lié aux événements de l'élément d'origine dont il était cloné . Par exemple, le calendrier apparaît sur l'élément d'origine ou le calendrier lui-même ne s'affiche pas selon la façon dont vous choisissez de réinitialiser le datpick imbriqué à partir de la ligne clonée. (S'il vous plaît voir le follow-up question I posted regarding the onchangeDate issue).

Regardez aussi pour quelle API datepicker vous faites référence parce qu'il ya beaucoup d'API pour cette fonctionnalité, comme Bootstrap-datepicker et jQuery-datepicker qui était le mien de Metronic et est de la jQuery-datepicker API

Je vais montrer l'échantillon codes de ceci aussi au cas où quelqu'un rencontre le même problème que moi.

NOTE: Je n'ai pas testé dans tous les navigateurs le 23/2/2017 donc je vais mettre à jour lors des tests.

Voici quelques extraits de code exemple pour $.rules(), $.datepicker(), and $.clone() API:

Voici comment je valide et les lignes de table de processus sans utiliser la technique $("form").submit().

REMARQUE: Ma forme enroule autour de ma table donc j'ai une déclaration de validation, mais je ne PAS utiliser la technique form.submit(), plutôt je processus en fonction des règles de validation dynamique I reset et sur chaque événement déclencheur.

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"); 
    } 

Voici comment je créé une nouvelle ligne vide en utilisant l'API à partir d'une ligne qui vient d'être traitée .clone $():

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; 
} 

Je trouve que la clé de la création dynamique datepicker est quand vous cloner un objet override l'ancien id ou même l'élément lui-même de l'objet cloné un exemple peut être vu dans la fonction ProcessRequest:

NOTE: I ha d jouer à des jeux avec l'écouteur d'événement onChangeDate afin de traiter les lignes sur datepicker close. Le seul problème est maintenant que l'écouteur d'événement onChangeDate n'est pas déclenché sur le nouvel objet cloné. J'ai essayé de délier l'événement et le lier mais pas de chance 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(); 

    } 
} 

NOTE: J'ai essayé de créer dynamic bootstrap popout confirmation dialogs en utilisant la technique similaire que je le datepicker en utilisant Ids au hasard mais je rencontre des erreurs où il prend deux fois de cliquer sur entrée. Si je répare je posterai des résultats.

J'ai eu une erreur avec le programme datepicker où la première sélection ne s'inscrivait probablement pas parce qu'elle était imbriquée dans un événement? Après avoir fait des recherches, j'ai trouvé qu'il y avait un similar issue with angular where user had to select date twice. J'ai placé un setTimeout à l'intérieur de OnClose et il a semblé corriger le problème. Je vais utiliser la même approche avec les pop-ups et voir comment ça se passe. J'espère pouvoir aider quelqu'un!


MISE À JOUR: Merci à artemisian j'ai pu résoudre le problème avec les datepickers dynamiques! S'il vous plaît voir this après en ce qui concerne clonage datepickers.

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)); 
    }); 
    } 
    } 
} 

J'ai alors fait cela donc je devais code réutilisable:

/**************************** ************************************************** * Enveloppé dans la fonction pour permettre la liaison **************************************** dynamique *************************************/

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 

}