DefaultDropMode.js 8.9 KB

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