JQuery固定表头插件fixedtableheader源码注释
在开发XX车站信息系统时,需要将大量数据显示在一个巨大的表格内部,由于表格是一个整体,无法分页,加之数据很多,超出一屏,为了方便用户,决定使用固定表头的插件,经过测试,发现JQuery 插件:fixedtableheader可以简单方便的实现功能。
它的使用很简单,需要设置的参数也只需2个,很实用。
使用方法:
//引入文件 <script type="mce-text/javascript" src="http://i.cnblogs.com/jquery.min.js"></script> <script type="mce-text/javascript" src="http://i.cnblogs.com/jquery.fixedtableheader.min.js">< //绑定表格,headerrowsize 后面的参数是绑定需要固定的表头的行数 <script type="mce-text/javascript"> $(document).ready(function() { $('.tbl').fixedtableheader({ highlightrow: true, headerrowsize: 4 }); }); </script>
使用时,我发现js文件只有 4KB,我很好奇它是怎么实现的,于是就有了下文。
大致原理是:创建一个绝对定位的table,只包含表头。当表格被用户拖动超出屏幕时,表头表格显示;表格正常显示时,表头表格隐藏。
/* Copyright (c) 2009 Mustafa OZCAN (http://www.mustafaozcan.net) * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. * Version: .0.2 * Requires: jquery.1.3+ */ jQuery.fn.fixedtableheader = function(options) { var settings = jQuery.extend({ //jQuery.extend( target [, object1 ] [, objectN ] ) headerrowsize: 1, //这是默认参数 highlightrow: false, highlightclass: "highlight" }, options); //用户设置的参数 //如果用户设置参数,会覆盖对应的默认参数 this.each(function(i) { //处理每个table(该插件使用class属性绑定,会存在多个table) var $tbl = $(this); var $tblhfixed = $tbl.find("tr:lt(" + settings.headerrowsize + ")"); //找到要固定表头tr var headerelement = "th"; if ($tblhfixed.find(headerelement).length == 0) headerelement = "td"; //没有th,默认td为表头单元格 if ($tblhfixed.find(headerelement).length > 0) { //有th单元格 $tblhfixed.find(headerelement).each(function() { $(this).css("width", $(this).width()); //设置表头th宽度 }); var $clonedTable = $tbl.clone().empty(); //创建表头表格,即一对完整的table标签 var tblwidth = GetTblWidth($tbl); $clonedTable.attr("id", "fixedtableheader" + i).css({ //设置悬浮表头绝对定位的位置 "position": "fixed", "top": "0", "left": $tbl.offset().left //.offset(): 获取表格的左边距 }).append($tblhfixed.clone()).width(tblwidth).hide().appendTo($("body")); //将表头插入table标签中 if (settings.highlightrow) //鼠标移过高亮 $("tr:gt(" + (settings.headerrowsize - 1) + ")", $tbl).hover(function() { $(this).addClass(settings.highlightclass); }, function() { $(this).removeClass(settings.highlightclass); }); $(window).scroll(function() { //当滚动条发生变化时触发scroll事件 if (jQuery.browser.msie && jQuery.browser.version == "6.0") //IE6.0 $clonedTable.css({ // "position": "absolute", "top": $(window).scrollTop(), "left": $tbl.offset().left }); else $clonedTable.css({ "position": "fixed", "top": "0", "left": $tbl.offset().left - $(window).scrollLeft() }) var sctop = $(window).scrollTop(); //页面滚动条向下滚动的高度,也即页面被隐藏的高度 var elmtop = $tblhfixed.offset().top; //此时原始表格距离浏览器客户区顶端的高度 if (sctop > elmtop && sctop <= (elmtop + $tbl.height() - $tblhfixed.height())) $clonedTable.show(); //原来的表头被滚动的不可见并且表格主体尚未被滚动出屏幕 else $clonedTable.hide(); // }); $(window).resize(function() { if ($clonedTable.outerWidth() != $tbl.outerWidth()) { //若悬浮表跟不上resize的变化 $tblhfixed.find(headerelement).each(function(index) { //重新设置悬浮表头clonedTable每个th/td的宽度 var w = $(this).width(); $(this).css("width", w); $clonedTable.find(headerelement).eq(index).css("width", w); }); $clonedTable.width($tbl.outerWidth()); //设置悬浮表的宽度,注意这里.width()和css('width')的区别 } $clonedTable.css("left", $tbl.offset().left); //jquery中offset是相对于浏览器客户区的相对偏移 }); } }); function GetTblWidth($tbl) { //获取元素宽度(包括padding和border) var tblwidth = $tbl.outerWidth(); return tblwidth; } };
在注释该代码过程中,一个很严重的疑惑产生了:
JQuery的.width() 和 CSS width 貌似不统一,有很大区别!所以又细细深入研究了一番,收获详见这里。
IE6不能使用position:fixed,具体见这里。
后记:2014-06-17
其实这个根本就达不到所谓的“fixtableheader”的效果,因为它只是简单的额把所有的表头都固定在了浏览器客户区的顶部,而非是table所在区域的顶部。