表头固定的表格绘制

已封装为jquery插件,其中

a、fixedtable.css

 1 .fix-header-table { overflow:auto; overflow-x:auto; overflow-y:hidden; position:relative; height:100%;}
 2 .fix-header-table table { border-collapse:collapse; table-layout:fixed; width:100%; }
 3 .fix-header-table td { line-height:40px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; padding:0 5px; }
 4 .fix-header-table tr.trForTdWidth td { border-style:none; height:0; }
 5 .divH { background:#f2f2f2; }
 6 .divH td { text-align:center; font-weight:bold; }
 7 .divH td.sortable { cursor:pointer; }
 8 .divB { overflow-x:hidden; overflow-y:auto; }
 9 .divB td { border-bottom:#dedede 1px solid; }
10 
11 .fix-header-table .table-header td { line-height:16px; padding:0; }
12 .fix-header-table .table-header td div { border-left:1px solid #D3D3D3; margin:12px 0; }
13 .fix-header-table .table-header td:first-child div { border-left:none; }
14 .fix-header-table tr.selected td { background-color:#eee; }
View Code

b、fixedtable.js

  1 /* Created By jcheng.matt
  2  * Date: 2016-10-08
  3  */
  4 
  5 (function ($) {
  6 
  7     // 固定表头表格对象
  8     var fixedtable = function (setting, obj) {
  9         this.setting = setting;
 10         this.obj = obj;
 11     };
 12 
 13     fixedtable.prototype.redraw = function () {
 14         var obj = this;
 15         // 表头
 16         var tbHeader = this.getHeader();
 17         // 表内容
 18         var tbBody = '<div class="divB">' + this.getBody() + '</div>';
 19         // 合并
 20         var html = '<div class="fix-header-table">'
 21         html += tbHeader;
 22         html += tbBody;
 23         html += '</div>';
 24 
 25         $(this.obj).empty().append(html);
 26         $(this.obj).find('.sortable').click(function (event) { obj.sort(event); });
 27         $(this.obj).find('tr[data-row-index]').click(function (event) { obj.select(event); });
 28 
 29         // 绑定resize事件
 30         $(window).resize(function () { obj.resize(); });
 31 
 32         this.resize();
 33     }
 34 
 35     fixedtable.prototype.getHeader = function () {
 36         var header = this.setting.header;
 37         var html = '<div class="divH"><table>';
 38         html += this.getTrForTdWidth();
 39         html += '<tr class="table-header">';
 40         for (var i = 0; i < header.length; i++) {
 41             var headerClass = header[i].headerClass ? header[i].headerClass : '';
 42             if (header[i].sortable) {
 43                 html += '<td data-index="' + i + '" class="sortable ' + headerClass + '" ><div>' + header[i].header + '</div></td>';
 44             }
 45             else {
 46                 html += '<td data-index="' + i + '" class="' + headerClass + '"><div>' + header[i].header + '</div></td>';
 47             }
 48         }
 49         html += '</tr>';
 50         html += '</table></div>';
 51         return html;
 52     }
 53 
 54     fixedtable.prototype.getBody = function () {
 55         var header = this.setting.header;
 56         var list = this.setting.data;
 57         var html = '<table>';
 58         html += this.getTrForTdWidth();
 59         for (var i = 0; i < list.length; i++) {
 60             html += '<tr class="detail" data-row-index="' + i + '">';
 61             for (var j = 0; j < header.length; j++) {
 62                 var prop = header[j].dataIndex;
 63                 var formatter = header[j].formatter ? header[j].formatter : this.setting.formatter;
 64                 var align = header[j].textAlign ? header[j].textAlign : this.setting.textAlign;
 65                 html += '<td style="text-align:' + align + '">' + formatter(list[i][prop], i, list[i]) + '</td>'
 66             }
 67             html += '</tr>';
 68         }
 69         html += '</table>';
 70         return html;
 71     }
 72 
 73     fixedtable.prototype.getTrForTdWidth = function () {
 74         var header = this.setting.header;
 75         var html = '<tr class="trForTdWidth">';
 76         for (var i = 0; i < header.length; i++) {
 77             html += '<td style="width:' + header[i].width + ';"></td>';
 78         }
 79         html += '</tr>';
 80         return html;
 81     }
 82 
 83     fixedtable.prototype.sort = function (event) {
 84         var obj = this;
 85         var header = this.setting.header;
 86         var index = +$(event.target).attr('data-index');
 87         var isDescending;
 88         if (!$(event.target).hasClass('asc')) {
 89             isDescending = false;
 90             $(event.target).addClass('asc');
 91         }
 92         else {
 93             isDescending = true;
 94             $(event.target).removeClass('asc');
 95         }
 96         list.sort(function (a, b) {
 97             var dataIndex = header[index].dataIndex;
 98             var compare = header[index].compare ? header[index].compare : this.setting.compare;
 99             return (isDescending ? 1 : -1) * compare(a[dataIndex], b[dataIndex]);
100         });
101         $(this.obj).find('.divB').html(this.getBody());
102         $(this.obj).find('tr[data-row-index]').click(function (event) { obj.select(event); });
103         $(this.obj).find('tr[data-row-index]').first().click();
104     }
105 
106     fixedtable.prototype.select = function (event) {
107         if ($(event.currentTarget).hasClass('selected')) {
108             return;
109         }
110 
111         $(event.currentTarget).siblings().removeClass('selected');
112         $(event.currentTarget).addClass('selected');
113 
114         if (this.setting.rowClick) {
115             this.setting.rowClick(event)
116         }
117     }
118 
119     fixedtable.prototype.resize = function () {
120         var fixedTable = $(this.obj);
121 
122         // 设置表体高度
123         fixedTable.find('.divB').height(fixedTable.height() - fixedTable.find('.divH').height());
124 
125         // ie7下,width 100%包含父元素的滚动条的宽度,需特殊处理
126         if (/MSIE\s*7/.test(navigator.userAgent)) {
127             var hasVerticalScroll = fixedTable.find('.divB').height() < fixedTable.find('.divB table').height();
128             if (hasVerticalScroll) {
129                 fixedTable.find('.divB table').width(fixedTable.find('.divB').width() - 17);
130             }
131         }
132 
133         // 设置表头与表体等宽(出现纵向滚动条会导致不等宽)
134         fixedTable.find('.divH, .divB').css('min-width', '');
135         fixedTable.find('.divH table').width(fixedTable.find('.divB table').width());
136 
137         var hasScroll = fixedTable.find('.divB table').width() > fixedTable.width();
138         if (hasScroll) {
139             // 当出现横向滚动条时,表体高度需减去滚动条的高度
140             fixedTable.find('.divB').height(fixedTable.height() - fixedTable.find('.divH').height() - 17);
141             // min-width的宽度包含滚动条的宽度,当出现纵向滚动条时需
142             fixedTable.find('table').each(function () {
143                 var hasVerticalScroll = fixedTable.find('.divB').height() < fixedTable.find('.divB table').height();
144                 $(this).parent().css('min-width', ($(this).width() + (hasVerticalScroll ? 17 : 0)) + 'px');
145             });
146         }
147     }
148 
149     $.fn.fixedtable = function (options) {
150         var fixedTableObj = this.prop('obj');
151         if (!fixedTableObj) {
152             var setting = $.extend({}, $.fn.fixedtable.defaults);
153             fixedTableObj = new fixedtable(setting, this[0]);
154             this.prop('obj', fixedtable);
155         }
156         if (options) {
157             fixedTableObj.setting = $.extend({}, $.fn.fixedtable.defaults, options);
158             fixedTableObj.redraw();
159         }
160 
161 
162         return {
163             resize: function () {
164                 fixedTableObj.resize();
165             }
166         };
167     };
168 
169     $.fn.fixedtable.defaults = {
170         header: [],
171         data: [],
172         textAlign: 'center',
173         formatter: function (arg) {
174             return arg;
175         },
176         compare: function (arg1, arg2) {
177             if (arg1 < arg2) {
178                 return -1;
179             }
180             else if (arg1 > arg2) {
181                 return 1;
182             }
183             else {
184                 return 0;
185             }
186         },
187         rowClick: null
188     }
189 } (jQuery));
View Code

c、index.html

 1 <html>
 2 <head>
 3     <title>演示</title>
 4     <link href="fixedtable.css" rel="stylesheet" type="text/css" />
 5     <style type="text/css">
 6         .rise { color:#cb0000; }
 7         .fall { color:#007c00; }
 8     </style>
 9 </head>
10 <body>
11     <div>
12         <div><input type="button" value="刷新" onclick="resize()" /></div>
13         <div id="productList" style="width:1200px; height:400px; border:1px red solid;"></div>
14     </div>
15     <script type="text/javascript" src="http://netws12-vpn/jquery/1.8_compress/jquery.js"></script>
16     <script src="fixedtable.js" type="text/javascript"></script>
17     <script type="text/javascript">
18         var data = JSON.parse('[{"Id":386942,"WindCode":"000011.OF","ProductName":"华夏大盘精选","ProductType":"混合型基金","ProductClassId":1,"NetValue":"9.987","NavDate":"2017-01-24","LastedReturn":"-0.488242327620548","Recent1WReturn":"1.4939024390244","Recent1MReturn":"-1.23615506329113","Recent3MReturn":"-4.14436672749522","Recent6MReturn":"-2.65471837258467","Last1Years":"8.97958911389916","Origin":1,"Comment":null,"HasAttachment":false,"Manager":"阳琨,佟巍","ManagerId":null,"SaleBeginDate":null,"SalesEndDate":null},{"Id":386943,"WindCode":"000198.OF","ProductName":"天弘余额宝","ProductType":"货币市场型基金","ProductClassId":1,"NetValue":"3.592","NavDate":"2017-01-24","LastedReturn":"0.00985100127148413","Recent1WReturn":"0.0676997093965305","Recent1MReturn":"0.293511369009213","Recent3MReturn":"0.710604208049393","Recent6MReturn":"1.30324472768988","Last1Years":"2.55870095046288","Origin":1,"Comment":null,"HasAttachment":false,"Manager":"王登峰","ManagerId":null,"SaleBeginDate":null,"SalesEndDate":null},{"Id":194263,"WindCode":"159915.OF","ProductName":"易方达创业板ETF","ProductType":"股票型基金","ProductClassId":1,"NetValue":"1.7845","NavDate":"2017-01-24","LastedReturn":"-1.36524430687596","Recent1WReturn":"-0.340667932536573","Recent1MReturn":"-5.23101433882102","Recent3MReturn":"-15.3824268576035","Recent6MReturn":"-17.2233045737081","Last1Years":"-12.6059062637739","Origin":1,"Comment":null,"HasAttachment":false,"Manager":"成曦","ManagerId":null,"SaleBeginDate":null,"SalesEndDate":null},{"Id":224735,"WindCode":"688888.OF","ProductName":"浙商聚潮产业成长","ProductType":"混合型基金","ProductClassId":1,"NetValue":"1.556","NavDate":"2017-01-24","LastedReturn":"-0.0642260757867624","Recent1WReturn":"0.842514581983158","Recent1MReturn":"-2.19987429289754","Recent3MReturn":"-4.9480757483201","Recent6MReturn":"-2.13836477987422","Last1Years":"9.42334739803095","Origin":1,"Comment":null,"HasAttachment":false,"Manager":"倪权生,唐桦","ManagerId":null,"SaleBeginDate":null,"SalesEndDate":null},{"Id":178498,"WindCode":"000010.OF","ProductName":"易方达天天B","ProductType":"货币市场型基金","ProductClassId":1,"NetValue":"4.141","NavDate":"2017-01-24","LastedReturn":"0.0101480032879236","Recent1WReturn":"0.0778444923164692","Recent1MReturn":"0.335762783591696","Recent3MReturn":"0.790143781115028","Recent6MReturn":"1.48484730061463","Last1Years":"2.89431621475745","Origin":1,"Comment":null,"HasAttachment":false,"Manager":"石大怿,刘朝阳","ManagerId":null,"SaleBeginDate":null,"SalesEndDate":null},{"Id":125577,"WindCode":"000001.OF","ProductName":"华夏成长","ProductType":"混合型基金","ProductClassId":1,"NetValue":"1.038","NavDate":"2017-01-24","LastedReturn":"-0.192307692307688","Recent1WReturn":"1.56555772994129","Recent1MReturn":"0.193049684953651","Recent3MReturn":"-7.12539916159948","Recent6MReturn":"-5.64859455462844","Last1Years":"-6.88248390221396","Origin":1,"Comment":null,"HasAttachment":false,"Manager":"董阳阳,许利明,孙萌","ManagerId":null,"SaleBeginDate":null,"SalesEndDate":null},{"Id":63905,"WindCode":"100058.OF","ProductName":"富国产业债","ProductType":"债券型基金","ProductClassId":1,"NetValue":"1.013","NavDate":"2017-01-24","LastedReturn":"0","Recent1WReturn":"-0.0986193293885819","Recent1MReturn":"0.881385109780586","Recent3MReturn":"-1.63099754586967","Recent6MReturn":"-0.686957215215817","Last1Years":"0.842707216337094","Origin":1,"Comment":null,"HasAttachment":false,"Manager":"黄纪亮","ManagerId":null,"SaleBeginDate":null,"SalesEndDate":null},{"Id":229772,"WindCode":"000065.OF","ProductName":"国富焦点驱动灵活配置","ProductType":"混合型基金","ProductClassId":1,"NetValue":"1.326","NavDate":"2017-01-24","LastedReturn":"0","Recent1WReturn":"0.151057401812696","Recent1MReturn":"0.683389756012791","Recent3MReturn":"-0.394590862359953","Recent6MReturn":"0.974803329836268","Last1Years":"4.76514880017546","Origin":1,"Comment":null,"HasAttachment":false,"Manager":"赵晓东","ManagerId":null,"SaleBeginDate":null,"SalesEndDate":null},{"Id":356466,"WindCode":"233009.OF","ProductName":"大摩多因子策略","ProductType":"混合型基金","ProductClassId":1,"NetValue":"1.623","NavDate":"2017-01-24","LastedReturn":"-0.490496627835686","Recent1WReturn":"0.995644057249539","Recent1MReturn":"-3.22003577817531","Recent3MReturn":"-4.95929704611373","Recent6MReturn":"-0.213700813717421","Last1Years":"20.2114597814387","Origin":1,"Comment":null,"HasAttachment":false,"Manager":"杨雨龙","ManagerId":null,"SaleBeginDate":null,"SalesEndDate":null},{"Id":381035,"WindCode":"002250.OF","ProductName":"红土创新改革红利","ProductType":"混合型基金","ProductClassId":1,"NetValue":"1.026","NavDate":"2017-01-24","LastedReturn":"-0.388349514563105","Recent1WReturn":"1.38339920948617","Recent1MReturn":"-0.581395348837217","Recent3MReturn":"-4.82374768089054","Recent6MReturn":"-0.677637947725075","Last1Years":"--","Origin":1,"Comment":null,"HasAttachment":false,"Manager":"丁硕","ManagerId":null,"SaleBeginDate":null,"SalesEndDate":null}]');
19         var headers = [
20                 { header: '产品名称', width: '85px', dataIndex: 'ProductName', textAlign: 'left' },
21                 { header: '产品代码', width: '40px', dataIndex: 'WindCode', sortable: true },
22                 { header: '类型', width: '50px', dataIndex: 'ProductType', sortable: true },
23                 { header: '净值/七日年化', width: '50px', dataIndex: 'NetValue', sortable: true, compare: compareNum },
24                 { header: '近1周', width: '30px', dataIndex: 'Recent1WReturn', formatter: getYieldHtml, sortable: true, compare: compareNum },
25                 { header: '近1月', width: '30px', dataIndex: 'Recent1MReturn', formatter: getYieldHtml, sortable: true, compare: compareNum },
26                 { header: '近3月', width: '30px', dataIndex: 'Recent3MReturn', formatter: getYieldHtml, sortable: true, compare: compareNum },
27                 { header: '近6月', width: '30px', dataIndex: 'Recent6MReturn', formatter: getYieldHtml, sortable: true, compare: compareNum },
28                 { header: '近一年', width: '30px', dataIndex: 'Last1Years', formatter: getYieldHtml, sortable: true, compare: compareNum },
29                 { header: '操作', width: '150px', dataIndex: '' }
30             ];
31         $('#productList').fixedtable({
32             header: headers,
33             data: data
34         });
35 
36         function getYieldHtml(value) {
37             if (value == '--') {
38                 return '<span>--</span>';
39             }
40 
41             var waveClass = '';
42             if (value > 0) {
43                 waveClass = 'rise';
44             }
45             else if (value < 0) {
46                 waveClass = 'fall'
47             }
48 
49             return '<span class="' + waveClass + '">' + (+value).toFixed(2) + '%</span>';
50         }
51 
52         function compareNum(arg1, arg2) {
53             if (arg1 == '--') {
54                 return -1;
55             }
56             if (arg2 == '--') {
57                 return 1;
58             }
59 
60             if (+arg1 < +arg2) {
61                 return -1;
62             }
63             else if (+arg1 > +arg2) {
64                 return 1;
65             }
66             else {
67                 return 0;
68             }
69         }
70 
71         function resize() {
72             $('#productList').height($('#productList').height() + 5);
73             $('#productList').fixedtable().resize();
74         }
75     </script>
76 </body>
77 </html>
View Code

下载: fixedtabledemo.rar

 

关于表格元素的几点说明:

1、在CSS中,内部表元素(如td、tr、col等)生成矩形框,这些矩形框包含内容、内边距和边框,但没有外边距,因此如果定义外边距,浏览器将忽略该定义;对于table元素,外边距有效,而对于内边距,当border-collapse为separate时有效,当border-collapse为collapse时无效,内边距的定义会被忽略

2、表显示的层级关系为:表 - 列组 - 列 - 行组 - 行 - 单元格,但对于边框并非层级重叠,而是边框合并

3、表的布局分为固定布局(table-layout:fixed;)和自动布局(table-layout:auto; 此为默认情况);在chrome中,当table的width为auto时(此为默认情况)就会触发自动布局,而无论table-layout的值是什么,但在ie中表现正常;关于浏览器处理固定布局与自动布局的详细步骤可以参考《css权威指南》

4、为了保持td中的文本不换行,可以应用以下样式:

  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;

  此样式兼容ie7、ie8、ie11、chrome,注意overflow:hidden是必须项,否则text-overflow:ellipsis无效

5、正常情况下,当table的宽度大于td初始宽度之和,多余的宽度将均分到各td,但ie7下,table第一行的td的文本对齐依据td的初始设置宽度,宽度重新配后文本的偏移距离并不随之调整,为兼容ie7,可添加空行(trForTdWdith)

 

关于div元素的宽度几点说明:

1、在文档流中,div的宽度取决于父元素,与子元素无关,这与table元素不同

2、css的overflow默认为visible,因此在默认情况下,当div的宽度小于子元素,子元素并不会截取,在这种情况下

  2.1 如果该div的overflow为auto,则该div会出现滚动条

  2.2 如果该div的overflow为visible(此为默认情况),但该div的某一父元素overflow为auto,则该父元素出现滚动条,但该div宽度依然不变,如同父元素overflow为默认值的情况

  2.3 如果该div及其父元素overflow均为默认情况,则页面会出现滚动条,但该div及其父元素不受影响,如同子元素宽度小于div的宽度的情况

3、在ie8及以上、chrome中,div为绝对定位且宽度未设定,并且其子元素为块级元素,这时div宽度取决于子元素;在ie7中,父元素并不会被子元素撑开,因此为了兼容ie7,须使用js动态设定父元素的宽度;对于绝对定位,如果其大小大于包含块,表现与2所示的情况相同

4、将div设为浮动也可以达到宽度被子元素撑开的目的,兼容性与设为绝对定位相同,即在ie7中,父元素并不会被子元素撑开,因此为了兼容ie7,须使用js动态设定父元素的宽度

 

关于div出现滚动条的几点说明:

1、当子元素宽度或高度大于父元素div,且div样式设为overflow:auto时,div将出现纵向或横向滚动条;在ie7、ie8、ie11、chrome,滚动条的宽度均为17px

2、设父元素为div1,子元素为div2,取父元素的高度或宽度(如$('#div1').width() 或$('#div1').height()),则父元素的宽高始终包含滚动条的宽度

3、对于子元素的高度或宽度,以宽度为例(高度表现与宽度相同),设子元素div2无内边距、外边距及边框,父元素出现纵向滚动条

  3.1 div2的宽度为100%时

    在ie8、ie11、chrome中,div2的宽度比父元素div1少17px,即:$('#div1').width() - $('#div2').width() == 17

    在ie7中,div2的宽度比父元素div1相同

  3.2 div2的宽度为auto时

     在所有浏览器下,div2的宽度均比父元素div1少17px,即:$('#div1').width() - $('#div2').width() == 17

4、设父元素div1定位为relative,子元素div2定位为absolute,在这种情况下可以通过设置div2的定位属性(top:30; bottom:0;)自动调节div2的高度,即通过css而非js调节绝对定位元素的高度;当div1出现滚动条时,在ie8、ie11、chrome中,bottom相对滚动条上边沿定位(即相对父元素内容区的底端定位),在ie7中,bottom相对滚动条下边沿定位(即相对父元素下边框定位),因此为兼容ie7,需使用js动态设置div2的高度

posted @ 2015-12-14 15:16  Matt_Cheng  阅读(372)  评论(0编辑  收藏  举报