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元素范围之内,就满足可插入的条件,同时上半部分就插入到前面,下半部分就插入到后面。(=。= 个人口味重,觉得这段话好邪恶啊)
为了标示出插入的位置,我们在选中的插入点处另插入一个元素,仅作标杆用。
下面是一个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代码细节欠缺考虑,仅供展示原理。
js 可拖动列表实现代码
声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@