如何透過 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

永久連結 | 評論 (7) | 此文章的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 tw

二月 15. 2009 12:21

will

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

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

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

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

will tw

二月 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 tw

三月 7. 2009 13:37

tomexou

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

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

tomexou tw

九月 2. 2009 15:49

TerryLi

不错,支持

TerryLi cn

九月 8. 2009 16:24

kenyu

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

kenyu tw

九月 8. 2009 16:50

Will 保哥

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

Will 保哥 tw

新增評論


(將顯示您的Gravatar圖示)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



線上預覽

三月 13. 2010 03:32