SemanticScuttle/includes/js/dojo/dnd/Manager.js

180 lines
5.5 KiB
JavaScript

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
};
}