Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / src / core / core / Element.position.js
1 /*!
2  * Ext JS Library 3.0.0
3  * Copyright(c) 2006-2009 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**\r
8  * @class Ext.Element\r
9  */\r
10 (function(){\r
11 var D = Ext.lib.Dom,\r
12         LEFT = "left",\r
13         RIGHT = "right",\r
14         TOP = "top",\r
15         BOTTOM = "bottom",\r
16         POSITION = "position",\r
17         STATIC = "static",\r
18         RELATIVE = "relative",\r
19         AUTO = "auto",\r
20         ZINDEX = "z-index";\r
21 \r
22 function animTest(args, animate, i) {\r
23         return this.preanim && !!animate ? this.preanim(args, i) : false        \r
24 }\r
25 \r
26 Ext.Element.addMethods({\r
27         /**\r
28       * Gets the current X position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
29       * @return {Number} The X position of the element\r
30       */\r
31     getX : function(){\r
32         return D.getX(this.dom);\r
33     },\r
34 \r
35     /**\r
36       * Gets the current Y position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
37       * @return {Number} The Y position of the element\r
38       */\r
39     getY : function(){\r
40         return D.getY(this.dom);\r
41     },\r
42 \r
43     /**\r
44       * Gets the current position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
45       * @return {Array} The XY position of the element\r
46       */\r
47     getXY : function(){\r
48         return D.getXY(this.dom);\r
49     },\r
50 \r
51     /**\r
52       * Returns the offsets of this element from the passed element. Both element must be part of the DOM tree and not have display:none to have page coordinates.\r
53       * @param {Mixed} element The element to get the offsets from.\r
54       * @return {Array} The XY page offsets (e.g. [100, -200])\r
55       */\r
56     getOffsetsTo : function(el){\r
57         var o = this.getXY(),\r
58                 e = Ext.fly(el, '_internal').getXY();\r
59         return [o[0]-e[0],o[1]-e[1]];\r
60     },\r
61 \r
62     /**\r
63      * Sets the X position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
64      * @param {Number} The X position of the element\r
65      * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object\r
66      * @return {Ext.Element} this\r
67      */\r
68     setX : function(x, animate){            \r
69             return this.setXY([x, this.getY()], animTest.call(this, arguments, animate, 1));\r
70     },\r
71 \r
72     /**\r
73      * Sets the Y position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
74      * @param {Number} The Y position of the element\r
75      * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object\r
76      * @return {Ext.Element} this\r
77      */\r
78     setY : function(y, animate){            \r
79             return this.setXY([this.getX(), y], animTest.call(this, arguments, animate, 1));\r
80     },\r
81 \r
82     /**\r
83      * Sets the element's left position directly using CSS style (instead of {@link #setX}).\r
84      * @param {String} left The left CSS property value\r
85      * @return {Ext.Element} this\r
86      */\r
87     setLeft : function(left){\r
88         this.setStyle(LEFT, this.addUnits(left));\r
89         return this;\r
90     },\r
91 \r
92     /**\r
93      * Sets the element's top position directly using CSS style (instead of {@link #setY}).\r
94      * @param {String} top The top CSS property value\r
95      * @return {Ext.Element} this\r
96      */\r
97     setTop : function(top){\r
98         this.setStyle(TOP, this.addUnits(top));\r
99         return this;\r
100     },\r
101 \r
102     /**\r
103      * Sets the element's CSS right style.\r
104      * @param {String} right The right CSS property value\r
105      * @return {Ext.Element} this\r
106      */\r
107     setRight : function(right){\r
108         this.setStyle(RIGHT, this.addUnits(right));\r
109         return this;\r
110     },\r
111 \r
112     /**\r
113      * Sets the element's CSS bottom style.\r
114      * @param {String} bottom The bottom CSS property value\r
115      * @return {Ext.Element} this\r
116      */\r
117     setBottom : function(bottom){\r
118         this.setStyle(BOTTOM, this.addUnits(bottom));\r
119         return this;\r
120     },\r
121 \r
122     /**\r
123      * Sets the position of the element in page coordinates, regardless of how the element is positioned.\r
124      * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
125      * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)\r
126      * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object\r
127      * @return {Ext.Element} this\r
128      */\r
129     setXY : function(pos, animate){\r
130             var me = this;\r
131         if(!animate || !me.anim){\r
132             D.setXY(me.dom, pos);\r
133         }else{\r
134             me.anim({points: {to: pos}}, me.preanim(arguments, 1), 'motion');\r
135         }\r
136         return me;\r
137     },\r
138 \r
139     /**\r
140      * Sets the position of the element in page coordinates, regardless of how the element is positioned.\r
141      * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
142      * @param {Number} x X value for new position (coordinates are page-based)\r
143      * @param {Number} y Y value for new position (coordinates are page-based)\r
144      * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object\r
145      * @return {Ext.Element} this\r
146      */\r
147     setLocation : function(x, y, animate){\r
148         return this.setXY([x, y], animTest.call(this, arguments, animate, 2));\r
149     },\r
150 \r
151     /**\r
152      * Sets the position of the element in page coordinates, regardless of how the element is positioned.\r
153      * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
154      * @param {Number} x X value for new position (coordinates are page-based)\r
155      * @param {Number} y Y value for new position (coordinates are page-based)\r
156      * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object\r
157      * @return {Ext.Element} this\r
158      */\r
159     moveTo : function(x, y, animate){\r
160         return this.setXY([x, y], animTest.call(this, arguments, animate, 2));        \r
161     },    \r
162     \r
163     /**\r
164      * Gets the left X coordinate\r
165      * @param {Boolean} local True to get the local css position instead of page coordinate\r
166      * @return {Number}\r
167      */\r
168     getLeft : function(local){\r
169             return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;\r
170     },\r
171 \r
172     /**\r
173      * Gets the right X coordinate of the element (element X position + element width)\r
174      * @param {Boolean} local True to get the local css position instead of page coordinate\r
175      * @return {Number}\r
176      */\r
177     getRight : function(local){\r
178             var me = this;\r
179             return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;\r
180     },\r
181 \r
182     /**\r
183      * Gets the top Y coordinate\r
184      * @param {Boolean} local True to get the local css position instead of page coordinate\r
185      * @return {Number}\r
186      */\r
187     getTop : function(local) {\r
188             return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;\r
189     },\r
190 \r
191     /**\r
192      * Gets the bottom Y coordinate of the element (element Y position + element height)\r
193      * @param {Boolean} local True to get the local css position instead of page coordinate\r
194      * @return {Number}\r
195      */\r
196     getBottom : function(local){\r
197             var me = this;\r
198             return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;\r
199     },\r
200 \r
201     /**\r
202     * Initializes positioning on this element. If a desired position is not passed, it will make the\r
203     * the element positioned relative IF it is not already positioned.\r
204     * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"\r
205     * @param {Number} zIndex (optional) The zIndex to apply\r
206     * @param {Number} x (optional) Set the page X position\r
207     * @param {Number} y (optional) Set the page Y position\r
208     */\r
209     position : function(pos, zIndex, x, y){\r
210             var me = this;\r
211             \r
212         if(!pos && me.isStyle(POSITION, STATIC)){           \r
213             me.setStyle(POSITION, RELATIVE);           \r
214         } else if(pos) {\r
215             me.setStyle(POSITION, pos);\r
216         }\r
217         if(zIndex){\r
218             me.setStyle(ZINDEX, zIndex);\r
219         }\r
220         if(x || y) me.setXY([x || false, y || false]);\r
221     },\r
222 \r
223     /**\r
224     * Clear positioning back to the default when the document was loaded\r
225     * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.\r
226     * @return {Ext.Element} this\r
227      */\r
228     clearPositioning : function(value){\r
229         value = value || '';\r
230         this.setStyle({\r
231             left : value,\r
232             right : value,\r
233             top : value,\r
234             bottom : value,\r
235             "z-index" : "",\r
236             position : STATIC\r
237         });\r
238         return this;\r
239     },\r
240 \r
241     /**\r
242     * Gets an object with all CSS positioning properties. Useful along with setPostioning to get\r
243     * snapshot before performing an update and then restoring the element.\r
244     * @return {Object}\r
245     */\r
246     getPositioning : function(){\r
247         var l = this.getStyle(LEFT);\r
248         var t = this.getStyle(TOP);\r
249         return {\r
250             "position" : this.getStyle(POSITION),\r
251             "left" : l,\r
252             "right" : l ? "" : this.getStyle(RIGHT),\r
253             "top" : t,\r
254             "bottom" : t ? "" : this.getStyle(BOTTOM),\r
255             "z-index" : this.getStyle(ZINDEX)\r
256         };\r
257     },\r
258     \r
259     /**\r
260     * Set positioning with an object returned by getPositioning().\r
261     * @param {Object} posCfg\r
262     * @return {Ext.Element} this\r
263      */\r
264     setPositioning : function(pc){\r
265             var me = this,\r
266                 style = me.dom.style;\r
267                 \r
268         me.setStyle(pc);\r
269         \r
270         if(pc.right == AUTO){\r
271             style.right = "";\r
272         }\r
273         if(pc.bottom == AUTO){\r
274             style.bottom = "";\r
275         }\r
276         \r
277         return me;\r
278     },    \r
279         \r
280     /**\r
281      * Translates the passed page coordinates into left/top css values for this element\r
282      * @param {Number/Array} x The page x or an array containing [x, y]\r
283      * @param {Number} y (optional) The page y, required if x is not an array\r
284      * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}\r
285      */\r
286     translatePoints : function(x, y){                \r
287             y = isNaN(x[1]) ? y : x[1];\r
288         x = isNaN(x[0]) ? x : x[0];\r
289         var me = this,\r
290                 relative = me.isStyle(POSITION, RELATIVE),\r
291                 o = me.getXY(),\r
292                 l = parseInt(me.getStyle(LEFT), 10),\r
293                 t = parseInt(me.getStyle(TOP), 10);\r
294         \r
295         l = !isNaN(l) ? l : (relative ? 0 : me.dom.offsetLeft);\r
296         t = !isNaN(t) ? t : (relative ? 0 : me.dom.offsetTop);        \r
297 \r
298         return {left: (x - o[0] + l), top: (y - o[1] + t)}; \r
299     },\r
300     \r
301     animTest : animTest\r
302 });\r
303 })();