表头固定(利用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 相关文章推荐
基于jQuery实现的文字按钮表单特效整理
Dec 07 Javascript
js的toUpperCase方法用法实例
Jan 27 Javascript
js比较日期大小的方法
May 12 Javascript
基于jquery实现省市联动特效
Dec 17 Javascript
详解jquery easyui之datagrid使用参考
Dec 05 Javascript
jQuery Ajax请求后台数据并在前台接收
Dec 10 Javascript
Angular 2.0+ 的数据绑定的实现示例
Aug 09 Javascript
详解使用webpack构建多页面应用
Dec 21 Javascript
详解使用webpack+electron+reactJs开发windows桌面应用
Feb 01 Javascript
Node.js 多线程完全指南总结
Mar 27 Javascript
使用layer模态框给新页面传值的方法
Sep 27 Javascript
js单线程的本质 Event Loop解析
Oct 29 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设计模式 Bridge (桥接模式)
2011/06/26 PHP
PHP中的Memcache详解
2014/04/05 PHP
thinkPHP模板算术运算相关函数用法分析
2016/07/12 PHP
PHP实现Unicode编码相互转换的方法示例
2020/11/17 PHP
PHP实现上传多图即时显示与即时删除的方法
2017/05/09 PHP
Laravel 读取 config 下的数据方法
2019/10/13 PHP
基于Jquery的文字滚动跑马灯插件(一个页面多个滚动区)
2010/07/26 Javascript
Javascript学习笔记-详解in运算符
2011/09/13 Javascript
iframe 上下滚动条如何默认在下方实现原理
2012/12/10 Javascript
JavaScript移除数组元素减少长度的方法
2013/09/05 Javascript
jQuery Ajax 加载数据时异步显示加载动画
2016/08/01 Javascript
web前端开发upload上传头像js示例代码
2016/10/22 Javascript
深入理解JavaScript继承的多种方式和优缺点
2017/05/12 Javascript
React教程之Props验证的具体用法(Props Validation)
2017/09/04 Javascript
2种简单的js倒计时方式
2017/10/20 Javascript
react项目实践之webpack-dev-serve
2018/09/14 Javascript
JS去除字符串最后的逗号实例分析【四种方法】
2019/06/20 Javascript
详解VUE中的插值( Interpolation)语法
2020/10/18 Javascript
解决vuex刷新数据消失问题
2020/11/12 Javascript
在Python中处理字符串之isdecimal()方法的使用
2015/05/20 Python
15行Python代码带你轻松理解令牌桶算法
2018/03/21 Python
Python3.5.3下配置opencv3.2.0的操作方法
2018/04/02 Python
python scipy卷积运算的实现方法
2019/09/16 Python
Python箱型图绘制与特征值获取过程解析
2019/10/22 Python
基于Python中random.sample()的替代方案
2020/05/23 Python
Python dict的常用方法示例代码
2020/06/23 Python
python怎么删除缓存文件
2020/07/19 Python
python实现不同数据库间数据同步功能
2021/02/25 Python
公益活动邀请函
2014/02/05 职场文书
教师节商场活动方案
2014/02/13 职场文书
职务说明书范文
2014/05/07 职场文书
2015元旦晚会主持人开场白+结束语
2014/12/14 职场文书
社区挂职锻炼个人工作总结
2015/10/23 职场文书
教师素质教育心得体会
2016/01/19 职场文书
MySQL单表千万级数据处理的思路分享
2021/06/05 MySQL
Java 超详细讲解设计模式之中的抽象工厂模式
2022/03/25 Java/Android