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 相关文章推荐
获取页面高度,窗口高度,滚动条高度等参数值getPageSize,getPageScroll
Sep 22 Javascript
js 代码集(学习js的朋友可以看下)
Jul 22 Javascript
jQuery EasyUI API 中文文档 - Menu菜单
Oct 03 Javascript
推荐一款jQuery插件模板
Jan 09 Javascript
将html页面保存成图片,图片写入pdf的实现方法(推荐)
Sep 17 Javascript
JS正则表达式验证密码格式的集中情况总结
Feb 23 Javascript
深入理解JavaScript 参数按值传递
May 24 Javascript
Vue-resource拦截器判断token失效跳转的实例
Oct 27 Javascript
详解使用vue-cli脚手架初始化Vue项目下的项目结构
Mar 08 Javascript
详解Vue取消eslint语法限制
Aug 04 Javascript
Next.js项目实战踩坑指南(笔记)
Nov 29 Javascript
js 闭包深入理解与实例分析
Mar 19 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中多维数组按指定value排序的实现代码
2014/08/19 PHP
php+mongodb判断坐标是否在指定多边形区域内的实例
2016/10/28 PHP
PHP获取页面执行时间的方法(推荐)
2016/12/10 PHP
FileUpload 控件 禁止手动输入或粘贴的实现代码
2010/04/07 Javascript
关于jquery append() html时的小问题的解决方法
2010/12/16 Javascript
javaScript面向对象继承方法经典实现
2013/08/20 Javascript
将list转换为json失败的原因
2013/12/17 Javascript
js中reverse函数的用法详解
2013/12/26 Javascript
JavaScript如何实现对数字保留两位小数一位自动补零
2015/12/18 Javascript
学习Node.js模块机制
2016/10/17 Javascript
Angular2生命周期钩子函数的详细介绍
2017/07/10 Javascript
vue实现验证码按钮倒计时功能
2018/04/10 Javascript
jQuery实现的滑块滑动导航效果示例
2018/06/04 jQuery
如何在vue里面优雅的解决跨域(路由冲突问题)
2019/01/20 Javascript
JS开发自己的类库实例分析
2019/08/28 Javascript
python实现查询IP地址所在地
2015/03/29 Python
Python 遍历列表里面序号和值的方法(三种)
2017/02/17 Python
python读取与写入csv格式文件的示例代码
2017/12/16 Python
Python实现读取字符串按列分配后按行输出示例
2018/04/17 Python
Python的matplotlib绘图如何修改背景颜色的实现
2019/07/16 Python
python多线程实现同时执行两个while循环的操作
2020/05/02 Python
如何在Python对Excel进行读取
2020/06/04 Python
深入了解python列表(LIST)
2020/06/08 Python
YSL圣罗兰美妆美国官网:Yves Saint Lauret US
2016/11/21 全球购物
资深地理教师自我评价
2013/09/21 职场文书
自我介绍演讲稿
2014/01/15 职场文书
十月份红领巾广播稿
2014/01/22 职场文书
《找不到快乐的波斯猫》教学反思
2014/02/24 职场文书
升国旗仪式主持词
2014/03/19 职场文书
励志演讲稿大全
2014/08/21 职场文书
小学教师师德师风演讲稿
2014/08/22 职场文书
2014院党委领导班子对照检查材料思想汇报
2014/09/24 职场文书
公司周年庆典标语
2014/10/07 职场文书
2015年幼儿园元旦游艺活动策划书
2014/12/09 职场文书
2016教师党员学习心得体会
2016/01/21 职场文书
一篇文章搞懂python混乱的切换操作与优雅的推导式
2021/08/23 Python