jquery实现表格可变列宽插件开发
工作中用到了表格的可变列宽,网上看了下,自己也实现了一个,整理贴记录。测试环境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的没有做处理,有时间再做更新,有兴趣的人也可以扩展和完善。
页:
[1]