VerticalDropMode.js 8.9 KB

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