jQuery 对行和列的值求和的脚本

jQuery script to sum values on rows and columns

我有以下 table 结构:

<table width="960" border="1" align="center" id="activity_table">
<tr>
    <td width="192">Activity</td>
    <td width="192" align="center">Option 1</td>                        
    <td width="192" align="center">Option 2</td>
    <td width="192" align="center">Total</td>
</tr>
<tr>
    <td>Activity 1</td>
    <td align="center">
        <input type="text" name="activity_1_option_1" id="activity_1_option_1" value="0" class="col1" size="10" />
    </td>                        
    <td align="center">
        <input type="text" name="activity_1_option_2" id="activity_1_option_2" value="0" class="col2" size="10" />
    </td>
    <td align="center">
        <input type="text" name="activity_1_total" id="activity_1_total" value="0" class="" size="10" readonly />
    </td>
</tr>
<tr>
    <td>Activity 2</td>
    <td align="center">
        <input type="text" name="activity_2_option_1" id="activity_2_option_1" value="0" class="col1" size="10" />
    </td>                        
    <td align="center">
        <input type="text" name="activity_2_option_2" id="activity_2_option_2" value="0" class="col2" size="10" />
    </td>
    <td align="center">
        <input type="text" name="activity_2_total" id="activity_2_total" value="0" class="" size="10" readonly />
    </td>
</tr>
<tr>
    <td>Activity 3</td>
    <td align="center">
        <input type="text" name="activity_3_option_1" id="activity_3_option_1" value="0" class="col1" size="10" />
    </td>                        
    <td align="center">
        <input type="text" name="activity_3_option_2" id="activity_3_option_2" value="0" class="col2" size="10" />
    </td>
    <td align="center">
        <input type="text" name="activity_3_total" id="activity_3_total" value="0" class="" size="10" readonly />
    </td>
</tr>
<tr class="total">
    <td>Total</td>
    <td align="center">
        <input type="text" name="total_activity_1" id="total_activity_1" value="0" class="" size="10" readonly />
    </td>                        
    <td align="center">
        <input type="text" name="total_activity_2" id="total_activity_2" value="0" class="" size="10" readonly />
    </td>
    <td align="center">
        <input type="text" name="grand_total" id="grand_total" value="0" class="" size="10" readonly />
    </td>
</tr>                        

我想做的是自动计算每一列和每一行的总和。

我设法编写了一个 jQuery 脚本来计算每列的总和,方法是添加 colX(其中 X 是列的编号)作为我想要的列的 class总和,但我不知道该怎么做才能为行工作。

这是我的脚本:

$('#activity_table tr:not(.total) input:text').bind('keyup change', function() {
var $table = $(this).closest('table');
var total = 0;
var thisNumber = $(this).attr('class').match(/(\d+)/)[1];

$table.find('tr:not(.total) .col'+thisNumber).each(function() {
    total += +$(this).val();
});

thisNumber++;
$table.find('.total td:nth-child('+thisNumber+') input').val(total);
});

我对你的 HTML 做了一些调整。总共 row/column 有 classes 可以让你一次 select 它们。避免使用正则表达式 selecting 元素,因为这会非常慢。如有必要,您可以使用两个 class,例如 column column123,它允许您 select 组或单个项目 class 名称。为了快速访问元素的索引,我使用 data- 属性。如果元素是由 jQuery 代码生成的,您还可以使用 JavaScript 数据对象 ("hashes") 或 jQuery 的 .data().

<html>
<head>
<script src="jquery.js"></script>
<script>
var rows = 3;
var cols = 2;

$( function() {
    var grand_total = 0;
    var row_totals = {};
    var col_totals = {};

    // I think there should be better approaches on initializing these
    for( var row = 1; row <= rows; row++ ) { row_totals[ row ] = 0 }
    for( var col = 1; col <= cols; col++ ) { col_totals[ col ] = 0 }

    $('input').each( function() {
        var $this = $(this);
        var val = $this.val() * 1; // the multiplication is to prevent string concatenation

        row_totals[ $this.attr('data-row') ] += val;
        col_totals[ $this.attr('data-col') ] += val;
        grand_total                          += val;
    } );

    $('.total.row').each( function() {
        var $this = $(this);
        $this.text( row_totals[ $this.attr('data-row') ] );
    } );

    $('.total.col').each( function() {
        var $this = $(this);
        $this.text( col_totals[ $this.attr('data-col') ] );
    } );

    $('.grand_total').text = grand_total;
} );
</script>
</head>
<body>

<table>
<tr>
<td class="total row" data-row="1"></td>
<td><input data-row="1" data-col="1" type="text" value="1">
<td><input data-row="1" data-col="2" type="text" value="2">
</tr>
<tr>
<td class="total row" data-row="2"></td>
<td><input data-row="2" data-col="1" type="text" value="3">
<td><input data-row="2" data-col="2" type="text" value="4">
</tr>
<tr>
<td class="total row" data-row="3"></td>
<td><input data-row="3" data-col="1" type="text" value="5">
<td><input data-row="3" data-col="2" type="text" value="6">
</tr>
<tr>
<td class="grand_total"></td>
<td class="total col" data-col="1"></td>
<td class="total col" data-col="2"></td>
</tr>
</table>

</body>
</html>

您可以在不引用 table.

中的任何 类、名称或 ID 的情况下执行此操作


下面的代码获取每列的总数。

它通过获取第 2 行 (tr:eq(1)) 中每个 tdcellIndex 来工作, 不是 第一个或最后一列。然后,它会过滤除第一行以外的所有行上具有匹配 cellIndextd。如果有一个 input 元素,它的值将添加到 运行 总数中。否则,我们位于列中的最后一个单元格,它获取总值。

$('td:not(:first-child):not(:last-child)',
  '#activity_table tr:eq(1)').each(function() {
  var ci= this.cellIndex;
  var total = 0;
  $('td', 
    '#activity_table tr:gt(0)')
    .filter(function() {
      return this.cellIndex === ci;
    })
    .each(function() {
      var inp= $('input', this);
      if(inp.length) {
        if(!$(this).closest('tr').is(':last-child')) {
          total+= $('input', this).val()*1;
        }
        else {
          $('input', this).val(total);
        }
      }
    });
});


下面的代码获取每一行的总数。

它遍历每一行,总计其 input 个元素。

$('#activity_table tr:gt(0)').each(function() {
  var total = 0;
  $('td:not(:first-child):not(:last-child)',
    this).each(function() {
    total+= $('input', this).val()*1;
  });
  $('input', this).last().val(total);
});


请注意 on is now preferred over bind。如果您从总计列和总计行中删除 input,您的事件处理程序将简化为:

$('#activity_table input').on('keyup change',...

我建议将所有样式移动到一个样式表中。我已经在 Fiddle:

中这样做了

Fiddle