3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @class Ext.core.Element
20 var ELEMENT = Ext.core.Element,
25 POSITION = "position",
27 RELATIVE = "relative",
31 Ext.override(Ext.core.Element, {
33 * 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).
34 * @return {Number} The X position of the element
37 return ELEMENT.getX(this.dom);
41 * 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).
42 * @return {Number} The Y position of the element
45 return ELEMENT.getY(this.dom);
49 * 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).
50 * @return {Array} The XY position of the element
53 return ELEMENT.getXY(this.dom);
57 * 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.
58 * @param {Mixed} element The element to get the offsets from.
59 * @return {Array} The XY page offsets (e.g. [100, -200])
61 getOffsetsTo : function(el){
63 e = Ext.fly(el, '_internal').getXY();
64 return [o[0]-e[0],o[1]-e[1]];
68 * 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).
69 * @param {Number} The X position of the element
70 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
71 * @return {Ext.core.Element} this
73 setX : function(x, animate){
74 return this.setXY([x, this.getY()], animate);
78 * 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).
79 * @param {Number} The Y position of the element
80 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
81 * @return {Ext.core.Element} this
83 setY : function(y, animate){
84 return this.setXY([this.getX(), y], animate);
88 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
89 * @param {String} left The left CSS property value
90 * @return {Ext.core.Element} this
92 setLeft : function(left){
93 this.setStyle(LEFT, this.addUnits(left));
98 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
99 * @param {String} top The top CSS property value
100 * @return {Ext.core.Element} this
102 setTop : function(top){
103 this.setStyle(TOP, this.addUnits(top));
108 * Sets the element's CSS right style.
109 * @param {String} right The right CSS property value
110 * @return {Ext.core.Element} this
112 setRight : function(right){
113 this.setStyle(RIGHT, this.addUnits(right));
118 * Sets the element's CSS bottom style.
119 * @param {String} bottom The bottom CSS property value
120 * @return {Ext.core.Element} this
122 setBottom : function(bottom){
123 this.setStyle(BOTTOM, this.addUnits(bottom));
128 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
129 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
130 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
131 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
132 * @return {Ext.core.Element} this
134 setXY: function(pos, animate) {
136 if (!animate || !me.anim) {
137 ELEMENT.setXY(me.dom, pos);
140 if (!Ext.isObject(animate)) {
143 me.animate(Ext.applyIf({ to: { x: pos[0], y: pos[1] } }, animate));
149 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
150 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
151 * @param {Number} x X value for new position (coordinates are page-based)
152 * @param {Number} y Y value for new position (coordinates are page-based)
153 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
154 * @return {Ext.core.Element} this
156 setLocation : function(x, y, animate){
157 return this.setXY([x, y], animate);
161 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
162 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
163 * @param {Number} x X value for new position (coordinates are page-based)
164 * @param {Number} y Y value for new position (coordinates are page-based)
165 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
166 * @return {Ext.core.Element} this
168 moveTo : function(x, y, animate){
169 return this.setXY([x, y], animate);
173 * Gets the left X coordinate
174 * @param {Boolean} local True to get the local css position instead of page coordinate
177 getLeft : function(local){
178 return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
182 * Gets the right X coordinate of the element (element X position + element width)
183 * @param {Boolean} local True to get the local css position instead of page coordinate
186 getRight : function(local){
188 return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
192 * Gets the top Y coordinate
193 * @param {Boolean} local True to get the local css position instead of page coordinate
196 getTop : function(local) {
197 return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
201 * Gets the bottom Y coordinate of the element (element Y position + element height)
202 * @param {Boolean} local True to get the local css position instead of page coordinate
205 getBottom : function(local){
207 return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
211 * Initializes positioning on this element. If a desired position is not passed, it will make the
212 * the element positioned relative IF it is not already positioned.
213 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
214 * @param {Number} zIndex (optional) The zIndex to apply
215 * @param {Number} x (optional) Set the page X position
216 * @param {Number} y (optional) Set the page Y position
218 position : function(pos, zIndex, x, y) {
221 if (!pos && me.isStyle(POSITION, STATIC)){
222 me.setStyle(POSITION, RELATIVE);
224 me.setStyle(POSITION, pos);
227 me.setStyle(ZINDEX, zIndex);
230 me.setXY([x || false, y || false]);
235 * Clear positioning back to the default when the document was loaded
236 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
237 * @return {Ext.core.Element} this
239 clearPositioning : function(value){
253 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
254 * snapshot before performing an update and then restoring the element.
257 getPositioning : function(){
258 var l = this.getStyle(LEFT);
259 var t = this.getStyle(TOP);
261 "position" : this.getStyle(POSITION),
263 "right" : l ? "" : this.getStyle(RIGHT),
265 "bottom" : t ? "" : this.getStyle(BOTTOM),
266 "z-index" : this.getStyle(ZINDEX)
271 * Set positioning with an object returned by getPositioning().
272 * @param {Object} posCfg
273 * @return {Ext.core.Element} this
275 setPositioning : function(pc){
277 style = me.dom.style;
281 if(pc.right == AUTO){
284 if(pc.bottom == AUTO){
292 * Translates the passed page coordinates into left/top css values for this element
293 * @param {Number/Array} x The page x or an array containing [x, y]
294 * @param {Number} y (optional) The page y, required if x is not an array
295 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
297 translatePoints: function(x, y) {
298 if (Ext.isArray(x)) {
303 relative = me.isStyle(POSITION, RELATIVE),
305 left = parseInt(me.getStyle(LEFT), 10),
306 top = parseInt(me.getStyle(TOP), 10);
308 if (!Ext.isNumber(left)) {
309 left = relative ? 0 : me.dom.offsetLeft;
311 if (!Ext.isNumber(top)) {
312 top = relative ? 0 : me.dom.offsetTop;
314 left = (Ext.isNumber(x)) ? x - o[0] + left : undefined;
315 top = (Ext.isNumber(y)) ? y - o[1] + top : undefined;
323 * Sets the element's box. Use getBox() on another element to get a box obj. If animate is true then width, height, x and y will be animated concurrently.
324 * @param {Object} box The box to fill {x, y, width, height}
325 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
326 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
327 * @return {Ext.core.Element} this
329 setBox: function(box, adjust, animate) {
333 if ((adjust && !me.autoBoxAdjust) && !me.isBorderBox()) {
334 w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
335 h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
337 me.setBounds(box.x, box.y, w, h, animate);
342 * Return an object defining the area of this Element which can be passed to {@link #setBox} to
343 * set another Element's size/location to match this element.
344 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
345 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
346 * @return {Object} box An object in the format<pre><code>
348 x: <Element's X position>,
349 y: <Element's Y position>,
350 width: <Element's width>,
351 height: <Element's height>,
352 bottom: <Element's lower bound>,
353 right: <Element's rightmost bound>
356 * The returned object may also be addressed as an Array where index 0 contains the X position
357 * and index 1 contains the Y position. So the result may also be used for {@link #setXY}
359 getBox: function(contentBox, local) {
364 getBorderWidth = me.getBorderWidth,
365 getPadding = me.getPadding,
366 l, r, t, b, w, h, bx;
370 left = parseInt(me.getStyle("left"), 10) || 0;
371 top = parseInt(me.getStyle("top"), 10) || 0;
386 l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
387 r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
388 t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
389 b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
399 bx.right = bx.x + bx.width;
400 bx.bottom = bx.y + bx.height;
405 * Move this element relative to its current position.
406 * @param {String} direction Possible values are: "l" (or "left"), "r" (or "right"), "t" (or "top", or "up"), "b" (or "bottom", or "down").
407 * @param {Number} distance How far to move the element in pixels
408 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
409 * @return {Ext.core.Element} this
411 move: function(direction, distance, animate) {
416 left = [x - distance, y],
417 right = [x + distance, y],
418 top = [x, y - distance],
419 bottom = [x, y + distance],
433 direction = direction.toLowerCase();
434 me.moveTo(hash[direction][0], hash[direction][1], animate);
438 * Quick set left and top adding default units
439 * @param {String} left The left CSS property value
440 * @param {String} top The top CSS property value
441 * @return {Ext.core.Element} this
443 setLeftTop: function(left, top) {
445 style = me.dom.style;
446 style.left = me.addUnits(left);
447 style.top = me.addUnits(top);
452 * Returns the region of this element.
453 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
454 * @return {Region} A Ext.util.Region containing "top, left, bottom, right" member data.
456 getRegion: function() {
457 return this.getPageBox(true);
461 * Returns the <b>content</b> region of this element. That is the region within the borders and padding.
462 * @return {Region} A Ext.util.Region containing "top, left, bottom, right" member data.
464 getViewRegion: function() {
466 isBody = me.dom === document.body,
467 scroll, pos, top, left, width, height;
469 // For the body we want to do some special logic
471 scroll = me.getScroll();
474 width = Ext.core.Element.getViewportWidth();
475 height = Ext.core.Element.getViewportHeight();
479 left = pos[0] + me.getBorderWidth('l') + me.getPadding('l');
480 top = pos[1] + me.getBorderWidth('t') + me.getPadding('t');
481 width = me.getWidth(true);
482 height = me.getHeight(true);
485 return Ext.create('Ext.util.Region', top, left + width, top + height, left);
489 * Return an object defining the area of this Element which can be passed to {@link #setBox} to
490 * set another Element's size/location to match this element.
491 * @param {Boolean} asRegion(optional) If true an Ext.util.Region will be returned
492 * @return {Object} box An object in the format<pre><code>
494 x: <Element's X position>,
495 y: <Element's Y position>,
496 width: <Element's width>,
497 height: <Element's height>,
498 bottom: <Element's lower bound>,
499 right: <Element's rightmost bound>
502 * The returned object may also be addressed as an Array where index 0 contains the X position
503 * and index 1 contains the Y position. So the result may also be used for {@link #setXY}
505 getPageBox : function(getRegion) {
508 isDoc = el === document.body,
509 w = isDoc ? Ext.core.Element.getViewWidth() : el.offsetWidth,
510 h = isDoc ? Ext.core.Element.getViewHeight() : el.offsetHeight,
518 return Ext.create('Ext.util.Region', t, r, b, l);
533 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
534 * @param {Number} x X value for new position (coordinates are page-based)
535 * @param {Number} y Y value for new position (coordinates are page-based)
536 * @param {Mixed} width The new width. This may be one of:<div class="mdetail-params"><ul>
537 * <li>A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels)</li>
538 * <li>A String used to set the CSS width style. Animation may <b>not</b> be used.
540 * @param {Mixed} height The new height. This may be one of:<div class="mdetail-params"><ul>
541 * <li>A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels)</li>
542 * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
544 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
545 * @return {Ext.core.Element} this
547 setBounds: function(x, y, width, height, animate) {
549 if (!animate || !me.anim) {
550 me.setSize(width, height);
551 me.setLocation(x, y);
553 if (!Ext.isObject(animate)) {
556 me.animate(Ext.applyIf({
560 width: me.adjustWidth(width),
561 height: me.adjustHeight(height)
569 * Sets the element's position and size the specified region. If animation is true then width, height, x and y will be animated concurrently.
570 * @param {Ext.util.Region} region The region to fill
571 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
572 * @return {Ext.core.Element} this
574 setRegion: function(region, animate) {
575 return this.setBounds(region.left, region.top, region.right - region.left, region.bottom - region.top, animate);