jQuery实现冻结表格行和列


Posted in Javascript onApril 29, 2015

客户要求实现对表格数据的头几行或者头几列进行冻结,即滚动时保持这几行/列不动,通过网上查找代码,参考已有的代码的思路,实现了可以任意对行、列进行冻结。

实现原理:

创建多个div,div之间通过css实现层叠,每个div放置当前表格的克隆。例如:需要行冻结时,创建存放冻结行表格的div,通过设置z-index属性和position属性,让冻结行表格在数据表格的上层。同理,需要列冻结时,创建存放冻结列表格的div,并放置在数据表格的上层。如果需要行列都冻结时,则除了创建冻结行、冻结列表格的div,还需要创建左上角的固定行列表格的div,并放置在所有div的最上层。
处理表格的滚动事件,在表格横向或者纵向滚动时,同时让相应的冻结行和冻结列也同步滚动。
处理html的resize事件,同步修改表格的滚动区域宽度和高度

代码如下:

/*
 * 锁定表头和列
 * 
 * 参数定义
 *   table - 要锁定的表格元素或者表格ID
 *   freezeRowNum - 要锁定的前几行行数,如果行不锁定,则设置为0
 *   freezeColumnNum - 要锁定的前几列列数,如果列不锁定,则设置为0
 *   width - 表格的滚动区域宽度
 *   height - 表格的滚动区域高度
 */
function freezeTable(table, freezeRowNum, freezeColumnNum, width, height) {
  if (typeof(freezeRowNum) == 'string')
    freezeRowNum = parseInt(freezeRowNum)
    
  if (typeof(freezeColumnNum) == 'string')
    freezeColumnNum = parseInt(freezeColumnNum)

  var tableId;
  if (typeof(table) == 'string') {
    tableId = table;
    table = $('#' + tableId);
  } else
    tableId = table.attr('id');
    
  var divTableLayout = $("#" + tableId + "_tableLayout");
  
  if (divTableLayout.length != 0) {
    divTableLayout.before(table);
    divTableLayout.empty();
  } else {
    table.after("<div id='" + tableId + "_tableLayout' style='overflow:hidden;height:" + height + "px; width:" + width + "px;'></div>");
    
    divTableLayout = $("#" + tableId + "_tableLayout");
  }
  
  var html = '';
  if (freezeRowNum > 0 && freezeColumnNum > 0)
    html += '<div id="' + tableId + '_tableFix" style="padding: 0px;"></div>';
    
  if (freezeRowNum > 0)
    html += '<div id="' + tableId + '_tableHead" style="padding: 0px;"></div>';
    
  if (freezeColumnNum > 0)
    html += '<div id="' + tableId + '_tableColumn" style="padding: 0px;"></div>';
    
  html += '<div id="' + tableId + '_tableData" style="padding: 0px;"></div>';
  
  
  $(html).appendTo("#" + tableId + "_tableLayout");
  
  var divTableFix = freezeRowNum > 0 && freezeColumnNum > 0 ? $("#" + tableId + "_tableFix") : null;
  var divTableHead = freezeRowNum > 0 ? $("#" + tableId + "_tableHead") : null;
  var divTableColumn = freezeColumnNum > 0 ? $("#" + tableId + "_tableColumn") : null;
  var divTableData = $("#" + tableId + "_tableData");
  
  divTableData.append(table);
  
  if (divTableFix != null) {
    var tableFixClone = table.clone(true);
    tableFixClone.attr("id", tableId + "_tableFixClone");
    divTableFix.append(tableFixClone);
  }
  
  if (divTableHead != null) {
    var tableHeadClone = table.clone(true);
    tableHeadClone.attr("id", tableId + "_tableHeadClone");
    divTableHead.append(tableHeadClone);
  }
  
  if (divTableColumn != null) {
    var tableColumnClone = table.clone(true);
    tableColumnClone.attr("id", tableId + "_tableColumnClone");
    divTableColumn.append(tableColumnClone);
  }
  
  $("#" + tableId + "_tableLayout table").css("margin", "0");
  
  if (freezeRowNum > 0) {
    var HeadHeight = 0;
    var ignoreRowNum = 0;
    $("#" + tableId + "_tableHead tr:lt(" + freezeRowNum + ")").each(function () {
      if (ignoreRowNum > 0)
        ignoreRowNum--;
      else {
        var td = $(this).find('td:first, th:first');
        HeadHeight += td.outerHeight(true);
        
        ignoreRowNum = td.attr('rowSpan');
        if (typeof(ignoreRowNum) == 'undefined')
          ignoreRowNum = 0;
        else
          ignoreRowNum = parseInt(ignoreRowNum) - 1;
      }
    });
    HeadHeight += 2;
    
    divTableHead.css("height", HeadHeight);
    divTableFix != null && divTableFix.css("height", HeadHeight);
  }
  
  if (freezeColumnNum > 0) {
    var ColumnsWidth = 0;
    var ColumnsNumber = 0;
    $("#" + tableId + "_tableColumn tr:eq(" + freezeRowNum + ")").find("td:lt(" + freezeColumnNum + "), th:lt(" + freezeColumnNum + ")").each(function () {
      if (ColumnsNumber >= freezeColumnNum)
        return;
        
      ColumnsWidth += $(this).outerWidth(true);
      
      ColumnsNumber += $(this).attr('colSpan') ? parseInt($(this).attr('colSpan')) : 1;
    });
    ColumnsWidth += 2;

    divTableColumn.css("width", ColumnsWidth);
    divTableFix != null && divTableFix.css("width", ColumnsWidth);
  }
  
  divTableData.scroll(function () {
    divTableHead != null && divTableHead.scrollLeft(divTableData.scrollLeft());
    
    divTableColumn != null && divTableColumn.scrollTop(divTableData.scrollTop());
  });
  
  divTableFix != null && divTableFix.css({ "overflow": "hidden", "position": "absolute", "z-index": "50" });
  divTableHead != null && divTableHead.css({ "overflow": "hidden", "width": width - 17, "position": "absolute", "z-index": "45" });
  divTableColumn != null && divTableColumn.css({ "overflow": "hidden", "height": height - 17, "position": "absolute", "z-index": "40" });
  divTableData.css({ "overflow": "scroll", "width": width, "height": height, "position": "absolute" });
  
  divTableFix != null && divTableFix.offset(divTableLayout.offset());
  divTableHead != null && divTableHead.offset(divTableLayout.offset());
  divTableColumn != null && divTableColumn.offset(divTableLayout.offset());
  divTableData.offset(divTableLayout.offset());
}

/*
 * 调整锁定表的宽度和高度,这个函数在resize事件中调用
 * 
 * 参数定义
 *   table - 要锁定的表格元素或者表格ID
 *   width - 表格的滚动区域宽度
 *   height - 表格的滚动区域高度
 */
function adjustTableSize(table, width, height) {
  var tableId;
  if (typeof(table) == 'string')
    tableId = table;
  else
    tableId = table.attr('id');
  
  $("#" + tableId + "_tableLayout").width(width).height(height);
  $("#" + tableId + "_tableHead").width(width - 17);
  $("#" + tableId + "_tableColumn").height(height - 17);
  $("#" + tableId + "_tableData").width(width).height(height);
}

function pageHeight() {
  if ($.browser.msie) {
    return document.compatMode == "CSS1Compat" ? document.documentElement.clientHeight : document.body.clientHeight;
  } else {
    return self.innerHeight;
  }
};

//返回当前页面宽度
function pageWidth() {
  if ($.browser.msie) {
    return document.compatMode == "CSS1Compat" ? document.documentElement.clientWidth : document.body.clientWidth;
  } else {
    return self.innerWidth;
  }
};

$(document).ready(function() {
  var table = $("table");
  var tableId = table.attr('id');
  var freezeRowNum = table.attr('freezeRowNum');
  var freezeColumnNum = table.attr('freezeColumnNum');
  
  if (typeof(freezeRowNum) != 'undefined' || typeof(freezeColumnNum) != 'undefined') {
    freezeTable(table, freezeRowNum || 0, freezeColumnNum || 0, pageWidth(), pageHeight());
    
    var flag = false;
    $(window).resize(function() {
      if (flag) 
        return ;
      
      setTimeout(function() { 
        adjustTableSize(tableId, pageWidth(), pageHeight()); 
        flag = false; 
      }, 100);
      
      flag = true;
    });
  }
});

使用时,只要在table元素设置freezeRowNum和freezeColumnNum属性值,即可实现冻结效果

<table id="reportTable" width="1900" freezeRowNum="2" freezeColumnNum="2" class="report" align="center">

...

</table>

以上所述就是本文的全部内容了,希望大家能够喜欢。

Javascript 相关文章推荐
非常实用的12个jquery代码片段
Nov 02 Javascript
js自定义回调函数
Dec 13 Javascript
jquery对dom节点的操作【推荐】
Apr 15 Javascript
jQuery 如何给Carousel插件添加新的功能
Apr 18 Javascript
vue,angular,avalon这三种MVVM框架优缺点
Apr 27 Javascript
老生常谈遮罩层 滚动条的问题
Apr 29 Javascript
第一次接触神奇的Bootstrap表单
Jul 27 Javascript
详解vue项目优化之按需加载组件-使用webpack require.ensure
Jun 13 Javascript
vue实现移动端图片裁剪上传功能
Aug 18 Javascript
js+html5生成自动排列对话框实例
Oct 09 Javascript
javascript随机变色实例代码
Oct 15 Javascript
vue实现两个组件之间数据共享和修改操作
Nov 12 Javascript
Js实现无刷新删除内容
Apr 29 #Javascript
纯js实现仿QQ邮箱弹出确认框
Apr 29 #Javascript
jQuery()方法的第二个参数详解
Apr 29 #Javascript
AngularJS模块管理问题的非常规处理方法
Apr 29 #Javascript
javascript通过元素id和name直接取得元素的方法
Apr 28 #Javascript
javascript中in运算符用法分析
Apr 28 #Javascript
setTimeout内不支持jquery的选择器的解决方案
Apr 28 #Javascript
You might like
php面向对象中static静态属性和静态方法的调用
2015/02/08 PHP
PHP笛卡尔积实现算法示例
2018/07/30 PHP
JavaScript 节点操作 以及DOMDocument属性和方法
2007/12/06 Javascript
asp.net HttpHandler实现图片防盗链
2009/11/09 Javascript
js 小数取整的函数
2010/05/10 Javascript
jQuery EasyUI中对表格进行编辑的实现代码
2010/06/10 Javascript
使用insertAfter()方法在现有元素后添加一个新元素
2014/05/28 Javascript
原生javascript实现图片按钮切换
2015/01/12 Javascript
jQuery对象和DOM对象之间相互转换的方法介绍
2015/02/28 Javascript
jQuery超赞的评分插件(8款)
2015/08/20 Javascript
Bootstrap Table的使用总结
2016/10/08 Javascript
使用开源工具制作网页验证码的方法
2016/10/17 Javascript
Node.js 数据加密传输浅析
2016/11/16 Javascript
JavaScript实现无穷滚动加载数据
2017/05/06 Javascript
JavaScript实现二叉树定义、遍历及查找的方法详解
2017/12/20 Javascript
10个经典的网页鼠标特效代码
2018/01/09 Javascript
vue如何将v-for中的表格导出来
2018/05/07 Javascript
jQuery动态移除与增加onclick属性的方法详解
2018/06/07 jQuery
vue脚手架搭建项目的兼容性配置详解
2018/07/17 Javascript
node.js爬虫框架node-crawler初体验
2020/10/29 Javascript
Python对两个有序列表进行合并和排序的例子
2014/06/13 Python
python使用Image处理图片常用技巧分析
2015/06/01 Python
python实现判断数组是否包含指定元素的方法
2015/07/15 Python
Python字典,函数,全局变量代码解析
2017/12/18 Python
Python SQLite3简介
2018/02/22 Python
Python实现确认字符串是否包含指定字符串的实例
2018/05/02 Python
Django项目在pycharm新建的步骤方法
2021/03/02 Python
阿拉伯时尚购物网站:Nisnass
2021/02/07 全球购物
shallow copy和deep copy的区别
2016/05/09 面试题
北大青鸟学生求职信
2013/09/24 职场文书
民族团结好少年事迹材料
2014/08/19 职场文书
学校运动会广播稿100条
2014/09/14 职场文书
2014年稽查工作总结
2014/12/20 职场文书
李强优秀员工观后感
2015/06/16 职场文书
python 自动化偷懒的四个实用操作
2021/04/11 Python
Python中相见恨晚的技巧
2021/04/13 Python