JavaScript html js Table排序
2009-06-15 12:08:06| 分类: JS | 标签: |字号大中小 订阅
程序的实现的是在客户端对表格进行排序,有以下特点:
1.自定义排序列、排序属性(例如innerHTML)、排序数据类型(包括int、float、date、string)、排序顺序(顺序和倒序);
2.自定义排序函数;
3.可同时设置多个排序列;
4.支持ie/ff。
网上也有很多其他的table排序函数,但有的是基于数组,有的不够灵活。我的这个能在原有table结构上加入功能,不用太多改动,基于oo的结构也易于使用(当然前提是对js有一定认识)。这里只是满足基本需求,接口可能不够完善,可以自己动手扩展。
基本步骤:
1,把需要排序的行放到tbody中(程序会直接取tbody的rows);
2,把排序行放到一个数组中;
3,按需求对数组进行排序(用数组的sort方法);
4,用一个文档碎片(document.createDocumentFragment())保存排好序的行;
5,把文档碎片appendChile到tbody中。
程序说明:
【排序函数】
排序就不得不说数组中sort这个方法,手册是这样介绍的:返回一个元素已经进行了排序的 Array 对象。也就是对一个数组进行排序,很多跟排序相关的操作都用到这个方法。
默认按照 ASCII 字符顺序进行升序排列,使用参数的话可以自定义排序方法了。
这里为了使排序能适合各种类型的值,定义了一个排序函数作为参数:
负值,如果所传递的第一个参数比第二个参数小。
零,如果两个参数相等。
正值,如果第一个参数比第二个参数大。
这些都是写自定义排序函数时要注意的。
【获取比较值】
很多时候要比较的值并不是直接取innerHTML的值,那怎么放这个比较值呢?我这里的方法是给td设置了一个属性来放这个值(例如_ext和_order),取这个值也有一点技巧,对ie来说用一般的方法取都可以,但ff就麻烦一点,对于自定义的数序需要用getAttribute来获取,对原有的属性(例如innerHTML)就需要td["属性"]这样的方式来取:
【排序对象】
排序对象主要是用来保存该排序的属性的,这里包括:
属性 默认值//说明
Attri "innerHTML";//获取数据的属性
DataType "string";//比较的数据类型
Down true;//是否按顺序
onSort function(){};//排序时执行
Compare null;//自定义排序函数
还有两个固定属性:
Index:td索引
Sort:设置当前排序对象为排序类的排序对象,并执行排序
一个table通常都有多个排序方式,排序对象的作用是保存各个排序方式的参数,排序时就直接使用当前排序对象的属性,这样各个排序方式就互相独立不会互相影响了。
还有文档碎片这里并不是必须的,但建议使用,大量dom操作时使用文档碎片会更有效率。
这里的触发对象是a,但按上去是没有边框的,因为我设置了这个样式:
使用方法:
首先实例化一个主排序对象,参数是table的id:
程序源码:
1.自定义排序列、排序属性(例如innerHTML)、排序数据类型(包括int、float、date、string)、排序顺序(顺序和倒序);
2.自定义排序函数;
3.可同时设置多个排序列;
4.支持ie/ff。
网上也有很多其他的table排序函数,但有的是基于数组,有的不够灵活。我的这个能在原有table结构上加入功能,不用太多改动,基于oo的结构也易于使用(当然前提是对js有一定认识)。这里只是满足基本需求,接口可能不够完善,可以自己动手扩展。
基本步骤:
1,把需要排序的行放到tbody中(程序会直接取tbody的rows);
2,把排序行放到一个数组中;
Each(this.tBody.rows, function(o){ this.Rows.push(o); }.bind(this));
3,按需求对数组进行排序(用数组的sort方法);
this.Rows.sort(!this._order.Compare ? this.Compare.bind(this) : this._order.Compare);
4,用一个文档碎片(document.createDocumentFragment())保存排好序的行;
var oFragment = document.createDocumentFragment(); Each(this.Rows, function(o){ oFragment.appendChild(o); });
5,把文档碎片appendChile到tbody中。
this.tBody.appendChild(oFragment);
程序说明:
【排序函数】
排序就不得不说数组中sort这个方法,手册是这样介绍的:返回一个元素已经进行了排序的 Array 对象。也就是对一个数组进行排序,很多跟排序相关的操作都用到这个方法。
默认按照 ASCII 字符顺序进行升序排列,使用参数的话可以自定义排序方法了。
这里为了使排序能适合各种类型的值,定义了一个排序函数作为参数:
Compare: function(o1, o2) { var value1 = this.GetValue(o1), value2 = this.GetValue(o2); return value1 < value2 ? -1 : value1 > value2 ? 1 : 0; },对于字符来说用localeCompare会更方便,但不支持日期和数字格式,所以这里用了大于小于号来做比较。要注意,如果为 sortfunction 参数提供了一个函数,那么该函数必须返回下列值之一:
负值,如果所传递的第一个参数比第二个参数小。
零,如果两个参数相等。
正值,如果第一个参数比第二个参数大。
这些都是写自定义排序函数时要注意的。
【获取比较值】
很多时候要比较的值并不是直接取innerHTML的值,那怎么放这个比较值呢?我这里的方法是给td设置了一个属性来放这个值(例如_ext和_order),取这个值也有一点技巧,对ie来说用一般的方法取都可以,但ff就麻烦一点,对于自定义的数序需要用getAttribute来获取,对原有的属性(例如innerHTML)就需要td["属性"]这样的方式来取:
var td = tr.getElementsByTagName("td")[this._order.Index], data = td[this._order.Attri] || td.getAttribute(this._order.Attri);取得了值后就根据需要的数据类型转换:
switch (this._order.DataType.toLowerCase()) { case "int": return parseInt(data) || 0; case "float": return parseFloat(data) || 0; case "date": return Date.parse(data) || 0; case "string": default: return data.toString() || ""; }这里要说明的是添加自定义属性并不是一个符合标准的方法,可以考虑放在title之类的属性中。
【排序对象】
排序对象主要是用来保存该排序的属性的,这里包括:
属性 默认值//说明
Attri "innerHTML";//获取数据的属性
DataType "string";//比较的数据类型
Down true;//是否按顺序
onSort function(){};//排序时执行
Compare null;//自定义排序函数
还有两个固定属性:
Index:td索引
Sort:设置当前排序对象为排序类的排序对象,并执行排序
一个table通常都有多个排序方式,排序对象的作用是保存各个排序方式的参数,排序时就直接使用当前排序对象的属性,这样各个排序方式就互相独立不会互相影响了。
还有文档碎片这里并不是必须的,但建议使用,大量dom操作时使用文档碎片会更有效率。
这里的触发对象是a,但按上去是没有边框的,因为我设置了这个样式:
a{outline:none;/*ff*/hide-focus:expression(this.hideFocus=true);/*ie*/}
使用方法:
首先实例化一个主排序对象,参数是table的id:
var to = new TableOrder("idTable");接着要添加一个排序对象,第一个参数是td索引,第二个参数是需要设置的属性(参考【排序对象】):
var order2 = to.Add(0, { onSort: function(){ Each(SetOrder._arr, function(o){ o.className = ""; }); }, Compare: function(o1, o2) { var value1 = /x/i.test(to.GetValue(o1)), value2 = /x/i.test(to.GetValue(o2)); return value1 && !value2 ? 1 : !value1 && value2 ? -1 : 0; } });然后设置一个触发对象执行排序对象的Sort方法来排序:
$("idBtn").onclick = function(){ order2.Sort(); }
程序源码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>Table排序</title> </head> <body> <style type="text/css"> .fu_list{ width:500px; border:1px solid #ebebeb;line-height:20px; font-size:12px;} .fu_list thead td{background-color:#ebebeb;} .fu_list td{padding:5px;} .fu_list a{outline:none;/*ff*/hide-focus:expression(this.hideFocus=true);/*ie*/} .fu_list a:link, .fu_list a:visited, .fu_list a:hover, .fu_list a:active{text-decoration:none;color:#333;} .fu_list thead a{padding-right:15px;} .fu_list thead a.up, .fu_list thead a.down{ background:url(http://www.fs12345.com/upphoto/cloud/5a539829-d9b9-4437-bc9c-20b32f1fc4b7.gif) right center no-repeat; } .fu_list thead a.down{background-image:url(http://www.fs12345.com/upphoto/cloud/76a4b69b-38b8-4abd-8a58-82d2ade8d526.gif);} </style> <table border="0" cellspacing="0" cellpadding="0" class="fu_list" id="idTable"> <thead> <tr> <td> <a href="javascript:void(0)" id="idTitle">名称</a> / <a href="javascript:void(0)" id="idExt">类型</a></td> <td width="150" align="center"><a href="javascript:void(0)" id="idAddtime" class="up">上传时间</a></td> <td width="50" align="center"><a href="javascript:void(0)" id="idSize">大小</a></td> </tr> </thead> <tbody> <tr> <td _ext="rar">new.rar</td> <td align="center" _order="2008/9/12 8:51:09">2008-9-12 8:51:09</td> <td align="right" _order="433247">423.09 K</td> </tr> <tr> <td _ext="js">Scroller.js</td> <td align="center" _order="2008/9/23 11:26:57">2008-9-23 11:26:57</td> <td align="right" _order="2556">2.5 K</td> </tr> <tr> <td _ext="js">AlertBox.js</td> <td align="center" _order="2008/9/23 11:26:57">2008-9-23 11:26:57</td> <td align="right" _order="3565">3.48 K</td> </tr> <tr> <td _ext="htm">1.htm</td> <td align="center" _order="2008/10/4 20:21:54">2008-10-4 20:21:54</td> <td align="right" _order="11394">11.13 K</td> </tr> <tr> <td _ext="htm">4.htm</td> <td align="center" _order="2008/10/4 20:21:54">2008-10-4 20:21:54</td> <td align="right" _order="351">351 b</td> </tr> <tr> <td _ext="xml">news.xml</td> <td align="center" _order="2008/10/4 20:24:11">2008-10-4 20:24:11</td> <td align="right" _order="14074">13.74 K</td> </tr> <tr> <td _ext="js">function.js</td> <td align="center" _order="2008/10/4 20:24:11">2008-10-4 20:24:11</td> <td align="right" _order="2844">2.78 K</td> </tr> <tr> <td _ext="mp3">紫色头发</td> <td align="center" _order="2008/10/7 0:07:43">2008-10-7 0:07:43</td> <td align="right" _order="3111293">2.97 M</td> </tr> <tr> <td _ext="doc">详细功略+剧情流程(一).doc</td> <td align="center" _order="2008/10/7 0:07:43">2008-10-7 0:07:43</td> <td align="right" _order="63488">62 K</td> </tr> <tr> <td _ext="doc">黑色头发.doc</td> <td align="center" _order="2008/10/7 0:07:54">2008-10-7 0:07:54</td> <td align="right" _order="164352">160.5 K</td> </tr> <tr> <td _ext="txt">禁止文件预览功能.txt</td> <td align="center" _order="2008/10/7 0:07:58">2008-10-7 0:07:58</td> <td align="right" _order="860">860 b</td> </tr> </tbody> </table> <input name="" type="button" value="有x的排前面" id="idBtn" /> <script type="text/javascript"> var $ = function (id) { return "string" == typeof id ? document.getElementById(id) : id; }; var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } } } Object.extend = function(destination, source) { for (var property in source) { destination[property] = source[property]; } return destination; } Function.prototype.bind = function(object) { var __method = this, args = Array.prototype.slice.call(arguments); args.shift(); return function() { return __method.apply(object, args.concat(Array.prototype.slice.call(arguments))); } } function Each(list, fun){ for (var i = 0, len = list.length; i < len; i++) { fun(list[i], i); } }; var TableOrder = Class.create(); TableOrder.prototype = { initialize: function(table) { this.tBody = $(table).tBodies[0];//tbody对象 this.Rows = [];//行集合 this._order = null;//排序对象 Each(this.tBody.rows, function(o){ this.Rows.push(o); }.bind(this)); }, //排序并显示 Sort: function() { //没有排序对象返回 if(!this._order){ return false }; //排序 this.Rows.sort(this._order.Compare || this.Compare.bind(this)); this._order.Down && this.Rows.reverse();//取反 //显示表格 var oFragment = document.createDocumentFragment(); Each(this.Rows, function(o){ oFragment.appendChild(o); }); this.tBody.appendChild(oFragment); //执行附加函数 this._order.onSort(); }, //比较函数 Compare: function(o1, o2) { var value1 = this.GetValue(o1), value2 = this.GetValue(o2); return value1 < value2 ? -1 : value1 > value2 ? 1 : 0; }, //获取比较值 GetValue: function(tr) { var td = tr.getElementsByTagName("td")[this._order.Index], data = td[this._order.Attri] || td.getAttribute(this._order.Attri); //数据转换 switch (this._order.DataType.toLowerCase()) { case "int": return parseInt(data) || 0; case "float": return parseFloat(data) || 0; case "date": return Date.parse(data) || 0; case "string": default: return data.toString() || ""; } }, //添加并返回一个排序对象 Add: function(index, options) { var oThis = this; return new function(){ //默认属性 this.Attri = "innerHTML";//获取数据的属性 this.DataType = "string";//比较的数据类型 this.Down = true;//是否按顺序 this.onSort = function(){};//排序时执行 this.Compare = null;//自定义排序函数 Object.extend(this, options || {}); //td索引 this.Index = index; this.Sort = function(){ oThis._order = this; oThis.Sort(); }; }; } } var to = new TableOrder("idTable"); function SetOrder(obj, index, options){ var o = $(obj); //_arr是记录排序项目(这里主要用来设置样式) !SetOrder._arr && (SetOrder._arr = []); SetOrder._arr.push(o); //添加一个排序对象 var order = to.Add(index, options); order.onSort = function(){ //设置样式 Each(SetOrder._arr, function(o){ o.className = ""; }); o.className = order.Down ? "down" : "up"; //取相反排序 order.Down = !order.Down } o.onclick = function(){ order.Sort(); return false; } } SetOrder("idTitle", 0); SetOrder("idExt", 0, { Attri: "_ext" }); SetOrder("idAddtime", 1, { Attri: "_order", DataType: "date" }); SetOrder("idSize", 2, { Attri: "_order", DataType: "int" }); var order2 = to.Add(0, { onSort: function(){ Each(SetOrder._arr, function(o){ o.className = ""; }); }, Compare: function(o1, o2) { var value1 = /x/i.test(to.GetValue(o1)), value2 = /x/i.test(to.GetValue(o2)); return value1 && !value2 ? 1 : !value1 && value2 ? -1 : 0; } }); $("idBtn").onclick = function(){ order2.Sort(); } </script> </body> </html>