JavaScript + Table 系列:排序

table估计每个跟web打过交道的人都会经常接触到,跟js结合能做出很多不错的体验。
这里打算结合js做一个系列,包括一些操作和效果,虽然现在还没什么“系列”概念,只是想到什么功能就写一下。

前一阵做了个网盘,用到了table的排序,趁热打铁做一个完整的table排序类出来。

先看效果:
 名称 / 类型上传时间大小
AlertBox.js2008-9-23 11:26:573.48 K
禁止文件预览功能.txt2008-10-7 0:07:58860 b
news.xml2008-10-4 20:24:1113.74 K
详细功略+剧情流程(二).doc2008-10-7 0:07:54160.5 K
详细功略+剧情流程(一).doc2008-10-7 0:07:4362 K
1.htm2008-10-4 20:21:5411.13 K
4.htm2008-10-4 20:21:54351 b
function.js2008-10-4 20:24:112.78 K
Scroller.js2008-9-23 11:26:572.5 K
神秘园 - Nocturne.mp32008-10-7 0:07:432.97 M
new.rar2008-9-12 8:51:09423.09 K


程序的实现的是在客户端对表格进行排序,有以下特点:
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 字符顺序进行升序排列,使用参数的话可以自定义排序方法了。
这里为了使排序能适合各种类型的值,定义了一个排序函数作为参数:

ContractedBlock.gif ExpandedBlockStart.gif Code
  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);

取得了值后就根据需要的数据类型转换:

ContractedBlock.gif ExpandedBlockStart.gif Code
    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索引,第二个参数是需要设置的属性(参考【排序对象】):

ContractedBlock.gif ExpandedBlockStart.gif Code
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(); }


程序源码:

ContractedBlock.gif ExpandedBlockStart.gif Code
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(); };
    };
  }
}



下载完整实例测试

 

 

TrackBack:http://www.cnblogs.com/cloudgamer/archive/2008/10/06/1304414.html

转载于:https://www.cnblogs.com/hdjjun/archive/2008/10/08/1306068.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值