本文所实现的表格排序大致可以分为以下几个步骤:
1、取得要排序的所有行,将其引用push到一个数组中
2、根据要排序的行的情况编写数组排序时使用的比较函数
3、对包含所有行引用的数组进行排序
4、将排序后的数组按照指定的顺序把数组所引用的行重新写回DOM
如果您对使用DOM操作表格还不太熟悉,您可以参考一下《使用DOM编写浏览器兼容的Table操作》,如果您对数组的排序还不太熟悉,可以参考一下《数组排序以及在汉字排序中localeCompare()方法的使用》,因为使用DOM操作表格和数组排序是表格排序的基础。
先看一下我们示例用的代码,本文会按照上面提到的步骤一步一步的分析:
1
var
asc
=
true
;
2
var
arrayTr
=
[];
//
存放所有要排序的行引用的容器
3
function
sortTable(){
4
//
取得所有要排序的行
5
var
oTable
=
document.getElementById(
"
oTable
"
);
6
var
oTBody
=
oTable.tBodies[
0
];
7
var
allTr
=
oTBody.rows;
8
//
将要排序的行放入数组以排序
9
for
(
var
i
=
0
;i
<
allTr.length;i
++
){
10
arrayTr.push(allTr[i]);
11
}
12
//
如果是升序
13
if
(asc){
14
arrayTr.sort(compareFunc);
15
oTable.rows[
0
].title
=
"
点击降序排列表格
"
;
16
asc
=
false
;
17
}
else
{
18
//
如果是降序
19
arrayTr.reverse();
20
oTable.rows[
0
].title
=
"
点击升序排列表格
"
;
21
asc
=
true
;
22
}
23
//
将排过续的行按照数序重写回DOM
24
var
oFragment
=
document.createDocumentFragment();
25
for
(
var
j
=
0
; j
<
arrayTr.length;j
++
){
26
oFragment.appendChild(arrayTr[j]);
27
}
28
oTBody.appendChild(oFragment);
29
}
程序的5--11行实现了我们所说的第一步,这里有两个需要说明的地方,一是我们在HTML中使用了<thead/>和<tbody />标签用于分割表格的标题本分以及要排序的部分,碍于篇幅HTML代码不再展示,二是《JavaScript高级程序设计》说Table的 tBodies属性是一个JS中的集合,而不是数组,没有sort()方法,所以不能用来直接排序,关于JS集合的概念还需要我们好好研究啊,不过这不是本文的重点,这里我们想说明的重点是,tBodies不能拿来直接排序。
程序的13--22行实现了第三步,这里我们隐藏了第二步的具体实现(在后面的部分会详细说明)我们认为这样可以更好的说明我们的思路,而不会让自己纠缠于具体的方法实现导致对程序没有一个总体的认识。还要说明的是程序中我们使用了一个全局性的容器来装载排序行,所以函数执行后,arrayTr总会包含最后一次排序的行引用顺序,这时如果我们想进行倒序的话只需调用reverse()方法,而不再需要对数组进行逆向排序。
程序的24行使用了document.createDocumentFragment()可以得到一个文档碎片,documentFragment是一个不完整的document对象,主要用于存放暂时没有加入dom树的Element。作为js操作dom的缓存,十分好用,他会一次性的将改动在DOM中呈现,而不是每次操作DOM都要是客户端重绘。
下面看用于实现我们第二步的函数的具体实现:
1
/*
*
2
* 比较函数
3
* @param {Object} param1 要比较的行1
4
* @param {Object} param2 要比较的行2
5
* @return {Number} 如果param1 > param2 返回 1
6
* 如果param1 == param2 返回 0
7
* 如果param1 < param2 返回 -1
8
*/
9
function
compareFunc(oTr1,oTr2){
10
var
param1
=
oTr1.cells[
0
].childNodes[
0
].nodeValue;
11
var
param2
=
oTr2.cells[
0
].childNodes[
0
].nodeValue;
12
//
如果两个参数均为字符串类型
13
if
(isNaN(param1)
&&
isNaN(param2)){
14
return
param1.localeCompare(param2);
15
}
16
//
如果参数1为数字,参数2为字符串
17
if
(
!
isNaN(param1)
&&
isNaN(param2)){
18
return
-
1
;
19
}
20
//
如果参数1为字符串,参数2为数字
21
if
(isNaN(param1)
&&
!
isNaN(param2)){
22
return
1
;
23
}
24
//
如果两个参数均为数字
25
if
(
!
isNaN(param1)
&&
!
isNaN(param2)){
26
if
(Number(param1)
>
Number(param2))
return
1
;
27
if
(Number(param1)
==
Number(param2))
return
0
;
28
if
(Number(param1)
<
Number(param2))
return
-
1
;
29
}
30
}
对于上述代码的具体解释,请参考《数组排序以及在汉字排序中localeCompare()方法的使用》,因为我们只在10行、11行改变了取数据的方式而已。
以上我们说明了单列表格的排序思路及方法,有了这些思路我们可以很容易的扩展我们的程序,实现具有更多功能的表格排序。