Upgrade to ExtJS 4.0.1 - Released 05/18/2011
[extjs.git] / docs / source / ResizeTracker.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="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../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-resizer-ResizeTracker'>/**
19 </span> * @class Ext.resizer.ResizeTracker
20  * @extends Ext.dd.DragTracker
21  */
22 Ext.define('Ext.resizer.ResizeTracker', {
23     extend: 'Ext.dd.DragTracker',
24     dynamic: true,
25     preserveRatio: false,
26
27     // Default to no constraint
28     constrainTo: null,
29
30     constructor: function(config) {
31         var me = this;
32
33         if (!config.el) {
34             if (config.target.isComponent) {
35                 me.el = config.target.getEl();
36             } else {
37                 me.el = config.target;
38             }
39         }
40         this.callParent(arguments);
41
42         // Ensure that if we are preserving aspect ratio, the largest minimum is honoured
43         if (me.preserveRatio &amp;&amp; me.minWidth &amp;&amp; me.minHeight) {
44             var widthRatio = me.minWidth / me.el.getWidth(),
45                 heightRatio = me.minHeight / me.el.getHeight();
46
47             // largest ratio of minimum:size must be preserved.
48             // So if a 400x200 pixel image has
49             // minWidth: 50, maxWidth: 50, the maxWidth will be 400 * (50/200)... that is 100
50             if (heightRatio &gt; widthRatio) {
51                 me.minWidth = me.el.getWidth() * heightRatio;
52             } else {
53                 me.minHeight = me.el.getHeight() * widthRatio;
54             }
55         }
56
57         // If configured as throttled, create an instance version of resize which calls
58         // a throttled function to perform the resize operation.
59         if (me.throttle) {
60             var throttledResizeFn = Ext.Function.createThrottled(function() {
61                     Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
62                 }, me.throttle);
63
64             me.resize = function(box, direction, atEnd) {
65                 if (atEnd) {
66                     Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
67                 } else {
68                     throttledResizeFn.apply(null, arguments);
69                 }
70             };
71         }
72     },
73
74     onBeforeStart: function(e) {
75         // record the startBox
76         this.startBox = this.el.getBox();
77     },
78
79 <span id='Ext-resizer-ResizeTracker-method-getDynamicTarget'>    /**
80 </span>     * @private
81      * Returns the object that will be resized on every mousemove event.
82      * If dynamic is false, this will be a proxy, otherwise it will be our actual target.
83      */
84     getDynamicTarget: function() {
85         var d = this.target;
86         if (this.dynamic) {
87             return d;
88         } else if (!this.proxy) {
89             this.proxy = d.isComponent ? d.getProxy().addCls(Ext.baseCSSPrefix + 'resizable-proxy') : d.createProxy({tag: 'div', cls: Ext.baseCSSPrefix + 'resizable-proxy', id: d.id + '-rzproxy'}, Ext.getBody());
90             this.proxy.removeCls(Ext.baseCSSPrefix + 'proxy-el');
91         }
92         this.proxy.show();
93         return this.proxy;
94     },
95
96     onStart: function(e) {
97         // returns the Ext.ResizeHandle that the user started dragging
98         this.activeResizeHandle = Ext.getCmp(this.getDragTarget().id);
99
100         // If we are using a proxy, ensure it is sized.
101         if (!this.dynamic) {
102             this.resize(this.startBox, {
103                 horizontal: 'none',
104                 vertical: 'none'
105             });
106         }
107     },
108
109     onDrag: function(e) {
110         // dynamic resizing, update dimensions during resize
111         if (this.dynamic || this.proxy) {
112             this.updateDimensions(e);
113         }
114     },
115
116     updateDimensions: function(e, atEnd) {
117         var me = this,
118             region = me.activeResizeHandle.region,
119             offset = me.getOffset(me.constrainTo ? 'dragTarget' : null),
120             box = me.startBox,
121             ratio,
122             widthAdjust = 0,
123             heightAdjust = 0,
124             adjustX = 0,
125             adjustY = 0,
126             dragRatio,
127             horizDir = offset[0] &lt; 0 ? 'right' : 'left',
128             vertDir = offset[1] &lt; 0 ? 'down' : 'up',
129             oppositeCorner,
130             axis; // 1 = x, 2 = y, 3 = x and y.
131
132         switch (region) {
133             case 'south':
134                 heightAdjust = offset[1];
135                 axis = 2;
136                 break;
137             case 'north':
138                 heightAdjust = -offset[1];
139                 adjustY = -heightAdjust;
140                 axis = 2;
141                 break;
142             case 'east':
143                 widthAdjust = offset[0];
144                 axis = 1;
145                 break;
146             case 'west':
147                 widthAdjust = -offset[0];
148                 adjustX = -widthAdjust;
149                 axis = 1;
150                 break;
151             case 'northeast':
152                 heightAdjust = -offset[1];
153                 adjustY = -heightAdjust;
154                 widthAdjust = offset[0];
155                 oppositeCorner = [box.x, box.y + box.height];
156                 axis = 3;
157                 break;
158             case 'southeast':
159                 heightAdjust = offset[1];
160                 widthAdjust = offset[0];
161                 oppositeCorner = [box.x, box.y];
162                 axis = 3;
163                 break;
164             case 'southwest':
165                 widthAdjust = -offset[0];
166                 adjustX = -widthAdjust;
167                 heightAdjust = offset[1];
168                 oppositeCorner = [box.x + box.width, box.y];
169                 axis = 3;
170                 break;
171             case 'northwest':
172                 heightAdjust = -offset[1];
173                 adjustY = -heightAdjust;
174                 widthAdjust = -offset[0];
175                 adjustX = -widthAdjust;
176                 oppositeCorner = [box.x + box.width, box.y + box.height];
177                 axis = 3;
178                 break;
179         }
180
181         var newBox = {
182             width: box.width + widthAdjust,
183             height: box.height + heightAdjust,
184             x: box.x + adjustX,
185             y: box.y + adjustY
186         };
187
188         // out of bounds
189         if (newBox.width &lt; me.minWidth || newBox.width &gt; me.maxWidth) {
190             newBox.width = Ext.Number.constrain(newBox.width, me.minWidth, me.maxWidth);
191
192             // Re-adjust the X position if we were dragging the west side
193             if (adjustX) {
194                 newBox.x = box.x + (box.width - newBox.width);
195             }
196         } else {
197             me.lastX = newBox.x;
198         }
199         if (newBox.height &lt; me.minHeight || newBox.height &gt; me.maxHeight) {
200             newBox.height = Ext.Number.constrain(newBox.height, me.minHeight, me.maxHeight);
201
202             // Re-adjust the Y position if we were dragging the north side
203             if (adjustY) {
204                 newBox.y = box.y + (box.height - newBox.height);
205             }
206         } else {
207             me.lastY = newBox.y;
208         }
209
210         // If this is configured to preserve the aspect ratio, or they are dragging using the shift key
211         if (me.preserveRatio || e.shiftKey) {
212             var newHeight,
213                 newWidth;
214
215             ratio = me.startBox.width / me.startBox.height;
216
217             // Calculate aspect ratio constrained values.
218             newHeight = Math.min(Math.max(me.minHeight, newBox.width / ratio), me.maxHeight);
219             newWidth = Math.min(Math.max(me.minWidth, newBox.height * ratio), me.maxWidth);
220
221             // X axis: width-only change, height must obey
222             if (axis == 1) {
223                 newBox.height = newHeight;
224             }
225
226             // Y axis: height-only change, width must obey
227             else if (axis == 2) {
228                 newBox.width = newWidth;
229             }
230
231             // Corner drag.
232             else {
233                 // Drag ratio is the ratio of the mouse point from the opposite corner.
234                 // Basically what edge we are dragging, a horizontal edge or a vertical edge.
235                 dragRatio = Math.abs(oppositeCorner[0] - this.lastXY[0]) / Math.abs(oppositeCorner[1] - this.lastXY[1]);
236
237                 // If drag ratio &gt; aspect ratio then width is dominant and height must obey
238                 if (dragRatio &gt; ratio) {
239                     newBox.height = newHeight;
240                 } else {
241                     newBox.width = newWidth;
242                 }
243
244                 // Handle dragging start coordinates
245                 if (region == 'northeast') {
246                     newBox.y = box.y - (newBox.height - box.height);
247                 } else if (region == 'northwest') {
248                     newBox.y = box.y - (newBox.height - box.height);
249                     newBox.x = box.x - (newBox.width - box.width);
250                 } else if (region == 'southwest') {
251                     newBox.x = box.x - (newBox.width - box.width);
252                 }
253             }
254         }
255
256         if (heightAdjust === 0) {
257             vertDir = 'none';
258         }
259         if (widthAdjust === 0) {
260             horizDir = 'none';
261         }
262         me.resize(newBox, {
263             horizontal: horizDir,
264             vertical: vertDir
265         }, atEnd);
266     },
267
268     getResizeTarget: function(atEnd) {
269         return atEnd ? this.target : this.getDynamicTarget();
270     },
271
272     resize: function(box, direction, atEnd) {
273         var target = this.getResizeTarget(atEnd);
274         if (target.isComponent) {
275             if (target.floating) {
276                 target.setPagePosition(box.x, box.y);
277             }
278             target.setSize(box.width, box.height);
279         } else {
280             target.setBox(box);
281             // update the originalTarget if this was wrapped.
282             if (this.originalTarget) {
283                 this.originalTarget.setBox(box);
284             }
285         }
286     },
287
288     onEnd: function(e) {
289         this.updateDimensions(e, true);
290         if (this.proxy) {
291             this.proxy.hide();
292         }
293     }
294 });
295 </pre>
296 </body>
297 </html>