锁定表头和固定列(Fixed table head and columns)

前段时间需要这个功能,但是找了很多都不能完美的实现,不是只能锁定表头,就是浏览器兼容问题什么的,在此就自己做了一个锁定表头和列的js方法,依赖于JQuery。

如使用jQuery1.9.x及以上版本,需要引用jQuery Migrate Plugin库,在jQuery官网即可下载到!

因为方法很简单,就未封装成插件的形式,仅仅以代码方式发布。这里把自己做的方式写出来,以资纪念。

支持IE6+,FF3.6+,Opera9+,Chrome9+

一、实现方式

这里的准备使用4个table实现,具体如下图:

image

上图红色部分为要取出来的部分,蓝色部分为拼接后可以看到的部分。最终结果如下图

image

实现后效果:

姓名班级成绩
主科文科理科总分
语文数学英语政治历史地理物理化学生物
学生1 班级3 64  104  150  93  32  82  26  44  83  678 
学生2 班级2 120  66  150  85  50  72  32  90  670 
学生3 班级2 133  61  49  97  67  13  64  60  552 
学生4 班级3 136  105  86  56  11  98  29  18  546 
学生5 班级2 129  146  62  64  67  70  57  16  612 
学生6 班级2 45  29  51  91  37  26  293 
学生7 班级1 28  25  127  96  43  90  75  13  28  525 
学生8 班级3 78  64  20  29  70  92  100  69  30  552 
学生9 班级2 65  10  139  19  57  86  57  79  76  588 
学生10 班级2 113  142  100  41  69  12  45  20  546 
学生11 班级3 41  84  42  23  89  88  21  398 
学生12 班级1 102  111  61  76  12  25  66  39  496 
学生13 班级2 49  144  56  75  18  58  39  13  88  540 
学生14 班级1 119  81  73  53  37  88  79  69  30  629 
学生15 班级3 120  78  86  58  50  20  42  24  485 
学生16 班级1 65  71  64  45  31  18  53  361 
学生17 班级1 72  139  24  20  39  49  19  21  23  406 
学生18 班级3 50  84  53  70  77  81  38  80  25  558 
学生19 班级1 56  147  134  59  57  31  48  86  625 
学生20 班级1 103  38  96  100  21  88  36  37  18  537 
学生21 班级1 133  150  28  37  96  88  12  36  87  667 
学生22 班级2 140  59  42  95  94  50  58  63  604 
学生23 班级1 51  19  17  19  93  35  49  292 
学生24 班级3 67  91  23  22  37  79  52  63  436 
学生25 班级3 29  17  149  44  13  29  98  70  455 
学生26 班级3 126  117  112  11  100  55  87  18  627 
学生27 班级3 144  115  131  97  19  92  79  72  753 
学生28 班级2 107  77  143  94  89  90  35  70  708 
学生29 班级3 14  33  44  78  67  27  49  23  340 
学生30 班级3 77  117  51  75  74  43  25  24  488 
学生31 班级1 76  140  148  50  100  33  83  81  23  734 
学生32 班级1 29  25  146  28  79  73  47  91  526 
学生33 班级2 96  44  121  94  17  20  19  418 
学生34 班级2 97  48  68  82  39  16  24  79  79  532 
学生35 班级3 126  69  40  13  48  34  81  97  513 
学生36 班级1 144  24  18  71  58  21  12  95  45  488 
学生37 班级1 23  94  93  78  46  88  72  15  90  599 
学生38 班级2 73  103  45  17  69  18  67  55  450 
学生39 班级3 19  16  36  18  50  48  19  75  24  305 
学生40 班级1 44  50  73  58  21  84  49  68  453 
学生41 班级2 94  98  24  34  52  27  87  95  512 
学生42 班级2 27  68  60  75  93  38  44  27  436 
学生43 班级3 102  146  138  72  58  19  34  57  60  686 
学生44 班级2 51  81  150  95  48  96  90  66  685 
学生45 班级1 93  37  109  84  100  59  90  59  81  712 
学生46 班级2 125  60  32  70  93  65  74  44  77  640 
学生47 班级1 139  45  52  54  64  46  45  66  517 
学生48 班级2 14  73  118  36  43  24  73  393 
学生49 班级3 45  114  114  65  94  32  30  501 
学生50 班级2 112  77  19  33  30  32  90  18  77  488 
学生51 班级2 19  66  140  36  44  34  62  17  34  452 
学生52 班级2 61  98  107  78  17  54  28  89  534 
学生53 班级1 48  23  65  23  70  58  36  45  75  443 
学生54 班级1 81  46  37  86  87  83  39  63  531 
学生55 班级1 48  23  145  53  80  35  31  426 
学生56 班级1 117  92  44  65  98  70  67  556 
学生57 班级3 148  25  63  29  96  34  34  34  92  555 
学生58 班级1 51  22  97  58  80  16  19  91  20  454 
学生59 班级2 118  20  62  26  93  77  66  34  497 
学生60 班级3 129  19  109  78  33  15  74  67  58  582 
学生61 班级3 112  68  65  15  79  63  97  72  85  656 
学生62 班级3 117  14  73  98  81  400 
学生63 班级1 87  103  30  21  43  87  25  398 
学生64 班级2 65  79  49  53  86  33  57  99  83  604 
学生65 班级2 144  122  47  11  76  64  66  71  608 
学生66 班级2 18  140  96  54  10  45  41  85  495 
学生67 班级2 30  14  70  20  44  25  77  97  20  397 
学生68 班级3 60  147  38  53  88  54  92  546 
学生69 班级2 86  115  23  90  52  50  89  79  42  626 
学生70 班级3 132  25  21  25  44  86  58  61  455 
学生71 班级3 149  102  68  98  96  95  25  47  687 
学生72 班级2 28  138  74  30  43  95  57  68  533 
学生73 班级3 54  148  81  40  86  23  91  73  95  691 
学生74 班级1 143  39  76  55  90  31  18  95  552 
学生75 班级2 83  95  48  86  61  97  68  84  24  646 
学生76 班级1 138  141  50  14  11  370 
学生77 班级3 25  33  46  25  62  93  41  43  75  443 
学生78 班级1 18  114  93  22  38  73  66  69  79  572 
学生79 班级3 84  10  72  94  30  95  32  41  56  514 
学生80 班级2 113  39  10  23  28  33  32  23  308 
学生81 班级3 83  36  13  13  89  15  39  71  72  431 
学生82 班级3 52  68  39  22  16  75  37  95  413 
学生83 班级3 90  132  20  36  86  69  39  95  567 
学生84 班级1 61  89  67  10  33  31  99  34  428 
学生85 班级1 83  93  105  79  19  30  84  500 
学生86 班级1 88  143  19  56  56  36  89  77  573 
学生87 班级1 70  115  66  36  76  16  89  468 
学生88 班级3 17  60  49  80  12  99  30  356 
学生89 班级1 129  128  48  76  47  46  46  89  610 
学生90 班级3 143  14  86  69  55  85  43  499 
学生91 班级2 44  127  143  22  18  62  33  44  500 
学生92 班级1 37  41  130  71  17  61  68  19  445 
学生93 班级3 45  17  22  10  90  83  31  11  310 
学生94 班级2 19  40  99  59  77  90  68  462 
学生95 班级1 126  19  68  91  53  68  23  87  85  620 
学生96 班级1 131  126  126  53  13  18  70  85  33  655 
学生97 班级1 53  47  33  87  98  98  62  28  95  601 
学生98 班级1 107  88  49  91  17  66  24  58  506 
学生99 班级1 118  145  69  70  29  43  13  45  536 
学生100 班级2 48  115  63  93  53  91  59  93  623 

二、整体的框架

1、最下面的是原始的Table。

2、用左边的table覆盖在上层,命名为tableColumn。

3、用上部的table覆盖在更上层,命名为tableHead。

4、在左上角覆盖固定不动的table,命名为tableFix。

自然在各自的外层都要用div框起来,以便后面的浮动和覆盖等等,所以结构的html如下:

<div id="MyTable_tableLayout"> <div id="MyTable_tableFix"> <table id="MyTable_tableFixClone" border="1" cellspacing="0" cellpadding="0"></table> </div> <div id="MyTable_tableHead"> <table id="MyTable_tableHeadClone" border="1" cellspacing="0" cellpadding="0"></table> </div> <div id="MyTable_tableColumn"> <table id="MyTable_tableColumnClone" border="1" cellspacing="0" cellpadding="0"></table> </div> <div id="MyTable_tableData"> <table id="MyTable" border="1" cellspacing="0" cellpadding="0"></table> </div> </div>

三、代码实现

整体框架结构出来后,下面要做的就是确定每个区域的高度,宽度,定位就算完成了。

首先确定下调用接口,调用时已经有table了,我们希望很简单的一行js即可高定,就用了一个方法实现。由于使用项目中table线宽全部都是1,所以未考虑其他线宽问题。

function FixTable(TableID, FixColumnNumber, width, height)

第一个参数:table的ID,第二个参数:要锁定的列数目,第三个参数:显示的宽度,第四个参数:显示的高度。

(一)首先创建上面所诉的框架出来:

if ($("#" + TableID + "_tableLayout").length != 0) { $("#" + TableID + "_tableLayout").before($("#" + TableID)); $("#" + TableID + "_tableLayout").empty(); } else { $("#" + TableID).after("<div id='" + TableID + "_tableLayout' style='overflow:hidden;height:" + height + "px; width:" + width + "px;'></div>"); } $('<div id="' + TableID + '_tableFix"></div>' + '<div id="' + TableID + '_tableHead"></div>' + '<div id="' + TableID + '_tableColumn"></div>' + '<div id="' + TableID + '_tableData"></div>').appendTo("#" + TableID + "_tableLayout"); var oldtable = $("#" + TableID); var tableFixClone = oldtable.clone(true); tableFixClone.attr("id", TableID + "_tableFixClone"); $("#" + TableID + "_tableFix").append(tableFixClone); var tableHeadClone = oldtable.clone(true); tableHeadClone.attr("id", TableID + "_tableHeadClone"); $("#" + TableID + "_tableHead").append(tableHeadClone); var tableColumnClone = oldtable.clone(true); tableColumnClone.attr("id", TableID + "_tableColumnClone"); $("#" + TableID + "_tableColumn").append(tableColumnClone); $("#" + TableID + "_tableData").append(oldtable); $("#" + TableID + "_tableLayout table").each(function () { $(this).css("margin", "0"); });

(二)计算tableFix,tableHead的高度:

var HeadHeight = $("#" + TableID + "_tableHead thead").height(); HeadHeight += 2; $("#" + TableID + "_tableHead").css("height", HeadHeight); $("#" + TableID + "_tableFix").css("height", HeadHeight);

(三)计算tableFix,tableColumn的宽度:

var ColumnsWidth = 0; var ColumnsNumber = 0; $("#" + TableID + "_tableColumn tr:last td:lt(" + FixColumnNumber + ")").each(function () { ColumnsWidth += $(this).outerWidth(true); ColumnsNumber++; }); ColumnsWidth += 2; if ($.browser.msie) { switch ($.browser.version) { case "7.0": if (ColumnsNumber >= 3) ColumnsWidth--; break; case "8.0": if (ColumnsNumber >= 2) ColumnsWidth--; break; } } $("#" + TableID + "_tableColumn").css("width", ColumnsWidth); $("#" + TableID + "_tableFix").css("width", ColumnsWidth);

(四)为tableHead和tableColumn添加联动的滚动条事件:

$("#" + TableID + "_tableData").scroll(function () { $("#" + TableID + "_tableHead").scrollLeft($("#" + TableID + "_tableData").scrollLeft()); $("#" + TableID + "_tableColumn").scrollTop($("#" + TableID + "_tableData").scrollTop()); });

(五)为较小的table修正样式:

if ($("#" + TableID + "_tableHead").width() > $("#" + TableID + "_tableHead table").width()) { $("#" + TableID + "_tableHead").css("width", $("#" + TableID + "_tableHead table").width()); $("#" + TableID + "_tableData").css("width", $("#" + TableID + "_tableHead table").width() + 17); } if ($("#" + TableID + "_tableColumn").height() > $("#" + TableID + "_tableColumn table").height()) { $("#" + TableID + "_tableColumn").css("height", $("#" + TableID + "_tableColumn table").height()); $("#" + TableID + "_tableData").css("height", $("#" + TableID + "_tableColumn table").height() + 17); }

(六)为整体添加样式,定位:

$("#" + TableID + "_tableFix").css({ "overflow": "hidden", "position": "relative", "z-index": "50", "background-color": "Silver" }); $("#" + TableID + "_tableHead").css({ "overflow": "hidden", "width": width - 17, "position": "relative", "z-index": "45", "background-color": "Silver" }); $("#" + TableID + "_tableColumn").css({ "overflow": "hidden", "height": height - 17, "position": "relative", "z-index": "40", "background-color": "Silver" }); $("#" + TableID + "_tableData").css({ "overflow": "scroll", "width": width, "height": height, "position": "relative", "z-index": "35" }); $("#" + TableID + "_tableFix").offset($("#" + TableID + "_tableLayout").offset()); $("#" + TableID + "_tableHead").offset($("#" + TableID + "_tableLayout").offset()); $("#" + TableID + "_tableColumn").offset($("#" + TableID + "_tableLayout").offset()); $("#" + TableID + "_tableData").offset($("#" + TableID + "_tableLayout").offset());

 

四、代码如下

 

完整代码如下:

function FixTable(TableID, FixColumnNumber, width, height) {
	/// <summary>
	///     锁定表头和列
	///     <para> sorex.cnblogs.com </para>
	/// </summary>
	/// <param name="TableID" type="String">
	///     要锁定的Table的ID
	/// </param>
	/// <param name="FixColumnNumber" type="Number">
	///     要锁定列的个数
	/// </param>
	/// <param name="width" type="Number">
	///     显示的宽度
	/// </param>
	/// <param name="height" type="Number">
	///     显示的高度
	/// </param>
	if ($("#" + TableID + "_tableLayout").length != 0) {
		$("#" + TableID + "_tableLayout").before($("#" + TableID));
		$("#" + TableID + "_tableLayout").empty();
	}
	else {
		$("#" + TableID).after("<div id='" + TableID + "_tableLayout' style='overflow:hidden;height:" + height + "px; width:" + width + "px;'></div>");
	}

	$('<div id="' + TableID + '_tableFix"></div>'
	+ '<div id="' + TableID + '_tableHead"></div>'
	+ '<div id="' + TableID + '_tableColumn"></div>'
	+ '<div id="' + TableID + '_tableData"></div>').appendTo("#" + TableID + "_tableLayout");


	var oldtable = $("#" + TableID);

	var tableFixClone = oldtable.clone(true);
	tableFixClone.attr("id", TableID + "_tableFixClone");
	$("#" + TableID + "_tableFix").append(tableFixClone);
	var tableHeadClone = oldtable.clone(true);
	tableHeadClone.attr("id", TableID + "_tableHeadClone");
	$("#" + TableID + "_tableHead").append(tableHeadClone);
	var tableColumnClone = oldtable.clone(true);
	tableColumnClone.attr("id", TableID + "_tableColumnClone");
	$("#" + TableID + "_tableColumn").append(tableColumnClone);
	$("#" + TableID + "_tableData").append(oldtable);

	$("#" + TableID + "_tableLayout table").each(function () {
		$(this).css("margin", "0");
	});


	var HeadHeight = $("#" + TableID + "_tableHead thead").height();
	HeadHeight += 2;
	$("#" + TableID + "_tableHead").css("height", HeadHeight);
	$("#" + TableID + "_tableFix").css("height", HeadHeight);


	var ColumnsWidth = 0;
	var ColumnsNumber = 0;
	$("#" + TableID + "_tableColumn tr:last td:lt(" + FixColumnNumber + ")").each(function () {
		ColumnsWidth += $(this).outerWidth(true);
		ColumnsNumber++;
	});
	ColumnsWidth += 2;
	if ($.browser.msie) {
		switch ($.browser.version) {
			case "7.0":
				if (ColumnsNumber >= 3) ColumnsWidth--;
				break;
			case "8.0":
				if (ColumnsNumber >= 2) ColumnsWidth--;
				break;
		}
	}
	$("#" + TableID + "_tableColumn").css("width", ColumnsWidth);
	$("#" + TableID + "_tableFix").css("width", ColumnsWidth);


	$("#" + TableID + "_tableData").scroll(function () {
		$("#" + TableID + "_tableHead").scrollLeft($("#" + TableID + "_tableData").scrollLeft());
		$("#" + TableID + "_tableColumn").scrollTop($("#" + TableID + "_tableData").scrollTop());
	});

	$("#" + TableID + "_tableFix").css({ "overflow": "hidden", "position": "relative", "z-index": "50", "background-color": "Silver" });
	$("#" + TableID + "_tableHead").css({ "overflow": "hidden", "width": width - 17, "position": "relative", "z-index": "45", "background-color": "Silver" });
	$("#" + TableID + "_tableColumn").css({ "overflow": "hidden", "height": height - 17, "position": "relative", "z-index": "40", "background-color": "Silver" });
	$("#" + TableID + "_tableData").css({ "overflow": "scroll", "width": width, "height": height, "position": "relative", "z-index": "35" });

	if ($("#" + TableID + "_tableHead").width() > $("#" + TableID + "_tableFix table").width()) {
		$("#" + TableID + "_tableHead").css("width", $("#" + TableID + "_tableFix table").width());
		$("#" + TableID + "_tableData").css("width", $("#" + TableID + "_tableFix table").width() + 17);
	}
	if ($("#" + TableID + "_tableColumn").height() > $("#" + TableID + "_tableColumn table").height()) {
		$("#" + TableID + "_tableColumn").css("height", $("#" + TableID + "_tableColumn table").height());
		$("#" + TableID + "_tableData").css("height", $("#" + TableID + "_tableColumn table").height() + 17);
	}

	$("#" + TableID + "_tableFix").offset($("#" + TableID + "_tableLayout").offset());
	$("#" + TableID + "_tableHead").offset($("#" + TableID + "_tableLayout").offset());
	$("#" + TableID + "_tableColumn").offset($("#" + TableID + "_tableLayout").offset());
	$("#" + TableID + "_tableData").offset($("#" + TableID + "_tableLayout").offset());
}

ps:之前的代码有点bug,在高度不够的时候定位会产生错误,在此修正了。

ps2:代码中使用了jquery的msie方法,此方法在1.9.x中删除,需要添加jQuery Migrate Plugin引用,在jQuery官网即可下载到。

ps3:代码在本页中就有,请需要代码的自行右键查看源代码查看即可。

ps4:效果也在本页有示例。

ps5:请阅读完毕后,还有问题,请发消息。

ps6:本人现在上此博客偏少,回复时间过长请见谅。

 

posted @ 2011-06-30 08:37  ☆磊☆  阅读(81329)  评论(85编辑  收藏  举报