- 浏览: 61026 次
- 性别:
- 来自: 顺德
最新评论
-
liuxf1122:
不支持最新的IE9、10和11!修改了也不行,不知如何是好啊! ...
JavaScript 工具库:Cloudgamer JavaScript Library v0.1 发布 -
gongyeye:
$$E.addEvent( this._container, ...
JavaScript 工具库:Cloudgamer JavaScript Library v0.1 发布 -
kingliu:
很好,很强大,学习了
JavaScript 工具库:Cloudgamer JavaScript Library v0.1 发布 -
lwkjob:
非常强大谢谢
图片延迟加载(按需加载)效果 -
zxh277100963:
判断ie版本 错误,我明细是IE8的判断出来是IE7
JavaScript 工具库:Cloudgamer JavaScript Library v0.1 发布
近来有客户要求用table显示一大串数据,由于滚动后就看不到表头,很不方便,所以想到这个效果。
上次做table排序对table有了一些了解,这次更是深入了解了一番,发现table原来是这么不简单。
还不清楚这个效果叫什么,就叫行定位吧,本来想把列定位也做出来,但暂时还没这个需求,等以后有时间再弄吧。
在淘宝的商品搜索页也看到类似的效果,但淘宝的不是table,只是li,在table相对会复杂一些。
要说明一下的是,我这个效果是用在一些普通的产品列表,当数据比较多时提高用户体验,而不是单单做数据显示,跟excel那样的方式是不同的。
效果预览
完整实例下载
程序原理
一开始的需求只是表头部分在滚动时能一直固定在头部,那关键要实现的就是让tr能定位。
首先想到的方法是给tr设置relative,用ie6/7测试以下代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<table cellpadding="5" cellspacing="0" border="1" width="100">
<tr style="position:relative; left:100px;">
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>
</body>
</html>
给tr设置relative后就能相对table定位了,看来很简单啊,但问题是这个方法ie8和ff都无效,而且存在很多问题,所以很快就被抛弃了。
ps:该效果用来做tr的拖动会很方便。
接着想到的是给table插入一个新tr,克隆原来的tr,并设置这个tr为fixed(ie6为absolute),例如:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<table cellpadding="5" cellspacing="0" border="1" width="100">
<tr style="position:fixed; left:100px;">
<td>1</td>
<td>2</td>
</tr>
<tr style="position:absolute; left:200px;">
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td>6</td>
</tr>
</table>
</body>
</html>
第一个问题是fixed的tr在ie7中不能进行定位,而且td在定位后并不能保持在表格中的布局,这样在原表格插tr就没意义了。
ps:fixed的相关应用可参考仿LightBox效果。
最后我用的方法是新建一个table,并把源tr克隆到新table中,然后通过对新table定位来实现效果。
用这个方法关键有两点,首先要做一个仿真度尽可能高的tr,还有是要准确的定位,这些请看后面的程序说明。
程序说明
【克隆table】
克隆一个元素用cloneNode就可以了,它有一个bool参数,表示克隆是否包含子节点。
程序第一步就是克隆原table:
this._oTable = $$(table);
this._nTable = this._oTable.cloneNode(false);
this._nTable.id = "";
要注意虽然ie的cloneNode参数是可选的(默认是false),但在ff是必须的,建议使用时都写上参数。
还要注意的是id属性也会被克隆,也就是克隆后会有两个相同id的元素(如果克隆对象有设置的话),这很容易会导致其他问题,程序会把克隆table的id属性设空。
ps:table请用class来绑定样式,用id的话新table就获取不了样式了。
克隆之后再设置样式:
$$D.setStyle(this._nTable, {
width: this._oTable.offsetWidth + "px",
position: $$B.ie6 ? "absolute" : "fixed",
zIndex: 99, borderTopWidth: 0, borderBottomWidth: 0
});
一般来说offsetWidth是width+padding+border的结果,但table比较特别,测试下面的代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<table border="5" id="t" style="padding:10px; width:100px;">
<tr>
<td>1</td>
<td>1</td>
</tr>
</table>
<table width="100" id="t2" style="border:10px solid #000;">
<tr>
<td>1</td>
<td>1</td>
</tr>
</table>
<script>
alert(document.getElementById("t").offsetWidth);
alert(document.getElementById("t2").offsetWidth);
</script>
</body>
</html>
只要给table设置width(style或本身的width属性),不管设置padding和border是多少,offsetWidth都等于width的值。
经测量offsetWidth是没错的,那就是说是table的width设置的问题。
w3c的table部分中说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这些中,所以还要判断一下:
if( oT.parentNode != this._oTable ){
nT = oT.parentNode.cloneNode(false).appendChild(nT).parentNode;
}
然后再插入到新table中:
if ( this._nTable.firstChild ) {
this._nTable.replaceChild( nT, this._nTable.firstChild );
} else {
this._nTable.appendChild(nT);
}
因为程序允许修改克隆的tr,所以会判断有没有插入过,没有就直接appendChild,否则用replaceChild替换原来的tr。
【table的border和frame属性】
table的border属性用来指定边框宽度,table特有的frame属性是用来设置或获取表格周围的边框显示的方式。
w3c的tabel的frame部分说明frame可以是以下值:
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.
这些值指明了要显示的边框。要留意的是虽然说void是默认值,但不设置的话其实是一个空值,这时四条边框都会显示。
还有frame对style设置的border没有效果,测试下面代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<table width="100" border="5" frame="lhs">
<tr>
<td>1</td>
<td>1</td>
</tr>
</table>
<table width="100" style="border:5px solid #000;" border="10" frame="lhs">
<tr>
<td>1</td>
<td>1</td>
</tr>
</table>
</body>
</html>
这里还可以看到如果同时设置table的border和style的border,那table的border就会失效。
程序中为了更美观会自动去掉新table上面和下面的边框,包括frame和style的:
if ( this._oTable.border > 0 ) {
switch (this._oTable.frame) {
case "above" :
case "below" :
case "hsides" :
this._nTable.frame = "void"; break;
case "" :
case "border" :
case "box" :
this._nTable.frame = "vsides"; break;
}
}
其中空值在设置collapse之后会比较麻烦,在ie6/ie7中测试:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<style type="text/css">
.t{width:100px; border-collapse:collapse;}
.t td{border:5px solid #999;}
</style>
<table class="t">
<tr>
<td>1</td>
<td>1</td>
</tr>
</table>
<br />
<table class="t" frame="vsides">
<tr>
<td>1</td>
<td>1</td>
</tr>
</table>
<br />
<table class="t" border="1">
<tr>
<td>1</td>
<td>1</td>
</tr>
</table>
<br />
<table class="t" border="1" frame="vsides">
<tr>
<td>1</td>
<td>1</td>
</tr>
</table>
</body>
</html>
后两个的转换还可以接受,所以在设置frame之前还是判断一下border先。
【获取背景色】
如果td是背景透明的话显然不太美观,最好是找一个合适的颜色来填充。
程序用的方法是,从当前td开始找,如果背景是透明的话,就再从父节点中找,直到找到有背景色为止。
一般来说透明的属性值是"transparent",但在chrome和safari里却是"rgba(0, 0, 0, 0)",所以用了一个属性来保存透明值:
_transparent: $$B.chrome || $$B.safari ? "rgba(0, 0, 0, 0)" : "transparent",
并在_getBgColor获取背景色程序中使用:
var bgc = "";
while (bgc === this._transparent && (node = node.parentNode) != document) {
bgc = $$D.getStyle(node, "backgroundColor");
}
return bgc === this._transparent ? "#fff" : bgc;
如果全部都是透明的话就会返回白色(#fff)。
这里没有考虑图片背景的情况,毕竟图片不一定会覆盖整个背景。
【parentNode/offsetParent/parentElement】
上面用到了parentNode,这里顺便说说它跟offsetParent,parentElement的区别。
先看看parentNode在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.
很简单,就是节点的父节点,看过dom都知道。
再看看比较容易区分的offsetParent,它在mozilla和msdn都说得比较模糊,在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.
这里主要有四点:
1,如果是根元素、body元素或元素的position是fixed,将返回null;
2,如果是area元素,会返回最接近的map元素;
3,返回至少符合以下一个条件的最接近该节点的元素:1,元素的position不是static;2,是body元素;3,源元素的position是static,祖先元素中的以下元素:td,th或table。
4,返回null。
其中第三点是最常见的情况,详细可以看下面的测试:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<table width="100" id="t">
<tr>
<td><div id="t1"></div></td>
<td id="t2"><div style="position:absolute;">
<div id="t3"></div>
</div></td>
</tr>
</table>
<div id="t4" style="position:fixed;"></div>
<script>
var $ = function (id) {
return "string" == typeof id ? document.getElementById(id) : id;
};
alert($("t").offsetParent)//body
alert($("t1").offsetParent)//td
alert($("t2").offsetParent)//table
alert($("t3").offsetParent)//div
alert($("t4").offsetParent)//null
</script>
</body>
</html>
可见offsetParent跟parentNode的区别还是很大的。
而parentNode跟parentElement除了前者是w3c标准,后者只ie支持,其他的区别就不是那么明显了。
在ie中大部分情况下两者的效果是一样的,当然如果是一模一样的话ie就没必要弄这么一个东西出来了,测试下面的代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<script>
var o = document.createDocumentFragment().appendChild(document.createElement("div"));
alert(o.parentNode)
alert(o.parentNode.nodeType)//11
alert(o.parentElement)//null
alert(document.body.parentNode)
alert(document.body.parentNode.nodeType)//1
alert(document.body.parentElement)//html
alert(document.body.parentNode.parentNode)
alert(document.body.parentNode.parentNode.nodeType)//9
alert(document.body.parentElement.parentElement)//null
</script>
</body>
</html>
可以看到当父节点的nodeType不是1,即不是element节点的话,它的parentElement就会是null。
这就明白了名字中“Element”的含义了。
【设置td宽度】
接下来就要设置td宽度了,要获取某元素的宽度可以通过以下方法:
1,支持defaultView的可以直接用getComputedStyle获取width。
2,获取offsetWidth,再减去border和padding的宽度。
这个本来也可以,但td的border宽度的获取比较麻烦,下面有更方便的方法。
3,获取clientWidth,再减去padding的宽度。
这个跟方法2差不多,但更简单方便。
注意ie的currentStyle不像getComputedStyle能获取准确值,而只是一个设置值,像百分比、auto这些并不会自动转成准确值,即使是得到准确值也不一定是实际值,例如td即使设置一个很大的准确值,实际值也不会超过table本身的宽度。
所以在td这种比较特殊的结构中,不要用currentStyle来获取td的宽度。
对于支持defaultView的当然可以直接获取,否则就用上面的方法3来获取:
style.width = (document.defaultView ? parseFloat(getStyle(o, "width"))
: ( o.clientWidth - parseInt(getStyle(o, "paddingLeft")) - parseInt(getStyle(o, "paddingRight")) )) + "px";
但这里不管哪个方法都有一个问题,就是出现scroll的情况,不过还好td这个元素即使设置了overflow为scroll也不会出现滚动条,除了ie8和chrome。
程序没对这个情况做处理,毕竟给td设scroll也不常见,而且支持这个的浏览器不多,没必要花太多时间在这里。
ps:关于td宽度的自动调整可以参考w3c的table-layout部分。
如果有影响原td结构的设置,例如colspan之类的就要留意,错误的结构很可能导致一些异常变形。
如果对原表格结构或内容做了修改,应该执行一次clone方法重构新table。
本部分对体验比较重要,如果设置不当就会有变形的感觉,很不美观。
【borderCollapse】
上面说到td的border宽度的获取比较麻烦,那到底有多烦呢?
如果只是一般情况的话,通过borderLeftWidth和borderRightWidth获取宽度就可以了。
ps:如果borderStyle是"none"的话,那么border就会没效,所以如果要取border宽度的话最好先判断一下borderStyle是不是"none"。
但table有一个特别的样式borderCollapse,设置table的边框模型。
它有两个值,分别是separate(分开,默认值)和collapse(合并)。
separate就是我们一般看到的效果,这里主要讨论collapse,先看mozilla怎么说的:
In the collapsed border model, adjacent table cells share borders.
意思是在collapse border模型中,相邻的td会共用边框。看下面的例子会更明白:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<style type="text/css">
.t{line-height:40px;width:200px; }
.t td{border:5px solid #999;}
</style>
<table class="t" style="border-collapse:collapse;">
<tr>
<td width="50"> </td>
<td style="border-left-width:10px; border-left-style:dotted;"> </td>
<td width="50"> </td>
</tr>
</table>
<table class="t">
<tr>
<td width="50"> </td>
<td style="border-left-width:10px; border-left-style:dotted;"> </td>
<td width="50"> </td>
</tr>
</table>
</body>
</html>
可以看到使用collapse之后,相邻td的边框都会变成一条。
再看w3c中Border conflict resolution的部分,可知相邻边框会按以下规则获取优先级最高的边框:
1,'border-style'是'hidden'的优先级最高;
2,'border-style'是'none'的优先级最低;
3,'border-width'大的优先级更高;
4,接着按以下'border-style'由高到低排列:'double', 'solid', 'dashed', 'dotted', 'ridge', 'outset', 'groove', 'inset';
5,接着按以下border所属对象由高到低排列:cell,row,row group,column,column group,table;
6,以上都一样的话,最后按left优先,top优先排列。
ps:从Border styles可知'hidden'和'none'的'border-style'基本是一样的,区别就在于collapse时的优先级。
那td跟table之间呢,参考下面的例子:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<style type="text/css">
.t{line-height:40px;width:200px;border-collapse:collapse;}
.t td{border:5px solid #999;}
</style>
<table class="t" id="t1">
<tr>
<td width="50" style="border-left:10px dotted #999;"> </td>
<td> </td>
<td width="50"> </td>
</tr>
</table>
<br />
<table class="t" id="t2" style="border-left:10px dotted #999;">
<tr>
<td width="50"> </td>
<td> </td>
<td width="50"> </td>
</tr>
</table>
</body>
</html>
可见table和td之间也是遵从同样规则。
还有的是当设置了collapse那cellspacing就无效了。顺便说说border-spacing,它其实就是cellspacing在css中的样式形式,只是ie在ie8才开始支持,详细可以看mozilla的说明。
collapse的一个常见应用是做边框表格,例如1px边框的表格:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<style type="text/css">
.t{line-height:40px;width:200px;}
.t1{border-collapse:collapse;}
.t1 td{border:1px solid #999;}
.t2{background-color:#999;}
.t2 td{background-color:#FFF;}
</style>
<table class="t t1">
<tr>
<td width="50"> </td>
<td> </td>
<td width="50"> </td>
</tr>
</table>
<table class="t t2" cellspacing="1">
<tr>
<td width="50"> </td>
<td> </td>
<td width="50"> </td>
</tr>
</table>
</body>
</html>
前者用的collapse,后者是用table背景色模拟,虽然效果都一样,但前者显然较好,才是真正的“边框”。
在使用了collapse之后,要写一个通用的获取边框宽度程序会变得十分麻烦,而且有些情况下甚至没办法判断获取。
详细情况这里就不细说了,有兴趣研究的话可以看看w3c的The collapsing border model,当然要想全部了解的话还要在各个浏览器中研究。
【元素位置】
table的样式设置好后,还需要获取原table和原tr的位置参数,为后面的元素定位做准备。
要获取某个元素相对文档的位置,传统的做法是获取对象的offsetLeft/offsetTop,然后不断获取offsetParent的offsetLeft/offsetTop,直到找不到offsetParent为止。
得到的结果就是相对文档的位置了,上面已经介绍过offsetParent,原理应该都明白了吧。
不过这里介绍一个更好的方法,通过getBoundingClientRect方法来获取。
在mozilla是这么说明的:
The returned value is a TextRectangle object, which contains read-only left, top, right and bottom properties describing the border-box, in pixels, with the top-left relative to the top-left of the viewport...
返回一个TextRectangle对象,包含left, top, right和bottom几个只读属性,以px为单位来表示边界框相对视窗左上角的位置。(偶英文烂啊)
注意是相对视窗,不是文档哦,如果要相对文档还必须加上scrollLeft/scrollTop。
通过下面的测试可以看到两个方法返回的结果都是相同的:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<style type="text/css">
.t{line-height:40px;width:200px; border:10px solid; margin-top:900px; margin-left:500px;}
</style>
<div class="t" id="t"></div>
<script>
var o = document.getElementById("t");
var rect = o.getBoundingClientRect();
var iLeft1 = rect.left + document.documentElement.scrollLeft, iTop1 = rect.top + document.documentElement.scrollTop;
var iLeft2 = o.offsetLeft, iTop2 = o.offsetTop;
while (o.offsetParent) { o = o.offsetParent; iLeft2 += o.offsetLeft; iTop2 += o.offsetTop; }
alert(iLeft1+"_"+iLeft2)
alert(iTop1+"_"+iTop2)
</script>
</body>
</html>
程序中就是用getBoundingClientRect来获取位置参数,显然用getBoundingClientRect更方便快捷。
这个方法虽然是ie的产物,但已经是w3c的标准,而且ff3,Opera和最新版的chrome都已经支持了这个方法,可以放心使用。
这里只是简单介绍,想了解更多可以看w3c的View Module部分。
获取原table和tr的位置后,还需要计算新table的位置。
程序可以自定义新table位于视窗位置的百分比,例如顶部是0,中间是0.5,底部是1,可以在程序初始化时或用setPos方法来设置。
这里主要获取视窗高度和新table在视窗的top值:
this._viewHeight = document.documentElement.clientHeight;
this._nTableViewTop = (this._viewHeight - this._nTableHeight) * this._pos;
定位范围实际上是从视框顶部到视框高度减去新table高度的范围内的,所以计算时要先把视窗高度减去新table的高度。
【元素定位】
万事俱备,只欠定位了。
由于要根据窗口滚动状态来判断计算定位,scrollTop/scrollLeft的获取必不可少。
但要注意在chrome/safari中就算用了DOCTYPE,也要用document.body来获取scrollTop/scrollLeft,尽管它确实有document.documentElement。
定位的第一步就是判断是否需要定位,这里的判断标准有两个,第一个是原tr是否超过了视窗范围,还有是新table要显示的位置是否在原table的显示范围内。
第一点可以通过原tr位置的顶部和底部是否超过视窗的顶部和底部来判断:
var top = $$D.getScrollTop(), left = $$D.getScrollLeft()
,outViewTop = this._oRowPos.top < top, outViewBottom = this._oRowPos.bottom > top + this._viewHeight;
if ( outViewTop || outViewBottom ) { }
在看第二点之前先看看程序中的auto属性,它是用来指定否自动定位的。
如果自动定位的话当原tr离开视框顶部新table就会定位到视框顶部,原tr离开底部新table就会定位到视框底部,这样看上去会比较自然顺畅。
如果不选择自动的话就会根据setPos方法中计算得到的新table视窗top值来设置定位:
var viewTop = !this.auto ? this._nTableViewTop
: (outViewTop ? 0 : (this._viewHeight - this._nTableHeight))
,posTop = viewTop + top;
接着就判断新table要显示的位置是否在原table的显示范围内,这个可以通过新table位置的顶部和底部是否超过原table的顶部和底部来判断:
if( posTop > this._oTablePos.top && posTop + this._nTableHeight < this._oTablePos.bottom ){ }
当符合所有的条件就可以进行定位了,如果是fixed定位的就使用相对视窗的top值:
tStyle.top = viewTop + "px";
tStyle.left = this._oTablePos.left - left + "px";
像ie6是absolute定位的就要使用相对文档的top值:
tStyle.top = posTop + "px";
tStyle.left = this._oTablePos.left + "px";
考虑到左右滚动的情况,left也必须设置。
当然不符合条件就会隐藏新table,程序中给top设置一个很大的负值来间接“隐藏”它。
用负值是因为这样不会把ie6的页面拉长,不用display是因为上面需要获取它的offsetHeight,如果用display隐藏就获取不了啦。
最后把run程序绑定到window的scroll事件中就可以了,而window在resize时视框高度会发生变化,所以resize事件要绑定setPos程序。
【覆盖select】
只要用到了定位,就不得不面对一个老对手“ie6的select”。
我在之前的文章也介绍过一些解决方法(参考这里的覆盖select),这里不能直接隐藏select,那看来只能用iframe了。
但用iframe有一个很大的问题,在ie6测试下面的代码,并拖动滚动条:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<style type="text/css">
body{height:1000px;}
.t{height:300px;width:200px; border:1px solid; position:absolute; background:#FFF;top:0;left:0;}
</style>
<iframe class="t" id="t"></iframe>
<select></select><br />
<select></select><br />
<select></select><br />
<select></select><br />
<select></select><br />
<select></select><br />
<select></select><br />
<select></select><br />
<select></select><br />
<select></select><br />
</body>
</html>
可以看到,即使是iframe,在拖动滚动条的时候,select仍然在后面闪啊闪,在本程序中这个现象会尤其明显。
看来还得用隐藏select的方法,最好的做法是只隐藏在新table后面的select,而不影响其他select的正常显示。
那关键就是如何判断select是否在新table后面,这个可以通过位置坐标判断。
一般的思路是判断新table和select的坐标,根据位置判断select的显示和隐藏。
但如果有多个实例,可能会导致select在一个实例中要隐藏,却在另一个要显示的情况。
为了解决冲突,程序给select加了一个_count属性作为计数器,用来记录有多少实例把该select隐藏了。
如果当前实例判断该select要隐藏,就给其_count加1,隐藏后存放到实例的_selects集合中。
在恢复显示_selects中的select时,先给select的_count减1,如果得到的_count是0,那说明没有其他实例要隐藏它,就可以设置显示了,最后清空_selects集合。
在判断是否隐藏select前还必须恢复一次该实例_selects里面的select,否则就会造成_count只加不减的情况。
程序中的_setSelect方法就是用来判断和设置select的:
this._resetSelect();
var rect = $$D.clientRect(this._nTable);
this._selects = $$A.filter(this._oTable.getElementsByTagName("select"), $$F.bind(function(o){
var r = $$D.clientRect(o);
if(r.top <= rect.bottom && r.bottom >= rect.top){
o._count ? o._count++ : (o._count = 1);
var visi = o.style.visibility;
if(visi != "hidden"){ o._css = visi; o.style.visibility = "hidden"; }
return true;
}
}, this))
其中_resetSelect方法是用来恢复显示select的:
$$A.forEach( this._selects, function(o){ !--o._count && ( o.style.visibility = o._css ); } );
this._selects = [];
但这个方法在快速滚屏时还是无能为力,而且select越多效率也随之下降,各位有更好方法的话欢迎交流。
使用说明
实例化一个TableFixed对象只需要一个参数table的id:
new TableFixed("idTable");
实例化时有4个可选属性:
index: 0,//tr索引
auto: true,//是否自动定位
pos: 0,//自定义定位位置百分比(0到1)
hide: false//是否隐藏(不显示)
其中index和pos在实例化之后就不能使用。
要修改克隆行可以用clone方法,其参数是要克隆tr的索引。
要修改自定义定位位置可以用setPos方法,其参数是要定位的位置百分比。
具体使用请参考实例。
发表评论
-
AlertBox 弹出层(信息提示框)效果
2010-10-11 11:06 1203弹出层就是相对文档或窗口定位的一个层,一般用来显示提示信息、广 ... -
JavaScript 图片3D展示空间(3DRoom)
2010-09-20 09:59 1345一般的平面效果,通过 ... -
ccs3/滤镜/canvas的图片旋转/缩放/翻转变换效果
2010-08-21 13:48 1650以前要实现图片的旋转或翻转,只能用ie的滤镜来实现,虽然can ... -
SlideView 图片滑动(扩展/收缩)展示效果
2010-07-30 08:52 1251滑动展示效果主要用在 ... -
ImageZoom 图片放大效果(扩展篇)
2010-04-16 21:32 1250上一篇ImageZoom已经对图片放大效果做了详细的分析,这次 ... -
ImageZoom 图片放大效果
2010-04-07 21:03 1266这个效果也叫放大镜效果,最早好像在ppg出现的,之后就有了很多 ... -
图片延迟加载(按需加载)效果
2010-03-11 21:13 2854之前在做一个图片浏览效果时,要看后面的小图必须等到前面的加载完 ... -
Lazyload 延迟加载(缓载)效果
2010-02-22 09:58 1550Lazyload是通过延迟加载 ... -
JavaScript 图片滑动展示效果
2008-05-13 01:34 1715看到jQuery实例:图片展示效果后,我也想拿来试试,但我不太 ... -
JavaScript 图片变换效果(ie only)
2008-05-23 12:02 2307仿照常见的那个图片变换flash做的效果,纯js。不过滤镜变换 ... -
JavaScript 图片滑动切换效果
2008-07-06 01:25 3187序一(08/07/06) 看到alibaba的一个图片切换效 ... -
JavaScript blog式日历控件
2008-08-23 00:25 1064近来要做一个记事本系统,想找一个合适的日历控件,但网上的都是那 ... -
JavaScript Table排序
2008-10-06 08:24 1082程序的实现的是在客户 ... -
JavaScript 日期联动选择器
2008-10-28 10:30 1252一个日期联动选择器, ... -
JavaScript 拖拉缩放效果
2008-12-03 09:07 788拖拉缩放效果,实现通过鼠标拖动来调整层的面积(宽高)大小。例如 ... -
JavaScript 滑动条效果
2008-12-24 08:27 2495这个滑动条(拖动条) ... -
JavaScript Tween算法及缓动效果
2009-01-06 09:17 1182Flash做动画时会用到Tween类,利用它可以做很多动画效果 ... -
JavaScript 颜色梯度和渐变效果
2009-03-11 08:24 1070近来看了Dean的“Convert any colour va ... -
JavaScript 浮动定位提示效果
2009-07-07 08:23 1119本来想做一个集合浮动 ... -
JavaScript 多级联动浮动菜单 (第二版)
2009-08-10 00:54 1849上一个版本(第一版请看这里)基本实现了多级联动和浮动菜单的功能 ...
相关推荐
要实现`table表格固定行和列`,我们可以采用以下几种方法: 1. **CSS样式实现** 通过CSS定位技术,我们可以将表头(thead)和第一列(th)设置为固定位置。例如,使用`position: fixed`可以将元素从正常文档流中...
为解决这一问题,开发者通常采用JavaScript来实现Table标题行的固定,使其在滚动时始终保持可见。本文将详细介绍四种不同的JavaScript方法来实现HTML固定Table标题行。 1. **CSS Sticky Positioning** CSS3中的`...
相反,若要删除特定行,可以使用`.remove()`方法,通过选择器定位到目标行: ```javascript $("#myTable tr:last").remove(); // 删除最后一行 ``` 接下来,我们讨论单元格的标记、修改和删除。标记通常意味着给...
4. **自定义渲染**:开发者可以根据需求自定义单元格和行的显示样式,包括颜色、字体、图标等,以增强信息的可读性和视觉效果。 5. **排序和筛选**:TreeTable支持对数据进行排序和筛选,用户可以通过点击列头进行...
本主题主要围绕"table的行列冻结、行冻结、列冻结"展开,讲解如何使用jQuery实现这一功能,并确保其在主流浏览器上的兼容性。 首先,"行列冻结"是指在表格中固定特定的行和列,即使在用户滚动页面时,这些行和列也...
在网页开发中,jQuery是一个非常流行的JavaScript库,它极大地简化了DOM操作、事件处理和动画效果。本项目涉及的主题是“jQuery Table 固定行和列”,这是一个常见需求,特别是对于那些展示大量数据的网页应用,它能...
总结来说,JavaScript的拖放功能是通过监听和响应鼠标事件,结合元素的定位信息,实现网页元素的动态移动。在实际项目中,开发者可以根据需求选择不同级别的复杂度,从简单的元素拖放到复杂的交互设计,都可以通过...
跑马灯的核心原理是利用JavaScript对HTML元素的定位和定时器(setTimeout或setInterval)来改变元素的位置,使其产生滚动的效果。以下是一些关键知识点: 1. DOM操作:JavaScript通过Document Object Model (DOM) ...
在网页设计中,"table表头拉伸效果"是一种常见的增强用户体验的技术,它允许用户在滚动数据时,表头能够随着用户的滚动保持可见,从而更好地理解数据列的含义。这种效果通常应用于大型数据表格,特别是在数据量大、...
本教程将详细介绍如何利用HTML、CSS以及JavaScript实现一个具有固定行列效果的表格特效,使用户在滚动时仍能看到关键的列名和行标识。 首先,我们需要创建一个基本的HTML结构,包含一个表格元素(`<table>`)。表格...
- 创建CSS类(如`locked`),设置对应的定位和宽度属性,以实现锁定效果。对于行和列锁定,CSS代码可能如下: ```css .locked { position: sticky; z-index: 1; /* 保证在其他元素之上 */ } .locked th, ....
本示例主要关注如何利用jQuery实现在HTML表格(table)中移动行(tr)的同时保持行内的序号不变,这对于数据排序或用户交互有着重要的应用。我们将探讨以下关键知识点: 1. jQuery选择器与DOM操作: jQuery提供了...
可以定位到Bootstrap Table的CSS类,如`.pagination`, `.page-item`, `.page-link`等,并添加或覆盖原有样式。 - **模板定制**:Bootstrap Table允许用户自定义分页栏的HTML模板。通过设置`paginationTemplate`选项...
以上代码示例展示了如何实现表格的固定行和列,但需要注意的是,`position: sticky`在某些旧版本的浏览器中可能不支持,因此在实际项目中,你可能需要使用JavaScript或者第三方库如DataTables、ag-Grid等进行兼容性...
一个基本的HTML表格由`<table>`标签开始,内部包含`<tr>`(行)标签,而每一行中又可以有多个`<td>`(单元格)或`<th>`(表头单元格)。如果我们想通过jQuery来操作这些元素,我们需要选择器来定位它们。 在jQuery...
在JavaScript编程中,拖动表格行和列...总的来说,实现JavaScript拖动表格行和列的功能需要理解DOM操作、事件处理、CSS定位以及可能的第三方库的运用。通过实践和调试,你可以创造出更加动态和交互丰富的Web表格应用。
<table id="data-table"> 数据1 数据2 <!-- 更多行... --> </table> ;"> 弹出框内容 ``` 3. **jQuery选择器与事件绑定** 接下来,我们使用jQuery的选择器选取所有的表格行,并为它们绑定点击事件。当...