E8-事关明细表里的控件事件绑定、日期的计算、明细表的求和等问题的处理办法

起因

下面的讲述的事情是从开发出差申请流程开始的。涉及的知识点偏多,且得容我慢慢梳理出来。以下篇幅可能会有点儿长,但内容我会争取写得精彩的。

图1

发起表单样式如图1,我想实现的是当修改出发日期或结束日期的时候,自动计算时长,时长不能被人为修改。并且时长要有合计。

经过

总结起来,需求还是挺简单的。那就一项一项的来。

一、解决出发日期控件和结束日期控件的事件绑定。

这里建议先读一下《E8-怎么监听表单里的日期控件被修改过_rarenmen的博客-CSDN博客》,这里讲述了关于日期控件的结构,以及需要监听的事件,是本文的一个基础知识点。

* 注:本文中,灰色字体代码为相关但非重点代码,下同。

上文提到的日期控件需要绑定事件
    $("#fieldfield10484span").bind('DOMNodeInserted',function(e){
        alert("444");
    });

 看到这里,引出了第一个问题,明细表里的日期控件的命名格式是“field9442_” + 行号 + “span”的格式,并且表单里有多少明细行,是由用户操作而来的,那么能不能在JQuery的选择器里用变量或模糊匹配呢

其实JQuery是支持选器的模糊匹配的,也测试成功了,适用于这个例子的语法如下,还有其它匹配方式,感兴趣的朋友请自行百度。

选择器模糊匹配

$("span[id^='field10484']").each(function(index,obj){

      $(obj).bind("DOMNodeInserted",function(){
        alert($(obj).attr("id"));
      });

});

 写了个HTML,试了一下,这么写,功能倒是可以实现给页面里现有的所有ID以field10484开头的SPAN标签梆定了事件,但这种方法存在两个问题:1、如果把它放在jQuery(document).ready(function(){});里,实现不了给新增行里的相应日期控件绑定事件,解决办法会在问题二里去说;2、如果这么处理,每次是给页面里所有的符合条件的控件绑定事件,仔细想,其实要做事情是当新增行的时候去给新增行里的日期控件绑定事件,那是给指定控件去绑事件的,看来要把之前的方法升级一下。在热心网友的帮助下,把绑定事件的方法改成了这样。

修改后的绑定事件方法
            for(var i = indexnum0Old;  i < indexnum0New; i++) {
                // 给指定的控件绑定事件
                (function (arg) {
                    jQuery("#field10484_"+arg+"span").bind("DOMNodeInserted", function(){
                        alert($(obj).attr("id"));
                    }); 
                }(i));//匿名function,i是实参
            }//end for

 我个人觉得,这里有两个值得关注的知识点:1、JQuery里的选择器里是要以写变量的;2、有这么一种定义匿名函数的方法,并可以直接给它传递实参。第一个问题聊到这里结束。

二、该选择在什么时候绑定控件的事件

之前提到了,如果在jQuery(document).ready(function(){});里绑定事件,作用对象只会是表单里的现有控件。就是在流程表单里设置的默认的空行里的对应控件被绑定事件了,但用户新增行的对应控件是没有绑定事件的。去分析了一下页面关于明细行的HTML代码,发现明细行是被包含在一个ID叫作detailDiv_0的DIV里。这么说,可以给detailDiv_0绑定DOMNodeInserted事件,当其中内容被改的时候,去绑定日期控件的事件。但这么做也不合适,在实测的时候,发现在点击新增的时候,触发执行了若干次的DOMNodeInserted事件。

明细行有关的HTML代码

 热心网友又给出了一个好方法。页面里有一个ID是indexnum0的控件,保存了内表的行数。可以给它绑定控件。嗯,看起来这是个好办法。这里需要注意,不能绑定change事件,要去绑定bindPropertyChange事件。

id = indexnum0的控件

 整理一下思路,实现给新增行的日期控件绑定事件。

更新一版代码

jQuery(document).ready(function(){
    var indexnum0Old = $("#indexnum0").val() * 1.0; 

    $("#indexnum0").bindPropertyChange(function(){
        var indexnum0New = $("#indexnum0").val() * 1.0;

        // 根据新旧行数的比较,判断是增行还是减行,如果是增行了,做事件绑定
        if(indexnum0New > indexnum0Old) {
            for(var i = indexnum0Old;  i < indexnum0New; i++) {
                // 给指定的控件绑定事件
                (function (arg) {

                    // 开始日期
                    jQuery("#field10484_"+arg+"span").bind("DOMNodeInserted", function(){
                        calculationDays(arg);
                    }); 

                    // 结束日期

                    jQuery("#field10485_"+arg+"span").bind("DOMNodeInserted", function(){
                        calculationDays(arg);
                    }); 
                }(i));//匿名function
                calculationDays(i); //计算天数的方法,
            }//end for
        }//end if
        indexnum0Old = indexnum0New;
    });//bindPropertyChange
});

以上代码里,calculationDays(i)是计算从开始日期到结束日期间,一共多少天,在给日期控件绑定了事件之后,调用一次这个方法,主要是解决在默认的空行里,只有默认开始日期和结束日期,但没有天数的问题。

三、怎么能让“时长”不被修改

明细表里有个字段,叫“时长”,记录从开始日期到结束日期间,一共的天数。

从需求的字面意思来看,这个问题非常简单,把“时长”设置成只读就好了。最简单的解决办法确实是这样,但新问题又来了。当用$("#field10486_" + line).val(totalDays);给“时长”赋值的时候,前台没有效果。看页面的源码可以发现,当控件属性被设置成“只读”的时候,<input>标签是存在但被隐藏的,应该是用作和后台的信息交互,用户所看到的内容其实是展示在对应的<span>标签里的文本。

只读控件的HTML结构

情况了解了,那么处理的方法也就有了。<input>控件正常赋值,判断<span>控件存不存在,如果存在,修改一下它其中的文字就好了。

代码

        $("#field10486_" + line).val(totalDays);

        if($("#field10486_" + line + "span").length>0){ // 判断<span>标签是否存在
            $("#field10486_" + line + "span").html(totalDays);
        }

四、“时长”变了,但“合计”不变怎么办

初发现这情况的时候,以为是由于“时长”设置成了“只读”造成的。这里可以说一句“实则不然”,但也有关系,当把“时长”设置成“编辑”的时候,在控件的onChange事件里有一个calSum(0)的方法,它是负责计算合计行的。参数里的0,我猜是和detailDiv_0里的0同样是代表的是第一个明细表。在用JS给"时长"对应的<input>控件赋值后,再调用一下这个方法,就可以实现计算合计。可能有些小伙伴会想,如果“时长”是可编辑的,是不是就没有这个问题了。其实在用JS去修改<input>控件的值时,onChange事件是不被触发的,依然会有同样问题。

到此,遇到的问题都讲述完了。整体粘一下代码。

<script type="text/javascript">
jQuery(document).ready(function(){
    var indexnum0Old = $("#indexnum0").val() * 1.0;

    $("#indexnum0").bindPropertyChange(function(){
        var indexnum0New = $("#indexnum0").val() * 1.0;

        // 根据新旧行数的比较,判断是增行还是减行,如果是增行了,做事件绑定
        if(indexnum0New > indexnum0Old) {
            for(var i = indexnum0Old;  i < indexnum0New; i++) {
                // 给指定的控件绑定事件
                (function (arg) {

                   // 开始日期
                    jQuery("#field10484_"+arg+"span").bind("DOMNodeInserted", function(){
                        calculationDays(arg);
                    }); 

                   // 结束日期
                    jQuery("#field10485_"+arg+"span").bind("DOMNodeInserted", function(){
                        calculationDays(arg);
                    }); 
                }(i));//匿名function
                calculationDays(i);
            }//end for
        }//end if
        indexnum0Old = indexnum0New;
    });//bindPropertyChange
});

// 根据行号,取开始日期和结束日期,计算时长
function  calculationDays(line) {
    if(line >= 0) {
        var beginDateStr = $("#field10484_" + line).val();
        var endDateStr =  $("#field10485_" + line).val();
        var totalDays, diffDate;
        var beginDate = Date.parse(beginDateStr);
        var endDate = Date.parse(endDateStr);
        diffDate = Math.abs(endDate - beginDate);
        totalDays = Math.floor(diffDate / (1000 * 3600 * 24)) + 1;
        $("#field10486_" + line).val(totalDays);

        // 触发计算合计的方法
        calSum(0);

        if($("#field10486_" + line + "span").length>0){
            $("#field10486_" + line + "span").html(totalDays);
        }
    }
}
</script>

结果

功能实现完成,至于知识点,这里先不整理了,有砖要搬,请小伙伴们自行归纳。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rarenmen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值