js 可拖动列表实现代码


Posted in Javascript onDecember 13, 2011

补充一点:
要禁止移动中选中文字,FF可以设置CSS
xxxx{-moz-user-select:none;}
其他的浏览器可以设置
XXXX.onselectstart = function(){return false}
一种实现原理就是点击没目标元素之后,创建一个占位元素(或者复制一份目标元素,即拷贝B),然后拖动目标元素(或者复制的来的新元素B);
找到相应的位置之后,插入目标元素。清除占位元素或者B。
比如有一个列表:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 
<title></title> 
<style type="text/css"> 
*{ margin: 0; padding: 0; -moz-user-select:none;} 
ul{ margin: 100px; border: 1px solid #adff2f; list-style: none;} 
li{ height: 30px; line-height: 30px; padding: 0; list-style: none;} 
li:hover{ background: #bdb76b; cursor: move;} 
</style> 
</head> 
<body> 
<ul id="outer_wrap"> 
<li>第一条</li> 
<li>第二条</li> 
<li>第三条</li> 
<li>第四条</li> 
<li>第五条</li> 
<li>第六条</li> 
<li>第七条</li> 
<li>第八条</li> 
</ul> 
</body> 
</html>

点击“<li>第一条</li>”(记为元素A),获取““<li>第一条</li>””的位置和尺寸信息,把元素A拷贝一遍(记为元素B),然后插入文档中,将元素B绝对定位到元素A的位置,然后鼠标移动的时候,元素B跟着拖动,接着就是判断插入点。
判断插入点就是判断当前鼠标所在的坐标,如果鼠标坐标落在除了元素A之外的其他LI元素范围之内,就满足可插入的条件,同时上半部分就插入到前面,下半部分就插入到后面。(=。= 个人口味重,觉得这段话好邪恶啊)

js 可拖动列表实现代码
为了标示出插入的位置,我们在选中的插入点处另插入一个元素,仅作标杆用。
下面是一个demo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 
<title></title> 
<style type="text/css"> 
*{ margin: 0; padding: 0; -moz-user-select:none;} 
ul{ margin: 100px; border: 1px solid #adff2f; list-style: none;} 
li{ height: 30px; line-height: 30px; padding: 0; list-style: none;} 
li:hover{ background: #bdb76b; cursor: move;} 
</style> 
</head> 
<body> 
<ul id="outer_wrap"> 
<li>第一条</li> 
<li>第二条</li> 
<li>第三条</li> 
<li>第四条</li> 
<li>第五条</li> 
<li>第六条</li> 
<li>第七条</li> 
<li>第八条</li> 
</ul> 
<script type="text/javascript"> 
function $(id){ 
return document.getElementById(id); 
} 
//获取鼠标位置 
function getMousePos(e){ 
return { 
x : e.pageX || e.clientX + document.body.scrollLeft, 
y : e.pageY || e.clientY + document.body.scrollTop 
} 
} 
//获取元素位置 
function getElementPos(el){ 
return { 
x : el.offsetParent ? el.offsetLeft + arguments.callee(el.offsetParent)['x'] : el.offsetLeft, 
y : el.offsetParent ? el.offsetTop + arguments.callee(el.offsetParent)['y'] : el.offsetTop 
} 
} 
//获取元素尺寸 
function getElementSize(el){ 
return { 
width : el.offsetWidth, 
height : el.offsetHeight 
} 
} 
//禁止选择 
document.onselectstart = function(){ 
return false; 
} 
//判断是否有挪动 
var MOVE = {}; 
MOVE.isMove = false; //就是创建的标杆 
var div = document.createElement('div'); 
div.style.width = '400px'; 
div.style.height = '1px'; 
div.style.fontSize = '0'; 
div.style.background = 'red'; 
var outer_wrap = $('outer_wrap'); 
outer_wrap.onmousedown = function(event){ 
//获取列表顺序 
var lis = outer_wrap.getElementsByTagName('li'); 
for(var i = 0; i < lis.length; i++){ 
lis[i]['pos'] = getElementPos(lis[i]); 
lis[i]['size'] = getElementSize(lis[i]); 
} 
event = event || window.event; 
var t = event.target || event.srcElement; 
if(t.tagName.toLowerCase() == 'li'){ 
var p = getMousePos(event); 
var el = t.cloneNode(true); 
el.style.position = 'absolute'; 
el.style.left = t.pos.x + 'px'; 
el.style.top = t.pos.y + 'px'; 
el.style.width = t.size.width + 'px'; 
el.style.height = t.size.height + 'px'; 
el.style.border = '1px solid #d4d4d4'; 
el.style.background = '#d4d4d4'; 
el.style.opacity = '0.7'; 
document.body.appendChild(el); 
document.onmousemove = function(event){ 
event = event || window.event; 
var current = getMousePos(event); 
el.style.left =t.pos.x + current.x - p.x + 'px'; 
el.style.top =t.pos.y + current.y - p.y+ 'px'; 
document.body.style.cursor = 'move'; 
//判断插入点 
for(var i = 0; i < lis.length; i++){ 
if(current.x > lis[i]['pos']['x'] && current.x < lis[i]['pos']['x'] + lis[i]['size']['width'] && current.y > lis[i]['pos']['y'] && current.y < lis[i]['pos']['y'] + lis[i]['size']['height']/2){ 
if(t != lis[i]){ 
MOVE.isMove = true; 
outer_wrap.insertBefore(div,lis[i]); 
} 
}else if(current.x > lis[i]['pos']['x'] && current.x < lis[i]['pos']['x'] + lis[i]['size']['width'] && current.y > lis[i]['pos']['y'] + lis[i]['size']['height']/2 && current.y < lis[i]['pos']['y'] + lis[i]['size']['height']){ 
if(t != lis[i]){ 
MOVE.isMove = true; 
outer_wrap.insertBefore(div,lis[i].nextSibling); 
} 
} 
} 
} 
//移除事件 
document.onmouseup = function(event){ 
event = event || window.event; 
document.onmousemove = null; 
if(MOVE.isMove){ 
outer_wrap.replaceChild(t,div); 
MOVE.isMove = false; 
} 
document.body.removeChild(el); 
el = null; 
document.body.style.cursor = 'normal'; 
document.onmouseup = null; 
} 
} 
} 
</script> 
</body> 
</html>

上面的demo代码细节欠缺考虑,仅供展示原理。
Javascript 相关文章推荐
ExtJS Grid使用SimpleStore、多选框的方法
Nov 20 Javascript
探讨jQuery的ajax使用场景(c#)
Dec 03 Javascript
jQuery实现防止提交按钮被双击的方法
Mar 24 Javascript
高性能JavaScript 重排与重绘(2)
Aug 11 Javascript
基于jQuery实现在线选座之高铁版
Aug 24 Javascript
AngularJS Bootstrap详细介绍及实例代码
Jul 28 Javascript
bootstrap——bootstrapTable实现隐藏列的示例
Jan 14 Javascript
Vue实现动态显示textarea剩余字数
May 22 Javascript
详解微信第三方小程序代开发
Jun 23 Javascript
Bootstrap Tooltip显示换行和左对齐的解决方案
Oct 11 Javascript
深入理解Puppeteer的入门教程和实践
Mar 05 Javascript
vue.js+elementUI实现点击左右箭头切换头像功能(类似轮播图效果)
Sep 05 Javascript
使用Mootools动态添加Css样式表代码,兼容各浏览器
Dec 12 #Javascript
分享一个用Mootools写的鼠标滑过进度条改变进度值的实现代码
Dec 12 #Javascript
背景图跟随鼠标移动的Mootools插件实现代码
Dec 12 #Javascript
用Mootools获得操作索引的两种方法分享
Dec 12 #Javascript
整理8个很棒的 jQuery 倒计时插件和教程
Dec 12 #Javascript
关于event.cancelBubble和event.stopPropagation()的区别介绍
Dec 11 #Javascript
Jquery阻止事件冒泡 event.stopPropagation
Dec 11 #Javascript
You might like
编写PHP脚本过滤用户上传的图片
2015/07/03 PHP
PHP函数按引用传递参数及函数可选参数用法示例
2018/06/04 PHP
javascript下string.format函数补充
2010/08/24 Javascript
如何通过javascript操作web控件的自定义属性
2013/11/25 Javascript
js解决select下拉选不中问题
2014/10/14 Javascript
javascript用正则表达式过滤空格的实现代码
2016/06/14 Javascript
AngularJS $injector 依赖注入详解
2016/09/14 Javascript
jQuery模拟爆炸倒计时功能实例代码
2017/08/21 jQuery
JavaScript事件处理程序详解
2017/09/19 Javascript
微信小程序实现动态改变view标签宽度和高度的方法【附demo源码下载】
2017/12/05 Javascript
Angular 向组件传递模板的两种方法
2018/02/23 Javascript
Vue自定义toast组件的实例代码
2018/08/15 Javascript
详解jenkins自动化部署vue
2019/05/14 Javascript
vue中实现回车键登录功能
2020/02/19 Javascript
JS深入学习之数组对象排序操作示例
2020/05/01 Javascript
Python常用模块用法分析
2014/09/08 Python
Python读写配置文件的方法
2015/06/03 Python
Python实现压缩和解压缩ZIP文件的方法分析
2017/09/28 Python
Python网络编程之TCP套接字简单用法示例
2018/04/09 Python
Python filter()及reduce()函数使用方法解析
2020/09/05 Python
CSS3网格的三个新特性详解
2014/04/04 HTML / CSS
美国家具网站:Cymax
2016/09/17 全球购物
阿里健康官方海外旗舰店:阿里健康国际自营
2017/11/24 全球购物
几道数据库的面试题或笔试题
2014/05/31 面试题
英文自我鉴定
2013/12/10 职场文书
十月份红领巾广播稿
2014/01/22 职场文书
2014迎新年晚会策划方案
2014/02/23 职场文书
数控专业自荐书范文
2014/03/16 职场文书
酒店开业庆典主持词
2014/03/21 职场文书
电子商务助理求职自荐信
2014/04/10 职场文书
土建施工员岗位职责
2014/07/16 职场文书
教师批评与自我批评剖析材料
2014/10/16 职场文书
高三毕业感言
2015/07/30 职场文书
python实现批量提取指定文件夹下同类型文件
2021/04/05 Python
Python一些基本的图像操作和处理总结
2021/06/23 Python
用Python编写简单的gRPC服务的详细过程
2021/07/04 Python