表头固定(利用jquery实现原理介绍)


Posted in Javascript onNovember 08, 2012

表头固定应该是一个用得比较多的功能,参考了网上几个例子,在几个常用浏览器下显示不是很完美。而且很多都是基于固定的表格,在编码时多写一个固定的表头,对于动态生成的不知道多少列的表格就无从下手。而且例子中大多只能满足限定高度的情况,如果限定宽度,出现横向滚动条就无能为力了。

我的目的就是要像jquery-ui那样,找到页面上存在的表格,调用一个方法就可以实现固定表头的功能。趁着动手学习写jquery插件的机会,自己写了一个表头固定的插件。
使用方式和jquery-ui中的插件一样,只需要一行代码 $('#table1').fixHeader({height:100});

下列浏览器测试通过
IE7 IE8 firefox16.0 chrome22.0
目前已知IE9下列不能对齐,手头暂时没有IE9来调试,以后再想法解决。

说明:
1 需要jquery,开发测试用的jquery-1.8.2,其他版本应该不大
2 表头部分的<tr>需要写在<thead>里
3 不限定宽度情况下,自动适应表格宽度(假设滚动条宽度为20px,实际宽度为表格宽度+20px)
4 支持多行表头固定
5 通常表格所有列都显示,无横向滚动条,只需要竖向滚动条的功能。该插件支持限定宽度条件下的表头固定。
6 限定宽度和高度的条件下固定表头显示时,表头固定功能无法单纯通过css来实现,需要通过js实现,会有轻微闪烁
7 已经考虑table和th,td的border-width设置成不同值的情况
8 已经考虑了表头中绑定的事件,原表头中绑定的事件仍然保留

特别注意:IE浏览器下,一定要设置表格中td和th的border-width,否则无法正确设置列宽,表头和数据部分会错位
使用方法:
限定高度:$('#table1').fixHeader({height:100});
限定高度和宽度:$('#table3').fixHeader({height:100,width:500});

下面为完整代码

/*! 
* fixHeader 1.0.0 
* Copyright 2012 chokobo 
* 
* make table header fixed 
* 
* notice: set th,id border-width in IE 
* 
* tested browser: IE7 IE8 firefox16.0 chrome22.0 
*/ 
(function( $, undefined ) { $.fn.fixHeader = function(options){ 
var defaults = { 
width: '', 
height: '' 
}; 
options = $.extend({}, defaults, options); 
var elem = this; 
if(options.height == ''){ 
return this; 
} 
var thead = elem.find('thead'); 
var fixTable = elem.clone().empty().removeAttr('id'); 
//set head default background-color 
if(fixTable.css('background-color') == 'transparent' || fixTable.css('background-color') == ''){ 
fixTable.css('background-color', '#fff'); 
} 
fixTable.css({ 
'position': 'absolute', 
'top': '0px', 
'border-bottom': $('tr:eq(0)', thead).find('th:eq(0), td:eq(0)').css('border-bottom-width') 
}); 

$('tr:eq(0)', thead).find('th, td').each(function(){ 
var col = $(this); 
if($.browser.mozilla){ 
col.width(col.width()); 
} 
else if($.browser.chrome){ 
var colBorderWidth = parseInt(col.css('border-width')); 
col.width(col.width()+colBorderWidth); 
} 
else if($.browser.msie){ 
var colBorderWidth = parseInt(col.css('border-width')); 
if(colBorderWidth){ 
col.width(col.width()+colBorderWidth+colBorderWidth/2);//IE7?? 
} 
} 
}); 
//make head 
var dummyHead = thead.clone(); 
thead.appendTo(fixTable); 
dummyHead.prependTo(elem); 

var tbodyWrapper = elem.wrap('<div class="body-wrapper"></div>').parent(); 
var tableWrapper = tbodyWrapper.wrap('<div class="table-wrapper" style="position:relative;"/>').parent(); 
setTableWidth(); 
setWrapperSize(); 
fixTable.prependTo(tableWrapper); 
return this; 
function setTableWidth(){ 
if($.browser.mozilla){ 
elem.width(elem.width()); 
fixTable.css('width',elem.css('width')); 
} 
else if($.browser.chrome){ 
elem.width(elem.outerWidth()); 
fixTable.width(elem.outerWidth()); 
} 
else if($.browser.msie){ 
elem.width(elem.outerWidth()); 
fixTable.width(elem.outerWidth()); 
} 
else{ 
elem.width(elem.outerWidth()); 
fixTable.width(elem.outerWidth()); 
} 
} 
function setWrapperSize(){ 
var elemWidth = elem.outerWidth(true); 
var elemHeight = elem.outerHeight(true); 
var scrollBarWidth = 20; 
if(options.width == ''){ 
tbodyWrapper.css({ 
'width': (elemWidth+scrollBarWidth) + 'px', 
'height': options.height, 
'overflow-x': 'hidden', 
'overflow-y': 'auto' 
}); 
} 
else{ 
if(elemWidth <= options.width){ 
tbodyWrapper.css({ 
'width': options.width+'px', 
'height': options.height, 
'overflow-x': 'hidden', 
'overflow-y': 'auto' 
}); 
} 
else{ 
tableWrapper.css({ 
'width': options.width, 
'height': options.height, 
'overflow': 'auto' 
}); 
tableWrapper.scroll(function(){ 
fixTable.css('top',tableWrapper.scrollTop()+'px'); 
}); 
} 
} 
} 
}; 
})( jQuery );

/* 
功能:固定表?。 
使用容器的ID?行?定$("#div").chromatable({width: "100%",height: "100%", scrolling: "yes"}) 
table必?包含有<thead>?嘶` 
??担?o。 
*/ 
(function($){ 
$.chromatable = { 
defaults: { 
width: "900px", //?定容器??度,待?U展程式 
height: "300px", //?定容器高度,待?U展程式 
scrolling: "yes" //yes跟?IE?L??l而滑?? no固定在?面上?H容器?L??l滑? 
} 
}; 
$.fn.chromatable = function(options){ 
var options = $.extend({}, $.chromatable.defaults, options); 
return this.each(function(){ 
var $divObj = $(this); 
var $tableObj = $divObj.find("table"); 
var $uniqueID = $tableObj.attr("ID") + ("wrapper"); 
var $class = $tableObj.attr("class"); 
var $tableWidth = $tableObj.width(); 
var top = $("#"+$tableObj.attr("ID")).offset().top; 
var left = $("#"+$tableObj.attr("ID")).offset().left 
$divObj.append("<table class='"+$class+"' id='"+$uniqueID+"' style='position:absolute;top:" +top+"px;left:"+left+"px;' width='"+$tableWidth+"' border='0' cellspacing='0' cellpadding='0'><thead>"+$("#"+$tableObj.attr("ID")).find("thead").html()+"</thead></table>"); $.each($("#"+$tableObj.attr("ID")).find("thead th"), function(i,item){ 
$("#"+$uniqueID).find("thead th").eq(i).width($(item).width()); 
$(item).width($(item).width()); 
}); 
if(options.scrolling === "yes") 
{ 
scrollEvent($tableObj.attr("ID"), $uniqueID); 
} 
resizeEvent($tableObj.attr("ID"), $uniqueID); 
}); 
function scrollEvent(tableId, uniqueID) 
{ 
var element = $("#"+uniqueID); 
$(window).scroll(function(){ 
var top = $("#"+tableId).offset().top; 
var scrolls = $(this).scrollTop(); 
if (scrolls > top) { 
if (window.XMLHttpRequest) { 
element.css({ 
position: "fixed", 
top: 0 
}); 
} else { 
element.css({ 
top: scrolls 
}); 
} 
}else { 
element.css({ 
position: "absolute", 
top: top 
}); 
} 
}); 
}; 
function resizeEvent(tableId, uniqueID) 
{ 
var element = $("#"+uniqueID); 
$(window).resize(function(){ 
var top = $("#"+tableId).offset().top; 
var scrolls = $(this).scrollTop(); 
if (scrolls > top) { 
if (window.XMLHttpRequest) { 
element.css({ 
position: "fixed", 
top: 0 
}); 
} else { 
element.css({ 
top: scrolls 
}); 
} 
}else { 
element.css({ 
position: "absolute", 
top: top 
}); 
} 
}); 
} 
}; 
})(jQuery);
Javascript 相关文章推荐
Add Formatted Data to a Spreadsheet
Jun 12 Javascript
Javascript 网页水印(非图片水印)实现代码
Mar 01 Javascript
js创建对象的几种常用方式小结(推荐)
Oct 24 Javascript
javascript学习笔记(四) Number 数字类型
Jun 19 Javascript
ES6入门教程之let和const命令详解
May 17 Javascript
Ionic + Angular.js实现验证码倒计时功能的方法
Jun 12 Javascript
图文详解vue框架安装步骤
Feb 12 Javascript
mongodb初始化并使用node.js实现mongodb操作封装方法
Apr 02 Javascript
angular4+百分比进度显示插件用法示例
May 05 Javascript
vue实现页面切换滑动效果
Jun 29 Javascript
使用Element的InfiniteScroll 无限滚动组件报错的解决
Jul 27 Javascript
JS+CSS实现过渡特效
Jan 02 Javascript
Javascript继承(上)——对象构建介绍
Nov 08 #Javascript
异步javascript的原理和实现技巧介绍
Nov 08 #Javascript
找出字符串中出现次数最多的字母和出现次数精简版
Nov 07 #Javascript
jquery 如何动态添加、删除class样式方法介绍
Nov 07 #Javascript
探索Emberjs制作一个简单的Todo应用
Nov 07 #Javascript
关于使用 jBox 对话框的提交不能弹出问题解决方法
Nov 07 #Javascript
seajs1.3.0源码解析之module依赖有序加载
Nov 07 #Javascript
You might like
PHP程序61条面向对象分析设计的经验小结
2008/11/12 PHP
一些php技巧与注意事项分析
2011/02/03 PHP
php判断上传的Excel文件中是否有图片及PHPExcel库认识
2013/01/11 PHP
php利用scws实现mysql全文搜索功能的方法
2014/12/25 PHP
PHP简单实现合并2个数字键数组值的方法
2017/05/30 PHP
PHP高并发和大流量解决方案整理
2019/12/24 PHP
javascript Split方法,indexOf方法、lastIndexOf 方法和substring 方法
2009/03/21 Javascript
JS字符串函数扩展代码
2011/09/13 Javascript
jquery中ajax函数执行顺序问题之如何设置同步
2014/02/28 Javascript
如何利用JS通过身份证号获取当事人的生日、年龄、性别
2016/01/22 Javascript
解析javascript瀑布流原理实现图片滚动加载
2016/03/10 Javascript
Node.js Express 框架 POST方法详解
2017/01/23 Javascript
微信小程序page的生命周期和音频播放及监听实例详解
2017/04/07 Javascript
AngularJS对动态增加的DOM实现ng-keyup事件示例
2018/03/12 Javascript
vue动画效果实现方法示例
2019/03/18 Javascript
微信小程序非跳转式组件授权登录的方法示例
2019/05/22 Javascript
elementUI select组件使用及注意事项详解
2019/05/29 Javascript
jQuery 筛选器简单操作示例
2019/10/02 jQuery
JS在Array数组中按指定位置删除或添加元素对象方法示例
2019/11/19 Javascript
jQuery插件实现图片轮播效果
2020/10/19 jQuery
微信小程序onShareTimeline()实现分享朋友圈
2021/01/07 Javascript
[00:44]TI7不朽珍藏III——军团指挥官不朽展示
2017/07/15 DOTA
Python实现约瑟夫环问题的方法
2016/05/03 Python
Python IDLE清空窗口的实例
2018/06/25 Python
python 获取一个值在某个区间的指定倍数的值方法
2018/11/12 Python
Python数据报表之Excel操作模块用法分析
2019/03/11 Python
python assert的用处示例详解
2019/04/01 Python
解决Keras中CNN输入维度报错问题
2020/06/29 Python
OSPREY LONDON官网:英国本土皮具品牌
2019/05/31 全球购物
公务员政审个人鉴定
2014/02/25 职场文书
学校食堂管理制度
2015/08/04 职场文书
2016关于军训的心得体会
2016/01/11 职场文书
2019年特色火锅店的创业计划书模板
2019/08/28 职场文书
基于PyTorch实现一个简单的CNN图像分类器
2021/05/29 Python
Win Server2016远程桌面如何允许多用户同时登录
2022/06/10 Servers
Win10多屏显示如何设置?Win10电脑多屏显示设置操作方法
2022/07/07 数码科技