最近几天都在忙找工作, 网投啊, 招聘会啊, 闲下来了, 就看下Javascript如何实现拖拽, 还想过一下关于Firefox和IE解释上差异问题.
在http://www.blueidea.com/上找到拖拽的相关代码, 看了一半, 就在他的基础上按着自己的思路走了下去(人总有想法嘛, 嘿嘿~), 总算实现了像GOOGLE/IG那样的拖拽效果, 在Firefox和IE上都能正常运行, 就是透明的CSS那还没解决掉... 成果不敢独占, 即使其实没那么几个人看我的BLOG.....嘿嘿, 不过我相信我牛起来的时候, 看这些东西也能触发一些灵感吧~! 现在把代码都贴出来, 如果能帮到路过的兄弟们, 那也算是我的荣幸! 解释我不就多说了, 因为很多地方我都注释了啦. 那写/* 不用empty后封的代码 */尽管忽略, 那些是我编写过程中更改了解决方案后不要的代码, 怕以后后悔了, 所以没删除, 只是注释掉.
- // DragDrop.JS
- // 全局变量, 临时存放正在被拖拽的物体
- var dragObject = null;
- // 全局变量, 存放鼠标坐标与鼠标所选元素的左上角坐标之间的偏移量
- var mouseOffset = null;
- // 指定鼠标移动事件函数为mouseMove
- document.onmousemove = mouseMove;
- // 指定鼠标按下事件函数为mouseDown
- document.onmousedown = mouseDown;
- // 指定鼠标释放事件函数为mouseUp
- document.onmouseup = mouseUp;
- // 表明鼠标是否被按下的标志值
- var iMouseDown = false;
- // 保存可DROP目标的堆栈
- var dropTargets = [];
- // 与dragObject同宽同高, 但没内容的DIV, 用于预示效果
- var tempDiv = document.createElement('div');
- // 自定义Number类型的函数NaN0, 如果自己不是数字, 则返回0
- // , 是数字返回自己
- Number.prototype.NaN0=function()
- {
- return isNaN(this)? 0: this;
- }
- // 保存所指向的元素当前所属的可DRAG目标
- var curTarget = null;
- // 保存所指向的元素的原始可DRAG目标
- var lastTarget = null;
- // 定义获取鼠标坐标函数
- function mouseCoords(ev)
- {
- // Firefox以event.pageX和event.pageY来代表鼠标相应于文档左上角的位置.
- // 如果你有一个500*500的窗口,而且你的鼠标在正中间,那么paegX和pageY将是
- // 250,当你将页面往下滚动500px,那么pageY将是750.此时pageX不变,还是250.
- // 此判断为判断ev.pageX || ev.pageY 是否不为空, 不为空代表是FireFox
- // 等浏览器
- if(ev.pageX || ev.pageY)
- {
- return {x:ev.pageX, y:ev.pageY};
- }
- // 如果不是FireFox那么就是IE了, 按照Window编程风格
- // MSIE将event.clientX与event.clientY来代表鼠标
- // 与ie窗口的位置,并不是文档.当我们有一个500*500的窗
- // 口,鼠标在正中间,那么clientX与clientY也是250,如
- // 果你垂直滚动窗口到任何位置,clientY仍然是250,因为
- // 相对ie窗口并没有变化.想得到正确的结果,我们必须加入
- // scrollLeft与scrollTop这两个相对于文档鼠标位置的属性.
- // 最后,由于MSIE并没有0,0的文档起始位置,因为通常会设置2px
- // 的边框在周围,边框的宽度包含在document.body.clientLeft
- // 与clientTop这两个属性中,我们再加入这些到鼠标的位置中
- return{
- x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
- y:ev.clientY + document.body.scrollTop - document.body.clientTop
- };
- }
- // 定义mouseDown函数
- function mouseDown(ev)
- {
- // 同mouseMove(ev)
- ev = ev || window.event;
- // IE和FireFox为首等浏览器获取鼠标所指向的元素的不同方法
- // IE使用event.srcElement来获取
- // FireFox等使用event.target
- var target = ev.target || ev.srcElement;
- // 检查所指元素是否有定义onmousedown和属性DragObj(后面将为可拖动物体添加此属性)
- if(target.onmousedown || target.getAttribute('DragObj'))
- {
- lastTarget = dragObject.offsetParent;
- return false;
- }
- // 标志鼠标已经按下
- iMouseDown = true;
- }
- /*
- // 给指定的item指定onmousedown函数
- function makeClickable(item)
- {
- // 如果item为空 返回
- if(!item) return;
- // 为item指定onmousedown函数
- item.onmousedown = function(ev)
- {
- // 这里为函数内容
- }
- }
- */
- // 定义获取鼠标鼠标坐标与鼠标所选元素的左上角坐标之间的偏移量的函数
- function getMouseOffset(target, ev)
- {
- // 同mouseMove(ev)
- ev = ev || window.event;
- // 获取鼠标所指向的元素的坐标
- var docPos = getPosition(target);
- // 获取鼠标坐标
- var mousePos = mouseCoords(ev);
- // 鼠标坐标 - 元素坐标 = 偏移坐标
- // 因为鼠标坐标一定 > 元素坐标, 才能指向元素
- return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
- }
- // 定义获取元素坐标函数
- function getPosition(e)
- {
- // 临时变量left和top, 用于存储元素距离浏览器浏览区域
- // 左上角的left和top值
- var left = 0;
- var top = 0;
- // 因为元素可能包含于一个或多个父容器元素中,
- // 用e.offsetLeft和e.offsetTop获取的left和top
- // 值都是相对于父元素而言的, 所以, 要获取元素真正的
- // left和top, 就要循环检测元素是否有父元素包含着它
- // 如果有把父元素的left和top都累加到left和top中
- // 最后把自己刷新成父元素, 继续下次循环
- while (e.offsetParent) // 元素存在父元素进入循环
- {
- // 把父元素的offsetLeft 累加到left中
- left += e.offsetLeft +
- (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0);
- // 把父元素的offsetTop 累加到top中
- top += e.offsetTop +
- (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0);
- e = e.offsetParent; // 获取自己的父元素
- }
- left += e.offsetLeft;
- top += e.offsetTop;
- // 不在存在父元素, 但最后一次的父元素还没累加进left, 固执行此步
- // 如果元素style不为空, 则把他的左边框阔度也+到left
- left += e.offsetLeft +
- (e.currentStyle?(parseInt(e.currentStyle.borderLeftWidth)).NaN0():0);
- // 不在存在父元素, 但最后一次的父元素还没累加进top, 固执行此步
- // 如果元素style不为空, 则把他的上边框阔度也+到top
- top += e.offsetTop +
- (e.currentStyle?(parseInt(e.currentStyle.borderTopWidth)).NaN0():0);
- return {x:left, y:top};
- }
- // 检测item1是否包含item2
- function isExists(item1, item2)
- {
- for (var i = 0; i < item1.childNodes.length; i++)
- {
- if (item1.childNodes[i] == item2)
- return true;
- }
- return false;
- }
- // 定义鼠标移动事件函数
- function mouseMove(ev)
- {
- // 获取鼠标事件的event对象, 对于IE, 该event存储在window.event中
- // 对于以FireFox为首的其他浏览器, event被相应的自定义函数获取
- // 这样让ev在所有浏览器下获取了event事件,在Firefox下"||window.event"将不起作用,
- // 因为ev已经有了赋值.在MSIE下ev是空的,所以ev将设置为window.event
- ev = ev || window.event;
- // 获取鼠标坐标
- var mousePos = mouseCoords(ev);
- // 遍历每个可DROP目标
- // 以下可以对mousePos操作来获取坐标
- // 判断dragObject是否为空, 不空即已指向一个元素
- // 在已经选定了元素并且在移动的时候, 改变元素的
- // 位置信息: 绝对定位, 元素坐标 = 鼠标坐标 - 偏移坐标
- if(dragObject)
- {
- if (isExists(lastTarget, dragObject))
- {
- lastTarget.removeChild(dragObject);
- document.getElementById('alloutside').appendChild(dragObject);
- }
- dragObject.style.position = 'absolute';
- dragObject.style.top = mousePos.y - mouseOffset.y;
- dragObject.style.left = mousePos.x - mouseOffset.x;
- dragObject.style.filter = 'alpha(opacity=50)';
- tempDiv.style.height = dragObject.style.height;
- tempDiv.style.width = dragObject.style.width;
- tempDiv.style.color = dragObject.style.color;
- tempDiv.style.marginTop = dragObject.style.marginTop;
- tempDiv.style.marginBottom = dragObject.style.marginBottom;
- tempDiv.style.marginLeft = dragObject.style.marginLeft;
- tempDiv.style.marginRight = dragObject.style.marginRight;
- tempDiv.style.backgroundColor = dragObject.style.backgroundColor;
- tempDiv.style.top = dragObject.style.top;
- tempDiv.style.left = dragObject.style.left;
- tempDiv.style.paddingTop = dragObject.style.paddingTop;
- tempDiv.style.paddingBottom = dragObject.style.paddingBottom;
- tempDiv.style.paddingLeft = dragObject.style.paddingLeft;
- tempDiv.style.paddingRight = dragObject.style.paddingRight;
- tempDiv.style.filter = 'alpha(opacity=50)';
- tempDiv.innerHTML = dragObject.innerHTML;
- tempDiv.setAttribute('used', '1');
- // 遍历每个可DROP目标
- for (var i = 0; i < dropTargets.length; i++)
- {
- // 获取可DROP目表存放在临时curTarget中
- var curTar = dropTargets[i];
- var targPos = getPosition(curTar);
- var targWidth = parseInt(curTar.offsetWidth);
- var targHeight = parseInt(curTar.offsetHeight);
- // 检测鼠标坐标是否大于某个可DROP目标坐标且不超出可DROP目标的范围.
- if ((mousePos.x > targPos.x) &
- (mousePos.x < (targPos.x + targWidth)) &
- (mousePos.y > targPos.y) &
- (mousePos.y < (targPos.y + targHeight)))
- {
- // dragObject在当前可DROP目标上
- var height = getPosition(curTar).y;
- var index = 0;
- var nextNode = curTar.childNodes[0];
- for (var i = 0; i < curTar.childNodes.length; i++)
- {
- var item = curTar.childNodes[i];
- if (item.nodeName.indexOf("DIV") != 0)
- {
- nextNode = item.nextSibling;
- index++;
- continue;
- }
- if (item.getAttribute('used'))
- {
- nextNode = item.nextSibling;
- index++;
- continue;
- }
- /* 不用empty后封的代码
- if (item.getAttribute('empty'))
- {
- curTar.insertBefore(tempDiv, item);
- break;
- }*/
- height += item.offsetHeight + parseInt(item.style.marginTop).NaN0() + parseInt(item.style.marginBottom).NaN0();
- if (mousePos.y > height)
- {
- index++;
- nextNode = item.nextSibling;
- }
- else
- {
- /* 不用empty后封的代码
- if (nextNode)*/
- curTar.insertBefore(tempDiv, nextNode);
- /* 不用empty后封的代码
- else
- curTar.appendChild(tempDiv);*/
- break;
- }
- }
- //鼠标坐标大于所有childNode的高的和或没有任何childNode
- if (index == curTar.childNodes.length || curTar.childNodes.length == 0)
- {
- /* 不用empty后封的代码
- if (nextNode)
- curTar.insertBefore(tempDiv, nextNode);
- else*/
- curTar.appendChild(tempDiv);
- }
- break;
- }
- }
- return false;
- }
- }
- // 定义鼠标释放时执行的函数
- function mouseUp(ev)
- {
- if (dragObject)
- {
- // 同mouseMove(ev)
- ev = ev || window.event;
- // 获取鼠标坐标
- var mousePos = mouseCoords(ev);
- var flag = 0;
- // 遍历每个可DROP目标
- for (var i = 0; i < dropTargets.length; i++)
- {
- // 获取可DROP目表存放在临时curTarget中
- curTarget = dropTargets[i];
- var targPos = getPosition(curTarget);
- var targWidth = parseInt(curTarget.offsetWidth);
- var targHeight = parseInt(curTarget.offsetHeight);
- // 检测鼠标坐标是否大于某个可DROP目标坐标且不超出可DROP目标的范围.
- if ((mousePos.x > targPos.x) &
- (mousePos.x < (targPos.x + targWidth)) &
- (mousePos.y > targPos.y) &
- (mousePos.y < (targPos.y + targHeight)))
- {
- // dragObject was dropped onto curTarget!
- var height = getPosition(curTarget).y;
- var index = 0;
- var nextNode = curTarget.childNodes[0];
- for (var i = 0; i < curTarget.childNodes.length; i++)
- {
- var item = curTarget.childNodes[i];
- if (item.nodeName.indexOf("DIV") != 0)
- {
- nextNode = item.nextSibling;
- index++;
- continue;
- }
- if (item.getAttribute('used'))
- {
- nextNode = item.nextSibling;
- index++;
- continue;
- }
- /* 不用empty后封的代码
- if (item.getAttribute('empty'))
- {
- curTarget.insertBefore(dragObject, item);
- break;
- }*/
- height += item.offsetHeight + parseInt(item.style.marginTop).NaN0() + parseInt(item.style.marginBottom).NaN0();
- if (mousePos.y > height)
- {
- index++;
- nextNode = item.nextSibling;
- }
- else
- {
- /* 不用empty后封的代码
- if (nextNode)*/
- curTarget.insertBefore(dragObject, nextNode);
- /* 不用empty后封的代码
- else
- curTarget.appendChild(dragObject);*/
- break;
- }
- }
- //鼠标坐标大于所有childNode的高的和或没有任何childNode
- if (index == curTarget.childNodes.length || curTarget.childNodes.length == 0)
- {
- /* 不用empty后封的代码
- if (nextNode)
- curTarget.insertBefore(dragObject, nextNode);
- else*/
- curTarget.appendChild(dragObject);
- }
- dragObject.style.position = '';
- dragObject.style.top = null;
- dragObject.style.left = null;
- lastTarget = null;
- curTarget = null;
- break;
- }
- else
- flag++;
- }
- if (flag == dropTargets.length)
- {
- dragObject.style.position = '';
- dragObject.style.top = null;
- dragObject.style.left = null;
- /* 不用empty后封的代码
- var indexLastDiv = lastTarget.childNodes.length - 1;
- var lastNode = lastTarget.childNodes[indexLastDiv];
- while (lastNode.nodeName.indexOf('DIV') != 0)
- {
- indexLastDiv--;
- lastNode = lastTarget.childNodes[indexLastDiv];
- }
- if (lastNode.getAttribute('used'))
- lastNode = lastTarget.childNodes[indexLastDiv - 1];
- lastTarget.insertBefore(dragObject, lastNode);
- */
- lastTarget.appendChild(dragObject);
- lastTarget = null;
- curTarget = null;
- }
- // 清空拖拽的东西
- dragObject.style.filter = '';
- dragObject = null;
- tempDiv.setAttribute('used', '0');
- tempDiv.parentNode.removeChild(tempDiv);
- iMouseDown = false;
- }
- }
- // 定义使元素能Drag(拖)的函数
- function makeDraggable(item)
- {
- // 如果元素为空
- if(!item) return;
- // 定义元素的onmousedown事件函数
- item.onmousedown = function(ev)
- {
- // 把item赋给dragObject
- dragObject = this.parentNode;
- lastTarget = dragObject.parentNode;
- // 获取鼠标偏移坐标
- mouseOffset = getMouseOffset(this, ev);
- return false;
- }
- }
- // 把dropTarget添加到可DROP堆栈中
- function addDropTarget(dropTarget)
- {
- dropTargets.push(dropTarget);
- }
随手写的DEMO.HTML
- <html>
- <script>
- function init()
- {
- makeDraggable(document.getElementById('divtest1'));
- makeDraggable(document.getElementById('divtest2'));
- makeDraggable(document.getElementById('divtest3'));
- addDropTarget(document.getElementById('divtest4'));
- addDropTarget(document.getElementById('divtest5'));
- addDropTarget(document.getElementById('divtest6'));
- }
- </script>
- <body onload="init();">
- <script language="JavaScript" type="text/javascript" src="DragDrop.Js">
- </script>
- <div id="divtest4" style="position:absolute; left:1%; top:10px; width: 32%; padding-bottom:5px; padding-top:5px; background-color:#FFFF00; height:100px; height:auto!important;">
- <div style="width: 98%; margin-bottom:5px; margin-left:1%; height:50px; background-color:#FF0000;">
- <div id="divtest1" style="width: 100%; position:relative; top:0px; height:20px; background-color:#0000FF;">
- </div>
- 1
- </div>
- <!--<div style="height:20px;" empty="1"></div>-->
- </div>
- <div id="divtest5" style="position:absolute; left:34%; top:10px; width: 32%; padding-bottom:5px; padding-top:5px; background-color:#FFFF00; height:100px; height:auto!important;">
- <div style="width: 98%; margin-bottom:5px; margin-left:1%; height:50px; background-color:#FF0000;">
- <div id="divtest2" style="width: 100%; position:relative; top:0px; height:20px; background-color:#0000FF;">
- </div>
- 2
- </div>
- <!--<div style="height:20px;" empty="1"></div>-->
- </div>
- <div id="divtest6" style="position:absolute; left:67%; top:10px; width: 32%; padding-bottom:5px; padding-top:5px; background-color:#FFFF00; height:100px; height:auto!important;">
- <div style="width: 98%; margin-bottom:5px; margin-left:1%; height:50px; background-color:#FF0000;">
- <div id="divtest3" style="width: 100%; position:relative; top:0px; height:20px; background-color:#0000FF;">
- </div>
- 3
- </div>
- <!--<div style="height:20px;" empty="1"></div>-->
- </div>
- <div id="alloutside" style="position:absolute; left:0%; top:0%; width: 32%;">
- </div>
- </body>
- </html>
就这两个东西, 原本是想搞这个出来了, 写个类试IG的RSS阅读器的, 其实也算是把我之前的一个项目改成用JS实现罢了, 呵呵, 有时间我会写下去! 想一下一个OA系统, 如果要删除东西, 点删除, 没趣了吧, 我用拖拽的, 拖到垃圾桶去, 用AJAX更新数据, 牛了点吧? 没有? 那算啦~~~
过往一直都用alert来调试javascript, 大家不要笑哦, 我也是前几天才发现原来vs 2005 也可以调试js的, 但是只针对IE浏览器(一般不爽ING), 总比之前用alert来调试爽啊...在写这东西的时候, 发现要兼容firefox, vs 2005 不符合需求(-_-关需求啥事呢? 不要问, 随口说的...), 在网上搜了一大轮后, 发现一个东东叫firebug, 是firefox的插件, 可以用来调试javascript, 这下就完全爽了!
说下我是怎么写的, 先在txt或者vs 2005编写javascript, 然后直接用firebug来调试, 当想使用什么属性但又不知道是否存在这属性的时候, 我就在firebug中点开相应的对象, 看下有什么属性, 这还不行, 因为有些东西是firefox支持但IE不支持的, 有些又是IE支持但firefox不知道的, 晕了吧? 不过一般都能找到不同的属性名代表同一个属性, 找到属性后就用这种方法a = (obj.prop1 || obj.prop2)来获取, 其中prop1是firefox支持但IE不支持, prop2是IE支持但firefox不支持, 这样的话就可以在IE的时候获取prop2在firefox下获取prop1了. 要看IE支持什么属性, 用vs 2005调试的时候点开对象自己看咯. 做这个东西不只是懂了拖拽, 更是懂了另外一个东东, 就是怎样更有效率地写Javascript代码. 先在firefox下调试, 然后在ie下磨合, 这样比较适合!
还要写作业~嘿嘿~作业也放上来哦~呵呵
www.blueidea.com和www.okajax.com都是好网站哦~值得收藏