/* Copyright (c) 2004-2006, The Dojo Foundation All Rights Reserved. Licensed under the Academic Free License version 2.1 or above OR the modified BSD license. For more information on Dojo licensing, see: http://dojotoolkit.org/community/licensing.shtml */ dojo.provide("dojo.dnd.HtmlDragAndDrop"); dojo.require("dojo.dnd.HtmlDragManager"); dojo.require("dojo.dnd.DragAndDrop"); dojo.require("dojo.html.*"); dojo.require("dojo.html.display"); dojo.require("dojo.html.util"); dojo.require("dojo.html.selection"); dojo.require("dojo.html.iframe"); dojo.require("dojo.lang.extras"); dojo.require("dojo.lfx.*"); dojo.require("dojo.event.*"); dojo.declare("dojo.dnd.HtmlDragSource", dojo.dnd.DragSource, { dragClass: "", // CSS classname(s) applied to node when it is being dragged onDragStart: function(){ var dragObj = new dojo.dnd.HtmlDragObject(this.dragObject, this.type); if(this.dragClass){ dragObj.dragClass = this.dragClass; } if(this.constrainToContainer){ dragObj.constrainTo(this.constrainingContainer || this.domNode.parentNode); } return dragObj; }, setDragHandle: function(node){ node = dojo.byId(node); dojo.dnd.dragManager.unregisterDragSource(this); this.domNode = node; dojo.dnd.dragManager.registerDragSource(this); }, setDragTarget: function(node){ this.dragObject = node; }, constrainTo: function(container){ this.constrainToContainer = true; if(container){ this.constrainingContainer = container; } }, /* * * see dojo.dnd.DragSource.onSelected */ onSelected: function(){ for(var i=0; i this.constraints.maxX) { x = this.constraints.maxX; } if (y > this.constraints.maxY) { y = this.constraints.maxY; } } this.setAbsolutePosition(x, y); dojo.event.topic.publish('dragMove', { source: this } ); }, /** * Set the position of the drag clone. (x,y) is relative to . */ setAbsolutePosition: function(x, y){ // The drag clone is attached to document.body so this is trivial if(!this.disableY) { this.dragClone.style.top = y + "px"; } if(!this.disableX) { this.dragClone.style.left = x + "px"; } }, /** * If the drag operation returned a success we remove the clone of * ourself from the original position. If the drag operation returned * failure we slide back over to where we came from and end the operation * with a little grace. */ onDragEnd: function(e){ switch(e.dragStatus){ case "dropSuccess": dojo.html.removeNode(this.dragClone); this.dragClone = null; break; case "dropFailure": // slide back to the start var startCoords = dojo.html.getAbsolutePosition(this.dragClone, true); // offset the end so the effect can be seen var endCoords = { left: this.dragStartPosition.x + 1, top: this.dragStartPosition.y + 1}; // animate var anim = dojo.lfx.slideTo(this.dragClone, endCoords, 300); var dragObject = this; dojo.event.connect(anim, "onEnd", function(e){ // pause for a second (not literally) and disappear // dojo.lang.setTimeout(function() { dojo.html.removeNode(dragObject.dragClone); // Allow drag clone to be gc'ed dragObject.dragClone = null; // }, // 50); }); anim.play(); break; } dojo.event.topic.publish('dragEnd', { source: this } ); }, constrainTo: function(container){ this.constrainToContainer=true; if(container){ this.constrainingContainer = container; }else{ this.constrainingContainer = this.domNode.parentNode; } } }, function(node, type){ this.domNode = dojo.byId(node); this.type = type; this.constrainToContainer = false; this.dragSource = null; // this.register(); dojo.dnd.DragObject.prototype.register.call(this); } ); dojo.declare("dojo.dnd.HtmlDropTarget", dojo.dnd.DropTarget, { vertical: false, onDragOver: function(e){ if(!this.accepts(e.dragObjects)){ return false; } // cache the positions of the child nodes this.childBoxes = []; for(var i = 0, child; i < this.domNode.childNodes.length; i++){ child = this.domNode.childNodes[i]; if(child.nodeType != dojo.html.ELEMENT_NODE){ continue; } var pos = dojo.html.getAbsolutePosition(child, true); var inner = dojo.html.getBorderBox(child); this.childBoxes.push({top: pos.y, bottom: pos.y+inner.height, left: pos.x, right: pos.x+inner.width, height: inner.height, width: inner.width, node: child}); } // TODO: use dummy node return true; }, _getNodeUnderMouse: function(e){ // find the child for(var i = 0, child; i < this.childBoxes.length; i++){ with(this.childBoxes[i]){ if (e.pageX >= left && e.pageX <= right && e.pageY >= top && e.pageY <= bottom){ return i; } } } return -1; }, createDropIndicator: function(){ this.dropIndicator = document.createElement("div"); with(this.dropIndicator.style){ position = "absolute"; zIndex = 999; if(this.vertical){ borderLeftWidth = "1px"; borderLeftColor = "black"; borderLeftStyle = "solid"; height = dojo.html.getBorderBox(this.domNode).height + "px"; top = dojo.html.getAbsolutePosition(this.domNode, true).y + "px"; }else{ borderTopWidth = "1px"; borderTopColor = "black"; borderTopStyle = "solid"; width = dojo.html.getBorderBox(this.domNode).width + "px"; left = dojo.html.getAbsolutePosition(this.domNode, true).x + "px"; } } }, onDragMove: function(e, dragObjects){ var i = this._getNodeUnderMouse(e); if(!this.dropIndicator){ this.createDropIndicator(); } var gravity = this.vertical ? dojo.html.gravity.WEST : dojo.html.gravity.NORTH; var hide = false; if(i < 0){ if(this.childBoxes.length){ var before = (dojo.html.gravity(this.childBoxes[0].node, e) & gravity); if(before){ hide = true; } }else{ var before = true; } }else{ var child = this.childBoxes[i]; var before = (dojo.html.gravity(child.node, e) & gravity); if(child.node === dragObjects[0].dragSource.domNode){ hide = true; }else{ var currentPosChild = before ? (i>0?this.childBoxes[i-1]:child) : (i