PortalDropZone.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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.ux.portal.PortalDropZone', {
  7. extend: 'Ext.dd.DropTarget',
  8. constructor: function(portal, cfg) {
  9. this.portal = portal;
  10. Ext.dd.ScrollManager.register(portal.body);
  11. Ext.ux.portal.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. proxy.moveProxy(overPortlet.el.dom.parentNode, match ? overPortlet.el.dom : null);
  94. } else {
  95. proxy.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 && this.portal.fireEvent('beforedrop', dropEvent) !== false) {
  123. // make sure panel is visible prior to inserting so that the layout doesn't ignore it
  124. panel.el.dom.style.display = '';
  125. if (pos !== false) {
  126. c.insert(pos, panel);
  127. } else {
  128. c.add(panel);
  129. }
  130. dd.proxy.hide();
  131. this.portal.fireEvent('drop', dropEvent);
  132. // scroll position is lost on drop, fix it
  133. var st = this.scrollPos.top;
  134. if (st) {
  135. var d = this.portal.body.dom;
  136. setTimeout(function() {
  137. d.scrollTop = st;
  138. },
  139. 10);
  140. }
  141. }
  142. delete this.lastPos;
  143. return true;
  144. },
  145. // internal cache of body and column coords
  146. getGrid: function() {
  147. var box = this.portal.body.getBox();
  148. box.columnX = [];
  149. this.portal.items.each(function(c) {
  150. box.columnX.push({
  151. x: c.el.getX(),
  152. w: c.el.getWidth()
  153. });
  154. });
  155. return box;
  156. },
  157. // unregister the dropzone from ScrollManager
  158. unreg: function() {
  159. Ext.dd.ScrollManager.unregister(this.portal.body);
  160. Ext.ux.portal.PortalDropZone.superclass.unreg.call(this);
  161. }
  162. });