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 相关文章推荐
没有document.getElementByName方法
Aug 19 Javascript
jquery无刷新验证邮箱地址实现实例
Feb 19 Javascript
jquery序列化表单去除指定元素示例代码
Apr 10 Javascript
基于JavaScript实现自定义滚动条
Jan 25 Javascript
微信小程序开发之从相册获取图片 使用相机拍照 本地图片上传
Apr 18 Javascript
BootStrap 动态表单效果
Jun 02 Javascript
webpack开发环境和生产环境的深入理解
Nov 08 Javascript
详解原生JS回到顶部
Mar 25 Javascript
基于vue-cli 路由 实现类似tab切换效果(vue 2.0)
May 08 Javascript
微信小程序scroll-view锚点链接滚动跳转功能
Dec 12 Javascript
javascript中contains是否包含功能实现代码(扩展字符、数组、dom)
Apr 07 Javascript
Vue实现动态查询规则生成组件
May 27 Vue.js
使用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 数据库字段复用的基本原理与示例
2011/07/22 PHP
简单介绍PHP非阻塞模式
2016/03/03 PHP
php操纵mysqli数据库的实现方法
2016/09/18 PHP
js中将多个语句写成一个语句的两种方法小结
2007/12/08 Javascript
JS动画效果代码3
2008/04/03 Javascript
jquery js 获取时间差、时间格式具体代码
2013/06/05 Javascript
在JavaScript中构建ArrayList示例代码
2014/09/17 Javascript
node.js中的fs.mkdir方法使用说明
2014/12/17 Javascript
谈谈Jquery ajax中success和complete有哪些不同点
2015/11/20 Javascript
jquery中取消和绑定hover事件的实现代码
2016/06/02 Javascript
ECMAScript6--解构
2017/03/30 Javascript
JavaScript全屏和退出全屏事件总结(附代码)
2017/08/17 Javascript
Vue press 支持图片放大功能的实例代码
2018/11/09 Javascript
深入理解Node内建模块和对象
2019/03/12 Javascript
react-native聊天室|RN版聊天App仿微信实例|RN仿微信界面
2019/11/12 Javascript
[01:51]2018年度CS GO最具人气外援-完美盛典
2018/12/16 DOTA
用python代码做configure文件
2014/07/20 Python
Python解决鸡兔同笼问题的方法
2014/12/20 Python
Python contextlib模块使用示例
2015/02/18 Python
Python的ORM框架中SQLAlchemy库的查询操作的教程
2015/04/25 Python
浅谈Python2获取中文文件名的编码问题
2018/01/09 Python
pytorch 输出中间层特征的实例
2019/08/17 Python
pytorch实现对输入超过三通道的数据进行训练
2020/01/15 Python
Python venv虚拟环境配置过程解析
2020/07/08 Python
python绘制高斯曲线
2021/02/19 Python
HTML5单选框、复选框、下拉菜单、文本域的实现代码
2020/12/01 HTML / CSS
美国渔具店:FishUSA
2019/08/07 全球购物
锐步英国官网:Reebok英国
2019/11/29 全球购物
专科毕业生就业推荐信
2013/11/01 职场文书
优秀社区干部事迹材料
2014/02/03 职场文书
护理专科毕业生自荐书范文
2014/02/19 职场文书
班班通项目实施方案
2014/02/25 职场文书
洗发露广告词
2014/03/14 职场文书
物流管理专业求职信
2014/05/29 职场文书
2015秋季运动会通讯稿
2015/07/18 职场文书
Python如何把不同类型数据的json序列化
2021/04/30 Python