客户要求实现对表格数据的头几行或者头几列进行冻结,即滚动时保持这几行/列不动,通过网上查找代码,参考已有的代码的思路,实现了可以任意对行、列进行冻结。
实现原理:
创建多个div,div之间通过css实现层叠,每个div放置当前表格的克隆。例如:需要行冻结时,创建存放冻结行表格的div,通过设置z-index属性和position属性,让冻结行表格在数据表格的上层。同理,需要列冻结时,创建存放冻结列表格的div,并放置在数据表格的上层。如果需要行列都冻结时,则除了创建冻结行、冻结列表格的div,还需要创建左上角的固定行列表格的div,并放置在所有div的最上层。
处理表格的滚动事件,在表格横向或者纵向滚动时,同时让相应的冻结行和冻结列也同步滚动。
处理html的resize事件,同步修改表格的滚动区域宽度和高度
代码如下:
1 /* 2 * 锁定表头和列 3 * 4 * 参数定义 5 * table - 要锁定的表格元素或者表格ID 6 * freezeRowNum - 要锁定的前几行行数,如果行不锁定,则设置为0 7 * freezeColumnNum - 要锁定的前几列列数,如果列不锁定,则设置为0 8 * width - 表格的滚动区域宽度 9 * height - 表格的滚动区域高度 10 */ 11 function freezeTable(table, freezeRowNum, freezeColumnNum, width, height) { 12 if (typeof(freezeRowNum) == 'string') 13 freezeRowNum = parseInt(freezeRowNum) 14 15 if (typeof(freezeColumnNum) == 'string') 16 freezeColumnNum = parseInt(freezeColumnNum) 17 18 var tableId; 19 if (typeof(table) == 'string') { 20 tableId = table; 21 table = $('#' + tableId); 22 } else 23 tableId = table.attr('id'); 24 25 var divTableLayout = $("#" + tableId + "_tableLayout"); 26 27 if (divTableLayout.length != 0) { 28 divTableLayout.before(table); 29 divTableLayout.empty(); 30 } else { 31 table.after("<div id='" + tableId + "_tableLayout' style='overflow:hidden;height:" + height + "px; " + width + "px;'></div>"); 32 33 divTableLayout = $("#" + tableId + "_tableLayout"); 34 } 35 36 var html = ''; 37 if (freezeRowNum > 0 && freezeColumnNum > 0) 38 html += '<div id="' + tableId + '_tableFix" style="padding: 0px;"></div>'; 39 40 if (freezeRowNum > 0) 41 html += '<div id="' + tableId + '_tableHead" style="padding: 0px;"></div>'; 42 43 if (freezeColumnNum > 0) 44 html += '<div id="' + tableId + '_tableColumn" style="padding: 0px;"></div>'; 45 46 html += '<div id="' + tableId + '_tableData" style="padding: 0px;"></div>'; 47 48 49 $(html).appendTo("#" + tableId + "_tableLayout"); 50 51 var divTableFix = freezeRowNum > 0 && freezeColumnNum > 0 ? $("#" + tableId + "_tableFix") : null; 52 var divTableHead = freezeRowNum > 0 ? $("#" + tableId + "_tableHead") : null; 53 var divTableColumn = freezeColumnNum > 0 ? $("#" + tableId + "_tableColumn") : null; 54 var divTableData = $("#" + tableId + "_tableData"); 55 56 divTableData.append(table); 57 58 if (divTableFix != null) { 59 var tableFixClone = table.clone(true); 60 tableFixClone.attr("id", tableId + "_tableFixClone"); 61 divTableFix.append(tableFixClone); 62 } 63 64 if (divTableHead != null) { 65 var tableHeadClone = table.clone(true); 66 tableHeadClone.attr("id", tableId + "_tableHeadClone"); 67 divTableHead.append(tableHeadClone); 68 } 69 70 if (divTableColumn != null) { 71 var tableColumnClone = table.clone(true); 72 tableColumnClone.attr("id", tableId + "_tableColumnClone"); 73 divTableColumn.append(tableColumnClone); 74 } 75 76 $("#" + tableId + "_tableLayout table").css("margin", "0"); 77 78 if (freezeRowNum > 0) { 79 var HeadHeight = 0; 80 var ignoreRowNum = 0; 81 $("#" + tableId + "_tableHead tr:lt(" + freezeRowNum + ")").each(function () { 82 if (ignoreRowNum > 0) 83 ignoreRowNum--; 84 else { 85 var td = $(this).find('td:first, th:first'); 86 HeadHeight += td.outerHeight(true); 87 88 ignoreRowNum = td.attr('rowSpan'); 89 if (typeof(ignoreRowNum) == 'undefined') 90 ignoreRowNum = 0; 91 else 92 ignoreRowNum = parseInt(ignoreRowNum) - 1; 93 } 94 }); 95 HeadHeight += 2; 96 97 divTableHead.css("height", HeadHeight); 98 divTableFix != null && divTableFix.css("height", HeadHeight); 99 } 100 101 if (freezeColumnNum > 0) { 102 var ColumnsWidth = 0; 103 var ColumnsNumber = 0; 104 $("#" + tableId + "_tableColumn tr:eq(" + freezeRowNum + ")").find("td:lt(" + freezeColumnNum + "), th:lt(" + freezeColumnNum + ")").each(function () { 105 if (ColumnsNumber >= freezeColumnNum) 106 return; 107 108 ColumnsWidth += $(this).outerWidth(true); 109 110 ColumnsNumber += $(this).attr('colSpan') ? parseInt($(this).attr('colSpan')) : 1; 111 }); 112 ColumnsWidth += 2; 113 114 divTableColumn.css("width", ColumnsWidth); 115 divTableFix != null && divTableFix.css("width", ColumnsWidth); 116 } 117 118 divTableData.scroll(function () { 119 divTableHead != null && divTableHead.scrollLeft(divTableData.scrollLeft()); 120 121 divTableColumn != null && divTableColumn.scrollTop(divTableData.scrollTop()); 122 }); 123 124 divTableFix != null && divTableFix.css({ "overflow": "hidden", "position": "absolute", "z-index": "50" }); 125 divTableHead != null && divTableHead.css({ "overflow": "hidden", "width": width - 17, "position": "absolute", "z-index": "45" }); 126 divTableColumn != null && divTableColumn.css({ "overflow": "hidden", "height": height - 17, "position": "absolute", "z-index": "40" }); 127 divTableData.css({ "overflow": "scroll", "width": width, "height": height, "position": "absolute" }); 128 129 divTableFix != null && divTableFix.offset(divTableLayout.offset()); 130 divTableHead != null && divTableHead.offset(divTableLayout.offset()); 131 divTableColumn != null && divTableColumn.offset(divTableLayout.offset()); 132 divTableData.offset(divTableLayout.offset()); 133 } 134 135 /* 136 * 调整锁定表的宽度和高度,这个函数在resize事件中调用 137 * 138 * 参数定义 139 * table - 要锁定的表格元素或者表格ID 140 * width - 表格的滚动区域宽度 141 * height - 表格的滚动区域高度 142 */ 143 function adjustTableSize(table, width, height) { 144 var tableId; 145 if (typeof(table) == 'string') 146 tableId = table; 147 else 148 tableId = table.attr('id'); 149 150 $("#" + tableId + "_tableLayout").width(width).height(height); 151 $("#" + tableId + "_tableHead").width(width - 17); 152 $("#" + tableId + "_tableColumn").height(height - 17); 153 $("#" + tableId + "_tableData").width(width).height(height); 154 } 155 156 function pageHeight() { 157 if ($.browser.msie) { 158 return document.compatMode == "CSS1Compat" ? document.documentElement.clientHeight : document.body.clientHeight; 159 } else { 160 return self.innerHeight; 161 } 162 }; 163 164 //返回当前页面宽度 165 function pageWidth() { 166 if ($.browser.msie) { 167 return document.compatMode == "CSS1Compat" ? document.documentElement.clientWidth : document.body.clientWidth; 168 } else { 169 return self.innerWidth; 170 } 171 }; 172 173 $(document).ready(function() { 174 var table = $("table"); 175 var tableId = table.attr('id'); 176 var freezeRowNum = table.attr('freezeRowNum'); 177 var freezeColumnNum = table.attr('freezeColumnNum'); 178 179 if (typeof(freezeRowNum) != 'undefined' || typeof(freezeColumnNum) != 'undefined') { 180 freezeTable(table, freezeRowNum || 0, freezeColumnNum || 0, pageWidth(), pageHeight()); 181 182 var flag = false; 183 $(window).resize(function() { 184 if (flag) 185 return ; 186 187 setTimeout(function() { 188 adjustTableSize(tableId, pageWidth(), pageHeight()); 189 flag = false; 190 }, 100); 191 192 flag = true; 193 }); 194 } 195 });
使用时,只要在table元素设置freezeRowNum和freezeColumnNum属性值,即可实现冻结效果
<table id="reportTable" width="1900" freezeRowNum="2" freezeColumnNum="2" class="report" align="center"> ... </table>