能实现鼠标拖放当然很好,例如IE的实现方法就不错,简单易用,但是只适用于IE,对于其他浏览器则,由于不支持拖拽的时间,需要我们自己去定义方法,使用mouse的低级事件来进行模拟。UGLY也没有办法,目前漂亮的实现拖放功能的是google的个性化主页和netvibes
简单介绍一下IE的方式:
IE建立了完善的Drag-Drop事件机制:
当某Dragable对象被drag时,事件激发属性是:dragstart->drag(一直持续)->dragend(停止) ,注意这些事件针对被Drag的对象。
对于Drag的目标对象,当被拽对象进入目标时候,dragenter被激发,然后只要被拽对象还在目标范围内,dragover就会一直继续激发(同时drag事件也会持续激发),这时如果放下/drop,则drop事件被激发,如果没有放下,而被拽离目标对象时则dragleave被激发。
对于默认本来不是合法的目标对象,可以通过改变dragenter和dragover的默认属性来使之成为合法的目标。
IE5.0以后,可以通过dataTransfer来进行拖拽对象的数据传递。
该对象除了setter/getter之外还有两个重要的属性:针对拖拽对象的effectAllowed(uninitiallized /none/copy/link/move/copyLink/copyMove/linkMove/all)和针对目标对象的dropEffect (none/move/copy/link)
另外,对于IE5.5以上,基本上对于所有的HTML元素,都可以使用dragDrop()方法使得本来不是拖拽对象的元素可以变为可拖拽对象(即可以激发dragstart, drag, dragend事件)
通用浏览器的方式:
可惜的是,没有很好的跨浏览器解决办法,(DOM3遥遥无期,XUL只适用于Mozilla),只能采取模拟的方式。思路是利用鼠标事件的低级方法,以及事件的鼠标位置和Div的style方法,来控制Div的位置。也就是在oDiv.style.left/oDiv.style.top和oEvent.clinetX/oEvent.clinetY上做文章。以及运用oDiv.offsetXXX诸方法。
让一个Div跟随鼠标移动,首先定位出初始时(即mousedown事件)鼠标初始点(clientX/Y)与div左上角(offsetLeft,offsetTop)之间的距离。
然后当鼠标移动时(mousemove事件),把div的位置(style.left/style.top)置为鼠标当前点(clientX/Y)与前面初始时获得的距离(DiffX/Y)之差。
Netvibes(google)的Drag.js:
预备知识:JSON与JavaScript的iterals:
ECMAScript v3规范中,变量可以直接为作为对象字面量(object literal) 如:
Var foo ={ x:1, y:2 } // An object initializer
object literals自 JavaScript 1.2 就被支持,但直到ECMAScript v3才成为标准。,JSON,使用了这种对象定义方法,JSON主要的好处时可以把对象通过纯文本来传递(好像XML),但是不需要XML parser,直接使用JavaScript的evel语句,客户端就可以得到对象
参考:
http://www.crockford.com/JSON/index.html
http://developer.yahoo.net/common/json.html
http://www.quirksmode.org/blog/archives/2005/12/the_ajax_respon.html
netvibes的拖拽界面实现的很不错,它和google的个性化主页实现的原理是一样的。其中实现DragDorp功能的主要是由Drag.js(http://www.netvibes.com/js/Drag.js)。
拖拽divModuleHeader时,首先mousedown事件被触发调用Drag.start, Drag.start 会调用divMoudle的onDragStart方法,并设置mousemove/moseup事件的处理函数。
然后mousemove事件触发Drag.drag,它会调用divModule的onDrag方法
然后mouseup事件触发Drag.end,它会调用divModule的onDragEnd方法
divMoudle的几个方法onDragStart,onDrag,onDragEnd,主要为了解决divMoudleGhost(指divMoudle下面红色的虚线标示框)的创建,在页面中的位置,移动。