VerticalDropMode.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  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.dropMode.VerticalDropMode"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.mdnd.dropMode.VerticalDropMode"] = true;
  8. dojo.provide("dojox.mdnd.dropMode.VerticalDropMode");
  9. dojo.require("dojox.mdnd.AreaManager");
  10. dojo.declare(
  11. "dojox.mdnd.dropMode.VerticalDropMode",
  12. null,
  13. {
  14. // summary:
  15. // Enabled a type of calcul for Dnd.
  16. // Default class to find the nearest target.
  17. // _oldXPoint: Integer
  18. // used to save a X position
  19. _oldXPoint: null,
  20. // _oldYPoint: Integer
  21. // used to save a Y position
  22. _oldYPoint: null,
  23. // _oldBehaviour: String
  24. // see <getDragPoint>
  25. _oldBehaviour: "up",
  26. addArea: function(/*Array*/areas, /*Object*/object){
  27. // summary:
  28. // Add a DnD Area into an array sorting by the x position.
  29. // areas:
  30. // array of areas
  31. // object:
  32. // data type of a DndArea
  33. // returns:
  34. // a sorted area
  35. //console.log("dojox.mdnd.dropMode.VerticalDropMode ::: addArea");
  36. var length = areas.length;
  37. var position = dojo.position(object.node, true);
  38. object.coords = {'x':position.x, 'y':position.y};
  39. if(length == 0){
  40. areas.push(object);
  41. }
  42. else{
  43. var x = object.coords.x;
  44. for(var i = 0; i < length; i++){
  45. if(x < areas[i].coords.x){
  46. for(var j = length-1; j >= i; j--)
  47. areas[j + 1] = areas[j];
  48. areas[i] = object;
  49. break;
  50. }
  51. }
  52. if(i == length){
  53. areas.push(object);
  54. }
  55. }
  56. return areas; // Array
  57. },
  58. updateAreas: function(/*Array*/areaList){
  59. // summary:
  60. // Refresh intervals between areas to determinate the nearest area to drop an item.
  61. // Algorithm :
  62. // the marker should be the vertical line passing by the
  63. // central point between two contiguous areas.
  64. // Note:
  65. // If the page has only one targetArea, it's not necessary to calculate coords.
  66. // areaList:
  67. // array of areas
  68. //console.log("dojox.mdnd.dropMode.VerticalDropMode ::: initAreas");
  69. var length = areaList.length;
  70. if(length > 1){
  71. var currentRight, nextLeft;
  72. for(var i = 0; i < length; i++){
  73. var area = areaList[i];
  74. var nextArea;
  75. area.coords.x1 = -1;
  76. area.coords.x2 = -1;
  77. if(i == 0){
  78. nextArea = areaList[i+1];
  79. this._updateArea(area);
  80. this._updateArea(nextArea);
  81. currentRight = area.coords.x + area.node.offsetWidth;
  82. nextLeft = nextArea.coords.x;
  83. area.coords.x2 = currentRight + (nextLeft-currentRight)/2;
  84. }
  85. else if(i == length-1){
  86. area.coords.x1 = areaList[i-1].coords.x2;
  87. }
  88. else{
  89. nextArea = areaList[i+1];
  90. this._updateArea(nextArea);
  91. currentRight = area.coords.x + area.node.offsetWidth;
  92. nextLeft = nextArea.coords.x;
  93. area.coords.x1 = areaList[i-1].coords.x2;
  94. area.coords.x2 = currentRight + (nextLeft-currentRight)/2;
  95. }
  96. }
  97. }
  98. },
  99. _updateArea : function(/*Object*/area){
  100. // summary:
  101. // update the DnD area object (i.e. update coordinates of its DOM node)
  102. // area:
  103. // the DnD area
  104. // tags:
  105. // protected
  106. //console.log("dojox.mdnd.dropMode.VerticalDropMode ::: _updateArea");
  107. var position = dojo.position(area.node, true);
  108. area.coords.x = position.x;
  109. area.coords.y = position.y;
  110. },
  111. initItems: function(/*Object*/area){
  112. // summary:
  113. // initialize the horizontal line in order to determinate the drop zone.
  114. // area:
  115. // the DnD area
  116. //console.log("dojox.mdnd.dropMode.VerticalDropMode ::: initItems");
  117. dojo.forEach(area.items, function(obj){
  118. //get the vertical middle of the item
  119. var node = obj.item.node;
  120. var position = dojo.position(node, true);
  121. var y = position.y + position.h/2;
  122. obj.y = y;
  123. });
  124. area.initItems = true;
  125. },
  126. refreshItems: function(/*Object*/area, /*Integer*/indexItem, /*Object*/size, /*Boolean*/added){
  127. // summary:
  128. // take into account the drop indicator DOM element in order to compute horizontal lines
  129. // area:
  130. // a DnD area object
  131. // indexItem:
  132. // index of a draggable item
  133. // size:
  134. // dropIndicator size
  135. // added:
  136. // boolean to know if a dropIndicator has been added or deleted
  137. //console.log("dojox.mdnd.dropMode.VerticalDropMode ::: refreshItems");
  138. if(indexItem == -1){
  139. return;
  140. }
  141. else if(area && size && size.h){
  142. var height = size.h;
  143. if(area.margin){
  144. height += area.margin.t;
  145. }
  146. var length = area.items.length;
  147. for(var i = indexItem; i < length; i++){
  148. var item = area.items[i];
  149. if(added){
  150. item.y += height;
  151. }
  152. else{
  153. item.y -= height;
  154. }
  155. }
  156. }
  157. },
  158. getDragPoint: function(/*Object*/coords, /*Object*/size, /*Object*/mousePosition){
  159. // summary:
  160. // return coordinates of the draggable item
  161. // description:
  162. // return for:
  163. // - X point : the middle
  164. // - Y point : search if the user goes up or goes down with his mouse.
  165. // - Up : top of the draggable item
  166. // - Down : bottom of the draggable item
  167. // coords:
  168. // an object encapsulating X and Y position
  169. // size:
  170. // an object encapsulating width and height values
  171. // mousePosition:
  172. // coordinates of mouse
  173. // returns:
  174. // an object of coordinates
  175. // example : {'x':10,'y':10}
  176. //console.log("dojox.mdnd.dropMode.VerticalDropMode ::: getDragPoint");
  177. var y = coords.y;
  178. if(this._oldYPoint){
  179. if(y > this._oldYPoint){
  180. this._oldBehaviour = "down";
  181. y += size.h;
  182. }
  183. else
  184. if(y <= this._oldYPoint){
  185. this._oldBehaviour = "up";
  186. }
  187. }
  188. this._oldYPoint = y;
  189. return {
  190. 'x': coords.x + (size.w / 2),
  191. 'y': y
  192. }; // Object
  193. },
  194. getTargetArea: function(/*Array*/areaList, /*Object*/ coords, /*integer*/currentIndexArea ){
  195. // summary:
  196. // get the nearest DnD area.
  197. // Coordinates are basically provided by the <getDragPoint> method.
  198. // areaList:
  199. // a list of DnD areas objects
  200. // coords:
  201. // coordinates [x,y] of the dragItem
  202. // currentIndexArea:
  203. // an index representing the active DnD area
  204. // returns:
  205. // the index of the DnD area
  206. //console.log("dojox.mdnd.dropMode.VerticalDropMode ::: getTargetArea");
  207. var index = 0;
  208. var x = coords.x;
  209. var end = areaList.length;
  210. if(end > 1){
  211. var start = 0, direction = "right", compute = false;
  212. if(currentIndexArea == -1 || arguments.length < 3){
  213. // first time : Need to search the nearest area in all areas.
  214. compute = true;
  215. }
  216. else{
  217. // check if it's always the same area
  218. if(this._checkInterval(areaList, currentIndexArea, x)){
  219. index = currentIndexArea;
  220. }
  221. else{
  222. if(this._oldXPoint < x){
  223. start = currentIndexArea + 1;
  224. }
  225. else{
  226. start = currentIndexArea - 1;
  227. end = 0;
  228. direction = "left";
  229. }
  230. compute = true;
  231. }
  232. }
  233. if(compute){
  234. if(direction === "right"){
  235. for(var i = start; i < end; i++){
  236. if(this._checkInterval(areaList, i, x)){
  237. index = i;
  238. break;
  239. }
  240. }
  241. }
  242. else{
  243. for(var i = start; i >= end; i--){
  244. if(this._checkInterval(areaList, i, x)){
  245. index = i;
  246. break;
  247. }
  248. }
  249. }
  250. }
  251. }
  252. this._oldXPoint = x;
  253. return index; // Integer
  254. },
  255. _checkInterval: function(/*Array*/areaList, /*Integer*/index, /*Coord*/x){
  256. // summary:
  257. // check if the dragNode is in the interval.
  258. // The x coordinate is basically provided by the <getDragPoint> method.
  259. // areaList:
  260. // a list of DnD areas objects
  261. // index:
  262. // index of a DnD area (to get the interval)
  263. // x:
  264. // coordinate x, of the dragNode
  265. // returns:
  266. // true if the dragNode is in intervall
  267. // tags:
  268. // protected
  269. var coords = areaList[index].coords;
  270. if(coords.x1 == -1){
  271. if(x <= coords.x2){
  272. return true;
  273. }
  274. }
  275. else
  276. if(coords.x2 == -1){
  277. if(x > coords.x1){
  278. return true;
  279. }
  280. }
  281. else{
  282. if(coords.x1 < x && x <= coords.x2){
  283. return true;
  284. }
  285. }
  286. return false; // Boolean
  287. },
  288. getDropIndex: function(/*Object*/ targetArea, /*Object*/ coords){
  289. // summary:
  290. // Return the index where the drop has to be placed.
  291. // targetArea:
  292. // a DnD area object
  293. // coords:
  294. // coordinates [x,y] of the draggable item
  295. // returns:
  296. // a number
  297. // or -1 if the area has no children or the drop index represents the last position in to the area
  298. //console.log("dojox.mdnd.dropMode.VerticalDropMode ::: getDropIndex");
  299. var length = targetArea.items.length;
  300. var coordinates = targetArea.coords;
  301. var y = coords.y;
  302. if(length > 0){
  303. // course all children in the target area.
  304. for(var i = 0; i < length; i++){
  305. // compare y value with y value of children
  306. if(y < targetArea.items[i].y){
  307. return i; // Integer
  308. }
  309. else{
  310. if(i == length-1){
  311. return -1;
  312. }
  313. }
  314. }
  315. }
  316. return -1;
  317. },
  318. destroy: function(){
  319. // can be overwritten.
  320. }
  321. });
  322. //------------
  323. //Singleton
  324. //------------
  325. (function(){
  326. dojox.mdnd.areaManager()._dropMode = new dojox.mdnd.dropMode.VerticalDropMode();
  327. }());
  328. }