DefaultDropMode.js 8.9 KB

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