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函数的引用, 关于内存的开销
Sep 17 Javascript
在javascript中如何得到中英文混合字符串的长度
Jan 17 Javascript
jqueryMobile使用示例分享
Jan 12 Javascript
form表单转Json提交的方法(推荐)
Sep 23 Javascript
Vue 仿百度搜索功能实现代码
Feb 16 Javascript
jQuery实现一个简单的轮播图
Feb 19 Javascript
JavaScript获取移动设备型号的实现代码(JS获取手机型号和系统)
Mar 10 Javascript
JavaScript简单实现的仿微博留言功能示例
Jan 17 Javascript
8个有意思的JavaScript面试题
Jul 30 Javascript
弱类型语言javascript中 a,b 的运算实例小结
Aug 07 Javascript
vue项目中使用eslint+prettier规范与检查代码的方法
Jan 16 Javascript
在Angular项目使用socket.io实现通信的方法
Jan 05 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
MYSQL环境变量设置方法
2007/01/15 PHP
php学习笔记 面向对象的构造与析构方法
2011/06/13 PHP
一个漂亮的php验证码类(分享)
2013/08/06 PHP
win平台安装配置Nginx+php+mysql 环境
2016/01/12 PHP
Joomla实现组件中弹出一个模式(modal)窗口的方法
2016/05/04 PHP
完美解决phpexcel导出到xls文件出现乱码的问题
2016/10/29 PHP
跟着JQuery API学Jquery 之三 筛选
2010/04/09 Javascript
在图片上显示左右箭头类似翻页的代码
2013/03/04 Javascript
点击按钮或链接不跳转只刷新页面的脚本整理
2013/10/22 Javascript
Extjs4中Form的使用之本地hiddenfield
2013/11/26 Javascript
快速获取/设置iframe内对象元素的几种js实现方法
2016/05/20 Javascript
微信小程序 UI布局常用技巧整理总结
2016/12/05 Javascript
简易Vue评论框架的实现(父组件的实现)
2018/01/08 Javascript
解决前后端分离 vue+springboot 跨域 session+cookie失效问题
2019/05/13 Javascript
layui 动态设置checbox 选中状态的例子
2019/09/02 Javascript
Layui 数据表格批量删除和多条件搜索的实例
2019/09/04 Javascript
nodeJS与MySQL实现分页数据以及倒序数据
2020/06/05 NodeJs
vue中destroyed方法的使用说明
2020/07/21 Javascript
JS实现鼠标按下拖拽效果
2020/07/23 Javascript
vue print.js打印支持Echarts图表操作
2020/11/13 Javascript
python实现问号表达式(?)的方法
2013/11/27 Python
简单谈谈Python中的反转字符串问题
2016/10/24 Python
Pycharm简单使用教程(入门小结)
2019/07/04 Python
pytorch实现查看当前学习率
2020/06/24 Python
8种常用的Python工具
2020/08/05 Python
仿CSDN Blog返回页面顶部功能实现原理及代码
2013/06/30 HTML / CSS
HTML5 自动聚焦(autofocus)属性使用介绍
2013/08/07 HTML / CSS
Html5 页面适配iPhoneX(就是那么简单)
2019/09/05 HTML / CSS
荷兰游戏商店:Allyouplay
2019/03/16 全球购物
Waterford英国官方网站:世界上最受欢迎的优质水晶品牌
2019/08/17 全球购物
生产车间班组长岗位职责
2014/01/06 职场文书
表扬信格式
2014/01/12 职场文书
师范毕业生自我鉴定
2014/01/15 职场文书
委托协议书范本
2014/04/22 职场文书
团干部培训方案
2014/06/03 职场文书
高考满分作文赏析(2篇)
2019/08/12 职场文书