验证事件侦听器上的动态表行

时间:2017-02-14 16:06:45

标签: jquery validation datatables bootstrap-datepicker

我有一个html表,我使用jQuery dataTables通过AJAX填充。我在页面上有两个表单,第一个表单验证表参数,它工作正常。

第二个验证包围整个表格,我的目标是使用工具提示创建自定义验证,除非我有另一种方法可以使用提交表单验证方法验证多个输入[type =' number' ]和每行中的一个日期选择器:

input[type=number]个事件 - 点击,键入输入字段类型=数字

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

如何触发表单中行的提交?

A:在类似元素使用NAME = 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>

是否可以使用name = value方法,即使它违反了典型的DOM指南,在这些指南中您有相同的唯一ID /名称?

我想如果所有行都突出显示为红色并不重要,即使目标是用户关注的行。

注意:

每一行的最后一列都有自己的日期选择器,如果该行中的任何其他列都有值,则必须提供该行的日期。

随后,如果提供日期并且该行中其他输入字段({1}}中没有一个具有提供的值,那么我需要触发错误。

基本上,

我有两类由行[name='QTY'].RecordRow标识的行。

如果行是.EmptyRow,并且input[name='QTY']您可能想删除所有Qtys,则至少有一个.EmptyRow必须有值。

每行RecorRow必须仅在用户触发两个事件侦听器之一时才输入有效日期。

有效:

enter image description here

enter image description here

无效: enter image description here

enter image description here

这是我到目前为止所拥有的

jQuery验证:

input[name='BUYDATE']

最后,

有人会建议用表单包装每一行并验证这种方式吗?似乎如果我这样做会违反DOM指南,因为我需要使用Id来使用 jQuery Validate 。我已经看到在一个页面上使用多个唯一ID,它可以在某些情况下工作。

1 个答案:

答案 0 :(得分:1)

我决定使用两个事件监听器一次验证一个动态表行,我在两个事件监听器上重置验证;

A)输入[type = number]点击,键盘

&安培;

B)在datepicker输入焦点和keyup

我使用内联规则重置验证器,即:

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

$(".element").rules('remove',"required");即时。

我还会在创建新行后动态创建新的$("#id").datepicker()对象。

我还使用$(this).clone()在处理原始行时创建动态行。我从没想过$.clone() API会有用,但我终于找到了一个有用的实例。

据我所知,克隆的对象没有绑定到原始行的事件监听器,我认为这取决于API。我实际上有证明我用一个日期选择器的嵌套输入文本克隆一行。

我最终选择使用jQuery.remove()函数删除输入文本框,然后重新创建它并将其绑定到datepicker API,然后为其提供一个新ID以使其正常工作。

现在的问题是changeDate事件没有绑定到新的datepicker对象,我记得我试图删除id并添加一个新的id,但该元素仍然绑定到原始元素的事件,它是从克隆。

例如,日历会弹出原始元素,或者日历本身不会显示,具体取决于您选择如何从克隆的行重新初始化嵌套的datepicker。 (请参阅follow-up question I posted regarding the onchangeDate issue)。

另请注意您要引用的datepicker API,因为有许多此功能的API,例如Bootstrap-datepickerjQuery-datepicker,我的来自Metronic,来自 jQuery-datepicker API

如果有人遇到与我相同的问题,我也会展示这样的示例代码。

注意:我没有在2/23/2017的所有浏览器中测试过,所以我会在测试时更新。

以下是$.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;
}

我发现创建动态datepicker的关键是当你克隆一个对象时覆盖旧的id甚至克隆对象的元素本身,可以在ProcessRequest函数中查看一个例子:

注意:我必须使用onChangeDate事件侦听器玩一些游戏,以便在datepicker close上处理行。现在唯一的问题是没有在新的克隆对象上触发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();

  }
}

注意:我一直在尝试使用类似的技术创建dynamic bootstrap popout confirmation dialogs,我使用的是与使用随机ID的日期选择器相同的技术,但是我遇到了一些错误输入。如果我修好,我会发布结果。

我在datepicker中遇到错误,第一个选择没有注册,可能是因为它嵌套在一个事件中?经过一些研究后,我发现有一个similar issue with angular where user had to select date twice。我在OnClose中设置了一个setTimeout,它似乎纠正了问题。我将使用与弹出窗口相同的方法,看看它是如何进行的。我希望我可以帮助别人!

<强>更新 感谢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

}