DndFromDojo.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.mdnd.adapter.DndFromDojo"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.mdnd.adapter.DndFromDojo"] = true;
  8. dojo.provide("dojox.mdnd.adapter.DndFromDojo");
  9. dojo.require("dojox.mdnd.AreaManager");
  10. dojo.require("dojo.dnd.Manager");
  11. dojo.declare(
  12. "dojox.mdnd.adapter.DndFromDojo",
  13. null,
  14. {
  15. // summary
  16. // Allow communication between Dojo dnd items and DojoX D&D areas
  17. // dropIndicatorSize: Object
  18. // size by default of dropIndicator (display only into a D&D Area)
  19. dropIndicatorSize : {'w':0,'h':50},
  20. // dropIndicatorSize: Object
  21. // size by default of dropIndicator (display only into a D&D Area)
  22. dropIndicatorSize: {'w':0,'h':50},
  23. // _areaManager: Object
  24. // Reference to the current DojoX Dnd Manager
  25. _areaManager: null,
  26. // _dojoManager
  27. // Reference to the current Dojo Manager
  28. _dojoManager: null,
  29. // _currentArea: Object
  30. // The current Area on mouse over
  31. _currentArea: null,
  32. // _oldArea: Object
  33. // The old area the mouse has passed over
  34. _oldArea: null,
  35. // _moveHandler: Object
  36. // The handler of mouse connection
  37. _moveHandler: null,
  38. // _subscribeHandler: Array
  39. // The list of dojo dnd topics
  40. _subscribeHandler: null,
  41. constructor: function(){
  42. this._areaManager = dojox.mdnd.areaManager();
  43. this._dojoManager = dojo.dnd.manager();
  44. this._currentArea = null;
  45. this._moveHandler = null;
  46. this.subscribeDnd();
  47. },
  48. subscribeDnd: function(){
  49. // summary:
  50. // Subscribe to somes topics of dojo drag and drop.
  51. //console.log(("dojox.mdnd.adapter.DndFromDojo ::: subscribeDnd");
  52. this._subscribeHandler = [
  53. dojo.subscribe("/dnd/start",this,"onDragStart"),
  54. dojo.subscribe("/dnd/drop/before", this, "onDrop"),
  55. dojo.subscribe("/dnd/cancel",this,"onDropCancel"),
  56. dojo.subscribe("/dnd/source/over",this,"onDndSource")
  57. ]
  58. },
  59. unsubscribeDnd: function(){
  60. // summary:
  61. // Unsubscribe to some topics of dojo drag and drop.
  62. //console.log(("dojox.mdnd.adapter.DndFromDojo ::: unsubscribeDnd");
  63. dojo.forEach(this._subscribeHandler, dojo.unsubscribe);
  64. },
  65. _getHoverArea: function(/*Object*/ coords){
  66. // summary:
  67. // Get a D&D dojoX area as a DOM node positioned under a specific point.
  68. // coords:
  69. // Object containing the coordinates x and y (mouse position)
  70. // tags:
  71. // protected
  72. //console.log("dojox.mdnd.adapter.DndFromDojo ::: _getHoverArea");
  73. var x = coords.x;
  74. var y = coords.y;
  75. this._oldArea = this._currentArea;
  76. this._currentArea = null;
  77. var areas = this._areaManager._areaList;
  78. for(var i = 0; i < areas.length; i++){
  79. var area = areas[i];
  80. var startX = area.coords.x;
  81. var endX = startX + area.node.offsetWidth;
  82. var startY = area.coords.y;
  83. var endY = startY + area.node.offsetHeight;
  84. // check if the coordinates mouse is in a D&D Area
  85. if(startX <= x && x <= endX && startY <= y && y <= endY){
  86. this._areaManager._oldIndexArea = this._areaManager._currentIndexArea;
  87. this._areaManager._currentIndexArea = i;
  88. this._currentArea = area.node;
  89. break;
  90. }
  91. }
  92. if(this._currentArea != this._oldArea){
  93. if(this._currentArea == null){
  94. // case when the dragNode was in a D&D area but it's out now.
  95. this.onDragExit();
  96. }
  97. else if(this._oldArea == null){
  98. // case when the dragNode was out a D&D area but it's in now.
  99. this.onDragEnter();
  100. }
  101. else{
  102. // case when the dragNode was in a D&D area and enter in an other D&D area directly.
  103. this.onDragExit();
  104. this.onDragEnter();
  105. }
  106. }
  107. //console.log("dojox.mdnd.adapter.DndFromDojo ::: _getHoverArea",this._dojoManager.avatar.node,this._currentArea,this._oldArea);
  108. },
  109. onDragStart: function(/*Object*/source, /*Array*/nodes, /*Boolean*/copy){
  110. // summary:
  111. // Occurs when the "/dnd/start" topic is published.
  112. // source:
  113. // the source which provides items
  114. // nodes:
  115. // the list of transferred items
  116. // copy:
  117. // copy items, if true, move items otherwise
  118. // tags:
  119. // callback
  120. //console.log("dojox.mdnd.adapter.DndFromDojo ::: onDragStart");
  121. // catch the dragNode to get the type when it's necessary.
  122. this._dragNode = nodes[0];
  123. this._copy = copy; this._source = source;
  124. // Connect the onMouseMove :
  125. // It's usefull to activate the detection of a D&D area and the dropIndicator place only if
  126. // the dragNode is out of a the source dojo. The classic behaviour of the dojo source is kept.
  127. this._outSourceHandler = dojo.connect(this._dojoManager, "outSource", this, function(){
  128. //dojo.disconnect(this._outSourceHandler);
  129. if(this._moveHandler == null){
  130. this._moveHandler = dojo.connect(dojo.doc, "mousemove", this, "onMouseMove");
  131. }
  132. });
  133. },
  134. onMouseMove: function(/*DOMEvent*/e){
  135. // summary:
  136. // Occurs when the user moves the mouse.
  137. // e:
  138. // the DOM event
  139. // tags:
  140. // callback
  141. //console.log("dojox.mdnd.adapter.DndFromDojo ::: onMouseMove");
  142. // calculate the coordonates of the mouse.
  143. var coords = {
  144. 'x': e.pageX,
  145. 'y': e.pageY
  146. };
  147. this._getHoverArea(coords);
  148. // if a D&D area has been found and if it's accepted to drop this type of dragged node
  149. if(this._currentArea && this._areaManager._accept){
  150. // specific case : a dropIndicator can be hidden (see onDndSource method)
  151. if(this._areaManager._dropIndicator.node.style.visibility == "hidden"){
  152. this._areaManager._dropIndicator.node.style.visibility = "";
  153. dojo.addClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
  154. }
  155. // place the dropIndicator in D&D Area with a default size.
  156. this._areaManager.placeDropIndicator(coords, this.dropIndicatorSize);
  157. }
  158. },
  159. onDragEnter: function(){
  160. // summary:
  161. // Occurs when the user drages an DOJO dnd item inside a D&D dojoX area.
  162. // tags:
  163. // callback
  164. //console.log("dojox.mdnd.adapter.DndFromDojo ::: onDragEnter");
  165. // Check if the type of dragged node is accepted in the selected D&D dojoX Area.
  166. var _dndType = this._dragNode.getAttribute("dndType");
  167. // need to have an array as type
  168. var type = (_dndType) ? _dndType.split(/\s*,\s*/) : ["text"];
  169. this._areaManager._isAccepted(type, this._areaManager._areaList[this._areaManager._currentIndexArea].accept);
  170. // if the D&D dojoX Area accepts the drop, change the color of Avatar.
  171. if(this._dojoManager.avatar){
  172. if(this._areaManager._accept){
  173. dojo.addClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
  174. }
  175. else{
  176. dojo.removeClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
  177. }
  178. }
  179. },
  180. onDragExit: function(){
  181. // summary:
  182. // Occurs when the user leaves a D&D dojoX area after dragging an DOJO dnd item over it.
  183. //console.log("dojox.mdnd.adapter.DndFromDojo ::: onDragExit");
  184. // if the dragged node exits of a D&D dojoX Area :
  185. this._areaManager._accept = false;
  186. // change color of avatar
  187. if(this._dojoManager.avatar){
  188. dojo.removeClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
  189. }
  190. // reset all variables and remove the dropIndicator.
  191. if(this._currentArea == null){
  192. this._areaManager._dropMode.refreshItems(this._areaManager._areaList[this._areaManager._oldIndexArea], this._areaManager._oldDropIndex, this.dropIndicatorSize, false);
  193. this._areaManager._resetAfterDrop();
  194. }
  195. else{
  196. this._areaManager._dropIndicator.remove();
  197. }
  198. },
  199. isAccepted: function(/*Node*/node, /*Object*/accept){
  200. // summary:
  201. // Check if a dragNode is accepted into a dojo target.
  202. // node:
  203. // The dragged node.
  204. // accept:
  205. // Object containing the type accepted for a target dojo.
  206. // returns:
  207. // true if the dragged node is accepted in the target dojo.
  208. //console.log("dojox.mdnd.adapter.DndFromDojo ::: isAccepted");
  209. var type = (node.getAttribute("dndType")) ? node.getAttribute("dndType") : "text";
  210. if(type && type in accept)
  211. return true; // Boolean
  212. else
  213. return false; // Boolean
  214. },
  215. onDndSource: function(/*Object*/ source){
  216. // summary:
  217. // Called when the mouse enters or exits of a source dojo.
  218. // source:
  219. // the dojo source/target
  220. // tags:
  221. // callback
  222. //console.log("dojox.mdnd.adapter.DndFromDojo ::: onDndSource",source);
  223. // Only the case : "source dojo into a D&D dojoX Area" is treated.
  224. if(this._currentArea == null){
  225. return;
  226. }
  227. if(source){
  228. // Enter in a source/target dojo.
  229. // test if the type of draggedNode is accepted :
  230. var accept = false;
  231. if(this._dojoManager.target == source){
  232. accept = true;
  233. }
  234. else{
  235. accept = this.isAccepted(this._dragNode, source.accept);
  236. }
  237. if(accept){
  238. // disconnect the onMouseMove to disabled the search of a drop zone in the D&D dojoX Area.
  239. dojo.disconnect(this._moveHandler);
  240. this._currentArea = this._moveHandler = null;
  241. // hidden the visibility of dojoX dropIndicator to prevent an offset when the dropIndicator disappears.
  242. // test if drop indicator is visible before applaying hidden style.
  243. var dropIndicator = this._areaManager._dropIndicator.node;
  244. if(dropIndicator && dropIndicator.parentNode !== null && dropIndicator.parentNode.nodeType == 1)
  245. dropIndicator.style.visibility = "hidden";
  246. }
  247. else{
  248. // if the type of dragged node is not accepted in the target dojo, the color of avatar
  249. // have to be the same that the color of D&D dojoX Area acceptance.
  250. this._resetAvatar();
  251. }
  252. }
  253. else{
  254. // Exit of a source/target dojo.
  255. // reconnect the onMouseMove to enabled the search of a drop zone in the D&D dojox Area.
  256. if(!this._moveHandler)
  257. this._moveHandler = dojo.connect(dojo.doc, "mousemove", this, "onMouseMove");
  258. this._resetAvatar();
  259. }
  260. },
  261. _resetAvatar: function(){
  262. // summary:
  263. // Function executed in onDndSource function to set the avatar
  264. // acceptance according to the dojox DnD AreaManager Acceptance.
  265. // It is used when The mouse exit a source/target dojo or if the
  266. // dragged node is not accepted in dojo source / target.
  267. // tags:
  268. // protected
  269. //console.log("dojox.mdnd.adapter.DndFromDojo ::: _resetAvatar");
  270. if(this._dojoManager.avatar){
  271. if(this._areaManager._accept){
  272. dojo.addClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
  273. }
  274. else{
  275. dojo.removeClass(this._dojoManager.avatar.node, "dojoDndAvatarCanDrop");
  276. }
  277. }
  278. },
  279. onDropCancel: function(){
  280. // summary:
  281. // Occurs when the "/dnd/cancel" topic is published.
  282. // tags:
  283. // callback
  284. //console.log("dojox.mdnd.adapter.DndFromDojo ::: onDropCancel");
  285. if(this._currentArea == null){
  286. // the dragged node is not in the D&D dojox Area => Cancel
  287. this._areaManager._resetAfterDrop();
  288. dojo.disconnect(this._moveHandler);
  289. dojo.disconnect(this._outSourceHandler);
  290. this._currentArea = this._moveHandler = this._outSourceHandler = null;
  291. }
  292. else{
  293. // the dragged node is in the D&D dojox Area
  294. // (catch when dragged node exits of a source/target dojo and stays in the same D&D dojox Area)
  295. // dojo cancel the drop but it's authorized in the D&D Area
  296. if(this._areaManager._accept){
  297. this.onDrop(this._source, [this._dragNode], this._copy, this._currentArea);
  298. }
  299. else{
  300. this._currentArea = null;
  301. dojo.disconnect(this._outSourceHandler);
  302. dojo.disconnect(this._moveHandler);
  303. this._moveHandler = this._outSourceHandler = null;
  304. }
  305. }
  306. },
  307. onDrop: function(/*Object*/source, /*Array*/nodes, /*Boolean*/copy){
  308. // summary:
  309. // Occurs when the user leaves a D&D dojox area after dragging an DOJO dnd item over it.
  310. // source:
  311. // the source which provides items
  312. // nodes:
  313. // the list of transferred items
  314. // copy:
  315. // copy items, if true, move items otherwise
  316. // tags:
  317. // callback
  318. //console.log("dojox.mdnd.adapter.DndFromDojo ::: onDrop", this._currentArea);
  319. dojo.disconnect(this._moveHandler);
  320. dojo.disconnect(this._outSourceHandler);
  321. this._moveHandler = this._outSourceHandler = null;
  322. if(this._currentArea){
  323. var dropIndex = this._areaManager._currentDropIndex;
  324. dojo.publish("/dnd/drop/after", [source, nodes, copy, this._currentArea, dropIndex]);
  325. this._currentArea = null;
  326. }
  327. if(this._areaManager._dropIndicator.node.style.visibility == "hidden"){
  328. this._areaManager._dropIndicator.node.style.visibility = "";
  329. }
  330. this._areaManager._resetAfterDrop();
  331. }
  332. });
  333. dojox.mdnd.adapter._dndFromDojo = null;
  334. (function(){
  335. dojox.mdnd.adapter._dndFromDojo = new dojox.mdnd.adapter.DndFromDojo();
  336. }());
  337. }