一个GridView客户端扩展脚本库

近期有个项目频繁使用到GridView控件,于是动手写了个针对GridView的客户端脚本库,用来优化GridView的用户体验,包括行选择(单行选定,多行选定),行点击(单击,双击),行操作(删除,移动)等。兼容包括IE在内的多种内核浏览器。

示例文件下载:http://files.cnblogs.com/wfyfngu/ClientTableDemo.zip

下面是使用该库的一个典型用法。

<! 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 >
  
< title > ClientTable.js Test </ title >
  
<!-- 引入GridView样式文件 -->
  
< link  rel ="stylesheet"  type ="text/css"  href ="/css/grid.css"   />
  
<!-- ClientTable必须的文件 -->
  
< script  type ="text/javascript"  src ="/script/RINDEX.js" ></ script >
  
< script  type ="text/javascript"  src ="/script/ClientTable.js" ></ script >
</ head >

< body >

  
< asp:GridView  id ="gridview1"  runat ="server" >
    
< EmptyDataTemplate >
      
< center > There're no items to show in this view. </ center >
    
</ EmptyDataTemplate >
  
</ asp:GridView >

< script  type ="text/javascript" >
//  实例化一个ClientTable对象
var  ETABLE  =   new  ClientTable( ' gridview1 ' null null );
//  例化一个ClientTable对象,隐藏表格的第一和第二列
//
 var ETABLE = new ClientTable('gridview1', null, [0,1]);
//
 捕捉行选中事件
ETABLE.onSelectChange  =   function (row) {
 
//  弹出最后一个被选中的行的索引
 alert(row.rowIndex);
};
</ script >

</ body >

</ html >

 

下面附上各个文件的代码。

RINDEX.js


/* *
 * @author wfyfngu
 * @create Apri 25, 2008
 
*/


/* *
 * @namespace RINDEX
 
*/
if  ( typeof  RINDEX  ==   ' undefined '
    RINDEX 
=  {};

/* *
 * @namespace RINDEX.Widget
 
*/
if  ( typeof  RINDEX.Widget  ==   ' undefined '
    RINDEX.Widget 
=  {};


/* *
 * RINDEX 控件公共实用类
 * @class RINDEX.Utility
 * @static
 
*/
RINDEX.Utility 
=  {

    
/* *
     * 获取一个值,该值指示当前的浏览器是否是IE
     * @field isIE
     * @type Boolean
     
*/
    isIE: document.all 
?   true  :  false ,
    
    
/* *
     * 获取一个 HTML 元素
     * @method getObject
     * @param obj {HTMLElement || String} 要获取的元素或元素的ID
     * @return HTMLElement
     
*/
    getObject: 
function (obj){
        
if  ( typeof  obj  ==   ' string ' ) {
            
if  ( this .isIE) 
                obj 
=  document.all(obj);
            
else  
                obj 
=  document.getElementById(obj);
        }
        
return  obj;
    },
    
    
/* *
     * 生成具有指定标签的 HTML 元素
     * @method createObject
     * @param tag {String} 要生成的元素的标签
     * @param id {String || Null} 生成的元素的ID
     * @return HTMLElement
     
*/
    createObject: 
function (tag, id){
        
var  obj  =  document.createElement(tag);
        
if  (obj) {
            
if  (id  !=   null
                obj.id 
=  id;
            
return  obj;
        }
        
// return document.body;
         return   null ;
    },
    
    
/* *
     * 追加指定的 CSS 样式到目标 HTML 对象
     * @method addCSS
     * @param obj {HTMLElement} 要追加样式的目标对象
     * @param className {String} CSS 样式名称
     * @return void
     
*/
    addCSS: 
function (obj, className){
        
try  {
            
var  css  =  obj.className;
            
var  index  =  css.indexOf(className);
            
if  (index  <   0
                css 
+=   '   '   +  className;
            
            obj.className 
=  css;
        } 
        
catch  (e) {
            
//  TODO : 删除下一行
            confirm( ' Exception: '   +  e);
        }
    },
    
    
/* *
     * 从目标 HTML 对象删除指定的 CSS 样式
     * @method addCSS
     * @param obj {HTMLElement} 要删除样式的目标对象
     * @param className {String} CSS 样式名称
     * @return void
     
*/
    removeCSS: 
function (obj, className){
        
try  {
            
var  css  =  obj.className;
            
var  cssArr  =  css.split( '   ' );
            
            
var  nwCss  =   '' ;
            
            
for  ( var  i  =   0 ; i  <  cssArr.length; i ++ ) {
                
if  (cssArr[i]  ==  className) 
                    
continue ;
                nwCss 
+=  cssArr[i]  +   '   ' ;
            }
            
            obj.className 
=  nwCss;
            
        } 
        
catch  (e) {
            
//  TODO : 删除下一行
            confirm( ' Exception: '   +  e);
        }
    },
    
    
/* *
     * 使用指定的数值格式化表格
     * @method formatTable
     * @param tableObject {HtmlTableElement} 要格式化的表格
     * @param border {Number} 表格的边框宽度
     * @param cellSpacing {Number} 表格单元格的间距
     * @param cellPadding {Number} 表格中单元格的边距
     * @param align {String} 表格的对齐方式
     * @return void
     
*/
    formatTable: 
function (tableObject, border, cellSpacing, cellPadding, align){
        
if  (border  ==   null   ||  isNaN(parseInt(border))) 
            border 
=   0 ;
        
else  
            border 
=  parseInt(border);
        
        
if  (cellSpacing  ==   null   ||  isNaN(parseInt(cellSpacing))) 
            cellSpacing 
=   0 ;
        
else  
            cellSpacing 
=  parseInt(border);
        
        
if  (cellPadding  ==   null   ||  isNaN(parseInt(cellPadding))) 
            cellPadding 
=   0 ;
        
else  
            cellPadding 
=  parseInt(border);
        
        tableObject.border 
=  border;
        tableObject.cellPadding 
=  cellSpacing;
        tableObject.cellSpacing 
=  cellPadding;
        
if  (align) 
            tableObject.align 
=  align;
    },
    
    
/* *
     * 还原因单击,双击或其它交互引起的任何控件格式的改变
     * 通常运用于FireFox等非IE内核的浏览器
     * @method refreshControl
     * @return void
     
*/
    refreshControl: 
function (){
        
var  sel;
        
if  (window.getSelection) {
            sel 
=  window.getSelection();
        }
        
else  
            
if  (document.getSelection) {
                sel 
=  document.getSelection();
            }
            
else  
                
if  (document.selection) {
                    sel 
=  document.selection;
                }
        
        
if  (sel) {
            
if  (sel.empty) {
                sel.empty();
            }
            
else  
                
if  (sel.removeAllRanges) {
                    sel.removeAllRanges();
                }
                
else  
                    
if  (sel.collapse) {
                        sel.collapse();
                    }
        }
    },
    
    
/* *
     * @method toString
     * @return String
     
*/
    toString: 
function (){
        
return   ' [Object:RINDEX.Utility] ' ;
    }
    
};

/* ============================================================================================== */

/* *
 * @class RINDEX.Lang
 * @static
 
*/
RINDEX.Lang 
=  {
    
    
/* *
     * 检查指定的对象是否是数组
     * @param {Object} input 要检查的对象
     * @return Boolean
     
*/
    isArray : 
function (input) {
        
if  (input  &&  input.slice  && input.push)
            
return   true ;
        
return   false ;
    },
    
    
/* *
     * 检查指定的对象是否是数字
     * @param {Object} input 要检查的对象
     * @return Boolean
     
*/
    isNumber : 
function (input) {
        
return   typeof  input  ==   ' number '   &&  isFinite(input);
    },
    
    
/* *
     * 从父类复制方法到指定的子类
     * @param subClass {Function}  子类
     * @param superClass {Function} 父类
     
*/
    extend : 
function (subClass, superClass) {
        
if  ( ! subClass ||! superClass) {
            
throw   new  Error( " Call RINDEX.Lang.extend failed, not all arguments are included. " );
        }
        
var  F  =   function () {};
        F.prototype
= superClass.prototype;
        subClass.prototype
= new  F();
        subClass.prototype.constructor
= subClass;
        subClass.superclass
= superClass.prototype;
        
if  (superClass.prototype.constructor  ==  Object.prototype.constructor) {
            superClass.prototype.constructor
= superClass;
        }
    },
    
    
/* *
     * @private
     
*/
    toString : 
function () {
        
return   ' [RINDEX.Lang] ' ;
    }

    
};

/* ============================================================================================== */

/* *
 * 可以用来表示一个平面坐标中某一特定位置的类
 * @class RINDEX.Position
 * @param {number} x X坐标
 * @param {number} y Y坐标
 
*/
RINDEX.Position 
=   function (x,y) {
    
    
/* *
     * X坐标
     * @field x
     * @type Number
     
*/
    
this .x  =  x;
    
    
/* *
     * Y坐标
     * @field y
     * @type Number
     
*/
    
this .y  =  y;
    
    
if ( ! RINDEX.Lang.isNumber( this .x))
        
this .x  =   0 ;
    
if ( ! RINDEX.Lang.isNumber( this .y))
        
this .y  =   0 ;
        
};

 

ClientTable.js

//  JScript File

if ( typeof  RINDEX  ==   ' undefined '   ||   typeof  RINDEX.Widget  ==   ' undefined ' )
    
throw   new  Error( ' Required file "RIndex.js" was missing. ' );

ClientTable 
=   function (tableToConvert, excludeRowClassNameArr, hiddenColumnIndexArr) {
  
  
this .table  =  RINDEX.Utility.getObject(tableToConvert);
    
    
this .selectedRows  =  [];
    
    
this .disabled  =   false ;
    
    
/* *
     * @field multiSelection
     * 获取一个值,该值指示是否可以同时选中多行
     *@type Boolean
     
*/
    
this .multiSelection  =   true ;
    
    
this .excludeClassName  =  excludeRowClassNameArr;
    
this .hiddenColumnIndex  =  hiddenColumnIndexArr;  //  要隐藏的列

    
if ( this .table  !=   null ) {
      
this .table.onselectstart  =   function () { return   false ;};
      RINDEX.Utility.formatTable(
this .table);
      RINDEX.Utility.addCSS(
this .table, ' editTable ' );
      
this ._init();
    }
  
};


ClientTable.prototype 
=  {

  
//  Events
  onRowSelected :  function (row) {
        
return   true ;
    },
    
  onSelectChange : 
function (row) {
        
return   true ;
    },
    
    onDblClick : 
function (row) {
        
return   true ;
    },

  _init : 
function () {
    
this ._format();
    
if ( ! this .disabled) {
      
this ._attachEvent();
    }
  },
  
  _format : 
function () {
    
if ( this .table.rules)
      
this .table.rules  =   ' none ' ;
    
var  rowCount  =   this .table.rows.length;
    
var  cellCount  =   null ;
    
var  tblHeader, tblRow;
    
    
//  Hide the haeder row
    tblHeader  =   this .table.rows[ 0 ];
    
if ( 0   in  tblHeader.cells) {
      
if (tblHeader.cells[ 0 ].tagName.toUpperCase()  ==   ' TH ' ) {
        
this ._hidColume( this .table.rows[ 0 ]);
      }
    }
    
    
//  Hide all other rows
     for ( var  i = 1 ; i < rowCount; i ++ ) {
      tblRow 
=   this .table.rows[i];
      
this ._hidColume(tblRow);
      
      
if ( this ._skipRow(tblRow))
        
continue ;
      
if (cellCount  ==   null ) {
        cellCount 
=  tblRow.cells.length;
      }
      
for ( var  cell = 0 ; cell < cellCount; cell ++ ){
        tblRow.cells[cell].className 
=   ' item- '   +  ((i + 1 ) % 2 );
      }
    }
  },
  
  _hidColume : 
function (rowEL) {
    
if ( this .hiddenColumnIndex  &&   this .hiddenColumnIndex.length) {
      
var  indexCount  =   this .hiddenColumnIndex.length;
      
if (indexCount > 0 ) {
      
        
if ( this ._skipRow(rowEL)) {
          rowEL.childNodes[
0 ].colSpan  -=  indexCount;
        } 
else  {
          
for ( var  cell = 0 ; cell < rowEL.cells.length; cell ++ ) {
            
for ( var  index = 0 ; index < indexCount; index ++ ){
              
if ( this .hiddenColumnIndex[index]  ==  cell) {
                rowEL.cells[cell].style.display 
=   ' none ' ;
              }
            }
          }
        }
        
      }
    }
  },
  
  _attachEvent : 
function (event) {
    
var  rowCount  =   this .table.rows.length;
    
var  tblRow;  var  self  =   this ;
    event 
=  event  ||  window.event;
    
for ( var  i = 1 ; i < rowCount; i ++ ) {
      tblRow 
=   this .table.rows[i];
      
if ( this ._skipRow(tblRow))
        
continue ;
      tblRow.onclick 
=   function (event) {
        self.select(
this , event);
      };
      tblRow.ondblclick 
=   function () {
        self.onDblClick(
this );
      };
    } 
  },
  
  _skipRow : 
function (rowEL) {
    
if (rowEL.className  &&   this .excludeClassName  &&   this .excludeClassName.length) {
      
for ( var  i = 0 ; i < this .excludeClassName.length; i ++ ) {
        
if ( this .excludeClassName  ==  rowEL.className)
          
return   true ;
      }
    }
    
return   false ;
  },
  
  select : 
function (row, event) {
    
        event 
=  event  ||  window.event;
            
        
if (RINDEX.Lang.isNumber(row))
            row 
=   this .table.rows[row];
            
        
if ( this .multiSelection  ==   false ) {
        
          
if ( this .selectedRows.length  >   0 ) {
            
if ( this .selectedRows[ 0 !=  row) {
              
this .unSelect( this .selectedRows[ 0 ]);
              
this .selectedRows  =  [row];
              
this ._appendSelectStyle(row);
              
this .onRowSelected(row);
                    
this .onSelectChange(row);
            }
          } 
else  {
            
this .selectedRows  =  [row];
            
this ._appendSelectStyle(row);
            
this .onRowSelected(row);
                
this .onSelectChange(row);
          }
        }
        
        
else  {
            
            
var  contains  =   false ;
            
for ( var  i = 0 ; i < this .selectedRows.length; i ++ ) {
                
if ( this .selectedRows[i]  ==  row) {
                    contains 
=   true ;
                    
break ;
                }
            }

            
if (event.ctrlKey) {
                
                
if ( ! contains) {
                    
this .selectedRows.push(row);
                    
this ._appendSelectStyle(row);
                    
this .onRowSelected(row);
                    
this .onSelectChange(row);
                } 
else  {
                    
this .unSelect(row);
                }
            }
            
            
else   if (event.shiftKey) {
            
              
var  baseRow  =   0 ;
              
if ( this .selectedRows.length  >   0 )
                baseRow 
=   this .selectedRows[ this .selectedRows.length - 1 ].rowIndex
                
              
var  nwArr  =  [];
              
var  rowIndex  =  row.rowIndex;
              
              
if (baseRow  <  rowIndex) {
                    
for ( var  value  =  rowIndex; value >= baseRow; value -- ) {
                            nwArr.push(value);
                    }
                } 
else  {
                    
for ( var  value  =  rowIndex; value <= baseRow; value ++ ) {
                            nwArr.push(value);
                    }
                }

                
this ._clearAllSelection();
                
                
for ( var  i = 0 ; i < nwArr.length; i ++ ) {
                  
this .selectedRows.push( this .table.rows[nwArr[i]]);
                  
this ._appendSelectStyle( this .table.rows[nwArr[i]]);
                }
                
                
this .onSelectChange(row);
                
            }
            
            
else  {
                
                
this ._clearAllSelection();
                
                
this .selectedRows.push(row);
                
this ._appendSelectStyle(row);
                
this .onRowSelected(row);
                
this .onSelectChange(row);
            }
            
        }
        
        RINDEX.Utility.refreshControl();
        
    },
    
    unSelect : 
function (row) {
      
if ( this .disabled)  return  row;
        
if (RINDEX.Lang.isNumber(row))
            row 
=   this .table.rows[row];
            
        
var  index  =   - 1 ;
        
for ( var  i = 0 ; i < this .selectedRows.length; i ++ ) {
            
if ( this .selectedRows[i]  ==  row) {
                index 
=  i;
                
break ;
            }
        }
        
        
if (index  >   - 1 ) {
            
this .selectedRows  =
                
this .selectedRows.slice( 0 ,index).concat( this .selectedRows.slice(index + 1 ));
            
this ._clearSelectStyle(row);
            
this .onSelectChange(row);
        }
            
    },
    
    moveUp : 
function (rowEL) { 
      
var  currentRowIndex  =  rowEL.rowIndex;
      
if (currentRowIndex < 2 )
        
return ;
      
var  nwRow  =   this .table.insertRow(currentRowIndex - 1 );
      
var  tempCell, rawCell;
      
for ( var  i = 0 ; i < rowEL.cells.length; i ++ ) {
        rawCell 
=  rowEL.cells[i];
        tempCell 
=  nwRow.insertCell(i);
        tempCell.innerHTML 
=  rawCell.innerHTML;
        tempCell.className 
=  rawCell.className;
      }
      
this .remove(rowEL);
      
this ._attachEvent();
      
this .select(nwRow);
    },
    
    moveDown : 
function (rowEL) {
      
var  currentRowIndex  =  rowEL.rowIndex;
      
if (currentRowIndex == this .table.rows.length - 1 )
        
return ;
      
var  nwRow  =   this .table.insertRow(currentRowIndex + 2 );
      
var  tempCell, rawCell;
      
for ( var  i = 0 ; i < rowEL.cells.length; i ++ ) {
        rawCell 
=  rowEL.cells[i];
        tempCell 
=  nwRow.insertCell(i);
        tempCell.innerHTML 
=  rawCell.innerHTML;
        tempCell.className 
=  rawCell.className;
      }
      
this .remove(rowEL);
      
this ._attachEvent();
      
this .select(nwRow);
    },
    
    remove : 
function (row) {
      
if ( this .disabled)  return  row;
        
if (RINDEX.Lang.isNumber(row))
            row 
=   this .table.rows[row];
        
try  {
            
this .unSelect(row);
            
this .table.deleteRow(row.rowIndex);
            
this ._format();
        } 
catch (e) {
            
//
        }
    },
    
    removeSelectedRows : 
function () {
      
if ( this .disabled)  return ;
        
while ( this .selectedRows.length  >   0 )
            
this .remove( this .selectedRows[ 0 ]);
    },
    
    getCellText : 
function (cellIndex) {
      
var  rowCount  =   this .selectedRows.length;
      
var  arr  =   new  Array(rowCount);
      
for ( var  i = 0 ; i < rowCount; i ++ ) {
        
if (document.all)
          arr[i] 
=   this .selectedRows[i].cells[cellIndex].innerText;
        
else
          arr[i] 
=   this .selectedRows[i].cells[cellIndex].textContent;
      }
      
return  arr;
    },
    
    changeHeaderText : 
function (textArr) {
      
var  headerRow  =   this .table.rows[ 0 ];
      
var  cellCount  =  headerRow.cells.length - 1 ;
      
var  tempCellEL;
      
for ( var  i = 0 ; i < textArr.length; i ++ ) {
        
if (i  >  cellCount)
          
continue ;
        tempCellEL 
=  headerRow.cells[i];
        
if (tempCellEL.tagName.toUpperCase()  ==   ' TH ' ) {
          tempCellEL.innerHTML 
=  textArr[i];
        }
      }
    },
    
    _appendSelectStyle : 
function (row) {
        
        
for ( var  cell = 0 ; cell < row.cells.length; cell ++ ) {
            RINDEX.Utility.addCSS(row.cells[cell], 
' selected ' );
        }
        
    },
    
    _clearSelectStyle : 
function (row) {
        
        
for ( var  cell = 0 ; cell < row.cells.length; cell ++ ) {
            RINDEX.Utility.removeCSS(row.cells[cell], 
' selected ' );
        }
        
    },
    
    _clearAllSelection : 
function () {
        
for ( var  i = 0 ; i < this .selectedRows.length; i ++ ) {
            
this ._clearSelectStyle( this .selectedRows[i]);
        }
        
this .selectedRows.length  =   0 ;
    },

  toString : 
function () {
    
return   ' [ClientTable] ' ;
  }

};

 

grid.css

.editTable  {
    border-collapse
: collapse ;
    cursor
:  default ;
    width
:  100% ;
    empty-cells
:  show ;
}

.editTable th,
.editTable td 
{
    font-size
:  12px ;
    padding
:  3px 5px ;
}

.editTable th 
{
    text-align
:  left ;
    font-weight
:  bold ;
    line-height
:  20px ;
    height
:  20px ;
    background-color
:  #f5fafa ;
    border-right
:  1px solid #C1DAD7 ;
    border-bottom
:  1px solid #C1DAD7 ;
    border-left
:  1px solid #C1DAD7 ;
    
/* border-color: #FFF #C1DAD7 #C1DAD7 #FFF; */
    white-space
:  nowrap ;
}

.editTable td.item-0,
.editTable td.item-1 
{
    border-bottom
:  1px solid #ccc ;
    
/* text-align: left; */
}

.editTable td.item-0 
{
    background-color
:  #fff ;
    color
:  #555 ;
    empty-cells
:  show ;
    font-family
:  "Lucida Sans Unicode", "Lucida Sans",  "Trebuchet MS", Verdana, Tahoma ;
}

.editTable td.item-1 
{
    background-color
:  #F5FAFA ;
    color
:  #555 ;
    empty-cells
:  show ;
    font-family
:   "Lucida Sans Unicode", "Lucida Sans",  "Trebuchet MS", Verdana, Tahoma ;
}

.editTable td.selected 
{
    color
:  #fff ;
    background-color
:  #ff8c00 ;
}

table tr.tfooter
{
    background-color
:  ButtonFace ;
    border
:  1px solid ;
    border-color
:  buttonhighlight buttonshadow buttonshadow buttonhighlight ;
}

table tr.tfooter td 
{
    text-align
:  right ;
}

转载于:https://www.cnblogs.com/wfyfngu/archive/2009/02/01/1381923.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值