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 相关文章推荐
Flash对联广告的关闭按钮讨论
Jan 30 Javascript
JavaScript创建一个欢迎cookie弹出窗实现代码
Mar 15 Javascript
div失去焦点事件实现思路
Apr 22 Javascript
js判断上传文件类型判断FileUpload文件类型代码
May 20 Javascript
直接在JS里创建JSON数据然后遍历使用
Jul 25 Javascript
jquery得到iframe src属性值的方法
Sep 25 Javascript
js格式化时间小结
Nov 03 Javascript
微信小程序 less文件编译成wxss文件实现办法
Dec 05 Javascript
ECMAScript6 新特性范例大全
Mar 24 Javascript
实例教学如何写vue插件
Nov 30 Javascript
vue 自定义指令自动获取文本框焦点的方法
Aug 25 Javascript
vue项目实现表单登录页保存账号和密码到cookie功能
Aug 31 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
动画 《Pokemon Sword·Shield》系列WEB动画《薄明之翼》第2话声优阵容公开!
2020/03/06 日漫
PHP的加密方式及原理
2012/06/14 PHP
Laravel 5.4重新登录实现跳转到登录前页面的原理和方法
2017/07/13 PHP
PHP实现的支付宝支付功能示例
2019/03/26 PHP
HTML中Select不用Disabled实现ReadOnly的效果
2008/04/07 Javascript
JavaScript获得选中文本内容的方法
2008/12/02 Javascript
添加JavaScript重载函数的辅助方法2
2010/07/04 Javascript
zTree插件之多选下拉菜单实例代码
2013/11/06 Javascript
JS中Date日期函数中的参数使用介绍
2014/01/02 Javascript
jQuery的live()方法对hover事件的处理示例
2014/02/27 Javascript
js右下角弹出提示框示例代码
2016/01/12 Javascript
jQuery使用Selectator插件实现多选下拉列表过滤框(附源码下载)
2016/04/08 Javascript
url传递的参数值中包含&amp;时,url自动截断问题的解决方法
2016/08/02 Javascript
js改变html的原有内容实现方法
2016/10/05 Javascript
基于javascript实现的快速排序
2016/12/02 Javascript
原生js实现倒计时功能(多种格式调用)
2017/01/12 Javascript
vue.js单页面应用实例的简单实现
2017/04/10 Javascript
原生JavaScript来实现对dom元素class的操作方法(推荐)
2017/08/16 Javascript
实例教学如何写vue插件
2017/11/30 Javascript
一篇文章,教你学会Vue CLI 插件开发
2019/04/17 Javascript
vue router 跳转时打开新页面的示例方法
2019/07/28 Javascript
element 动态合并表格的步骤
2020/12/31 Javascript
代码讲解Python对Windows服务进行监控
2018/02/11 Python
TensorFlow实现AutoEncoder自编码器
2018/03/09 Python
python Opencv将图片转为字符画
2021/02/19 Python
朴素贝叶斯Python实例及解析
2018/11/19 Python
int在python中的含义以及用法
2019/06/27 Python
python3.6 tkinter实现屏保小程序
2019/07/30 Python
Golang GBK转UTF-8的例子
2019/08/26 Python
竞职演讲稿范文
2014/01/11 职场文书
电气自动化专业职业规划范文
2014/02/16 职场文书
党课培训主持词
2014/04/01 职场文书
初中生毕业评语
2014/12/29 职场文书
文明礼仪主题班会
2015/08/13 职场文书
解决Nginx 配置 proxy_pass 后 返回404问题
2021/03/31 Servers
Pytorch 统计模型参数量的操作 param.numel()
2021/05/13 Python