Last time I did table sorting, I gained some understanding of the table. This time I learned more about it and found that the table is so complicated.
I don’t know yet what this effect is called, let’s just call it row positioning. I originally wanted to do column positioning, but there is no need for it yet. I will do it when I have time.
Program Principle
The initial requirement is that the head part of the watch can always be fixed on the head when scrolling. The key thing to achieve is to enable tr to be positioned.
The first thing that comes to mind is to set relative for tr and test the following code with ie6/7:
The last method I used was to create a new table, clone the source tr into the new table, and then position the new table to achieve the effect.
There are two key points in using this method. First, you need to make a TR with the highest degree of simulation possible, and secondly, you need to accurately position it. Please see the following program instructions for these.
Procedure Description
【Clone table】
To clone an element, just use cloneNode. It has a bool parameter indicating whether the clone contains child nodes.
The first step of the program is to clone the original table:
It should be noted that although the cloneNode parameter of ie is optional (default is false), it is required in ff. It is recommended to write the parameters when using it.
Also note that the id attribute will also be cloned, that is, there will be two elements with the same id after cloning (if the clone object is set), which can easily lead to other problems. The program will clone the table Leave the id attribute empty.
ps: Please use class to bind the style to the table. If you use id, the new table will not be able to obtain the style.
Clone and then set the style:
Generally speaking, offsetWidth is the result of width padding border, but table is special. Test the following code:
【克隆tr】
table有一个rows集合,包括了table的所有tr(包括thead和tfoot里面的)。
程序的Clone方法会根据其参数克隆对应索引的tr:
由于tr可能是包含在thead这些中,所以还要判断一下:
然后再插入到新table中:
Because the program allows modification of the cloned tr, it will determine whether it has been inserted. If not, it will directly appendChild, otherwise replace the original tr with replaceChild.
[table’s border and frame attributes]
The border attribute of table is used to specify the border width, and the table-specific frame attribute is used to set or get the display method of the border around the table.
The frame part of the w3c label indicates that the frame can have the following values:
void: No sides. This is the default value.
above: The top side only.
below: The bottom side only.
hsides: The top and bottom sides only.
vsides: The right and left sides only.
lhs: The left-hand side only.
rhs: The right-hand side only.
box: All four sides.
border: All four sides.
These values specify the border to be displayed. It should be noted that although void is the default value, if it is not set, it is actually a null value, and all four borders will be displayed.
Also, frame has no effect on the border set by style. Test the following code:
ParentNode is used above. By the way, let’s talk about the difference between it and offsetParent and parentElement.
First look at the description of parentNode in w3c:
The parent of this node. All nodes, except Document, DocumentFragment, and Attr may have a parent. However, if a node has just been created and not yet added to the tree, or if it has been removed from the tree, this is null.
It is very simple, it is the parent node of the node. Anyone who has seen DOM knows it.
Look at offsetParent, which is easier to distinguish. It is vague in both mozilla and msdn, but it is clearer in w3c:
The offsetParent attribute, when called on element A, must return the element determined by the following algorithm:
1,If any of the following holds true return null and stop this algorithm:
A is the root element.
A is the HTML body element.
The computed value of the position property for element A is fixed.
2,If A is an area HTML element which has a map HTML element somewhere in the ancestor chain return the nearest ancestor map HTML element and stop this algorithm.
3, Return the nearest ancestor element of A for which at least one of the following is true and stop this algorithm if such an ancestor is found:
The computed value of the position property is not static .
It is the HTML body element.
The computed value of the position property of A is static and the ancestor is one of the following HTML elements: td, th, or table.
4,Return null .
There are four main points here:
1. If it is a root element, body element or the position of the element is fixed, null will be returned;
2. If it is an area element, the closest map element will be returned. ;
3, returns the element closest to the node that meets at least one of the following conditions: 1. The position of the element is not static; 2. It is a body element; 3. The position of the source element is static, and the following elements among the ancestor elements: td, th or table.
4, returns null.
The third point is the most common situation. For details, you can see the test below:
【设置td宽度】
接下来就要设置td宽度了,要获取某元素的宽度可以通过以下方法:
1,支持defaultView的可以直接用getComputedStyle获取width。
2,获取offsetWidth,再减去border和padding的宽度。
这个本来也可以,但td的border宽度的获取比较麻烦,下面有更方便的方法。
3,获取clientWidth,再减去padding的宽度。
这个跟方法2差不多,但更简单方便。
注意ie的currentStyle不像getComputedStyle能获取准确值,而只是一个设置值,像百分比、auto这些并不会自动转成准确值,即使是得到准确值也不一定是实际值,像td即使设置一个很大的准确值,实际值也不会超过table本身的宽度。
所以在td这种比较特殊的结构中,除非是很理想的状况,否则用currentStyle基本没戏,而且在这个效果中即使是差了1px也会看不舒服。
对于支持defaultView的当然可以直接获取,否则就用上面的方法3来获取:
But no matter which method here, there is a problem, that is, scroll occurs, but fortunately, even if the td element is set to overflow to scroll, the scroll bar will not appear, except for ie8 and chrome.
The program does not handle this situation. After all, it is not common to set scroll for td, and there are not many browsers that support this. There is no need to spend too much time here.
ps: Regarding the automatic adjustment of td width, please refer to the table-layout part of w3c .
If there are settings that affect the original td structure, such as colspan, please pay attention. The wrong structure may cause some abnormal deformation.
If the structure or content of the original table is modified, the Clone method should be executed to reconstruct the new table.
This part is more important for the experience. If it is not set properly, it will feel deformed, which is very unsightly.
【borderCollapse】
It is mentioned above that obtaining the border width of td is troublesome, but how troublesome is it?
If it is just a general case, just get the width through borderLeftWidth and borderRightWidth.
ps: If borderStyle is "none", then the border will be invalid, so if you want to get the border width, it is best to first determine whether borderStyle is "none".
But table has a special style borderCollapse, which sets the table's border model.
It has two values, namely separate (separate, default value) and collapse (merge).
separate is the effect we usually see. Here we mainly discuss collapse. Let’s first see what mozilla says:
In the collapsed border model, adjacent table cells share borders .
means that in the collapse border model, adjacent tds will share the border. It will be clearer if you look at the following example:
collapse is to make a border table, such as a table with a 1px border:
在使用了collapse之后,要写一个通用的获取边框宽度程序会变得十分麻烦,而且有些情况下甚至没办法判断获取。
详细情况这里就不细说了,有兴趣研究的话可以看看w3c的The collapsing border model,当然要想全部了解的话还要在各个浏览器中研究。
【元素位置】
table的样式设置好后,还需要获取原table和原tr的位置参数,为后面的元素定位做准备。
要获取某个元素相对文档的位置,传统的做法是获取对象的offsetLeft/offsetTop,然后不断获取offsetParent的offsetLeft/offsetTop,直到找不到offsetParent为止。
得到的结果就是相对文档的位置了,上面已经介绍过offsetParent,原理应该都明白了吧。
程序的SetRect设置区域属性方法中也使用了这个思路:
获取原table和tr的位置后,还需要计算新table的位置。
程序可以自定义新table位于视窗位置的百分比,例如顶部是0,中间是0.5,底部是1,可以在程序初始化时或用SetPos方法来设置。
这里主要获取视窗高度和新table在视窗的top值:
定位范围实际上是从视框顶部到视框高度减去新table高度的范围内的,所以计算时要先把视窗高度减去新table的高度。
【元素定位】
万事俱备,只欠定位了。
由于要根据窗口滚动状态来判断计算定位,scrollTop/scrollLeft的获取必不可少。
但在chrome中就算用了DOCTYPE,也要用document.body来获取scrollTop/scrollLeft,尽管它确实有document.documentElement。
对chrome了解不多,也不知哪里能查它的相关文档,程序里就直接做个判断算了:
定位的第一步就是判断是否需要定位,这里的判断标准有两个,第一个是原tr是否超过了视窗范围,还有是新table要显示的位置是否在原table的显示范围内。
第一点可以通过原tr位置的顶部和底部是否超过视窗的顶部和底部来判断:
在看第二点之前先看看程序中的Auto属性,它是用来指定否自动定位的。
如果自动定位的话当原tr离开视框顶部新table就会定位到视框顶部,原tr离开底部新table就会定位到视框底部,这样看上去会比较自然顺畅。
如果不选择自动的话就会根据SetPos方法中计算得到的新table视窗top值来设置定位:
接着就判断新table要显示的位置是否在原table的显示范围内,这个可以通过新table位置的顶部和底部是否超过原table的顶部和底部来判断:
当符合所有的条件就可以进行定位了,如果是fixed定位的就使用相对视窗的top值:
For example, if ie6 is positioned absolutely, you need to use the top value of the relative document:
Considering left and right scrolling, left must also be set.
Of course, if the conditions are not met, the new table will be hidden. The program sets a large negative value for top to indirectly "hide" it.
The negative value is used because it will not stretch the IE6 page. The reason why display is not used is because its offsetHeight needs to be obtained above. If it is hidden by display, it cannot be obtained.
Finally, just bind the Run program to the scroll event of the window. The height of the view frame will change when the window is resized, so the resize event needs to be bound to the SetPos program.
【Cover select】
As long as you use positioning, you have to face an old rival "ie6's select".
I have also introduced some solutions in previous articles (Refer to the overlay select here). You cannot hide the select directly here, so it seems that you can only use iframe.
But there is a big problem with iframe. Test the following code in ie6 and drag the scroll bar:
使用说明
实例化一个TableFixed对象只需要一个参数table的id:
实例化时有4个可选属性:
Index: 0,//tr索引
Auto: true,//是否自动定位
Pos: 0,//自定义定位位置百分比(0到1)
Hide: false//是否隐藏(不显示)
其中Index和Pos在实例化之后就不能使用。
要修改克隆行可以用Clone方法,其参数是要克隆tr的索引。
要修改自定义定位位置可以用SetPos方法,其参数是要定位的位置百分比。
具体使用请参考实例。
Program source code