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入门教程(2) JS基础知识
Jan 31 Javascript
Js切换功能的简单方法
Nov 23 Javascript
Js与下拉列表处理问题解决
Feb 13 Javascript
Jquery实现侧边栏跟随滚动条固定(兼容IE6)
Apr 02 Javascript
详解jquery事件delegate()的使用方法
Jan 25 Javascript
js倒计时简单实现代码
Aug 11 Javascript
easyui-datagrid特殊字符不能显示的处理方法
Apr 12 Javascript
对象不支持indexOf属性或方法的解决方法(必看)
May 28 Javascript
Vue.use源码学习小结
Jun 20 Javascript
利用JS代码自动删除稿件的普通弹幕功能
Sep 20 Javascript
微信小程序修改数组长度的问题的解决
Dec 17 Javascript
vue+openlayers绘制省市边界线
Dec 24 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环境搭建最新方法
2006/09/05 PHP
php使用function_exists判断函数可用的方法
2014/11/19 PHP
PHP集成百度Ueditor 1.4.3
2014/11/23 PHP
php通过正则表达式记取数据来读取xml的方法
2015/03/09 PHP
关于PHP文件的自动运行方法分析
2016/05/13 PHP
php实现批量删除挂马文件及批量替换页面内容完整实例
2016/07/08 PHP
PHP使用DOM和simplexml读取xml文档的方法示例
2017/02/08 PHP
jquery imgareaselect 使用利用js与程序结合实现图片剪切
2009/07/30 Javascript
jQuery 相关控件的事件操作分解
2009/08/03 Javascript
jQuery 幻灯片插件(带缩略图功能)
2011/01/24 Javascript
JS获取农历日期具体实例
2013/11/14 Javascript
异步安全加载javascript文件的方法
2015/07/21 Javascript
图解JavaScript中的this关键字
2020/05/28 Javascript
JS实现环形进度条(从0到100%)效果
2016/07/05 Javascript
jQuery中checkbox反复调用attr('checked', true/false)只有第一次生效的解决方法
2016/11/16 Javascript
Bootstrap fileinput组件封装及使用详解
2017/03/10 Javascript
使用webpack-dev-server处理跨域请求的方法
2018/04/18 Javascript
vue+axios实现文件下载及vue中使用axios的实例
2018/09/21 Javascript
Vue路由管理器Vue-router的使用方法详解
2020/02/05 Javascript
javascript中可能用得到的全部的排序算法
2020/03/05 Javascript
[11:57]《一刀刀一天》第十七期:TI中国军团加油!
2014/05/26 DOTA
[01:03:36]Ti4 循环赛第三日DK vs Titan
2014/07/12 DOTA
python实现倒计时的示例
2014/02/14 Python
python制作爬虫爬取京东商品评论教程
2016/12/16 Python
python 简单照相机调用系统摄像头实现方法 pygame
2018/08/03 Python
分享PyCharm的几个使用技巧
2019/11/10 Python
Python中logger日志模块详解
2020/08/04 Python
美国知名的百货清仓店:Neiman Marcus Last Call
2016/08/03 全球购物
澳大利亚领先的女帽及配饰公司:Morgan&Taylor
2019/12/01 全球购物
初一生物教学反思
2014/01/18 职场文书
小学班主任评语
2014/12/29 职场文书
爱心募捐通知范文
2015/04/27 职场文书
2016年教师节特级教师获奖感言
2015/12/09 职场文书
学校教代会开幕词
2016/03/04 职场文书
Java8利用Stream对列表进行去除重复的方法详解
2022/04/14 Java/Android
JS前端可扩展的低代码UI框架Sunmao使用详解
2022/07/23 Javascript