HeaderResizer.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-grid-plugin-HeaderResizer'>/**
  19. </span> * Plugin to add header resizing functionality to a HeaderContainer.
  20. * Always resizing header to the left of the splitter you are resizing.
  21. */
  22. Ext.define('Ext.grid.plugin.HeaderResizer', {
  23. extend: 'Ext.AbstractPlugin',
  24. requires: ['Ext.dd.DragTracker', 'Ext.util.Region'],
  25. alias: 'plugin.gridheaderresizer',
  26. disabled: false,
  27. config: {
  28. <span id='Ext-grid-plugin-HeaderResizer-cfg-dynamic'> /**
  29. </span> * @cfg {Boolean} dynamic
  30. * True to resize on the fly rather than using a proxy marker.
  31. * @accessor
  32. */
  33. dynamic: false
  34. },
  35. colHeaderCls: Ext.baseCSSPrefix + 'column-header',
  36. minColWidth: 40,
  37. maxColWidth: 1000,
  38. wResizeCursor: 'col-resize',
  39. eResizeCursor: 'col-resize',
  40. // not using w and e resize bc we are only ever resizing one
  41. // column
  42. //wResizeCursor: Ext.isWebKit ? 'w-resize' : 'col-resize',
  43. //eResizeCursor: Ext.isWebKit ? 'e-resize' : 'col-resize',
  44. init: function(headerCt) {
  45. this.headerCt = headerCt;
  46. headerCt.on('render', this.afterHeaderRender, this, {single: true});
  47. },
  48. <span id='Ext-grid-plugin-HeaderResizer-method-destroy'> /**
  49. </span> * @private
  50. * AbstractComponent calls destroy on all its plugins at destroy time.
  51. */
  52. destroy: function() {
  53. if (this.tracker) {
  54. this.tracker.destroy();
  55. }
  56. },
  57. afterHeaderRender: function() {
  58. var headerCt = this.headerCt,
  59. el = headerCt.el;
  60. headerCt.mon(el, 'mousemove', this.onHeaderCtMouseMove, this);
  61. this.tracker = new Ext.dd.DragTracker({
  62. disabled: this.disabled,
  63. onBeforeStart: Ext.Function.bind(this.onBeforeStart, this),
  64. onStart: Ext.Function.bind(this.onStart, this),
  65. onDrag: Ext.Function.bind(this.onDrag, this),
  66. onEnd: Ext.Function.bind(this.onEnd, this),
  67. tolerance: 3,
  68. autoStart: 300,
  69. el: el
  70. });
  71. },
  72. // As we mouse over individual headers, change the cursor to indicate
  73. // that resizing is available, and cache the resize target header for use
  74. // if/when they mousedown.
  75. onHeaderCtMouseMove: function(e, t) {
  76. var me = this,
  77. prevSiblings,
  78. headerEl, overHeader, resizeHeader, resizeHeaderOwnerGrid, ownerGrid;
  79. if (me.headerCt.dragging) {
  80. if (me.activeHd) {
  81. me.activeHd.el.dom.style.cursor = '';
  82. delete me.activeHd;
  83. }
  84. } else {
  85. headerEl = e.getTarget('.' + me.colHeaderCls, 3, true);
  86. if (headerEl){
  87. overHeader = Ext.getCmp(headerEl.id);
  88. // On left edge, go back to the previous non-hidden header.
  89. if (overHeader.isOnLeftEdge(e)) {
  90. resizeHeader = overHeader.previousNode('gridcolumn:not([hidden]):not([isGroupHeader])')
  91. // There may not *be* a previous non-hidden header.
  92. if (resizeHeader) {
  93. ownerGrid = me.headerCt.up('tablepanel');
  94. resizeHeaderOwnerGrid = resizeHeader.up('tablepanel');
  95. // Need to check that previousNode didn't go outside the current grid/tree
  96. // But in the case of a Grid which contains a locked and normal grid, allow previousNode to jump
  97. // from the first column of the normalGrid to the last column of the lockedGrid
  98. if (!((resizeHeaderOwnerGrid === ownerGrid) || ((ownerGrid.ownerCt.isXType('tablepanel')) &amp;&amp; ownerGrid.ownerCt.view.lockedGrid === resizeHeaderOwnerGrid))) {
  99. resizeHeader = null;
  100. }
  101. }
  102. }
  103. // Else, if on the right edge, we're resizing the column we are over
  104. else if (overHeader.isOnRightEdge(e)) {
  105. resizeHeader = overHeader;
  106. }
  107. // Between the edges: we are not resizing
  108. else {
  109. resizeHeader = null;
  110. }
  111. // We *are* resizing
  112. if (resizeHeader) {
  113. // If we're attempting to resize a group header, that cannot be resized,
  114. // so find its last visible leaf header; Group headers are sized
  115. // by the size of their child headers.
  116. if (resizeHeader.isGroupHeader) {
  117. prevSiblings = resizeHeader.getGridColumns();
  118. resizeHeader = prevSiblings[prevSiblings.length - 1];
  119. }
  120. // Check if the header is resizable. Continue checking the old &quot;fixed&quot; property, bug also
  121. // check whether the resizablwe property is set to false.
  122. if (resizeHeader &amp;&amp; !(resizeHeader.fixed || (resizeHeader.resizable === false) || me.disabled)) {
  123. me.activeHd = resizeHeader;
  124. overHeader.el.dom.style.cursor = me.eResizeCursor;
  125. }
  126. // reset
  127. } else {
  128. overHeader.el.dom.style.cursor = '';
  129. delete me.activeHd;
  130. }
  131. }
  132. }
  133. },
  134. // only start when there is an activeHd
  135. onBeforeStart : function(e){
  136. var t = e.getTarget();
  137. // cache the activeHd because it will be cleared.
  138. this.dragHd = this.activeHd;
  139. if (!!this.dragHd &amp;&amp; !Ext.fly(t).hasCls(Ext.baseCSSPrefix + 'column-header-trigger') &amp;&amp; !this.headerCt.dragging) {
  140. //this.headerCt.dragging = true;
  141. this.tracker.constrainTo = this.getConstrainRegion();
  142. return true;
  143. } else {
  144. this.headerCt.dragging = false;
  145. return false;
  146. }
  147. },
  148. // get the region to constrain to, takes into account max and min col widths
  149. getConstrainRegion: function() {
  150. var me = this,
  151. dragHdEl = me.dragHd.el,
  152. region = Ext.util.Region.getRegion(dragHdEl),
  153. nextHd;
  154. // If forceFit, then right constraint is based upon not being able to force the next header
  155. // beyond the minColWidth. If there is no next header, then the header may not be expanded.
  156. if (me.headerCt.forceFit) {
  157. nextHd = me.dragHd.nextNode('gridcolumn:not([hidden]):not([isGroupHeader])');
  158. }
  159. return region.adjust(
  160. 0,
  161. me.headerCt.forceFit ? (nextHd ? nextHd.getWidth() - me.minColWidth : 0) : me.maxColWidth - dragHdEl.getWidth(),
  162. 0,
  163. me.minColWidth
  164. );
  165. },
  166. // initialize the left and right hand side markers around
  167. // the header that we are resizing
  168. onStart: function(e){
  169. var me = this,
  170. dragHd = me.dragHd,
  171. dragHdEl = dragHd.el,
  172. width = dragHdEl.getWidth(),
  173. headerCt = me.headerCt,
  174. t = e.getTarget(),
  175. xy, gridSection, dragHct, firstSection, lhsMarker, rhsMarker, el, offsetLeft, offsetTop, topLeft, markerHeight, top;
  176. if (me.dragHd &amp;&amp; !Ext.fly(t).hasCls(Ext.baseCSSPrefix + 'column-header-trigger')) {
  177. headerCt.dragging = true;
  178. }
  179. me.origWidth = width;
  180. // setup marker proxies
  181. if (!me.dynamic) {
  182. xy = dragHdEl.getXY();
  183. gridSection = headerCt.up('[scrollerOwner]');
  184. dragHct = me.dragHd.up(':not([isGroupHeader])');
  185. firstSection = dragHct.up();
  186. lhsMarker = gridSection.getLhsMarker();
  187. rhsMarker = gridSection.getRhsMarker();
  188. el = rhsMarker.parent();
  189. offsetLeft = el.getLocalX();
  190. offsetTop = el.getLocalY();
  191. topLeft = el.translatePoints(xy);
  192. markerHeight = firstSection.body.getHeight() + headerCt.getHeight();
  193. top = topLeft.top - offsetTop;
  194. lhsMarker.setTop(top);
  195. rhsMarker.setTop(top);
  196. lhsMarker.setHeight(markerHeight);
  197. rhsMarker.setHeight(markerHeight);
  198. lhsMarker.setLeft(topLeft.left - offsetLeft);
  199. rhsMarker.setLeft(topLeft.left + width - offsetLeft);
  200. }
  201. },
  202. // synchronize the rhsMarker with the mouse movement
  203. onDrag: function(e){
  204. if (!this.dynamic) {
  205. var xy = this.tracker.getXY('point'),
  206. gridSection = this.headerCt.up('[scrollerOwner]'),
  207. rhsMarker = gridSection.getRhsMarker(),
  208. el = rhsMarker.parent(),
  209. topLeft = el.translatePoints(xy),
  210. offsetLeft = el.getLocalX();
  211. rhsMarker.setLeft(topLeft.left - offsetLeft);
  212. // Resize as user interacts
  213. } else {
  214. this.doResize();
  215. }
  216. },
  217. onEnd: function(e){
  218. this.headerCt.dragging = false;
  219. if (this.dragHd) {
  220. if (!this.dynamic) {
  221. var dragHd = this.dragHd,
  222. gridSection = this.headerCt.up('[scrollerOwner]'),
  223. lhsMarker = gridSection.getLhsMarker(),
  224. rhsMarker = gridSection.getRhsMarker(),
  225. offscreen = -9999;
  226. // hide markers
  227. lhsMarker.setLeft(offscreen);
  228. rhsMarker.setLeft(offscreen);
  229. }
  230. this.doResize();
  231. }
  232. },
  233. doResize: function() {
  234. if (this.dragHd) {
  235. var dragHd = this.dragHd,
  236. nextHd,
  237. offset = this.tracker.getOffset('point');
  238. // resize the dragHd
  239. if (dragHd.flex) {
  240. delete dragHd.flex;
  241. }
  242. Ext.suspendLayouts();
  243. // Set the new column width.
  244. dragHd.setWidth(this.origWidth + offset[0]);
  245. // In the case of forceFit, change the following Header width.
  246. // Constraining so that neither neighbour can be sized to below minWidth is handled in getConstrainRegion
  247. if (this.headerCt.forceFit) {
  248. nextHd = dragHd.nextNode('gridcolumn:not([hidden]):not([isGroupHeader])');
  249. if (nextHd) {
  250. delete nextHd.flex;
  251. nextHd.setWidth(nextHd.getWidth() - offset[0]);
  252. }
  253. }
  254. // Apply the two width changes by laying out the owning HeaderContainer
  255. Ext.resumeLayouts(true);
  256. }
  257. },
  258. disable: function() {
  259. this.disabled = true;
  260. if (this.tracker) {
  261. this.tracker.disable();
  262. }
  263. },
  264. enable: function() {
  265. this.disabled = false;
  266. if (this.tracker) {
  267. this.tracker.enable();
  268. }
  269. }
  270. });</pre>
  271. </body>
  272. </html>