if(!dojo._hasResource["dojo.dnd.Manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. dojo._hasResource["dojo.dnd.Manager"] = true; dojo.provide("dojo.dnd.Manager"); dojo.require("dojo.dnd.common"); dojo.require("dojo.dnd.autoscroll"); dojo.require("dojo.dnd.Avatar"); dojo.declare("dojo.dnd.Manager", null, { // summary: the manager of DnD operations (usually a singleton) constructor: function(){ this.avatar = null; this.source = null; this.nodes = []; this.copy = true; this.target = null; this.canDropFlag = false; this.events = []; }, // avatar's offset from the mouse OFFSET_X: 16, OFFSET_Y: 16, // methods overSource: function(source){ // summary: called when a source detected a mouse-over conditiion // source: Object: the reporter if(this.avatar){ this.target = (source && source.targetState != "Disabled") ? source : null; this.avatar.update(); } dojo.publish("/dnd/source/over", [source]); }, outSource: function(source){ // summary: called when a source detected a mouse-out conditiion // source: Object: the reporter if(this.avatar){ if(this.target == source){ this.target = null; this.canDropFlag = false; this.avatar.update(); dojo.publish("/dnd/source/over", [null]); } }else{ dojo.publish("/dnd/source/over", [null]); } }, startDrag: function(source, nodes, copy){ // summary: called to initiate the DnD operation // source: Object: the source which provides items // nodes: Array: the list of transferred items // copy: Boolean: copy items, if true, move items otherwise this.source = source; this.nodes = nodes; this.copy = Boolean(copy); // normalizing to true boolean this.avatar = this.makeAvatar(); dojo.body().appendChild(this.avatar.node); dojo.publish("/dnd/start", [source, nodes, this.copy]); this.events = [ dojo.connect(dojo.doc, "onmousemove", this, "onMouseMove"), dojo.connect(dojo.doc, "onmouseup", this, "onMouseUp"), dojo.connect(dojo.doc, "onkeydown", this, "onKeyDown"), dojo.connect(dojo.doc, "onkeyup", this, "onKeyUp") ]; var c = "dojoDnd" + (copy ? "Copy" : "Move"); dojo.addClass(dojo.body(), c); }, canDrop: function(flag){ // summary: called to notify if the current target can accept items var canDropFlag = Boolean(this.target && flag); if(this.canDropFlag != canDropFlag){ this.canDropFlag = canDropFlag; this.avatar.update(); } }, stopDrag: function(){ // summary: stop the DnD in progress dojo.removeClass(dojo.body(), "dojoDndCopy"); dojo.removeClass(dojo.body(), "dojoDndMove"); dojo.forEach(this.events, dojo.disconnect); this.events = []; this.avatar.destroy(); this.avatar = null; this.source = null; this.nodes = []; }, makeAvatar: function(){ // summary: makes the avatar, it is separate to be overwritten dynamically, if needed return new dojo.dnd.Avatar(this); }, updateAvatar: function(){ // summary: updates the avatar, it is separate to be overwritten dynamically, if needed this.avatar.update(); }, // mouse event processors onMouseMove: function(e){ // summary: event processor for onmousemove // e: Event: mouse event var a = this.avatar; if(a){ //dojo.dnd.autoScrollNodes(e); dojo.dnd.autoScroll(e); var s = a.node.style; s.left = (e.pageX + this.OFFSET_X) + "px"; s.top = (e.pageY + this.OFFSET_Y) + "px"; var copy = Boolean(this.source.copyState(dojo.dnd.getCopyKeyState(e))); if(this.copy != copy){ this._setCopyStatus(copy); } } }, onMouseUp: function(e){ // summary: event processor for onmouseup // e: Event: mouse event if(this.avatar && (!("mouseButton" in this.source) || this.source.mouseButton == e.button)){ if(this.target && this.canDropFlag){ var params = [this.source, this.nodes, Boolean(this.source.copyState(dojo.dnd.getCopyKeyState(e))), this.target]; dojo.publish("/dnd/drop/before", params); dojo.publish("/dnd/drop", params); }else{ dojo.publish("/dnd/cancel"); } this.stopDrag(); } }, // keyboard event processors onKeyDown: function(e){ // summary: event processor for onkeydown: // watching for CTRL for copy/move status, watching for ESCAPE to cancel the drag // e: Event: keyboard event if(this.avatar){ switch(e.keyCode){ case dojo.keys.CTRL: var copy = Boolean(this.source.copyState(true)); if(this.copy != copy){ this._setCopyStatus(copy); } break; case dojo.keys.ESCAPE: dojo.publish("/dnd/cancel"); this.stopDrag(); break; } } }, onKeyUp: function(e){ // summary: event processor for onkeyup, watching for CTRL for copy/move status // e: Event: keyboard event if(this.avatar && e.keyCode == dojo.keys.CTRL){ var copy = Boolean(this.source.copyState(false)); if(this.copy != copy){ this._setCopyStatus(copy); } } }, // utilities _setCopyStatus: function(copy){ // summary: changes the copy status // copy: Boolean: the copy status this.copy = copy; this.source._markDndStatus(this.copy); this.updateAvatar(); dojo.removeClass(dojo.body(), "dojoDnd" + (this.copy ? "Move" : "Copy")); dojo.addClass(dojo.body(), "dojoDnd" + (this.copy ? "Copy" : "Move")); } }); // summary: the manager singleton variable, can be overwritten, if needed dojo.dnd._manager = null; dojo.dnd.manager = function(){ // summary: returns the current DnD manager, creates one if it is not created yet if(!dojo.dnd._manager){ dojo.dnd._manager = new dojo.dnd.Manager(); } return dojo.dnd._manager; // Object }; }