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 this 的一些学习总结
Aug 02 Javascript
JS实现状态栏跑马灯文字效果代码
Oct 24 Javascript
AngularJS基础 ng-focus 指令简单示例
Aug 01 Javascript
jQuery实现简洁的轮播图效果实例
Sep 07 Javascript
详解微信小程序——自定义圆形进度条
Dec 29 Javascript
javascript中BOM基础知识总结
Feb 14 Javascript
jQuery zTree树插件动态加载实例代码
May 11 jQuery
详解webpack 多入口配置
Jun 16 Javascript
微信小程序联网请求的轮播图
Jul 07 Javascript
使用Vue写一个datepicker的示例
Jan 27 Javascript
jQuery实现根据身份证号获取生日、年龄、性别等信息的方法
Jan 09 jQuery
Vue开发环境中修改端口号的实现方法
Aug 15 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 中关于ord($str)&amp;gt;0x80的详细说明
2012/09/23 PHP
PHP 文件编程综合案例-文件上传的实现
2013/07/03 PHP
php curl常用的5个经典例子
2017/01/20 PHP
Thinkphp 框架扩展之标签库驱动原理与用法分析
2020/04/23 PHP
jquery 简单的进度条实现代码
2010/03/11 Javascript
JavaScript toFixed() 方法
2010/04/15 Javascript
尝试在让script的type属性等于text/html
2013/01/15 Javascript
一个简单的弹性返回顶部JS代码实现介绍
2013/06/09 Javascript
Jquery操作下拉框(DropDownList)实现取值赋值
2013/08/13 Javascript
对于Form表单reset方法的新认识
2014/03/05 Javascript
前端学习笔记style,currentStyle,getComputedStyle的用法与区别
2016/05/28 Javascript
JS阻止事件冒泡行为和闭包的方法
2016/06/16 Javascript
js控制li的隐藏和显示实例代码
2016/10/15 Javascript
jQuery实现弹幕效果
2017/02/17 Javascript
javascript实现二叉树的代码
2017/06/08 Javascript
vue2.0移除或更改的一些东西(移除index key)
2017/08/28 Javascript
jQuery实现点击下拉框中的值累加到文本框中的方法示例
2017/10/28 jQuery
原生js调用json方法总结
2018/02/22 Javascript
vue项目中vue-i18n和element-ui国际化开发实现过程
2018/04/25 Javascript
Vue动态加载异步组件的方法
2018/11/21 Javascript
通过javascript实现段落的收缩与展开
2019/06/26 Javascript
javascrpt密码强度校验函数详解
2020/03/18 Javascript
JS数组降维的实现Array.prototype.concat.apply([], arr)
2020/04/28 Javascript
微信小程序实现登录注册功能
2020/12/29 Javascript
Python网络编程详解
2017/10/31 Python
python中的set实现不重复的排序原理
2018/01/24 Python
python实现Windows电脑定时关机
2018/06/20 Python
OPENCV去除小连通区域,去除孔洞的实例讲解
2018/06/21 Python
django+xadmin+djcelery实现后台管理定时任务
2018/08/14 Python
python两个list[]相加的实现方法
2020/09/23 Python
系统管理员的职责包括那些?管理的对象是什么?
2013/01/18 面试题
工程师自我评价怎么写
2013/09/19 职场文书
职业生涯规划书基本格式
2014/01/06 职场文书
教师四风对照检查材料思想汇报
2014/09/17 职场文书
讲座开场白台词和结束语
2015/05/29 职场文书
解决SpringCloud Feign传对象参数调用失败的问题
2021/06/23 Java/Android