Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / HeaderResizer.html
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> * @class Ext.grid.plugin.HeaderResizer
20  * @extends Ext.util.Observable
21  *
22  * Plugin to add header resizing functionality to a HeaderContainer.
23  * Always resizing header to the left of the splitter you are resizing.
24  */
25 Ext.define('Ext.grid.plugin.HeaderResizer', {
26     extend: 'Ext.util.Observable',
27     requires: ['Ext.dd.DragTracker', 'Ext.util.Region'],
28     alias: 'plugin.gridheaderresizer',
29
30     disabled: false,
31
32 <span id='Ext-grid-plugin-HeaderResizer-cfg-dynamic'>    /**
33 </span>     * @cfg {Boolean} dynamic
34      * Set to true to resize on the fly rather than using a proxy marker. Defaults to false.
35      */
36     configs: {
37         dynamic: true
38     },
39
40     colHeaderCls: Ext.baseCSSPrefix + 'column-header',
41
42     minColWidth: 40,
43     maxColWidth: 1000,
44     wResizeCursor: 'col-resize',
45     eResizeCursor: 'col-resize',
46     // not using w and e resize bc we are only ever resizing one
47     // column
48     //wResizeCursor: Ext.isWebKit ? 'w-resize' : 'col-resize',
49     //eResizeCursor: Ext.isWebKit ? 'e-resize' : 'col-resize',
50
51     init: function(headerCt) {
52         this.headerCt = headerCt;
53         headerCt.on('render', this.afterHeaderRender, this, {single: true});
54     },
55
56 <span id='Ext-grid-plugin-HeaderResizer-method-destroy'>    /**
57 </span>     * @private
58      * AbstractComponent calls destroy on all its plugins at destroy time.
59      */
60     destroy: function() {
61         if (this.tracker) {
62             this.tracker.destroy();
63         }
64     },
65
66     afterHeaderRender: function() {
67         var headerCt = this.headerCt,
68             el = headerCt.el;
69
70         headerCt.mon(el, 'mousemove', this.onHeaderCtMouseMove, this);
71
72         this.tracker = Ext.create('Ext.dd.DragTracker', {
73             disabled: this.disabled,
74             onBeforeStart: Ext.Function.bind(this.onBeforeStart, this),
75             onStart: Ext.Function.bind(this.onStart, this),
76             onDrag: Ext.Function.bind(this.onDrag, this),
77             onEnd: Ext.Function.bind(this.onEnd, this),
78             tolerance: 3,
79             autoStart: 300,
80             el: el
81         });
82     },
83
84     // As we mouse over individual headers, change the cursor to indicate
85     // that resizing is available, and cache the resize target header for use
86     // if/when they mousedown.
87     onHeaderCtMouseMove: function(e, t) {
88         if (this.headerCt.dragging) {
89             if (this.activeHd) {
90                 this.activeHd.el.dom.style.cursor = '';
91                 delete this.activeHd;
92             }
93         } else {
94             var headerEl = e.getTarget('.' + this.colHeaderCls, 3, true),
95                 overHeader, resizeHeader;
96
97             if (headerEl){
98                 overHeader = Ext.getCmp(headerEl.id);
99
100                 // On left edge, go back to the previous non-hidden header.
101                 if (overHeader.isOnLeftEdge(e)) {
102                     resizeHeader = overHeader.previousNode('gridcolumn:not([hidden])');
103
104                 }
105                 // Else, if on the right edge, we're resizing the column we are over
106                 else if (overHeader.isOnRightEdge(e)) {
107                     resizeHeader = overHeader;
108                 }
109                 // Between the edges: we are not resizing
110                 else {
111                     resizeHeader = null;
112                 }
113
114                 // We *are* resizing
115                 if (resizeHeader) {
116                     // If we're attempting to resize a group header, that cannot be resized,
117                     // so find its last visible leaf header; Group headers are sized
118                     // by the size of their child headers.
119                     if (resizeHeader.isGroupHeader) {
120                         resizeHeader = resizeHeader.down(':not([isGroupHeader]):not([hidden]):last');
121                     }
122
123                     // Check if the header is resizable. Continue checking the old &quot;fixed&quot; property, bug also
124                     // check whether the resizablwe property is set to false.
125                     if (resizeHeader &amp;&amp; !(resizeHeader.fixed || (resizeHeader.resizable === false) || this.disabled)) {
126                         this.activeHd = resizeHeader;
127                         overHeader.el.dom.style.cursor = this.eResizeCursor;
128                     }
129                 // reset
130                 } else {
131                     overHeader.el.dom.style.cursor = '';
132                     delete this.activeHd;
133                 }
134             }
135         }
136     },
137
138     // only start when there is an activeHd
139     onBeforeStart : function(e){
140         var t = e.getTarget();
141         // cache the activeHd because it will be cleared.
142         this.dragHd = this.activeHd;
143
144         if (!!this.dragHd &amp;&amp; !Ext.fly(t).hasCls('x-column-header-trigger') &amp;&amp; !this.headerCt.dragging) {
145             //this.headerCt.dragging = true;
146             this.tracker.constrainTo = this.getConstrainRegion();
147             return true;
148         } else {
149             this.headerCt.dragging = false;
150             return false;
151         }
152     },
153
154     // get the region to constrain to, takes into account max and min col widths
155     getConstrainRegion: function() {
156         var dragHdEl = this.dragHd.el,
157             region   = Ext.util.Region.getRegion(dragHdEl);
158
159         return region.adjust(
160             0,
161             this.maxColWidth - dragHdEl.getWidth(),
162             0,
163             this.minColWidth
164         );
165     },
166
167     // initialize the left and right hand side markers around
168     // the header that we are resizing
169     onStart: function(e){
170         var me       = this,
171             dragHd   = me.dragHd,
172             dragHdEl = dragHd.el,
173             width    = dragHdEl.getWidth(),
174             headerCt = me.headerCt,
175             t        = e.getTarget();
176
177         if (me.dragHd &amp;&amp; !Ext.fly(t).hasCls('x-column-header-trigger')) {
178             headerCt.dragging = true;
179         }
180
181         me.origWidth = width;
182
183         // setup marker proxies
184         if (!me.dynamic) {
185             var xy           = dragHdEl.getXY(),
186                 gridSection  = headerCt.up('[scrollerOwner]'),
187                 dragHct      = me.dragHd.up(':not([isGroupHeader])'),
188                 firstSection = dragHct.up(),
189                 lhsMarker    = gridSection.getLhsMarker(),
190                 rhsMarker    = gridSection.getRhsMarker(),
191                 el           = rhsMarker.parent(),
192                 offsetLeft   = el.getLeft(true),
193                 offsetTop    = el.getTop(true),
194                 topLeft      = el.translatePoints(xy),
195                 markerHeight = firstSection.body.getHeight() + headerCt.getHeight(),
196                 top = topLeft.top - offsetTop;
197
198             lhsMarker.setTop(top);
199             rhsMarker.setTop(top);
200             lhsMarker.setHeight(markerHeight);
201             rhsMarker.setHeight(markerHeight);
202             lhsMarker.setLeft(topLeft.left - offsetLeft);
203             rhsMarker.setLeft(topLeft.left + width - offsetLeft);
204         }
205     },
206
207     // synchronize the rhsMarker with the mouse movement
208     onDrag: function(e){
209         if (!this.dynamic) {
210             var xy          = this.tracker.getXY('point'),
211                 gridSection = this.headerCt.up('[scrollerOwner]'),
212                 rhsMarker   = gridSection.getRhsMarker(),
213                 el          = rhsMarker.parent(),
214                 topLeft     = el.translatePoints(xy),
215                 offsetLeft  = el.getLeft(true);
216
217             rhsMarker.setLeft(topLeft.left - offsetLeft);
218         // Resize as user interacts
219         } else {
220             this.doResize();
221         }
222     },
223
224     onEnd: function(e){
225         this.headerCt.dragging = false;
226         if (this.dragHd) {
227             if (!this.dynamic) {
228                 var dragHd      = this.dragHd,
229                     gridSection = this.headerCt.up('[scrollerOwner]'),
230                     lhsMarker   = gridSection.getLhsMarker(),
231                     rhsMarker   = gridSection.getRhsMarker(),
232                     currWidth   = dragHd.getWidth(),
233                     offset      = this.tracker.getOffset('point'),
234                     offscreen   = -9999;
235
236                 // hide markers
237                 lhsMarker.setLeft(offscreen);
238                 rhsMarker.setLeft(offscreen);
239             }
240             this.doResize();
241         }
242     },
243
244     doResize: function() {
245         if (this.dragHd) {
246             var dragHd = this.dragHd,
247                 nextHd,
248                 offset = this.tracker.getOffset('point');
249
250             // resize the dragHd
251             if (dragHd.flex) {
252                 delete dragHd.flex;
253             }
254
255             this.headerCt.suspendLayout = true;
256             dragHd.setWidth(this.origWidth + offset[0], false);
257
258             // In the case of forceFit, change the following Header width.
259             // Then apply the two width changes by laying out the owning HeaderContainer
260             // If HeaderContainer is configured forceFit, inhibit upstream layout notification, so that
261             // we can also shrink the following Header by an equal amount, and *then* inform the upstream layout.
262             if (this.headerCt.forceFit) {
263                 nextHd = dragHd.nextNode('gridcolumn:not([hidden]):not([isGroupHeader])');
264                 if (nextHd) {
265                     delete nextHd.flex;
266                     nextHd.setWidth(nextHd.getWidth() - offset[0], false);
267                 }
268             }
269             this.headerCt.suspendLayout = false;
270             this.headerCt.doComponentLayout(this.headerCt.getFullWidth());
271         }
272     },
273
274     disable: function() {
275         this.disabled = true;
276         if (this.tracker) {
277             this.tracker.disable();
278         }
279     },
280
281     enable: function() {
282         this.disabled = false;
283         if (this.tracker) {
284             this.tracker.enable();
285         }
286     }
287 });</pre>
288 </body>
289 </html>