/*
Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
Available via Academic Free License >= 2.1 OR the modified BSD license.
see: http://dojotoolkit.org/license for details
*/
if(!dojo._hasResource["dojox.mdnd.adapter.DndFromDojo"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.mdnd.adapter.DndFromDojo"] = true;
dojo.provide("dojox.mdnd.adapter.DndFromDojo");
dojo.require("dojox.mdnd.AreaManager");
dojo.require("dojo.dnd.Manager");
dojo.declare(
"dojox.mdnd.adapter.DndFromDojo",
null,
{
// summary
// Allow communication between Dojo dnd items and DojoX D&D areas
// dropIndicatorSize: Object
// size by default of dropIndicator (display only into a D&D Area)
dropIndicatorSize : {'w':0,'h':50},
// dropIndicatorSize: Object
// size by default of dropIndicator (display only into a D&D Area)
dropIndicatorSize: {'w':0,'h':50},
// _areaManager: Object
// Reference to the current DojoX Dnd Manager
_areaManager: null,
// _dojoManager
// Reference to the current Dojo Manager
_dojoManager: null,
// _currentArea: Object
// The current Area on mouse over
_currentArea: null,
// _oldArea: Object
// The old area the mouse has passed over
_oldArea: null,
// _moveHandler: Object
// The handler of mouse connection
_moveHandler: null,
// _subscribeHandler: Array
// The list of dojo dnd topics
_subscribeHandler: null,
constructor: function(){
this._areaManager = dojox.mdnd.areaManager();
this._dojoManager = dojo.dnd.manager();
this._currentArea = null;
this._moveHandler = null;
this.subscribeDnd();
},
subscribeDnd: function(){
// summary:
// Subscribe to somes topics of dojo drag and drop.
//console.log(("dojox.mdnd.adapter.DndFromDojo ::: subscribeDnd");
this._subscribeHandler = [
dojo.subscribe("/dnd/start",this,"onDragStart"),
dojo.subscribe("/dnd/drop/before", this, "onDrop"),
dojo.subscribe("/dnd/cancel",this,"onDropCancel"),
dojo.subscribe("/dnd/source/over",this,"onDndSource")
]
},
unsubscribeDnd: function(){
// summary:
// Unsubscribe to some topics of dojo drag and drop.
//console.log(("dojox.mdnd.adapter.DndFromDojo ::: unsubscribeDnd");
dojo.forEach(this._subscribeHandler, dojo.unsubscribe);
},
_getHoverArea: function(/*Object*/ coords){
// summary:
// Get a D&D dojoX area as a DOM node positioned under a specific point.
// coords:
// Object containing the coordinates x and y (mouse position)
// tags:
// protected
//console.log("dojox.mdnd.adapter.DndFromDojo ::: _getHoverArea");
var x = coords.x;
var y = coords.y;
this._oldArea = this._currentArea;
this._currentArea = null;
var areas = this._areaManager._areaList;
for(var i = 0; i < areas.length; i++){
var area = areas[i];
var startX = area.coords.x;
var endX = startX + area.node.offsetWidth;
var startY = area.coords.y;
var endY = startY + area.node.offsetHeight;
// check if the coordinates mouse is in a D&D Area
if(startX <= x && x <= endX && startY <= y && y <= endY){
this._areaManager._oldIndexArea = this._areaManager._currentIndexArea;
this._areaManager._currentIndexArea = i;
this._currentArea = area.node;
break;
}
}
if(this._currentArea != this._oldArea){
if(this._currentArea == null){
// case when the dragNode was in a D&D area but it's out now.
this.onDragExit();
}
else if(this._oldArea == null){
// case when the dragNode was out a D&D area but it's in now.
this.onDragEnter();
}
else{
// case when the dragNode was in a D&D area and enter in an other D&D area directly.
this.onDragExit();
this.onDragEnter();
}
}
//console.log("dojox.mdnd.adapter.DndFromDojo ::: _getHoverArea",this._dojoManager.avatar.node,this._currentArea,this._oldArea);
},
onDragStart: function(/*Object*/source, /*Array*/nodes, /*Boolean*/copy){
// summary:
// Occurs when the "/dnd/start" topic is published.
// source:
// the source which provides items
// nodes:
// the list of transferred items
// copy:
// copy items, if true, move items otherwise
// tags:
// callback
//console.log("dojox.mdnd.adapter.DndFromDojo ::: onDragStart");
// catch the dragNode to get the type when it's necessary.
this._dragNode = nodes[0];
this._copy = copy; this._source = source;
// Connect the onMouseMove :
// It's usefull to activate the detection of a D&D area and the dropIndicator place only if
// the dragNode is out of a the source dojo. The classic behaviour of the dojo source is kept.
this._outSourceHandler = dojo.connect(this._dojoManager, "outSource", this, function(){
//dojo.disconnect(this._outSourceHandler);
if(this._moveHandler == null){
this._moveHandler = dojo.connect(dojo.doc, "mousemove", this, "onMouseMove");
}
});
},
onMouseMove: function(/*DOMEvent*/e){
// summary:
// Occurs when the user moves the mouse.
// e:
// the DOM event
// tags:
// callback
//console.log("dojox.mdnd.adapter.DndFromDojo ::: onMouseMove");
// calculate the coordonates of the mouse.
var coords = {
'x': e.pageX,
'y': e.pageY
};
this._getHoverArea(coords);
// if a D&D area has been found and if it's accepted to drop this type of dragged node
if(this._currentArea && this._areaManager._accept){
// specific case : a dropIndicator can be hidden (see onDndSource method)
if(this._areaManager._dropIndicator.node.style.visibility == "hidden"){
this._areaManager._dropIndicator.node.style.visibility = "";
dojo.addClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
}
// place the dropIndicator in D&D Area with a default size.
this._areaManager.placeDropIndicator(coords, this.dropIndicatorSize);
}
},
onDragEnter: function(){
// summary:
// Occurs when the user drages an DOJO dnd item inside a D&D dojoX area.
// tags:
// callback
//console.log("dojox.mdnd.adapter.DndFromDojo ::: onDragEnter");
// Check if the type of dragged node is accepted in the selected D&D dojoX Area.
var _dndType = this._dragNode.getAttribute("dndType");
// need to have an array as type
var type = (_dndType) ? _dndType.split(/\s*,\s*/) : ["text"];
this._areaManager._isAccepted(type, this._areaManager._areaList[this._areaManager._currentIndexArea].accept);
// if the D&D dojoX Area accepts the drop, change the color of Avatar.
if(this._dojoManager.avatar){
if(this._areaManager._accept){
dojo.addClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
}
else{
dojo.removeClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
}
}
},
onDragExit: function(){
// summary:
// Occurs when the user leaves a D&D dojoX area after dragging an DOJO dnd item over it.
//console.log("dojox.mdnd.adapter.DndFromDojo ::: onDragExit");
// if the dragged node exits of a D&D dojoX Area :
this._areaManager._accept = false;
// change color of avatar
if(this._dojoManager.avatar){
dojo.removeClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
}
// reset all variables and remove the dropIndicator.
if(this._currentArea == null){
this._areaManager._dropMode.refreshItems(this._areaManager._areaList[this._areaManager._oldIndexArea], this._areaManager._oldDropIndex, this.dropIndicatorSize, false);
this._areaManager._resetAfterDrop();
}
else{
this._areaManager._dropIndicator.remove();
}
},
isAccepted: function(/*Node*/node, /*Object*/accept){
// summary:
// Check if a dragNode is accepted into a dojo target.
// node:
// The dragged node.
// accept:
// Object containing the type accepted for a target dojo.
// returns:
// true if the dragged node is accepted in the target dojo.
//console.log("dojox.mdnd.adapter.DndFromDojo ::: isAccepted");
var type = (node.getAttribute("dndType")) ? node.getAttribute("dndType") : "text";
if(type && type in accept)
return true; // Boolean
else
return false; // Boolean
},
onDndSource: function(/*Object*/ source){
// summary:
// Called when the mouse enters or exits of a source dojo.
// source:
// the dojo source/target
// tags:
// callback
//console.log("dojox.mdnd.adapter.DndFromDojo ::: onDndSource",source);
// Only the case : "source dojo into a D&D dojoX Area" is treated.
if(this._currentArea == null){
return;
}
if(source){
// Enter in a source/target dojo.
// test if the type of draggedNode is accepted :
var accept = false;
if(this._dojoManager.target == source){
accept = true;
}
else{
accept = this.isAccepted(this._dragNode, source.accept);
}
if(accept){
// disconnect the onMouseMove to disabled the search of a drop zone in the D&D dojoX Area.
dojo.disconnect(this._moveHandler);
this._currentArea = this._moveHandler = null;
// hidden the visibility of dojoX dropIndicator to prevent an offset when the dropIndicator disappears.
// test if drop indicator is visible before applaying hidden style.
var dropIndicator = this._areaManager._dropIndicator.node;
if(dropIndicator && dropIndicator.parentNode !== null && dropIndicator.parentNode.nodeType == 1)
dropIndicator.style.visibility = "hidden";
}
else{
// if the type of dragged node is not accepted in the target dojo, the color of avatar
// have to be the same that the color of D&D dojoX Area acceptance.
this._resetAvatar();
}
}
else{
// Exit of a source/target dojo.
// reconnect the onMouseMove to enabled the search of a drop zone in the D&D dojox Area.
if(!this._moveHandler)
this._moveHandler = dojo.connect(dojo.doc, "mousemove", this, "onMouseMove");
this._resetAvatar();
}
},
_resetAvatar: function(){
// summary:
// Function executed in onDndSource function to set the avatar
// acceptance according to the dojox DnD AreaManager Acceptance.
// It is used when The mouse exit a source/target dojo or if the
// dragged node is not accepted in dojo source / target.
// tags:
// protected
//console.log("dojox.mdnd.adapter.DndFromDojo ::: _resetAvatar");
if(this._dojoManager.avatar){
if(this._areaManager._accept){
dojo.addClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
}
else{
dojo.removeClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
}
}
},
onDropCancel: function(){
// summary:
// Occurs when the "/dnd/cancel" topic is published.
// tags:
// callback
//console.log("dojox.mdnd.adapter.DndFromDojo ::: onDropCancel");
if(this._currentArea == null){
// the dragged node is not in the D&D dojox Area => Cancel
this._areaManager._resetAfterDrop();
dojo.disconnect(this._moveHandler);
dojo.disconnect(this._outSourceHandler);
this._currentArea = this._moveHandler = this._outSourceHandler = null;
}
else{
// the dragged node is in the D&D dojox Area
// (catch when dragged node exits of a source/target dojo and stays in the same D&D dojox Area)
// dojo cancel the drop but it's authorized in the D&D Area
if(this._areaManager._accept){
this.onDrop(this._source, [this._dragNode], this._copy, this._currentArea);
}
else{
this._currentArea = null;
dojo.disconnect(this._outSourceHandler);
dojo.disconnect(this._moveHandler);
this._moveHandler = this._outSourceHandler = null;
}
}
},
onDrop: function(/*Object*/source, /*Array*/nodes, /*Boolean*/copy){
// summary:
// Occurs when the user leaves a D&D dojox area after dragging an DOJO dnd item over it.
// source:
// the source which provides items
// nodes:
// the list of transferred items
// copy:
// copy items, if true, move items otherwise
// tags:
// callback
//console.log("dojox.mdnd.adapter.DndFromDojo ::: onDrop", this._currentArea);
dojo.disconnect(this._moveHandler);
dojo.disconnect(this._outSourceHandler);
this._moveHandler = this._outSourceHandler = null;
if(this._currentArea){
var dropIndex = this._areaManager._currentDropIndex;
dojo.publish("/dnd/drop/after", [source, nodes, copy, this._currentArea, dropIndex]);
this._currentArea = null;
}
if(this._areaManager._dropIndicator.node.style.visibility == "hidden"){
this._areaManager._dropIndicator.node.style.visibility = "";
}
this._areaManager._resetAfterDrop();
}
});
dojox.mdnd.adapter._dndFromDojo = null;
(function(){
dojox.mdnd.adapter._dndFromDojo = new dojox.mdnd.adapter.DndFromDojo();
}());
}