JavaScript拖拽框架与跨列拖放实现

来源:互联网 发布:淘宝客服售后提成 编辑:程序博客网 时间:2024/04/29 09:00

http://www.desteps.com/web/impact/1142.html

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>
js拖拽组件3
</title>
<script type="text/javascript" >
var Drag={
"obj":null,
"init":function(handle, dragBody, e){
if (e == null) {
handle.onmousedown=Drag.start;
}
handle.root = dragBody;
if(isNaN(parseInt(handle.root.style.left)))handle.root.style.left="0px";
if(isNaN(parseInt(handle.root.style.top)))handle.root.style.top="0px";//确保后来能够取得top值
handle.root.onDragStart=new Function();
handle.root.onDragEnd=new Function();
handle.root.onDrag=new Function();
if (e !=null) {
var handle=Drag.obj=handle;
e=Drag.fixe(e);
var top=parseInt(handle.root.style.top);
var left=parseInt(handle.root.style.left);
handle.root.onDragStart(left,top,e.pageX,e.pageY);
handle.lastMouseX=e.pageX;
handle.lastMouseY=e.pageY;
document.onmousemove=Drag.drag;
document.onmouseup=Drag.end;
}
},
"start":function(e){
var handle=Drag.obj=this;
e=Drag.fixEvent(e);
var top=parseInt(handle.root.style.top);
var left=parseInt(handle.root.style.left);
//alert(left)
//一般情况下 left top 在初始的时候都为0
handle.root.onDragStart(left,top,e.pageX,e.pageY);
handle.lastMouseX=e.pageX;
handle.lastMouseY=e.pageY;
document.onmousemove=Drag.drag;
document.onmouseup=Drag.end;
return false;
},
"drag":function(e){//这里的this为document 所以拖动对象只能保存在Drag.obj里
e=Drag.fixEvent(e);
var handle=Drag.obj;
var mouseY=e.pageY;
var mouseX=e.pageX;
var top=parseInt(handle.root.style.top);
var left=parseInt(handle.root.style.left);//这里的top和left是handle.root距离浏览器边框的上边距和左边距
var currentLeft,currentTop;
currentLeft=left+mouseX-handle.lastMouseX;
currentTop=top+(mouseY-handle.lastMouseY);
//上一瞬间的上边距加上鼠标在两个瞬间移动的距离 得到现在的上边距
handle.root.style.left=currentLeft +"px";
handle.root.style.top=currentTop+"px";
//更新当前的位置
handle.lastMouseX=mouseX;
handle.lastMouseY=mouseY;
//保存这一瞬间的鼠标值 用于下一次计算位移
handle.root.onDrag(currentLeft,currentTop,e.pageX,e.pageY);//调用外面对应的函数
return false;
},
"end":function(){
document.onmousemove=null;
document.onmouseup=null;
Drag.obj.root.onDragEnd(parseInt(Drag.obj.root.style.left),parseInt(Drag.obj.root.style.top));
Drag.obj=null;
},
"fixEvent":function(e){//格式化事件参数对象
if(typeof e=="undefined")e=window.event;
if(typeof e.layerX=="undefined")e.layerX=e.offsetX;
if(typeof e.layerY=="undefined")e.layerY=e.offsetY;
if(typeof e.pageX == "undefined")e.pageX = e.clientX + document.body.scrollLeft - document.body.clientLeft;
if(typeof e.pageY == "undefined")e.pageY = e.clientY + document.body.scrollTop - document.body.clientTop;
return e;
}
};
</script>
<script type="text/javascript">
//------------------------Utility------------------------
function findPosX(obj) {//辅助函数 得到元素左边与浏览器左边的边距
var curleft = 0;
if (obj && obj.offsetParent) {
while (obj.offsetParent) {
curleft += obj.offsetLeft;
obj = obj.offsetParent;
}
} else if (obj && obj.x) curleft += obj.x;
return curleft;// + document.body.scrollLeft - document.body.clientLeft;
}
function findPosY(obj) {//辅助函数 得到元素上边与浏览器上边的边距
var curtop = 0;
if (obj && obj.offsetParent) {
while (obj.offsetParent) {
curtop += obj.offsetTop;
obj = obj.offsetParent;
}
} else if (obj && obj.y) curtop += obj.y;
return curtop;// + document.body.scrollTop - document.body.clientTop;
}
var dragGhost = document.createElement("div");
dragGhost.style.border = "dashed 1px #CCCCCC";
dragGhost.style.background = "white";
dragGhost.style.display = "none";
dragGhost.style.margin = "10px";
var container;
var columns = [];
//------------------------Start Here------------------------
window.onload = function(){
container = document.getElementById("container");
for(var i=0;i<container.childNodes.length;i++){
if(container.childNodes[i].className == "column"){//筛选出所有的列 ff下的childNodes不可靠 :/
columns.push(container.childNodes[i]);
}
}
for(var i=0;i<columns.length;i++){
var column = columns[i];
for(var j=0;j<column.childNodes.length;j++){
var item = column.childNodes[j];
if(item.className == "item"){
item.column = column;//给每个拖拽对象要指明它属于哪一列 而且这个属性会随着拖动而更新的
new dragItem(item);
}
}
}
}
var isIE = document.all;
//------------------------Drag Item------------------------
function dragItem(item){
//item实际上是dragBody(拖动的时候移动的整体)
//在这里需要根据item找到handle(能够拖动的把手)
var handle;
for(var i=0;i<item.childNodes.length;i++){
if(item.childNodes[i].nodeName.toLowerCase() == "h3"){
handle = item.childNodes[i];
break;
}
}
if(!handle)return;
Drag.init(handle,item);
item.onDragStart = function(left,top,mouseX,mouseY){
//开始拖动的时候设置透明度
this.style.opacity = "0.5";
this.style.filter = "alpha(opacity=50)";
dragGhost.style.height = (isIE?this.offsetHeight:this.offsetHeight - 2) + "px";
//this指的是item
this.style.width = this.offsetWidth + "px";//因为初始的width为auto
this.style.left = (findPosX(this) - 5) + "px";
this.style.top = (findPosY(this) - 5) + "px";
this.style.position = "absolute";
//将ghost插入到当前位置
dragGhost.style.display = "block";
this.column.insertBefore(dragGhost,this);
//记录每一列的左边距 在拖动过程中判断拖动对象所在的列会用到
this.columnsX = [];
for(var i=0;i<columns.length;i++){
this.columnsX.push(findPosX(columns[i]));
}
}
item.onDrag = function(left,top,mouseX,mouseY){
//先要判断在哪一列移动
var columnIndex = 0;
for(var i=0;i<this.columnsX.length;i++){
if((left + this.offsetWidth/2) > this.columnsX[i]){
columnIndex = i;
}
}
//如果columnIndex在循环中没有被赋值 则表示当前拖动对象在第一列的左边
//此时也把它放到第一列
var column = columns[columnIndex];
if(this.column != column){
//之前拖动对象不在这个列
//将ghost放置到这一列的最下方
column.appendChild(dragGhost);
this.column = column;
}
//然后在判断放在这一列的什么位置
var currentNode = null;
for(var i=0;i<this.column.childNodes.length;i++){
if(this.column.childNodes[i].className == "item"
&& this.column.childNodes[i] != this//不能跟拖动元素自己比较 否则不能在本列向下移动
&& top < findPosY(this.column.childNodes[i])){//从上到下找到第一个比拖动元素的上边距大的元素
currentNode = this.column.childNodes[i];
break;
}
}
if(currentNode)
this.column.insertBefore(dragGhost,currentNode);
else//拖到最下边 没有任何一个元素的上边距比拖动元素的top大 则添加到列的最后
this.column.appendChild(dragGhost);
}
item.onDragEnd = function(left,top,mouseX,mouseY){
this.style.opacity = "1";
this.style.filter = "alpha(opacity=100)";
this.column.insertBefore(this,dragGhost);
this.style.position = "static";
this.style.display = "block";
this.style.width = "auto";
dragGhost.style.display = "none";
}
}
</script>
<style type="text/css">
#container{width:800px;}
.column{width:200px;border:solid 1px #CCCCCC;background:#FCFCFC;padding:0px;float:left;margin:10px;}
.item{text-align:center;padding:0px;margin:10px;border:solid 1px #CCCCCC;background:white;width:auto;}
.item h3{margin:0px;height:20px;border-bottom:solid 1px #CCCCCC;background:#CCCCCC;color:white;cursor:move;}
</style>
</head>
<body>
<div id="container">
<div class="column">
<div class="item">
<h3>Header</h3>
<p>column1 item1</p>
</div>
<div class="item">
<h3>Header</h3>
<p>column1 item2<br />Some text here, so that the height is different!</p>
</div>
<div class="item">
<h3>Header</h3>
<p>column1 item3</p>
</div>
<div class="item">
<h3>Header</h3>
<p>column1 item4</p>
</div>
</div>
<div class="column" style="width:300px;">
<div class="item">
<h3>Header</h3>
<p>column2 item1</p>
</div>
<div class="item">
<h3>Header</h3>
<p>column2 item2</p>
</div>
<div class="item">
<h3>Header</h3>
<p>column2 item3<br />Some text here, so that the height is different!</p>
</div>
<div class="item">
<h3>Header</h3>
<p>column2 item4<br />Some text here, so that the height is different!</p>
</div>
</div>
<div class="column">
<div class="item">
<h3>Header</h3>
<p>column3 item1</p>
</div>
<div class="item">
<h3>Header</h3>
<p>column3 item2</p>
</div>
<div class="item">
<h3>Header</h3>
<p>column3 item3</p>
</div>
<div class="item">
<h3>Header</h3>
<p>column3 item4</p>
</div>
</div>
</div>
</body>
</html>