这里的DataTable指的是http://www.datatables.net/的DataTable工具。
DataTable在实现时,一共使用了两种方式:
- 支持水平或垂直滚动;
- 不支持水平或垂直滚动;
这两种方式的实现方式是完全不同的。后一种不支持滚动的DataTable,数据和列标题都是在同一个HTML Table元素中。这种永远也不会出现标题列和数据列对不齐的问题。
而第一种为了支持一些特殊的功能,比如"固定列标题",采用了拆分数据列和标题列的方式,分别用一个Table元素包装起来。第二种比较简单,不做介绍,主要讲第一种的原理。
'sScrollX': "100%" || 'sScrollY':"400"
凡是使用了这个feature的DataTable,数据列和标题列其实不在同一个table元素中。
如何确定每一列的宽度
知识准备:
- oSettings是DataTable类的一个配置对象。
- oSettings.aoColumns是一个数组,保存了每一列的配置。
- oSettings.aoData包含了DataTable所有缓存的数据;oSettings.aoData是一个数组,它的长度就是总共的记录数。
- outerWidth:是width, padding和border之和。
实现步骤:
1. 从第一个可见列开始,遍历oSettings.aoData,找出该列中最长的值。如此重复,直到找出每一个可见列的最长的值。
2. 用第1步中找出的所有的最长值构建一个临时隐藏的表(Table元素,在JS中存储为nCalcTmp对象),加入到HTML页面中。
3. 计算整个临时表的长度。这一步比较诡异,不是直接取的临时表的长度,而是遍历每一列,把每一个可见列的outerWidth加起来算出来的。
4. 使用jQuery的width()方法,从临时表的tbody中获取第一行每一列的width,并赋给oSettings.aoColumns[i].sWidth。
5. 最终标题列的每一列的width,就是由oSettings.aoColumns[i].sWidth决定的。
面临的问题:
1.有风险的是第1步,虽然取的是每列最长值,但是这些值在表中显示时可能会换行。而实际显示时,这些实际记录显示的值在显示时可能并不会换行,从而使最终的长度计算失误。导致列标题和数据列对不齐。
其中一个解决办法是强制使每一列不能换行,这种方法适合数量都不长的情况。如果真的需要换行,初始时设置sWidth可能有效。
2.临时表中的数据非常简单,thead中只包含原来的列标题,tbody只包含一行数据,每一列的内容都是这一列最长的值。
计算整个临时表的长度时,竟然不是取表的width,而是通过计算每一列第一个单元格的outerWidth,然后相加得出来的。如果使用了border-spacing这样的样式,这样算出来的表的width肯定错误的。好在这个临时表不需要显示。
真正值得商榷的是,此时通过计算得出的临时表的长度也被赋给了真正显示的表的width样式。好在最后还是取临时表的outerWidth赋给真正显示的表作为最终的长度(在table的width不是百分比的情况下)。
3.标题列的长度使用的是临时表的数据列的width,如果标题列的padding和border与数据列的padding和border不一样,受table上width的限制,将导致th上的width失去作用,致使数据列和标题列对不齐。