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

news/2024/7/11 0:47:29 标签: javascript, 开发语言, 其他, jquery

起因

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

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

结果

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


http://www.niftyadmin.cn/n/1009302.html

相关文章

【游戏逆向】D3D HOOK实现透视讲解

实现目的: 目前大部分游戏通过Direct3D实现3D效果,通过挂钩相应函数,可以实现3D透视,屏幕挂字效果。而透视,屏蔽特定效果,设置透明在很多游戏(特别是FPS)中发挥着巨大的作用! 实现思路: [D3D] DirectX的功能都是以COM组件的形式提供的。在Direct3D中,主要通过采…

ECharts x轴文本标签全部显示

如果echarts显示标签的时候没有全部显示 代码如下&#xff1a; xAxis: {axisLabel: {interval: 0, //设置文本标签全部显示rotate: 5, //如果内容重叠最好设置一下旋转&#xff0c;就不会重叠了formatter: function(value) { //如果再不行就用formatter自己来截取换行return va…

Python———运行环境搭建

不管用什么工具开发 Python 程序&#xff0c;都必须安装 Python 的运行环境。 目前最常用的是Windows 、 Linux 平台。这里 我们以Windows10为主讲解。 其实编程和平台关系不大。大家也可以使用Linux、Mac。 Windows 平台下 Python 环境搭建 第一步&#xff1a;进入 python 官…

mac m1通过qemu和grub制作操作系统引导盘

文章目录 前言grub安装引导盘FAQ参考附录qemu安装ubuntuGRUB安装到回环设备吧啦吧啦... 前言 我电脑是mac m1芯片的&#xff0c;做了如下尝试&#xff0c;最终在第4种方式下成功&#xff1a; 开始用了parallels desktop安装了ubuntu 22版本的&#xff0c;因为本机是arm64芯片…

计算机键盘顺序设计很糟糕,你知道吗

计算机键盘顺序设计非常糟糕&#xff0c;你知道吗&#xff1f; 非常有意思的一个问题 趣讲大白话&#xff1a;惯性很厉害 【趣讲信息科技214期】 **************************** 早在1714年&#xff0c;就开始相继有英、美、法、意、瑞士等国家的人发明了各种形式的打字机。 18…

初学spring5(七)AOP就这么简单

学习回顾&#xff1a;初学spring5&#xff08;六&#xff09;静态/动态代理模式 一、什么是AOP&#xff1f; AOP&#xff08;Aspect Oriented Programming&#xff09;意为&#xff1a;面向切面编程&#xff0c;通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术…

使用javax.validation.constraints校验参数合法性

在Java开发过程中&#xff0c;数据校验是一项至关重要的任务。为了确保数据的完整性和正确性&#xff0c;我们通常需要对输入的数据进行一系列的校验。javax.validation.constraints提供了一套基于注解的校验框架&#xff0c;能够让我们简洁、高效地完成数据校验工作。本文将深…

Vue计算属性与监听器

文章目录 计算属性配置项 computedHTML 结构Vue 实例数据方法计算属性绑定数据和方法完整代码 监听器配置项 watch简单类型写法深度监听写法 计算属性配置项 computed 使用 Vue 实现一个商品价格计算器&#xff0c;设置一个初始单价&#xff0c;初始数量为 1&#xff0c;用户可…