PortalDropZone.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /**
  2. * @class Ext.app.PortalDropZone
  3. * @extends Ext.dd.DropTarget
  4. * Internal class that manages drag/drop for {@link Ext.app.PortalPanel}.
  5. */
  6. Ext.define('Ext.app.PortalDropZone', {
  7. extend: 'Ext.dd.DropTarget',
  8. constructor: function(portal, cfg) {
  9. this.portal = portal;
  10. Ext.dd.ScrollManager.register(portal.body);
  11. Ext.app.PortalDropZone.superclass.constructor.call(this, portal.body, cfg);
  12. portal.body.ddScrollConfig = this.ddScrollConfig;
  13. },
  14. ddScrollConfig: {
  15. vthresh: 50,
  16. hthresh: -1,
  17. animate: true,
  18. increment: 200
  19. },
  20. createEvent: function(dd, e, data, col, c, pos) {
  21. return {
  22. portal: this.portal,
  23. panel: data.panel,
  24. columnIndex: col,
  25. column: c,
  26. position: pos,
  27. data: data,
  28. source: dd,
  29. rawEvent: e,
  30. status: this.dropAllowed
  31. };
  32. },
  33. notifyOver: function(dd, e, data) {
  34. var xy = e.getXY(),
  35. portal = this.portal,
  36. proxy = dd.proxy;
  37. // case column widths
  38. if (!this.grid) {
  39. this.grid = this.getGrid();
  40. }
  41. // handle case scroll where scrollbars appear during drag
  42. var cw = portal.body.dom.clientWidth;
  43. if (!this.lastCW) {
  44. // set initial client width
  45. this.lastCW = cw;
  46. } else if (this.lastCW != cw) {
  47. // client width has changed, so refresh layout & grid calcs
  48. this.lastCW = cw;
  49. //portal.doLayout();
  50. this.grid = this.getGrid();
  51. }
  52. // determine column
  53. var colIndex = 0,
  54. colRight = 0,
  55. cols = this.grid.columnX,
  56. len = cols.length,
  57. cmatch = false;
  58. for (len; colIndex < len; colIndex++) {
  59. colRight = cols[colIndex].x + cols[colIndex].w;
  60. if (xy[0] < colRight) {
  61. cmatch = true;
  62. break;
  63. }
  64. }
  65. // no match, fix last index
  66. if (!cmatch) {
  67. colIndex--;
  68. }
  69. // find insert position
  70. var overPortlet, pos = 0,
  71. h = 0,
  72. match = false,
  73. overColumn = portal.items.getAt(colIndex),
  74. portlets = overColumn.items.items,
  75. overSelf = false;
  76. len = portlets.length;
  77. for (len; pos < len; pos++) {
  78. overPortlet = portlets[pos];
  79. h = overPortlet.el.getHeight();
  80. if (h === 0) {
  81. overSelf = true;
  82. } else if ((overPortlet.el.getY() + (h / 2)) > xy[1]) {
  83. match = true;
  84. break;
  85. }
  86. }
  87. pos = (match && overPortlet ? pos : overColumn.items.getCount()) + (overSelf ? -1 : 0);
  88. var overEvent = this.createEvent(dd, e, data, colIndex, overColumn, pos);
  89. if (portal.fireEvent('validatedrop', overEvent) !== false && portal.fireEvent('beforedragover', overEvent) !== false) {
  90. // make sure proxy width is fluid in different width columns
  91. proxy.getProxy().setWidth('auto');
  92. if (overPortlet) {
  93. dd.panelProxy.moveProxy(overPortlet.el.dom.parentNode, match ? overPortlet.el.dom : null);
  94. } else {
  95. dd.panelProxy.moveProxy(overColumn.el.dom, null);
  96. }
  97. this.lastPos = {
  98. c: overColumn,
  99. col: colIndex,
  100. p: overSelf || (match && overPortlet) ? pos : false
  101. };
  102. this.scrollPos = portal.body.getScroll();
  103. portal.fireEvent('dragover', overEvent);
  104. return overEvent.status;
  105. } else {
  106. return overEvent.status;
  107. }
  108. },
  109. notifyOut: function() {
  110. delete this.grid;
  111. },
  112. notifyDrop: function(dd, e, data) {
  113. delete this.grid;
  114. if (!this.lastPos) {
  115. return;
  116. }
  117. var c = this.lastPos.c,
  118. col = this.lastPos.col,
  119. pos = this.lastPos.p,
  120. panel = dd.panel,
  121. dropEvent = this.createEvent(dd, e, data, col, c, pos !== false ? pos : c.items.getCount());
  122. if (this.portal.fireEvent('validatedrop', dropEvent) !== false &&
  123. this.portal.fireEvent('beforedrop', dropEvent) !== false) {
  124. Ext.suspendLayouts();
  125. // make sure panel is visible prior to inserting so that the layout doesn't ignore it
  126. panel.el.dom.style.display = '';
  127. dd.panelProxy.hide();
  128. dd.proxy.hide();
  129. if (pos !== false) {
  130. c.insert(pos, panel);
  131. } else {
  132. c.add(panel);
  133. }
  134. Ext.resumeLayouts(true);
  135. this.portal.fireEvent('drop', dropEvent);
  136. // scroll position is lost on drop, fix it
  137. var st = this.scrollPos.top;
  138. if (st) {
  139. var d = this.portal.body.dom;
  140. setTimeout(function() {
  141. d.scrollTop = st;
  142. },
  143. 10);
  144. }
  145. }
  146. delete this.lastPos;
  147. return true;
  148. },
  149. // internal cache of body and column coords
  150. getGrid: function() {
  151. var box = this.portal.body.getBox();
  152. box.columnX = [];
  153. this.portal.items.each(function(c) {
  154. box.columnX.push({
  155. x: c.el.getX(),
  156. w: c.el.getWidth()
  157. });
  158. });
  159. return box;
  160. },
  161. // unregister the dropzone from ScrollManager
  162. unreg: function() {
  163. Ext.dd.ScrollManager.unregister(this.portal.body);
  164. Ext.app.PortalDropZone.superclass.unreg.call(this);
  165. }
  166. });