js动态表格计算问题


现在有一个动态表格,用户可以随意增加删除行(这个功能已经实现),现在的问题是:当这些行都在变化时,如何计算出合计呢?
图片描述

以下是动态表格程序:


 <script type="text/javascript">
 var $cc = function(id){



            return document.getElementById(id);

        }

    //全选
    function checkAll(target){
        var checkeds = document.getElementsByName("b_id");
        for (var i =0;i<checkeds.length;i++) {
            checkeds[i].checked=target.checked;
        }
    }


    //刷新行号
   function refreshRowNo(){

            var tbody = $cc("tbody");

            for (var i =0;i<tbody.rows.length;i++){

            tbody.rows[i].cells[0].innerHTML=i+1;

            }

            var xxx=tbody.rows.length;

          document.getElementById('xh').value=xxx;

        }




    //添加行
    function AddRow() {
    var tbody = $cc("tbody");

            var row = tbody.insertRow(tbody.rows.length);

    var sss=tbody.rows.length;
        row.insertCell(row.cells.length);
        row.insertCell(row.cells.length).innerHTML = '<input type="checkbox" name="b_id" style="max-width:20px;max-height:20px;"/>';
        row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpmc'+sss+']" style="width:120px"/>';
           row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpgg'+sss+']" style="width:120px"/>';
           row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpcz'+sss+']" style="width:120px"/>';
        row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpdw'+sss+']" style="width:120px"/>';
        row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpsl'+sss+']" style="width:120px" class="num"/>';
           row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpbiaozhun'+sss+']" style="width:120px"/>';
        row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpbeizhu'+sss+']" style="width:120px"/>';
        refreshRowNo();

    }


    //删除行
    function DelRow() {
        var checkeds = document.getElementsByName("b_id");
        var ischeck = false;
        for (var i = checkeds.length - 1; i >= 0; i--) {
            if (checkeds[i].checked) {
                ischeck = true;
                break;
            }
        }
        if (ischeck) {
            if (confirm("确定删除选中行?")) {
                for (var i = checkeds.length - 1; i >= 0; i--) {
                    if (checkeds[i].checked) {
                        var index = checkeds[i].parentNode.parentNode.rowIndex;
                        $cc("tbody").deleteRow(index - 1);
                    }
                }
                refreshRowNo();
            }
        }else{
            alert("请选中需要删除的行!");
        }
    }  

</script>
<div class="second1-right">
        <table cellpadding="1" cellspacing="2" style="border-collapse:collapse">
            <tr>
                <th style="width:40px">序号</th>
                <th style="width:max-width:20px;max-height:20px;"><input type="checkbox" onclick="checkAll(this)" /></th>
                <th style="width:240px">产品名称</th>
                <th style="width:240px">规格</th>
                <th style="width:120px">材质</th>
                <th style="width:120px">单位</th>
                <th style="width:120px">数量(台)</th>
                <th style="width:120px">标准</th>
                <th style="width:120px">备注</th>
            </tr>
            <tbody id="tbody">
                <tr>
                 <input  id="xh"type="hidden" name="hlqgcp[xuhao]" value="1" >
                    <td style="width:40px">1</td>
                    <td><input type="checkbox" name="b_id" style="max-width:20px;max-height:20px;"/></td>
                    <td><input type="text" name="hlqgcp[hlqgcpmc1]" style="width:120px"/></td>
                    <td><input type="text" name="hlqgcp[hlqgcpgg1]" style="width:120px"/></td>
                     <td><input type="text" name="hlqgcp[hlqgcpcz1]" style="width:120px"/></td>
                     <td><input type="text" name="hlqgcp[hlqgcpdw1]" style="width:120px"/></td>
                    <td><input type="text" name="hlqgcp[hlqgcpsl1]"  style="width:120px" class="num"/></td>
                   <td><input type="text" name="hlqgcp[hlqgcpbiaozhun1]" style="width:120px"/></td>
                    <td><input type="text" name="hlqgcp[hlqgcpbeizhu1]"  style="width:120px"/></td>
                </tr>

            </tbody>
            <tr>


                <td ></td>
                <td></td>
                <td style="text-align:center; color:#0087CB; ">总计:</td>
                <td></td>
                <td></td>
                 <td></td>
                <td style="text-align:center; color:#0087CB; border-right:0"></td>
                  <td></td>
                <td ></td>
            </tr>
        </table>

        <ul>
            <li>
                <input type="button" onclick="AddRow()" value="增加一行" class="second1-right-anniu"/>
                <input type="button" onclick="DelRow()" value="删除" class="second1-right-anniu"/>

            </li>
        </ul> 
        </div>

计算机科学 动态表格 JavaScript 求和

teetii 10 years, 3 months ago

原生,硬派!

不急着写代码,先看需求。“行变化时重新计算总和”这个太浅显了,事实上离需求的本质还有点远。这个需求其实暗含了这样一个三段论的分析:

  1. 表格的行增删会引发 数据变化
  2. 单元格内输入了合法内容都会引发 数据变化
  3. 数据变化 时,需要重复计算并更新总和。

“数据变化”才是这个需求的本质和枢纽。某些事件触发实质数据变化,而无论原因是什么,只要数据变化了就要触发后续的计算动作。

所以这个需求你需要一个 事件模型


事实上大多数浏览器都支持 原生的自定义事件系统 ,但偏偏恨人的是IE任何版本都不支持……

所以这时候就该上jQuery,填平浏览器之间实现不一致的坑:

http://jsfiddle.net/vw66e1v0/

这个实现的关键点在于事件冒泡。 数据变化 事件的实体只在 <table> 上绑定一次,但表格中任意子元素都可以响应 数据变化 事件。这个响应的原理是:子元素无对应事件的行为时,会将事件逐级上报,最终必然在 <table> 上统一处理。

坦桑尼亚造船厂 answered 10 years, 3 months ago

你不是可以取到指定的列吗?根据你第一个图,要求和的列是第七列,数组下标是6。
同时,你不是也可以取到有效的数据行数吗?无论你增加或删除操作,操作结束后的表格都可以映射为一个固定的二维数组,已经可以计算求和了呀,难道是我理解错误。

如果不是准备单独写操作结束后的遍历求和的方法(实际上也没有必要),在你refreshRowNo的方法中已经在做这样的事情了。每当添加完或删除完都会执行刷新行标的动作,这时已经可以取到相应栏位的值,我的思路是将其存入一个全局的数组中,以供后面求和使用。

在复选框选中或取消选中时,删除或保留数组中对应下标的值,最后在对数组的值进行求和,就可以得到你想要的总计数值了吧。

简单的代码是这样:


 var cells; //用于存储每行的数量
//刷新行号
function refreshRowNo(){
        var tbody = $cc("tbody");
        cells = [];
        for (var i =0;i<tbody.rows.length;i++){

        tbody.rows[i].cells[0].innerHTML=i+1;
        cells.push(tbody.rows[i].cells[6].innerHTML);

        }

        var xxx=tbody.rows.length;

      document.getElementById('xh').value=xxx;

    }

    //为你的checkbox点击事件加入这样的处理,我这里写的是jquery的选择方式,仅仅是想表达出这个思想。
    //或者将我的这个思路改成符合你操作逻辑的方法
    function checkClick(obj){
        //之前存下的cells数组中,index和行号的关系是index = rowNo-1,这个没有错对吧
        //所以这里根据行号获取到下标
        var index = parseInt($(obj).parent().prev('td').html())-1;

        if($(obj).prop("checked")){
            //原来没选中,现在选中的情况,需要计算入总计
            sum(index);
        }else{
            //原来选中,现在取消选中的情况,需要从总计中减掉
            minus(index);
        }
    }

    function sum(index){
        //总计那一行既然是固定的,给目标栏位加上ID应该更好操作些
        var sum = parseInt($("#sum").html()==""?"0":$("#sum").html());  //当前的总和,没有则为0
        sum += parseInt(cells[index]);
        $("#sum").html(sum); 
    }

    function minus(index){
     //总计那一行既然是固定的,给目标栏位加上ID应该更好操作些
        var sum = parseInt($("#sum").html()==""?"0":$("#sum").html());  //当前的总和,没有则为0
        sum -= parseInt(cells[index]);
        $("#sum").html(sum); 
    }

这样一来,每当你添加或者删除行后刷新行号的同时,将所有行的待计算项存入这个空数组中,然后根据checkbox的勾选情况选择相应的值进行计算。

不知道这个答案是否符合题主所述问题?

小⑤俺D嫁 answered 10 years, 3 months ago


 

<script type="text/javascript"> var $cc = function(id){ return document.getElementById(id); } //全选 function checkAll(target){ var checkeds = document.getElementsByName("b_id"); for (var i =0;i<checkeds.length;i++) { checkeds[i].checked=target.checked; } } //刷新行号 function refreshRowNo(){ var tbody = $cc("tbody"); for (var i =0;i<tbody.rows.length;i++){ tbody.rows[i].cells[0].innerHTML=i+1; } var xxx=tbody.rows.length; document.getElementById('xh').value=xxx; } //添加行 function AddRow() { var tbody = $cc("tbody"); var row = tbody.insertRow(tbody.rows.length); var sss=tbody.rows.length; row.insertCell(row.cells.length); row.insertCell(row.cells.length).innerHTML = '<input type="checkbox" name="b_id" style="max-width:20px;max-height:20px;"/>'; row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpmc'+sss+']" style="width:120px"/>'; row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpgg'+sss+']" style="width:120px"/>'; row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpcz'+sss+']" style="width:120px"/>'; row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpdw'+sss+']" style="width:120px"/>'; row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpsl'+sss+']" style="width:120px" class="num"/>'; row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpbiaozhun'+sss+']" style="width:120px"/>'; row.insertCell(row.cells.length).innerHTML = '<input type="text" name="hlqgcp[hlqgcpbeizhu'+sss+']" style="width:120px"/>'; refreshRowNo(); } //删除行 function DelRow() { var checkeds = document.getElementsByName("b_id"); var ischeck = false; for (var i = checkeds.length - 1; i >= 0; i--) { if (checkeds[i].checked) { ischeck = true; break; } } if (ischeck) { if (confirm("确定删除选中行?")) { for (var i = checkeds.length - 1; i >= 0; i--) { if (checkeds[i].checked) { var index = checkeds[i].parentNode.parentNode.rowIndex; $cc("tbody").deleteRow(index - 1); } } refreshRowNo(); } }else{ alert("请选中需要删除的行!"); } } function CountNum(){ var body = $cc('tbody'), count = 0; for(var i = body.rows.length; i--;){ //每一行的, 第7个单元格(下标为6), firstChild 为 input 的DOM对象 count += body.rows[i].cells[6].firstChild.value * 1; } return count; } </script> <div class="second1-right"> <table cellpadding="1" cellspacing="2" style="border-collapse:collapse"> <tr> <th style="width:40px">序号</th> <th style="width:max-width:20px;max-height:20px;"><input type="checkbox" onclick="checkAll(this)" /></th> <th style="width:240px">产品名称</th> <th style="width:240px">规格</th> <th style="width:120px">材质</th> <th style="width:120px">单位</th> <th style="width:120px">数量(台)</th> <th style="width:120px">标准</th> <th style="width:120px">备注</th> </tr> <tbody id="tbody"> <tr> <input id="xh"type="hidden" name="hlqgcp[xuhao]" value="1" > <td style="width:40px">1</td> <td><input type="checkbox" name="b_id" style="max-width:20px;max-height:20px;"/></td> <td><input type="text" name="hlqgcp[hlqgcpmc1]" style="width:120px"/></td> <td><input type="text" name="hlqgcp[hlqgcpgg1]" style="width:120px"/></td> <td><input type="text" name="hlqgcp[hlqgcpcz1]" style="width:120px"/></td> <td><input type="text" name="hlqgcp[hlqgcpdw1]" style="width:120px"/></td> <td><input type="text" name="hlqgcp[hlqgcpsl1]" style="width:120px" class="num"/></td> <td><input type="text" name="hlqgcp[hlqgcpbiaozhun1]" style="width:120px"/></td> <td><input type="text" name="hlqgcp[hlqgcpbeizhu1]" style="width:120px"/></td> </tr> </tbody> <tr> <td ></td> <td></td> <td style="text-align:center; color:#0087CB; ">总计:</td> <td></td> <td></td> <td></td> <td style="text-align:center; color:#0087CB; border-right:0"></td> <td></td> <td ></td> </tr> </table> <ul> <li> <input type="button" onclick="AddRow()" value="增加一行" class="second1-right-anniu"/> <input type="button" onclick="DelRow()" value="删除" class="second1-right-anniu"/> <input type="button" onclick="alert(CountNum())" value="计算总合"> </li> </ul> </div>
OHshit answered 10 years, 3 months ago

Your Answer