javascript 拖动表格行实现代码


Posted in Javascript onMay 05, 2011

行拖动的实现思路非常简单,选中一行,往上拖就与上面的行交换位置,往下拖就与下面的行交换位置。问题是如何得到交换行。我见过一个非常详细的教程,它会把表格里的每一行的高度与Y坐标计算出来,换言之,都时是比较e.pageX是否在[rowTop,rowBottom]区间之内。但这也带来第二个问题,有多少行就有多个这样的区间。于是解法就变成取事件源对象,然后再往上取其父对象,如果其父对象是TR元素,就取其[rowTop,rowBottom]区间....思路非常直接,同时也客观做出一个限制——不能使用代理拖动。先不谈是拖动代理还是拖动实物,光是在移动鼠标的过程要做的计算量就非常大,幸好还在IE的承受范围之内。有更好的方法吗?

人之所以先入为主,因为他就握着这么几把锁匙。如果他手上的锁匙非常多时,他在开门时就会稍微停下来,认真挑选了。因此熟悉掌握越多的原生API就越好,我们就才获取更优的选项。换一个思路,在拖动时(mousedown)保存当前行及其样式与坐标,拖动中取得鼠标所在位置上的元素,这个元素是使用一个巧妙的API取得document.elementFromPoint(x,y)。通常情况,我们取得的是TD,当然如果你在里面塞进一个DIV,那就是DIV罗。然后我们再取得其TR元素,然后比较mousedown时保存的TR元素是不是同一个元素,不是同一个元素,我们才做进一步的操作。这时我们就要判其是向上移向下移,简单的减法而已。接着是交换两行,使用insertBefore。最后当mouseup时,还原行的样式就是!由于没有复杂的坐标计算,整个程式出奇的高效!

完整演示代码

<!doctype html>
<html>
 <head>
  <title>表格行拖动</title>
  <script>
     window.onload = function(){
    //绑定事件
    var addEvent = document.addEventListener ? function(el,type,callback){
     el.addEventListener( type, callback, !1 );
    } : function(el,type,callback){
     el.attachEvent( "on" + type, callback );
    }
    //移除事件
    var removeEvent = document.removeEventListener ? function(el,type,callback){
     el.removeEventListener( type, callback );
    } : function(el,type,callback){
     el.detachEvent( "on" + type, callback);
    }
    //精确获取样式
    var getStyle = document.defaultView ? function(el,style){
     return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
    } : function(el,style){
     style = style.replace(/\-(\w)/g, function($, $1){
      return $1.toUpperCase();
     });
     return el.currentStyle[style];
    }
    var dragManager = {
     clientY:0,
     draging:function(e){//mousemove时拖动行
      var dragObj = dragManager.dragObj;
      if(dragObj){
       e = e || event;
       if(window.getSelection){//w3c
        window.getSelection().removeAllRanges();
       }else if(document.selection){
        document.selection.empty();//IE
       }
       var y = e.clientY;
       var down = y > dragManager.clientY;//是否向下移动
       var tr = document.elementFromPoint(e.clientX,e.clientY);
       if(tr && tr.nodeName == "TD"){
        tr = tr.parentNode
        dragManager.clientY = y;
        if( dragObj !== tr){
         tr.parentNode.insertBefore(dragObj, (down ? tr.nextSibling : tr));
        }
       };
      }
     },
     dragStart:function(e){
      e = e || event;
      var target = e.target || e.srcElement;
      if(target.nodeName === "TD"){
       target = target.parentNode;
       dragManager.dragObj = target;
       if(!target.getAttribute("data-background")){
        var background = getStyle(target,"background-color");
        target.setAttribute("data-background",background)
       }
       //显示为可移动的状态
       target.style.backgroundColor = "#ccc";
       target.style.cursor = "move";
       dragManager.clientY = e.clientY;
       addEvent(document,"mousemove",dragManager.draging);
       addEvent(document,"mouseup",dragManager.dragEnd);
      }
     },
     dragEnd:function(e){
      var dragObj = dragManager.dragObj
      if (dragObj) {
       e = e || event;
       var target = e.target || e.srcElement;
       if(target.nodeName === "TD"){
        target = target.parentNode;
        dragObj.style.backgroundColor = dragObj.getAttribute("data-background");
        dragObj.style.cursor = "default";
        dragManager.dragObj = null;
        removeEvent(document,"mousemove",dragManager.draging);
        removeEvent(document,"mouseup",dragManager.dragEnd);
       }
      }
     },
     main:function(el){
      addEvent(el,"mousedown",dragManager.dragStart);
     }
    }
    var el = document.getElementById("table");
    dragManager.main(el);
   }
   
  </script>
  <style>
   .table{
    width:60%;
    border: 1px solid red;
    border-collapse: collapse;
   }
   .table td{
    border: 1px solid red;
    height: 20px;
   }
  </style>
 </head>
 <body>
  <h1>表格行拖动</h1>
  <table id="table" class="table">
   <tbody>
    <tr>
     <td>1</td>
     <td>One</td>
     <td>dom.require</td>
    </tr>
    <tr id="2" >
     <td class="2">2</td>
     <td>Two</td>
     <td>ControlJS </td>
    </tr>
    <tr id="3" >
     <td class="3">3</td>
     <td>Three</td>
     <td>HeadJS</td>
    </tr>
    <tr id="4" >
     <td class="4">4</td>
     <td>Four</td>
     <td>LAB.js</td>
    </tr>
    <tr id="5" >
     <td class="5">5</td>
     <td>Five</td>
     <td>$script.js</td>
    </tr>
    <tr id="6" >
     <td class="6">6</td>
     <td>Six</td>
     <td>NBL.js</td>
    </tr>
   </tbody>
  </table>
 </body>
</html>

核心代码

window.onload = function(){
 //绑定事件
 var addEvent = document.addEventListener ? function(el,type,callback){
  el.addEventListener( type, callback, !1 );
 } : function(el,type,callback){
  el.attachEvent( "on" + type, callback );
 }
 //移除事件
 var removeEvent = document.removeEventListener ? function(el,type,callback){
  el.removeEventListener( type, callback );
 } : function(el,type,callback){
  el.detachEvent( "on" + type, callback);
 }
 //精确获取样式
 var getStyle = document.defaultView ? function(el,style){
  return document.defaultView.getComputedStyle(el, null).getPropertyValue(style)
 } : function(el,style){
  style = style.replace(/\-(\w)/g, function($, $1){
   return $1.toUpperCase();
  });
  return el.currentStyle[style];
 }
 var dragManager = {
  clientY:0,
  draging:function(e){//mousemove时拖动行
   var dragObj = dragManager.dragObj;
   if(dragObj){
    e = e || event;//清除选区
    if(window.getSelection){//w3c
     window.getSelection().removeAllRanges();
    }else if(document.selection){
     document.selection.empty();//IE
    }
    var y = e.clientY;
    var down = y > dragManager.clientY;//是否向下移动
    var tr = document.elementFromPoint(e.clientX,e.clientY);
    if(tr && tr.nodeName == "TD"){
     tr = tr.parentNode
     dragManager.clientY = y;
     if( dragObj !== tr){
      tr.parentNode.insertBefore(dragObj, (down ? tr.nextSibling : tr));
     }
    };
   }
  },
  dragStart:function(e){
   e = e || event;
   var target = e.target || e.srcElement;
   if(target.nodeName === "TD"){
    target = target.parentNode;
    dragManager.dragObj = target;
    if(!target.getAttribute("data-background")){
     var background = getStyle(target,"background-color");
     target.setAttribute("data-background",background)
    }
    //显示为可移动的状态
    target.style.backgroundColor = "#ccc";
    target.style.cursor = "move";
    dragManager.clientY = e.clientY;
    addEvent(document,"mousemove",dragManager.draging);
    addEvent(document,"mouseup",dragManager.dragEnd);
   }
  },
  dragEnd:function(e){
   var dragObj = dragManager.dragObj
   if (dragObj) {
    e = e || event;
    var target = e.target || e.srcElement;
    if(target.nodeName === "TD"){
     target = target.parentNode;
     dragObj.style.backgroundColor = dragObj.getAttribute("data-background");
     dragObj.style.cursor = "default";
     dragManager.dragObj = null;
     removeEvent(document,"mousemove",dragManager.draging);
     removeEvent(document,"mouseup",dragManager.dragEnd);
    }
   }
  },
  main:function(el){
   addEvent(el,"mousedown",dragManager.dragStart);
  }
 }
 var el = document.getElementById("table");
 dragManager.main(el);
}

实现代码二

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" > 
<head > 
<title>无标题页</title> 
</head> 
<body> 
<table id="tb1" border="1" cellpadding="3"> 
<tr> 
<th>移动</th> 
<th>数据</th> 
<th>数据</th> 
<th>数据</th> 
</tr> 
<tr> 
<td>*</td> 
<td>11111111111</td> 
<td>sdgergserhserhserh</td> 
<td>awegaw</td> 
</tr> 
<tr> 
<td>*</td> 
<td>222222222</td> 
<td>serherwwwwww</td> 
<td>fafafff</td> 
</tr> 
<tr> 
<td>*</td> 
<td>333333333</td> 
<td>qqqqqqqwewer</td> 
<td>yukyuk</td> 
</tr> 
</table> 
<script type="text/javascript"> 
var curTr = null; 
var tb1 = document.getElementById('tb1'); 
var trs = tb1.getElementsByTagName('tr'); 
tb1.onselectstart = function(){ 
if(curTr){ 
document.selection.empty(); return true; 
} 
}; 
for(var i=1; i<trs.length; i++) { 
var tds = trs[i].getElementsByTagName('td'); 
tds[0].style.cursor = 'move'; 
tds[0].onmousedown = function(){ 
curTr = this.parentNode; 
curTr.style.backgroundColor = '#eff'; 
}; 
tds[0].onmouseover = function() { 
if(curTr && curTr != this.parentNode) { 
this.parentNode.swapNode(curTr); 
} 
} 
} 
document.body.onmouseup = function(){ 
if(curTr){ 
curTr.style.backgroundColor = ''; 
curTr = null; 
} 
}; 
</script> 
</body> 
</html>

注:不兼容firefox,在IE和chrome下测试通过哦。

Javascript 相关文章推荐
JS实现模仿微博发布效果实例代码
Dec 16 Javascript
用js替换除数字与逗号以外的所有字符的代码
Jun 07 Javascript
谷歌地图打不开的解决办法
Aug 07 Javascript
jQuery实现简单的tab标签页效果
Sep 12 Javascript
使用BootStrapValidator完成前端输入验证
Sep 28 Javascript
php简单数据库操作类的封装
Jun 08 Javascript
JavaScript 程序错误Cannot use 'in' operator to search的解决方法
Jul 10 Javascript
仿京东快报向上滚动的实例
Dec 13 Javascript
JS与jQuery实现ListBox上移,下移,左移,右移操作功能示例
May 31 jQuery
Vue SPA 初次进入加载动画实现代码
Nov 14 Javascript
在vue和element-ui的table中实现分页复选功能
Dec 04 Javascript
Handtrack.js库实现实时监测手部运动(推荐)
Feb 08 Javascript
小试JQuery的AutoComplete插件
May 04 #Javascript
为你的网站增加亮点的9款jQuery插件推荐
May 03 #Javascript
通过jquery的$.getJSON做一个跨域ajax请求试验
May 03 #Javascript
Jquery 绑定时间实现代码
May 03 #Javascript
jqgrid 简单学习笔记
May 03 #Javascript
用js实现判断当前网址的来路如果不是指定的来路就跳转到指定页面
May 02 #Javascript
jQuery之网页换肤实现代码
Apr 30 #Javascript
You might like
PHP设计模式之适配器模式代码实例
2015/05/11 PHP
CodeIgniter控制器之业务逻辑实例分析
2016/01/20 PHP
如何利用预加载优化Laravel Model查询详解
2017/08/11 PHP
laravel学习笔记之模型事件的几种用法示例
2017/08/15 PHP
thinkPHP中钩子的使用方法实例分析
2017/11/16 PHP
PHP微信网页授权的配置文件操作分析
2019/05/29 PHP
javascript中的几个运算符
2007/06/29 Javascript
IE FF OPERA都可用的弹出层实现代码
2009/09/29 Javascript
JS函数验证总结(方便js客户端输入验证)
2010/10/29 Javascript
jQuery+.net实现浏览更多内容(改编php版本)
2013/03/28 Javascript
jQuery 获取和设置select下拉框的值实现代码
2013/11/08 Javascript
IE中的File域无法清空使用jQuery重设File域
2014/04/24 Javascript
js实例属性和原型属性示例详解
2014/11/23 Javascript
jQuery封装的屏幕居中提示信息代码
2016/06/08 Javascript
JavaScript编程中实现对象封装特性的实例讲解
2016/06/24 Javascript
通过修改360抢票的刷新频率和突破8车次限制实现方法
2017/01/04 Javascript
js控制一个按钮是否可点击(可使用)disabled的实例
2017/02/14 Javascript
AngularJS双向绑定和依赖反转实例详解
2017/04/15 Javascript
微信小程序组件之srcoll-view的详解
2017/10/19 Javascript
使用webpack打包koa2 框架app
2018/02/02 Javascript
python MySQLdb Windows下安装教程及问题解决方法
2015/05/09 Python
Python求算数平方根和约数的方法汇总
2016/03/09 Python
wxPython之解决闪烁的问题
2018/01/15 Python
浅谈pandas用groupby后对层级索引levels的处理方法
2018/11/06 Python
Face++ API实现手势识别系统设计
2018/11/21 Python
python定时按日期备份MySQL数据并压缩
2019/04/19 Python
Pycharm+Python+PyQt5使用详解
2019/09/25 Python
使用Tensorflow将自己的数据分割成batch训练实例
2020/01/20 Python
python实现经典排序算法的示例代码
2021/02/07 Python
沙特阿拉伯排名第一的在线时尚购物应用程序:1Zillion
2020/08/08 全球购物
门卫班长岗位职责
2013/12/15 职场文书
直接有效的自我评价
2014/01/11 职场文书
初中高效课堂实施方案
2014/02/26 职场文书
励志演讲稿范文
2014/04/29 职场文书
Oracle数据库事务的开启与结束详解
2022/06/25 Oracle
利用Java连接Hadoop进行编程
2022/06/28 Java/Android