上次做table排序对table有了一些了解,这次更是深入了解了一番,发现table原来是这么不简单。
还不清楚这个效果叫什么,就叫行定位吧,本来想把列定位也做出来,但暂时还没这个需求,等以后有时间再弄吧。
程序原理
一开始的需求只是表头部分在滚动时能一直固定在头部,那关键要实现的就是让tr能定位。
首先想到的方法是给tr设置relative,用ie6/7测试以下代码:
[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]
给tr设置relative后就能相对table定位了,看来很简单啊,但问题是这个方法ie8和ff都无效,而且存在很多问题,所以很快就被抛弃了。
ps:该效果用来做tr的拖动会很方便。
接着想到的是给table插入一个新tr,克隆原来的tr,并设置这个tr为fixed(ie6为absolute),例如:
Code
[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]
第一个问题是fixed的tr在ie7中不能进行定位,而且td在定位后并不能保持在表格中的布局,这样在原表格插tr就没意义了。
ps:fixed的相关应用可参考仿LightBox效果。
最后我用的方法是新建一个table,并把源tr克隆到新table中,然后通过对新table定位来实现效果。
用这个方法关键有两点,首先要做一个仿真度尽可能高的tr,还有是要准确的定位,这些请看后面的程序说明。
程序说明
【克隆table】
克隆一个元素用cloneNode就可以了,它有一个bool参数,表示克隆是否包含子节点。
程序第一步就是克隆原table:
this._oTable = $(table);//源table
this._nTable = this._oTable.cloneNode(false);//新table
this._nTable.id = "";//避免id冲突
要注意虽然ie的cloneNode参数是可选的(默认是false),但在ff是必须的,建议使用时都写上参数。
还要注意的是id属性也会被克隆,也就是克隆后会有两个相同id的元素(如果克隆对象有设置的话),这很容易会导致其他问题,程序会把克隆table的id属性设空。
ps:table请用class来绑定样式,用id的话新table就获取不了样式了。
克隆之后再设置样式:
this._style.width = this._oTable.offsetWidth + "px";
this._style.position = isIE6 ? "absolute" : "fixed";
this._style.zIndex = 100;
一般来说offsetWidth是width+padding+border的结果,但table比较特别,测试下面的代码:
[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]
只要给table设置width(style或本身的width属性),不管设置padding和border是多少,offsetWidth都等于width的值。
经测量offsetWidth是没错的,那就是说是table的width设置的问题。
中说width属性是the desired width of the entire table,我估计entire就是包含了padding和border,找不到什么其他说明,先这么理解吧。
定位方面,除了不支持fixed的ie6用absolute,其他都使用fixed定位。
【克隆tr】
table有一个rows集合,包括了table的所有tr(包括thead和tfoot里面的)。
程序的Clone方法会根据其参数克隆对应索引的tr:
this._index = Math.max(0, Math.min(this._oTable.rows.length - 1, isNaN(index) ? this._index : index));
this._oRow = this._oTable.rows[this._index];
var oT = this._oRow, nT = oT.cloneNode(true);
由于tr可能是包含在thead这些中,所以还要判断一下: