如何透過 jQuery 進行表格內容數據的垂直加總與水平加總

分享到噗浪!

前幾天為了讓手下的工程師學習 jQuery 物件操作,出了一個小題目給他們練習。我們有一個統計表同時包括「水平加總」與「垂直加總」兩個需求,且這兩個需求已經用 ASP.NET MVC 開發完成了,都是在 View 中寫 C# 程式進行運算的,我的題目是要將運算的部分改用 jQuery 動態算出。

如下圖例,就是我們的統計表格,標示紅框的部分就是要進行 jQuery 運算的欄位,而這幾格分別都有分別標記 hTotal (水平統計) 與 vTotal (垂直統計) 類別。

統計表格,標示紅框的部分就是要進行 jQuery 運算的欄位,而這幾格分別都有分別標記 hTotal (水平統計) 與 vTotal (垂直統計) 類別

而 這個表格的 HTML 如下:

<table id="tbStat" class="styletable">
	<thead>
	<tr>
		<td>日期</td>
		<td>選項1</td>
		<td>選項2</td>
		<td>選項3</td>
		<td>選項4</td>
		<td>參加<br />人數</td>
	</tr>
	</thead>
	<tbody>
	
	<tr>
		<td>2009/2/12</td>
		<td>42</td>
		<td>33</td>
		<td>60</td>
		<td>6</td>
		<th class="hTotal">0</th>
	</tr>
	
	<tr>
		<td>2009/2/11</td>
		<td>59</td>
		<td>50</td>
		<td>85</td>
		<td>14</td>
		<th class="hTotal">0</th>
	</tr>
	
	<tr>
		<td>2009/2/10</td>
		<td>74</td>
		<td>60</td>
		<td>127</td>
		<td>16</td>
		<th class="hTotal">0</th>
	</tr>
	
	<tr>
		<td>2009/2/9</td>
		<td>64</td>
		<td>61</td>
		<td>118</td>
		<td>17</td>
		<th class="hTotal">0</th>
	</tr>
	
	<tr>
		<th>加總:</th>
		<th class="vTotal">0</th>
		<th class="vTotal">0</th>
		<th class="vTotal">0</th>
		<th class="vTotal">0</th>
		<th class="vTotal">0</th>
	</tr>
	</tbody>
</table>

也許各位也可以試著練習看看你要花多少時間將這個需求做出來,考驗一下你對 jQuery 的掌握度。

我自己實做這個需求大概花了約 5 分鐘時間用 jQuery 語法寫出來,建議各位先不要看我寫的程式碼,先用自己的方式將此功能寫出來,寫完且驗證成功後,再來看看我的寫法。

我的程式碼如下:

 $(function()
 {
	  $('.hTotal').each(function(i) {
		  var hTotal = 0;
		  $(this).parent().find('td:gt(0)')
			.each(function(i)
			{
				hTotal += parseInt($(this).text());
			});
		  $(this).text(hTotal);
	  });
	  
	  $('.vTotal').each(function(i) {
		  var vTotal = 0;
		  $(this).parent().parent()
			.find('td:nth-child(' + (i+2) +'),th:nth-child(' + (i+2) +')')
			.each(function(i)
			{
				vTotal += parseInt($(this).text());
			});
		  $(this).text(vTotal);
	  });
 });

這段程式碼分別以 $('.hTotal') 與 $('.vTotal') 開場,並且利用 parent() 與 find() 與 each() 與 nth-child 就可以運算出所有相關的儲存格內容,加總後再透過寫入儲存格內。

比較要提到的是計算 vTotal 欄位的部分,由於水平儲存格是套用 th 但其他欄位是套用 td,由於標籤不一樣,所以在使用 find() 的時候,必須指定兩次 Selector 並透過逗號分隔,才能同時取得兩個標籤的 find() 結果。

最後,我要特別推薦由黑暗執行緒站長 Jeffrey 所親自操刀錄製的 邊做邊學 jQuery 教學影片系列,這一系列的教學影片有非常鞭辟入裡的技術解說,相信看了這些影片後不只可以讓你對 jQuery 有更深一層的認識,更能讓你精通 jQuery 所有重要觀念!

相關連結

  

此文章由 will 發表於 2009/2/14 上午 10:10:51

永久連結 | 評論 (8) | 此文章的RSSRSS comment feed |

分類: JavaScript

標籤:

評論

二月 15. 2009 01:40

Ammon

如果把 th 換成 td, 可以更簡短:p

$(function(){
  var v = $('#tbStat tr:last td');
  $('#tbStat tr:gt(0)').each(function(){
      var t = 0;
      $('td', this).each(function(i){
          var txt = $(this).text();
          if (/^\d+$/.test(txt)) {
              var j = parseInt(txt);
              t += j;
              v.eq(i).html(j+parseInt(v.eq(i).text())); // .addClass('vTotal')
          }
      });
      $('td:last',this).html(t); //.addClass('hTotal')
  });
});

Ammon 台灣

二月 15. 2009 12:21

will

@Ammon: 你這段 Code 的確是比我的短,且可以在 td, th 不用加上任何 class 的情況下達到通用型的水平與垂直加總運算。這也再次證明 jQuery 的無窮魅力: 你永遠有機會寫出更完美的程式!

不過真的要挑毛病的話,我是有想到兩點:

1. 你這段 Code 的可讀性比較差。
有時後在標籤中適當的加上一些 class 有註解的效果,而且 jQuery 的程式也比較容易找到進入點,對看 Code 的人比較友善。

2. 你這段 Code 的執行速度較慢一些。
因為你對目前這範例表格的 DOM 寫入操作高達 20 次,我的只要 9 次,若對於大型表格的加總可能會有效率問題,不過這通常不是什麼太大的問題。

will 台灣

二月 16. 2009 16:25

citypig

我的解法,花了可能不止5分鐘:

var vTotal = [0,0,0,0,0];
$("tr:gt(0):lt(4)").each(function(i){
  var hTotal = 0;
  $("td:gt(0)",this).each(function(j){
    hTotal += parseInt($(this).text());
    vTotal[j] += parseInt($(this).text());
  });
  $("th",this).text(hTotal);
  vTotal[4] += hTotal;
});
$(".vTotal").each(function(i){
  $(this).text(vTotal[i]);
});

citypig 台灣

三月 7. 2009 13:37

tomexou

原題目不變,我還是覺得will寫的角度比較直覺,具高可讀性
在取vTotal時
>$(this).parent().parent()
可替代成:
$(this).parent().siblings()

這樣找的節點很少,也更直覺。

tomexou 台灣

九月 2. 2009 15:49

TerryLi

不错,支持

TerryLi 中華人民共和國

九月 8. 2009 16:24

kenyu

想請問,當動態增加一個row時
total的資料並不會重新計算
這部份要如何改呢?
感謝您的回答...Smile

kenyu 台灣

九月 8. 2009 16:50

Will 保哥

kenyu: 把計算的程式包成一個 function,動態增加 row 時你重新執行該 function 重新計算即可。

Will 保哥 台灣

八月 9. 2010 15:04

hayaman

$('.vTotal').each(function(i) {
      var vTotal = 0;
      $(this).parent().parent()
      .find('td:nth-child(' + (i+2) +'),th:nth-child(' + (i+2) +')')
      .each(function(i)
      {
        vTotal -= parseInt($(this).text());
      });
    
      $(this).text(vTotal);
    });
請問要如何改成相減的呢

hayaman 台灣

新增評論


( 您輸入的Email不會顯示於網站上 )

  Country flag

biuquote
  • 評論
  • 線上預覽
Loading