工作中用到了表格的可变列宽,网上看了下,自己也实现了一个,整理贴记录。
测试环境chrome,ie8,firefox
jquery版本1.8.2
原理:监听table第一行的mousemove事件,当鼠标位置在某列的边框附近时,mousedown即可拖动该列,mouseup时结束。其中当拖动时,2种方式:拖动时列宽随时变化,另一种是拖动结束时最后才计算列宽,采用后者相对好点,可以减少对dom的操作,提高性能和友好性。
参考ext grid的实现方式,当拖动时有2条参考线,分别表示列的左边框和右边框,通过拖动右边框来实现大小的改变。
表格样例
<table id="tbl"border="1" cellspacing="0" cellpadding="0">
<tr>
<th style="width:100px">col1</th>
<th style="width:100px">col2</th>
<th style="width:200px">col3</th>
<th style="width:200px">col4</th>
<th style="width:300px">col5</th>
</tr>
<tr>
<td>1</td><td>1</td><td>1</td><td>1</td><td>1</td>
</tr>
<tr>
<td>2</td><td>2</td><td>2</td><td>2</td><td>2</td>
</tr>
<tr>
<td>3</td><td>3</td><td>3</td><td>3</td><td>3</td>
</tr>
<tr>
<td>4</td><td>4</td><td>4</td><td>4</td><td>4</td>
</tr>
</table>
代码是经过很多次修改的,应该把一步步测试修改的记录下的,完整功能的代码看起来逻辑没有一步步来清晰了,代码如下
//全局变量
var resizing = false; //是否为拖动状态
var resizable = false; //当时是否可拖动
var minWidth = 20; //没列的最小宽度
var resizeHeader; //当前拖动的列
var leftLine; //左参考线
var rightLine; //有参考线
$(function(){
//监听标题行的mouosemove事件
$("table th").mousemove(function(e){
var target = $(e.target);
if(resizing){
//当已经在拖动变化列宽时
onDraging(e);
}else if(fnIsLeftEdge(e)){
//靠近左边框时,将当前的处理header
//设置为左边的一个,这样就相当于是拖动列
//的右边框,可以只计算该header的右边框参
//考线的移动,方便处理
resizeHeader = target.prev();
//不响应第一列的左边框拖动事件
if(resizeHeader.length == 0)
return;
//当鼠标停在左边框时,设置当前为可拖动状态
resizable = true;
//设置鼠标样式为拖动时的样式
target.css("cursor", "col-resize");
}else if(fnIsRightEdge(e)){
//当鼠标停留在右边框时
resizeHeader = target;
resizable = true;
target.css("cursor", "col-resize");
}else{
//超出可拖动的区域,设为不可拖动状态
resizable = false;
target.css("cursor", "default");
}
});
//当在拖动列上点击鼠标
$("table th").mousedown(function(e){
onDragingStart(e);
});
//当在document上移动鼠标,因为拖动可能超出表格的范围
$(document).mousemove(function(e){
onDraging(e);
});
//当拖动而释放时候未在标题行的释放也需要结束拖动
$(document).mouseup(function(e){
onDragingEnd(e);
});
});
/**
* 计算当前鼠标位置是不是在可拖动的范围内
* @param event e目标事件
* @side boolean true表示在左边边框附近,false表示右边
* @return boolean true在表格边框附近,false未在
*/
function _fnIsColEdge(e, side){
var target = $(e.target);
var x = e.pageX;
var offset = target.offset();
var left = offset.left;
var right = left + target.outerWidth();
return side ? x<=left+2 : x >=right-2;
}
/**
* 计算当前鼠标位置是不是在左边框附近
* @param event e目标事件
* @return boolean true是, false否
*/
function fnIsLeftEdge(e){
return _fnIsColEdge(e, true);
}
/**
* 计算当前鼠标位置是不是在右边框附近
* @param event e目标事件
* @return boolean true是, false否
*/
function fnIsRightEdge(e){
return _fnIsColEdge(e, false);
}
/**
* 初始化拖动状态
* @param event e目标事件
* @return void
*/
function onDragingStart(e){
//当前是否为拖动状态
if(resizable){
var target = $(e.target);
//设置当前文本不可选中,否则拖动时会选中文本
if(!$.browser.mozilla){
$(document).bind("selectstart", function(){ return false; });
}else{
$("body").css("-moz-user-select", "none");
}
//创建参考线
if(!leftLine){
leftLine = $("<div></div>");
leftLine.addClass("resize_line");
leftLine.appendTo("body");
rightLine = leftLine.clone();
rightLine.appendTo("body");
}
//显示参考线
leftLine.css({"top":resizeHeader.offset().top, "left": resizeHeader.offset().left, "height": $("table").innerHeight()});
rightLine.css({"top":resizeHeader.offset().top, "left": e.pageX, "css":"col-resize", "height": $("table").innerHeight()});
leftLine.show();
rightLine.show();
//设置为已经在拖动
resizing = true;
}
}
/**
* 列宽拖动中
* @param event e目标事件
* @return void
*/
function onDraging(e){
//如果已经在拖动
if(resizing){
//拖动后的列宽不能小于最小列宽
if(e.pageX - resizeHeader.offset().left > minWidth){
rightLine.css("left", e.pageX);
}
}
}
/**
* 鼠标释放拖动结束,改变列宽,结束拖动状态
* @param event e目标事件
* @return void
*/
function onDragingEnd(e){
//如果已经在拖动
if(resizing){
resizing = false;
//隐藏参考线
rightLine.hide();
leftLine.hide();
//设置文本可以选中
if(!$.browser.mozilla){
$(document).unbind("selectstart");
}else{
$("body").css("-moz-user-select", "");
}
//计算设置新的列宽
doResize();
}
}
/**
* 设置新的列宽
* @param event e目标事件
* @return void
*/
function doResize(){
//计算列宽的变化值
var newWidth = parseInt(rightLine.css("left"), 10) - resizeHeader.offset().left - resizeHeader.width();
//设置新列宽
resizeHeader.width(resizeHeader.width() + newWidth);
}
参考线的样式
.resize_line{
width:0px;
border-style: solid;
border-color: #0066FF;
border-width: 0 1px 0 1px;
position:absolute;
}
整理修改后可作为jquery的插件使用,附件是示例和插件代码。
目前对分组的header即使用了rowspan和colspan的没有做处理,有时间再做更新,有兴趣的人也可以扩展和完善。
分享到:
相关推荐
jQuery可调整表和列宽插件
jquery 实现表格列宽调整,很不错的资源,免费下载学习哦。
利用jquery实现表格动态分页,前台用jquery实现。后台用java实现动态查询数据,分页。
jquery实现表格排序,绝对实用。jquery实现表格排序,绝对实用。
jQuery动态改变列宽,可以实现拖动jQuery动态改变列宽,可以实现拖动
可以通过鼠标拖动方便调整table表格列宽的jquery查看ZTable插件,支持多浏览器
使用jquery实现点击表格列可以编辑,自己学习之余给大家分享
jQuery实现表头固定表格内容滚动效果 jQuery实现表头固定表格内容滚动效果
jQuery实现表格动态修改和隐藏jQuery实现表格动态修改和隐藏jQuery实现表格动态修改和隐藏
JQuery实现可编辑的表格JQuery实现可编辑的表格
本demo使用jQuery包,实现表格列宽可拖拽功能,并实现页面reset时的重新布局。使用jQuery,方便函数的调用,给要处理的表格添加id 后,直接调用$("#id").movedTh()即可方便实现,修改了firfox的兼容性。
jquery插件colResizable实现表格列可拖拽伸缩表格大小
jQuery实现可编辑化的表格,有兴趣的可以看看
jquery表格变色jquery表格变色jquery表格变色jquery表格变色jquery表格变色jquery表格变色jquery表格变色jquery表格变色jquery表格变色jquery表格变色jquery表格变色jquery表格变色
jquery可编辑表格插件,简单好用,做列表时一个非常不错的选择
jQuery实现表格头和列固定插件RWD Table.zip
jquery实现表格隔行换色和鼠标经过提示效果源码
DataTables - jQuery表格插件
jQuery实现表格的增加、修改、删除、保存代码