Dom + Javascript 在本机浏览器中对的表格数据进行排序

80酷酷网    80kuku.com

  dom|javascript|浏览器|排序|数据

在本机浏览器中对的表格数据进行排序
在Web应用中,数据从服务器端返回到客户端,以表格形式表现出来。如果要对数据集按指定的列排序显示,常规做法都是向服务器发出请求,服务器端程序重新从数据库中取出按指定列排序的数据,返回给客户端,页面重新显示排序后数据。
 
采用这种方式有如下缺点:
1- 响应时间延迟,每次排序都要向服务器端发送请求,等待结果返回,同时增加网络负载。
2- 编程复杂,可维护性差,而且客户端和服务器端代码耦合度很高,客户端和服务器端都要处理排序涉及的列名、排序方式,如果有分页和查询条件,都需要在客户端页面中保留,排序请求时重新传递到服务器端,当参数数量很多时极易出错。
3- 重用度很低,针对不同表格,很难抽象出一个公共程序来共用,需要逐个编写代码实现,增加工作量。
 
现在换一个角度考虑,数据既然已下载到了客户端,在重新排序时没有必要再重服务器端获取,只要对浏览器中的数据重新排序显示就可以了。要实现该目标,需要做到以下几点:
1 - 获得表格中要排序的数据,将其放入一个2维数组中。
2 - 对2维数组排序。
3 - 用排序后的数据重新更新表格。
 
利用浏览器支持的DOM(Document Object Model)和JavaScript即可实现上述目标。
 
通常页面中会很多的<table>,要获得需要排序数据所在的table,需要在<table>中增加一个id属性,便于document对象用getElementById得到该表格对象,例如要排序的表格定义如下:
 <table id="st" >
    <tr>
        <td>1</td>
        <td>2</td>
    </tr>
</table>
 
在javascript中,用var objTable = document.getElementById("st")就可得到表格对象,该对象在DOM中定义为一个Element。
 
然后用 var objRows = objTable.getElementsByTagName("tr")得到该表格中全部的行对象,ObjRows.length返回该表格行数;var rowi = objRows[i].getElementsByTagName("td")得到第i行的全部<td>节点,i从0开始计数,rowi.item(j)则可得到第i行,第j列的节点,该节点的innerHTML为该节点<td></td>之间的内容。
 
获取表格数据到2维数组的代码见源代码,此处略。
 
下面说明在javascript中2维数组的构造和排序。
javascript不支持2维数组,因此需要用数组的数组来模拟一个2维数组,其方法是先定义一个1维数组,元素个数为2维数组的行数,然后对每个元素赋一个值,值为一个数组,其元素个数为2维数组的列数。构造代码如下:
 
var rows = new Array(R);  //R为行数
for(var i = 0; i < rows.length; i++){
    rows[i] = new Array(C);    //C为列数
}
 
 
利用javascript中的Array.sort(comparer)对rows中的元素排序,比较方式由重新定义的比较函数得到。要根据第j列元素的大小排序,只要定义如下函数即可:
 
function compareCol(a,b){
   
    if (a[j] < b[j])
        return -1;
 
    if (a[j] > b[j])
        return 1;
 
   return 0;
 
}
 
因为compareCol只能有两个参数,因此j要定义为全局变量。
 
用rows.sort(compareCol)就可实现根据j列值的大小对行进行排序。根据javascript文档,字符串比较大小是按照其Unicode编码的大小来比较,对英文排序没有问题,对中文排序时就不是按通常的拼音排序,那需要javascript提供本地化支持,目前没有发现javascript此功能。该功能在java中可用java.text.Collator实现。
 
 
 以上介绍了在本地对浏览器中的数据进行排序的主要思想,为方便使用,将这些功能进行了封装,以javascript函数的提供,存放在sorttable.js文件中,在需要的页面中用<script type=text/javascript src='sorttable.js'></script>引入。
 
 
 下面说明排序函数原型和使用方法。
 
函数1 function sortTable(tableId,sortCol,compareType)
对页面中指定表格中的数据进行排序,通常第一行为标题行,排序时从第二行开始,第一次调用为升序排列,第二次为降序排列,依次轮换。
tableId    为<table id=''>中id的值,在同一个页面中要唯一。
sortCol    排序时用来比较大小的数据所在的列,从1开始计数。
compareType 排序时比较大小的方式,s-按字符串比较大小,n-按数字比较大小。
 
 
 
 函数2 function sortTableInRange(tableId,sortCol,compareType,startRow,endRow,startCol,endCol)
 
        对表格中指定的区域数据排序,有时数据第一列为流水号,最后一行为合计,这些数据不需要参与排序,可用此函数来对部分数据排序。
      
        tableId    为<table id=''>中id的值,在同一个页面中要唯一。
        sortCol    排序时用来比较大小的数据所在的列,从1开始计数。
        compareType 排序时比较大小的方式,s-按字符串比较大小,n-按数字比较大小。
        startRow,endRow 要排序区域开始和结束行号,从1开始计数。例如对第2行到第7行排序,startRow=2,endRow=7
        startCol,endCol  要排序区域开始和结束列号,从1开始计数。
 
 
 
 
 
存在的问题:
1- 中文不能按拼音排序。
 
 
要注意的问题:
要排序的table必须用ID标示,并要作为参数传给排序函数,表格中的数据应该是可以排序的,否则结果不可预知;要排序的表格不能有嵌套表,否则排序出错。
 
 
本函数已在IE6.0 ,FireFox1.01中运行通过。源代码和例子代码见后。
 
 
 
 
参考资料:
 
Danny Goodman with Michael Morrison   JavaScript Bible 5th  ,John Wiley and Sons  2004
 
David Flanagan  JavaScript The Definitive Guide 4th ,  O'Reilly  2001
 
 
 
 
 
 附源代码:要运行例子,需要将javascript代码保存到sorttable.js文件中,html部分代码保存到同一目录下另一文件中即可。
 
 
sorttable.js
 
 //=========================================================
 //
 //  在本机对浏览器页面表格中的数据行进行排序的javascript函数
 // 
 //  author William  QQ: 22967225
//  create date 2005-12-2
 //  version 1.0
 //=========================================================

 //column index for sort
 var indexCol;
 //比较函数,用于Array.sort()排序时比较用。
 //本函数比较数组元素array1[indexCol]和元素array2[indexCol]Unicode值的大小
 function arrayCompare(array1,array2){
  //alert(array1.length+"--"+array1[indexCol]);
  if (array1[indexCol] < array2[indexCol])
   return -1;
  if (array1[indexCol] > array2[indexCol])
   return 1;
 
  return 0;
 
 }
 //比较数组元素array1[indexCol]和元素array2[indexCol]的数值大小
 function arrayCompareNumber(array1,array2){
 
  if (parseInt(array1[indexCol]) < parseInt(array2[indexCol]))
   return -1;
  if (parseInt(array1[indexCol]) > parseInt(array2[indexCol]))
   return 1;
 
  return 0;
 }

 //与arrayCompare相反方式比较大小,用于倒序使用
 function arrayCompareRev(array1,array2){
 
  if (array1[indexCol] < array2[indexCol])
   return 1;
  if (array1[indexCol] > array2[indexCol])
   return -1;
 
  return 0;
 
 }
 //与arrayCompareNumber相反方式比较大小,用于倒序使用
 function arrayCompareNumberRev(array1,array2){
  if (parseInt(array1[indexCol]) < parseInt(array2[indexCol]))
   return 1;
  if (parseInt(array1[indexCol]) > parseInt(array2[indexCol]))
   return -1;
 
  return 0;
 }
 
 //define a 2-dimension array
 function BiArray(rows,cols){
 
  //simulate multidimension array
  this.rows = rows;
  this.cols = cols;
 
  //construct array
  var lines = new Array(rows);
  for(var i = 0;i < lines.length; i++){
   lines[i] = new Array(cols);
  }
 
 
  // 设置数组在(i,j)的元素值为value
  this.setElement = function(i,j,value){ lines[i][j] = value; };
 
  // 获取数组在(i,j)处元素的值
  this.getElement = function(i,j){return lines[i][j];};
 
  // 返回数组第i行所在的数组
  this.getLine = function(i){return lines[i];};
 
  // 根据第j列字符串的值,对数组的行进行排序,排序结果为升序
  this.sortLine = function(j){
       indexCol = j;
       lines.sort(arrayCompare);
      };
 
  // 根据第j列数值的值,对数组的行进行排序,排序结果为升序
  this.sortLineByNumber = function(j){
       indexCol = j;
       lines.sort(arrayCompareNumber);
      };
 
  // 根据第j列字符串的值,对数组的行进行排序,排序结果为倒序
  this.sortLineRev = function(j){
       indexCol = j;
       lines.sort(arrayCompareRev);
      };
 
  // 根据第j列数值的值,对数组的行进行排序,排序结果为倒序
  this.sortLineByNumberRev = function(j){
       indexCol = j;
       lines.sort(arrayCompareNumberRev);
      };
  //将二维数组转为字符串格式
  this.toString = function(){
       var rst ="";
       for(var i = 0; i < lines.length; i++){
        for(var j = 0; j < lines[i].length; j++){
         rst += lines[i][j];
         rst += '\t';
        }
        rst += '\n';
       }
       return rst;
      };
 } // end of BiArray define
 
 //ascending or descending
 var asce = true;

 /**
  对表格中指定范围的数据进行排序
  tableId    要排序的表格的id,值格式为 <table id="tb1" >
  sortCol    用于排序的列号,从1开始计数
  compareType   排序时比较方式,s-按字符串比较,n-按数值比较
  startRow   排序范围起始行号,从1开始计数
  endRow     排序范围结束行号,从1开始计数
  startCol   排序范围起始列号,从1开始计数
  endCol     排序范围结束列号,从1开始计数
 */
 function sortTableInRange(tableId,sortCol,compareType,startRow,endRow,startCol,endCol){
 
 
  try{
   var table = document.getElementById(tableId);
   // get all row object of the table
   var objRows = table.getElementsByTagName("tr");
   //alert(objRows.length);
  
   endRow = (endRow < objRows.length ? endRow : objRows.length);
  
   var sortRows = endRow - startRow + 1;
   //alert("sortRows "+sortRows);
   if (sortRows < 2) //only one line,don't sort
    return ;
  
  
   endCol = (endCol < objRows[1].getElementsByTagName("td").length ? endCol :
     objRows[1].getElementsByTagName("td").length);
  
  
   // column number of sort
   //var cols = objRows[1].childNodes.length;
   var cols = endCol - startCol + 1;
   
  
   
   // define a array to store table cell and sort them
   var tabData = new BiArray(sortRows,cols);
  
  
   var ari = 0;
   // retrived table cell data save to array
   for(i = startRow - 1; i < endRow; i++){
    //retrived all <td> cell
    var cells = objRows[i].getElementsByTagName("td");
   
    var arj = 0;
    for(var j = startCol - 1; j < endCol; j++){
     tabData.setElement(ari,arj,cells.item(j).innerHTML);
     arj++;
    
    }
    ari++;
   }
  
   if (asce){
    if (compareType == "n" || compareType == 'N')
     tabData.sortLineByNumber(sortCol- startCol);
    else
     tabData.sortLine(sortCol - startCol);
    asce = false;
   }else{
    if (compareType == "n" || compareType == 'N')
     tabData.sortLineByNumberRev(sortCol - startCol);
    else
     tabData.sortLineRev(sortCol - startCol);
    asce = true;
   }
   ari = 0;
   //update table data with array
   for(i = startRow -1; i < endRow; i++){
    //retrived all <td> cell
    var cells = objRows[i].getElementsByTagName("td");
   
    arj = 0;
    for(var j = startCol - 1; j < endCol; j++){
     cells.item(j).innerHTML = tabData.getElement(ari,arj);
     arj++;
    }
    ari++;
   }

  }catch(e){
   alert(e);
  }
 }

 /**
  对表格除第一行外的数据行排序,是sortYableInRange(tableId,sortCol,compareType,2,tabRows,1,tabCols)
  的特例。
  tableId    要排序的表格的id,值格式为 <table id="tb1" >
  用于排序的列号,从1开始计数
  compareType   排序时比较方式,s-按字符串比较,n-按数值比较
 */
 function sortTable(tableId,sortCol,compareType){
 
 
  try{
   var table = document.getElementById(tableId);
   // get all row object of the table
   var objRows = table.getElementsByTagName("tr");
   //alert(objRows.length);
  
  
   var endRows = objRows.length;
  
   if (endRows < 2) //only one line,don't sort
    return ;
  
   // column number of table
   var cols = objRows[1].getElementsByTagName("td").length;
  
  
   sortTableInRange(tableId,sortCol,compareType,2,endRows,1,cols);
  
  }catch(e){
   alert(e);
  }
 }

 ==========javascript 代码结束============
 
例子HTML页面代码
 
<html>
<head content="text/html; charset=gb2312" >
<script type="text/javascript" src="sorttable.js">
</script>
</head>
 <body>
  常规排序例子

  <table id="t1" border="1">
   <tr>
    <td width="20%"><a href="#" >城市</a></td>
    <td width="30%"><a href="#" >品牌</a></td>
    <td width="30%"><a href="#" >销量</a></td>
   </tr>
   <tr>
   
    <td><a href="#" >北京</a></td>
    <td>GOOGLE</td>
    <td>64</td>
   </tr>
   <tr>
    <td>上海</td>
    <td>CISCO</td>
    <td>54</td>
   </tr>
   <tr>
    <td>广州</td>
    <td>MS</td>
    <td>9</td>
   </tr>
   <tr>
   
    <td>南京</td>
    <td>INTEL</td>
    <td>120</td>
   </tr>
  </table>
 

 
对部分数据排序例子(对第2-5行,第2-4列区域排序)

  <table id="t2" border="1">
   <tr>
    <td>序号</td>
    <td width="20%"><a href="#" >城市</a></td>
    <td width="30%"><a href="#" >品牌</a></td>
    <td width="30%"><a href="#" >销量</a></td>
   </tr>
   <tr>
    <td>1</td>
    <td><a href="#" >北京</a></td>
    <td>GOOGLE</td>
    <td>64</td>
   </tr>
   <tr>
    <td>2</td>
    <td>上海</td>
    <td>CISCO</td>
    <td>54</td>
   </tr>
   <tr>
    <td>3</td>
    <td>广州</td>
    <td>MS</td>
    <td>9</td>
   </tr>
   <tr>
    <td>4</td>
    <td>南京</td>
    <td>INTEL</td>
    <td>120</td>
   </tr>
  </table>
 </body>
</html>



分享到
  • 微信分享
  • 新浪微博
  • QQ好友
  • QQ空间
点击: