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 相关文章推荐
clientX,pageX,offsetX,x,layerX,screenX,offsetLeft区别分析
Mar 12 Javascript
js,jQuery 排序的实现代码,网页标签排序的实现,标签排序
Apr 27 Javascript
JS.findElementById()使用介绍
Sep 21 Javascript
javascript页面倒计时实例
Jul 25 Javascript
js判断鼠标位置是否在某个div中的方法
Feb 26 Javascript
老生常谈 关于JavaScript的类的继承
Jun 24 Javascript
JS 面向对象之继承---多种组合继承详解
Jul 10 Javascript
在js中实现邮箱格式的验证方法(推荐)
Oct 24 Javascript
js 能实现监听F5页面刷新子iframe 而父页面不刷新的方法
Nov 09 Javascript
template.js前端模板引擎使用详解
Oct 10 Javascript
jQuery 点击获取验证码按钮及倒计时功能
Sep 20 jQuery
输入框跟随文字内容适配宽实现示例
Aug 14 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 print EOF实现方法
2009/05/21 PHP
探讨PHP JSON中文乱码的解决方法详解
2013/06/06 PHP
Avengerls vs Newbee BO3 第二场2.18
2021/03/10 DOTA
Mozilla中显示textarea中选择的文字
2006/09/07 Javascript
Jquery Ajax学习实例7 Ajax所有过程事件分析示例
2010/03/23 Javascript
JavaScript高级程序设计 阅读笔记(十四) js继承机制的实现
2012/08/14 Javascript
js根据给定的日期计算当月有多少天实现思路及代码
2013/02/25 Javascript
常用的jQuery前端技巧收集
2014/12/24 Javascript
JavaScript设计模式之工厂模式和构造器模式
2015/02/11 Javascript
javascript无刷新评论实现方法
2015/05/13 Javascript
浅谈JavaScript中的字符编码转换问题
2015/07/07 Javascript
JS实现漂亮的窗口拖拽效果(可改变大小、最大化、最小化、关闭)
2015/10/10 Javascript
JS控制层作圆周运动的方法
2016/06/20 Javascript
Google 地图API Map()构造器详解
2016/08/06 Javascript
浅谈JS之tagNaem和nodeName
2016/09/13 Javascript
jQuery动画_动力节点节点Java学院整理
2017/07/04 jQuery
基于vue.js路由参数的实例讲解——简单易懂
2017/09/07 Javascript
vue cli构建的项目中请求代理与项目打包问题
2018/02/26 Javascript
详解Vue.js中.native修饰符
2018/04/24 Javascript
基于vue2的canvas时钟倒计时组件步骤解析
2018/11/05 Javascript
vue实现输入框的模糊查询的示例代码(节流函数的应用场景)
2019/09/01 Javascript
JS面向对象编程——ES6 中class的继承用法详解
2020/03/03 Javascript
利用Python和OpenCV库将URL转换为OpenCV格式的方法
2015/03/27 Python
python交互式图形编程实例(二)
2017/11/17 Python
Python3.4学习笔记之列表、数组操作示例
2019/03/01 Python
CentOS7安装Python3的教程详解
2019/04/10 Python
python+webdriver自动化环境搭建步骤详解
2019/06/03 Python
python 设置输出图像的像素大小方法
2019/07/04 Python
浅谈tensorflow 中的图片读取和裁剪方式
2020/06/30 Python
python判断是空的实例分享
2020/07/06 Python
Django路由层URLconf作用及原理解析
2020/09/24 Python
HTML5的新特性(1)
2016/03/03 HTML / CSS
如何查询Oracle数据库中已经创建的索引
2013/10/11 面试题
公务员群众路线心得体会
2014/11/03 职场文书
高中班主任评语
2014/12/30 职场文书
清明节文明祭祀倡议书
2015/04/28 职场文书