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 相关文章推荐
javascript void(0)的妙用
Oct 21 Javascript
原生js实现淘宝首页点击按钮缓慢回到顶部效果
Apr 06 Javascript
javascript if条件判断方法小结
May 17 Javascript
浅谈javascript的call()、apply()、bind()的用法
Feb 21 Javascript
jQuery遍历节点树方法分析
Sep 08 Javascript
JS日程管理插件FullCalendar简单实例
Feb 07 Javascript
JavaScript手风琴页面制作
May 17 Javascript
jQuery ajax动态生成table功能示例
Jun 14 jQuery
JS传播事件、取消事件默认行为、阻止事件传播详解
Aug 14 Javascript
JS使用setInterval实现的简单计时器功能示例
Apr 19 Javascript
Layui 带多选框表格监听事件以及按钮自动点击写法实例
Sep 02 Javascript
JS实现盒子拖拽效果
Feb 06 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字符串截取问题
2006/11/28 PHP
2个自定义的PHP in_array 函数,解决大量数据判断in_array的效率问题
2014/04/08 PHP
PHP 获取客户端 IP 地址的方法实例代码
2018/11/11 PHP
php post换行的方法
2020/02/03 PHP
javascript vvorld 在线加密破解方法
2008/11/13 Javascript
JQuery 无废话系列教程(二) jquery实战篇上
2009/06/23 Javascript
javascript 日期常用的方法
2009/11/11 Javascript
仅Firefox中链接A无法实现模拟点击以触发其默认行为
2011/07/31 Javascript
基于JavaScript 数据类型之Boolean类型分析介绍
2013/04/19 Javascript
HTML长文本截取含有HTML代码同样适用的两种方法
2013/07/31 Javascript
web网页按比例显示图片实现原理及js代码
2013/08/09 Javascript
node.js实现多图片上传实例
2014/06/03 Javascript
使用Nodejs开发微信公众号后台服务实例
2014/09/03 NodeJs
Internet Explorer 11 浏览器介绍:别叫我IE
2014/09/28 Javascript
浅谈JavaScript中的分支结构
2016/07/01 Javascript
老生常谈JavaScript 正则表达式语法
2016/08/20 Javascript
微信小程序 火车票查询实例讲解
2016/10/17 Javascript
Nodejs 发布自己的npm包并制作成命令行工具的实例讲解
2018/05/15 NodeJs
jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】
2018/08/28 jQuery
webuploader分片上传的实现代码(前后端分离)
2018/09/10 Javascript
修改layui的后台模板的左侧导航栏可以伸缩的方法
2019/09/10 Javascript
[43:57]Liquid vs Mineski 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/19 DOTA
Python面向对象之类和对象实例详解
2018/12/10 Python
Python用61行代码实现图片像素化的示例代码
2018/12/10 Python
Python静态类型检查新工具之pyright 使用指南
2019/04/26 Python
Python获取好友地区分布及好友性别分布情况代码详解
2019/07/10 Python
关于tensorflow的几种参数初始化方法小结
2020/01/04 Python
Dower & Hall官网:英国小众轻奢珠宝品牌
2019/01/31 全球购物
个人自我鉴定范文
2013/10/04 职场文书
清洁工表扬信
2014/01/08 职场文书
地球物理学专业推荐信
2014/09/08 职场文书
财务工作犯错检讨书
2014/10/07 职场文书
群众路线专项整治方案
2014/10/27 职场文书
2015年电话销售工作总结范文
2015/04/20 职场文书
个人更名证明
2015/06/23 职场文书
听课评课活动心得体会
2016/01/15 职场文书