您好,欢迎访问一九零五行业门户网

JavaScript Table行定位效果_javascript技巧

上次做table排序对table有了一些了解,这次更是深入了解了一番,发现table原来是这么不简单。
还不清楚这个效果叫什么,就叫行定位吧,本来想把列定位也做出来,但暂时还没这个需求,等以后有时间再弄吧。
程序原理
一开始的需求只是表头部分在滚动时能一直固定在头部,那关键要实现的就是让tr能定位。
首先想到的方法是给tr设置relative,用ie6/7测试以下代码:
1 2
3 4
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
给tr设置relative后就能相对table定位了,看来很简单啊,但问题是这个方法ie8和ff都无效,而且存在很多问题,所以很快就被抛弃了。
ps:该效果用来做tr的拖动会很方便。
接着想到的是给table插入一个新tr,克隆原来的tr,并设置这个tr为fixed(ie6为absolute),例如:
code
1 2
3 4
5 6
[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比较特别,测试下面的代码:
1 1
1 1
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
只要给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没有效果,测试下面代码:
1 1
1 1
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
这里还可以看到如果同时设置table的border和style的border,那table的border就会失效。
程序中为了更美观会自动去掉新table上面和下面的边框,包括frame和style的:
code
复制代码 代码如下:
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;
}
}
this._style.bordertopwidth = this._style.borderbottomwidth = 0;
其中空值在设置collapse之后会比较麻烦,在ie6/ie7中测试:
code
1 1
1 1
1 1
1 1
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
后两个的转换还可以接受,所以在设置frame之前还是判断一下border先。
【获取背景色】
如果td是背景透明的话显然不太美观,最好是找一个合适的颜色来填充。
程序用的方法是,从当前td开始找,如果背景是透明的话,就再从父节点中找,直到找到有背景色为止。
一般来说透明的属性值是transparent,但在chrome里却是rgba(0, 0, 0, 0),所以用了一个属性来保存透明值:
复制代码 代码如下:
this._transparent = ischrome ? rgba(0, 0, 0, 0) : transparent;
并在getbgcolor获取背景色程序中使用:
复制代码 代码如下:
while (bgc == this._transparent && (node = node.parentnode) != document) {
bgc = currentstyle(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。
其中第三点是最常见的情况,详细可以看下面的测试:
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
可见offsetparent跟parentnode的区别还是很大的。
而parentnode跟parentelement除了前者是w3c标准,后者只ie支持,其他的区别就不是那么明显了。
在ie中大部分情况下两者的效果是一样的,当然如果是一模一样的话ie就没必要弄这么一个东西出来了,测试下面的代码:
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
可以看到当父节点的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基本没戏,而且在这个效果中即使是差了1px也会看不舒服。
对于支持defaultview的当然可以直接获取,否则就用上面的方法3来获取:
style.width = (document.defaultview ? parsefloat(css.width)
    : (o.clientwidth - parseint(css.paddingleft) - parseint(css.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会共用边框。看下面的例子会更明白:
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
可以看到使用collapse之后,相邻td的边框都合并成一条而且是以相邻边框中宽度较大的那条为准。
那td跟table之间呢,参考下面的例子:
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
可见table和td之间也是遵从同样规则。
还有的是当设置了collapse那cellspacing就无效了。顺便说说border-spacing,它其实就是cellspacing在css中的样式形式,只是ie在ie8才开始支持,详细可以看mozilla的说明。collapse的一个常见应用是做边框表格,例如1px边框的表格:
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
前者用的collapse,后者是用table背景色模拟,虽然效果都一样,但前者显然较好,才是真正的“边框”。在使用了collapse之后,要写一个通用的获取边框宽度程序会变得十分麻烦,而且有些情况下甚至没办法判断获取。
详细情况这里就不细说了,有兴趣研究的话可以看看w3c的the collapsing border model,当然要想全部了解的话还要在各个浏览器中研究。
【元素位置】
table的样式设置好后,还需要获取原table和原tr的位置参数,为后面的元素定位做准备。
要获取某个元素相对文档的位置,传统的做法是获取对象的offsetleft/offsettop,然后不断获取offsetparent的offsetleft/offsettop,直到找不到offsetparent为止。
得到的结果就是相对文档的位置了,上面已经介绍过offsetparent,原理应该都明白了吧。
程序的setrect设置区域属性方法中也使用了这个思路:
复制代码 代码如下:
//获取原table位置
var o = this._otable, ileft = o.offsetleft, itop = o.offsettop;
while (o.offsetparent) { o = o.offsetparent; ileft += o.offsetleft; itop += o.offsettop; }
this._otableleft = ileft;
this._otabletop = itop;
this._otablebottom = itop + this._otableheight;
//获取原tr位置
o = this._orow; itop = o.offsettop;
while (o.offsetparent) { o = o.offsetparent; itop += o.offsettop; }
this._orowtop = itop;
this._orowbottom = itop + this._orow.offsetheight;
不过这里介绍一个更好的方法,通过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。
通过下面的测试可以看到两个方法返回的结果都是相同的:
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
程序中如果支持getboundingclientrect就会用它来获取位置参数:
复制代码 代码如下:
//用getboundingclientrect获取原table位置
var top = this._doc.scrolltop, rect = this._otable.getboundingclientrect();
this._otableleft = rect.left + this._doc.scrollleft;
this._otabletop = rect.top + top;
this._otablebottom = rect.bottom + top;
//获取原tr位置
rect = this._orow.getboundingclientrect();
this._orowtop = rect.top + top;
this._orowbottom = rect.bottom + top;
显然用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._ntviewtop = (this._viewheight - this._ntableheight) * this._pos;
定位范围实际上是从视框顶部到视框高度减去新table高度的范围内的,所以计算时要先把视窗高度减去新table的高度。
【元素定位】
万事俱备,只欠定位了。
由于要根据窗口滚动状态来判断计算定位,scrolltop/scrollleft的获取必不可少。
但在chrome中就算用了doctype,也要用document.body来获取scrolltop/scrollleft,尽管它确实有document.documentelement。
对chrome了解不多,也不知哪里能查它的相关文档,程序里就直接做个判断算了:
this._doc = ischrome ? document.body : document.documentelement;
定位的第一步就是判断是否需要定位,这里的判断标准有两个,第一个是原tr是否超过了视窗范围,还有是新table要显示的位置是否在原table的显示范围内。
第一点可以通过原tr位置的顶部和底部是否超过视窗的顶部和底部来判断:
var top = this._doc.scrolltop, left = this._doc.scrollleft
    ,outviewtop = this._orowtop  top, outviewbottom = this._orowbottom > 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))//视窗top
    ,postop = viewtop + top;//位置top
接着就判断新table要显示的位置是否在原table的显示范围内,这个可以通过新table位置的顶部和底部是否超过原table的顶部和底部来判断:
if(postop > this._otabletop && postop + this._ntableheight  this._otablebottom){}
当符合所有的条件就可以进行定位了,如果是fixed定位的就使用相对视窗的top值:
this._style.top = viewtop + px;
this._style.left = this._otableleft - left + px;
像ie6是absolute定位的就要使用相对文档的top值:
this._style.top = postop + px;
this._style.left = this._otableleft + px;
考虑到左右滚动的情况,left也必须设置。
当然不符合条件就会隐藏新table,程序中给top设置一个很大的负值来间接“隐藏”它。
用负值是因为这样不会把ie6的页面拉长,不用display是因为上面需要获取它的offsetheight,如果用display隐藏就获取不了啦。
最后把run程序绑定到window的scroll事件中就可以了,而window在resize时视框高度会发生变化,所以resize事件要绑定setpos程序。
【覆盖select】
只要用到了定位,就不得不面对一个老对手“ie6的select”。
我在之前的文章也介绍过一些解决方法(参考这里的覆盖select),这里不能直接隐藏select,那看来只能用iframe了。
但用iframe有一个很大的问题,在ie6测试下面的代码,并拖动滚动条:
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
可以看到,即使是iframe,在拖动滚动条的时候,select仍然在后面闪啊闪,在本程序中这个现象会尤其明显。
看来还得用隐藏select的方法,最好的做法是只隐藏在新table后面的select,而不影响其他select的正常显示。
那关键就是如何判断select是否在新table后面,这个可以通过位置坐标判断,刚好可以用到上面的getboundingclientrect。
一般的思路是判断新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 = this._ntable.getboundingclientrect();
//把需要隐藏的放到_selects集合
this._selects = filter(this._otable.getelementsbytagname(select), bind(this, function(o){
var r = o.getboundingclientrect();
if(r.top = 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;
}
}))
其中resetselect方法是用来恢复显示select的:
复制代码 代码如下:
foreach(this._selects, function(o){ !--o._count && (o.style.visibility = o._css); });
this._selects = [];
但这个方法在快速滚屏时还是无能为力,而且select越多效率也随之下降,各位有更好方法的话欢迎交流。
【chrome一个bug】
在测试的时候发现chrome一个bug,测试下面代码:
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
一个毫不相干的操作居然令table没有自动撑开,加上前面的问题,看来chrome的路还很长啊。
使用说明
实例化一个tablefixed对象只需要一个参数table的id:
new tablefixed(idtable);
实例化时有4个可选属性:
index: 0,//tr索引
auto: true,//是否自动定位
pos: 0,//自定义定位位置百分比(0到1)
hide: false//是否隐藏(不显示)
其中index和pos在实例化之后就不能使用。
要修改克隆行可以用clone方法,其参数是要克隆tr的索引。
要修改自定义定位位置可以用setpos方法,其参数是要定位的位置百分比。
具体使用请参考实例。
程序源码
var tablefixed = function(table, options){ this._otable = $(table);//原table this._ntable = this._otable.clonenode(false);//新table this._ntable.id = ;//避免id冲突 this._otableleft = this._otabletop = this._otablebottom = 0;//记录原table坐标参数 this._orowtop = this._orowbottom = 0;//记录原tr坐标参数 this._viewheight = this._otableheight = this._ntableheight = 0;//记录高度 this._ntableviewtop = 0;//记录新table视框top this._selects = [];//select集合,用于ie6覆盖select this._style = this._ntable.style;//用于简化代码 //chrome的scroll用document.body this._doc = ischrome ? document.body : document.documentelement; //chrome透明用rgba(0, 0, 0, 0) this._transparent = ischrome ? rgba(0, 0, 0, 0) : transparent; this.setoptions(options); this._index = this.options.index; this._pos = this.options.pos; this.auto = !!this.options.auto; this.hide = !!this.options.hide; addeventhandler(window, resize, bind(this, this.setpos)); addeventhandler(window, scroll, bind(this, this.run)); this._otable.parentnode.insertbefore(this._ntable, this._otable); this.clone(); }; tablefixed.prototype = { //设置默认属性 setoptions: function(options) { this.options = {//默认值 index: 0,//tr索引 auto: true,//是否自动定位 pos: 0,//自定义定位位置百分比(0到1) hide: false//是否隐藏(不显示) }; extend(this.options, options || {}); }, //克隆表格 clone: function(index) { //设置table样式 this._style.width = this._otable.offsetwidth + px; this._style.position = isie6 ? absolute : fixed; this._style.zindex = 100; //设置index 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); if(ot.parentnode != this._otable){ nt = ot.parentnode.clonenode(false).appendchild(nt).parentnode; } //插入新行 if(this._ntable.firstchild){ this._ntable.replacechild(nt, this._ntable.firstchild); }else{ this._ntable.appendchild(nt); } //去掉table上面和下面的边框 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; } } this._style.bordertopwidth = this._style.borderbottomwidth = 0; //设置td样式 var ntds = this._ntable.rows[0].cells; foreach(this._orow.cells, bind(this, function(o, i){ var css = currentstyle(o), style = ntds[i].style; //设置td背景 style.backgroundcolor = this.getbgcolor(o, css.backgroundcolor); //设置td的width,没考虑ie8/chrome设scroll的情况 style.width = (document.defaultview ? parsefloat(css.width) : (o.clientwidth - parseint(css.paddingleft) - parseint(css.paddingright))) + px; })); //获取table高度 this._otableheight = this._otable.offsetheight; this._ntableheight = this._ntable.offsetheight; this.setrect(); this.setpos(); }, //获取背景色 getbgcolor: function(node, bgc) { //不要透明背景(没考虑图片背景) while (bgc == this._transparent && (node = node.parentnode) != document) { bgc = currentstyle(node).backgroundcolor; } return bgc == this._transparent ? #fff : bgc; }, //设置坐标属性 setrect: function() { if(this._otable.getboundingclientrect){ //用getboundingclientrect获取原table位置 var top = this._doc.scrolltop, rect = this._otable.getboundingclientrect(); this._otableleft = rect.left + this._doc.scrollleft; this._otabletop = rect.top + top; this._otablebottom = rect.bottom + top; //获取原tr位置 rect = this._orow.getboundingclientrect(); this._orowtop = rect.top + top; this._orowbottom = rect.bottom + top; }else{//chrome不支持getboundingclientrect //获取原table位置 var o = this._otable, ileft = o.offsetleft, itop = o.offsettop; while (o.offsetparent) { o = o.offsetparent; ileft += o.offsetleft; itop += o.offsettop; } this._otableleft = ileft; this._otabletop = itop; this._otablebottom = itop + this._otableheight; //获取原tr位置 o = this._orow; itop = o.offsettop; while (o.offsetparent) { o = o.offsetparent; itop += o.offsettop; } this._orowtop = itop; this._orowbottom = itop + this._orow.offsetheight; } }, //设置新table位置属性 setpos: function(pos) { //设置pos this._pos = math.max(0, math.min(1, isnan(pos) ? this._pos : pos)); //获取位置 this._viewheight = document.documentelement.clientheight; this._ntableviewtop = (this._viewheight - this._ntableheight) * this._pos; this.run(); }, //运行 run: function() { if(!this.hide){ var top = this._doc.scrolltop, left = this._doc.scrollleft //原tr是否超过顶部和底部 ,outviewtop = this._orowtop top + this._viewheight; //原tr超过视窗范围 if(outviewtop || outviewbottom){ var viewtop = !this.auto ? this._ntableviewtop : (outviewtop ? 0 : (this._viewheight - this._ntableheight))//视窗top ,postop = viewtop + top;//位置top //在原table范围内 if(postop > this._otabletop && postop + this._ntableheight = 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; } })) }, //恢复select样式 resetselect: function() { foreach(this._selects, function(o){ !--o._count && (o.style.visibility = o._css); }); this._selects = []; } };
[ctrl+a 全选 注:如需引入外部js需刷新才能执行]
下载完成测试代码
转载请注明出处:http://www.cnblogs.com/cloudgamer/
其它类似信息

推荐信息