950 lines
29 KiB
JavaScript
950 lines
29 KiB
JavaScript
//@tag dom,core
|
|
//@define Ext.Element-all
|
|
//@define Ext.Element-style
|
|
//@require Ext.Element-position
|
|
|
|
/**
|
|
* @class Ext.dom.Element
|
|
*/
|
|
|
|
Ext.dom.Element.addMembers({
|
|
WIDTH: 'width',
|
|
HEIGHT: 'height',
|
|
MIN_WIDTH: 'min-width',
|
|
MIN_HEIGHT: 'min-height',
|
|
MAX_WIDTH: 'max-width',
|
|
MAX_HEIGHT: 'max-height',
|
|
TOP: 'top',
|
|
RIGHT: 'right',
|
|
BOTTOM: 'bottom',
|
|
LEFT: 'left',
|
|
/**
|
|
* @property VISIBILITY
|
|
* Visibility mode constant for use with {@link #setVisibilityMode}. Use `visibility` to hide element.
|
|
*/
|
|
VISIBILITY: 1,
|
|
|
|
/**
|
|
* @property DISPLAY
|
|
* Visibility mode constant for use with {@link #setVisibilityMode}. Use `display` to hide element.
|
|
*/
|
|
DISPLAY: 2,
|
|
|
|
/**
|
|
* @property OFFSETS
|
|
* Visibility mode constant for use with {@link #setVisibilityMode}. Use offsets to hide element.
|
|
*/
|
|
OFFSETS: 3,
|
|
|
|
SEPARATOR: '-',
|
|
|
|
trimRe: /^\s+|\s+$/g,
|
|
wordsRe: /\w/g,
|
|
spacesRe: /\s+/,
|
|
styleSplitRe: /\s*(?::|;)\s*/,
|
|
transparentRe: /^(?:transparent|(?:rgba[(](?:\s*\d+\s*[,]){3}\s*0\s*[)]))$/i,
|
|
classNameSplitRegex: /[\s]+/,
|
|
|
|
borders: {
|
|
t: 'border-top-width',
|
|
r: 'border-right-width',
|
|
b: 'border-bottom-width',
|
|
l: 'border-left-width'
|
|
},
|
|
|
|
paddings: {
|
|
t: 'padding-top',
|
|
r: 'padding-right',
|
|
b: 'padding-bottom',
|
|
l: 'padding-left'
|
|
},
|
|
|
|
margins: {
|
|
t: 'margin-top',
|
|
r: 'margin-right',
|
|
b: 'margin-bottom',
|
|
l: 'margin-left'
|
|
},
|
|
|
|
/**
|
|
* @property {String} defaultUnit
|
|
* The default unit to append to CSS values where a unit isn't provided.
|
|
*/
|
|
defaultUnit: "px",
|
|
|
|
isSynchronized: false,
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
synchronize: function() {
|
|
var dom = this.dom,
|
|
hasClassMap = {},
|
|
className = dom.className,
|
|
classList, i, ln, name;
|
|
|
|
if (className.length > 0) {
|
|
classList = dom.className.split(this.classNameSplitRegex);
|
|
|
|
for (i = 0, ln = classList.length; i < ln; i++) {
|
|
name = classList[i];
|
|
hasClassMap[name] = true;
|
|
}
|
|
}
|
|
else {
|
|
classList = [];
|
|
}
|
|
|
|
this.classList = classList;
|
|
|
|
this.hasClassMap = hasClassMap;
|
|
|
|
this.isSynchronized = true;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Adds the given CSS class(es) to this Element.
|
|
* @param {String} names The CSS class(es) to add to this element.
|
|
* @param {String} [prefix] (optional) Prefix to prepend to each class.
|
|
* @param {String} [suffix] (optional) Suffix to append to each class.
|
|
*/
|
|
addCls: function(names, prefix, suffix) {
|
|
if (!names) {
|
|
return this;
|
|
}
|
|
|
|
if (!this.isSynchronized) {
|
|
this.synchronize();
|
|
}
|
|
|
|
var dom = this.dom,
|
|
map = this.hasClassMap,
|
|
classList = this.classList,
|
|
SEPARATOR = this.SEPARATOR,
|
|
i, ln, name;
|
|
|
|
prefix = prefix ? prefix + SEPARATOR : '';
|
|
suffix = suffix ? SEPARATOR + suffix : '';
|
|
|
|
if (typeof names == 'string') {
|
|
names = names.split(this.spacesRe);
|
|
}
|
|
|
|
for (i = 0, ln = names.length; i < ln; i++) {
|
|
name = prefix + names[i] + suffix;
|
|
|
|
if (!map[name]) {
|
|
map[name] = true;
|
|
classList.push(name);
|
|
}
|
|
}
|
|
|
|
dom.className = classList.join(' ');
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Removes the given CSS class(es) from this Element.
|
|
* @param {String} names The CSS class(es) to remove from this element.
|
|
* @param {String} [prefix=''] Prefix to prepend to each class to be removed.
|
|
* @param {String} [suffix=''] Suffix to append to each class to be removed.
|
|
*/
|
|
removeCls: function(names, prefix, suffix) {
|
|
if (!names) {
|
|
return this;
|
|
}
|
|
|
|
if (!this.isSynchronized) {
|
|
this.synchronize();
|
|
}
|
|
|
|
if (!suffix) {
|
|
suffix = '';
|
|
}
|
|
|
|
var dom = this.dom,
|
|
map = this.hasClassMap,
|
|
classList = this.classList,
|
|
SEPARATOR = this.SEPARATOR,
|
|
i, ln, name;
|
|
|
|
prefix = prefix ? prefix + SEPARATOR : '';
|
|
suffix = suffix ? SEPARATOR + suffix : '';
|
|
|
|
if (typeof names == 'string') {
|
|
names = names.split(this.spacesRe);
|
|
}
|
|
|
|
for (i = 0, ln = names.length; i < ln; i++) {
|
|
name = prefix + names[i] + suffix;
|
|
|
|
if (map[name]) {
|
|
delete map[name];
|
|
Ext.Array.remove(classList, name);
|
|
}
|
|
}
|
|
|
|
dom.className = classList.join(' ');
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Replaces a CSS class on the element with another.
|
|
* If the old name does not exist, the new name will simply be added.
|
|
* @param {String} oldName The CSS class to replace.
|
|
* @param {String} newName The replacement CSS class.
|
|
* @param {String} [prefix=''] Prefix to prepend to each class to be replaced.
|
|
* @param {String} [suffix=''] Suffix to append to each class to be replaced.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
replaceCls: function(oldName, newName, prefix, suffix) {
|
|
if (!oldName && !newName) {
|
|
return this;
|
|
}
|
|
|
|
oldName = oldName || [];
|
|
newName = newName || [];
|
|
|
|
if (!this.isSynchronized) {
|
|
this.synchronize();
|
|
}
|
|
|
|
if (!suffix) {
|
|
suffix = '';
|
|
}
|
|
|
|
var dom = this.dom,
|
|
map = this.hasClassMap,
|
|
classList = this.classList,
|
|
SEPARATOR = this.SEPARATOR,
|
|
i, ln, name;
|
|
|
|
prefix = prefix ? prefix + SEPARATOR : '';
|
|
suffix = suffix ? SEPARATOR + suffix : '';
|
|
|
|
if (typeof oldName == 'string') {
|
|
oldName = oldName.split(this.spacesRe);
|
|
}
|
|
if (typeof newName == 'string') {
|
|
newName = newName.split(this.spacesRe);
|
|
}
|
|
|
|
for (i = 0, ln = oldName.length; i < ln; i++) {
|
|
name = prefix + oldName[i] + suffix;
|
|
|
|
if (map[name]) {
|
|
delete map[name];
|
|
Ext.Array.remove(classList, name);
|
|
}
|
|
}
|
|
|
|
for (i = 0, ln = newName.length; i < ln; i++) {
|
|
name = prefix + newName[i] + suffix;
|
|
|
|
if (!map[name]) {
|
|
map[name] = true;
|
|
classList.push(name);
|
|
}
|
|
}
|
|
|
|
dom.className = classList.join(' ');
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Checks if the specified CSS class exists on this element's DOM node.
|
|
* @param {String} name The CSS class to check for.
|
|
* @return {Boolean} `true` if the class exists, else `false`.
|
|
*/
|
|
hasCls: function(name) {
|
|
if (!this.isSynchronized) {
|
|
this.synchronize();
|
|
}
|
|
|
|
return this.hasClassMap.hasOwnProperty(name);
|
|
},
|
|
|
|
/**
|
|
* Sets the specified CSS class on this element's DOM node.
|
|
* @param {String/Array} className The CSS class to set on this element.
|
|
*/
|
|
setCls: function(className) {
|
|
var map = this.hasClassMap,
|
|
i, ln, name;
|
|
|
|
if (typeof className == 'string') {
|
|
className = className.split(this.spacesRe);
|
|
}
|
|
|
|
for (i = 0, ln = className.length; i < ln; i++) {
|
|
name = className[i];
|
|
if (!map[name]) {
|
|
map[name] = true;
|
|
}
|
|
}
|
|
|
|
this.classList = className.slice();
|
|
this.dom.className = className.join(' ');
|
|
},
|
|
|
|
/**
|
|
* Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
|
|
* @param {String} className The CSS class to toggle.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
toggleCls: function(className, force){
|
|
if (typeof force !== 'boolean') {
|
|
force = !this.hasCls(className);
|
|
}
|
|
|
|
return (force) ? this.addCls(className) : this.removeCls(className);
|
|
},
|
|
|
|
/**
|
|
* @private
|
|
* @param {String} firstClass
|
|
* @param {String} secondClass
|
|
* @param {Boolean} flag
|
|
* @param {String} prefix
|
|
* @return {Mixed}
|
|
*/
|
|
swapCls: function(firstClass, secondClass, flag, prefix) {
|
|
if (flag === undefined) {
|
|
flag = true;
|
|
}
|
|
|
|
var addedClass = flag ? firstClass : secondClass,
|
|
removedClass = flag ? secondClass : firstClass;
|
|
|
|
if (removedClass) {
|
|
this.removeCls(prefix ? prefix + '-' + removedClass : removedClass);
|
|
}
|
|
|
|
if (addedClass) {
|
|
this.addCls(prefix ? prefix + '-' + addedClass : addedClass);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the width of this Element.
|
|
* @param {Number/String} width The new width.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
setWidth: function(width) {
|
|
return this.setLengthValue(this.WIDTH, width);
|
|
},
|
|
|
|
/**
|
|
* Set the height of this Element.
|
|
* @param {Number/String} height The new height.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
setHeight: function(height) {
|
|
return this.setLengthValue(this.HEIGHT, height);
|
|
},
|
|
|
|
/**
|
|
* Set the size of this Element.
|
|
*
|
|
* @param {Number/String} width The new width. This may be one of:
|
|
*
|
|
* - A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels).
|
|
* - A String used to set the CSS width style. Animation may **not** be used.
|
|
* - A size object in the format `{width: widthValue, height: heightValue}`.
|
|
*
|
|
* @param {Number/String} height The new height. This may be one of:
|
|
*
|
|
* - A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels).
|
|
* - A String used to set the CSS height style. Animation may **not** be used.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
setSize: function(width, height) {
|
|
if (Ext.isObject(width)) {
|
|
// in case of object from getSize()
|
|
height = width.height;
|
|
width = width.width;
|
|
}
|
|
|
|
this.setWidth(width);
|
|
this.setHeight(height);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the minimum width of this Element.
|
|
* @param {Number/String} width The new minimum width.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
setMinWidth: function(width) {
|
|
return this.setLengthValue(this.MIN_WIDTH, width);
|
|
},
|
|
|
|
/**
|
|
* Set the minimum height of this Element.
|
|
* @param {Number/String} height The new minimum height.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
setMinHeight: function(height) {
|
|
return this.setLengthValue(this.MIN_HEIGHT, height);
|
|
},
|
|
|
|
/**
|
|
* Set the maximum width of this Element.
|
|
* @param {Number/String} width The new maximum width.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
setMaxWidth: function(width) {
|
|
return this.setLengthValue(this.MAX_WIDTH, width);
|
|
},
|
|
|
|
/**
|
|
* Set the maximum height of this Element.
|
|
* @param {Number/String} height The new maximum height.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
setMaxHeight: function(height) {
|
|
return this.setLengthValue(this.MAX_HEIGHT, height);
|
|
},
|
|
|
|
/**
|
|
* Sets the element's top position directly using CSS style (instead of {@link #setY}).
|
|
* @param {String} top The top CSS property value.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
setTop: function(top) {
|
|
return this.setLengthValue(this.TOP, top);
|
|
},
|
|
|
|
/**
|
|
* Sets the element's CSS right style.
|
|
* @param {String} right The right CSS property value.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
setRight: function(right) {
|
|
return this.setLengthValue(this.RIGHT, right);
|
|
},
|
|
|
|
/**
|
|
* Sets the element's CSS bottom style.
|
|
* @param {String} bottom The bottom CSS property value.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
setBottom: function(bottom) {
|
|
return this.setLengthValue(this.BOTTOM, bottom);
|
|
},
|
|
|
|
/**
|
|
* Sets the element's left position directly using CSS style (instead of {@link #setX}).
|
|
* @param {String} left The left CSS property value.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
setLeft: function(left) {
|
|
return this.setLengthValue(this.LEFT, left);
|
|
},
|
|
|
|
setMargin: function(margin) {
|
|
var domStyle = this.dom.style;
|
|
|
|
if (margin || margin === 0) {
|
|
margin = this.self.unitizeBox((margin === true) ? 5 : margin);
|
|
domStyle.setProperty('margin', margin, 'important');
|
|
}
|
|
else {
|
|
domStyle.removeProperty('margin-top');
|
|
domStyle.removeProperty('margin-right');
|
|
domStyle.removeProperty('margin-bottom');
|
|
domStyle.removeProperty('margin-left');
|
|
}
|
|
},
|
|
|
|
setPadding: function(padding) {
|
|
var domStyle = this.dom.style;
|
|
|
|
if (padding || padding === 0) {
|
|
padding = this.self.unitizeBox((padding === true) ? 5 : padding);
|
|
domStyle.setProperty('padding', padding, 'important');
|
|
}
|
|
else {
|
|
domStyle.removeProperty('padding-top');
|
|
domStyle.removeProperty('padding-right');
|
|
domStyle.removeProperty('padding-bottom');
|
|
domStyle.removeProperty('padding-left');
|
|
}
|
|
},
|
|
|
|
setBorder: function(border) {
|
|
var domStyle = this.dom.style;
|
|
|
|
if (border || border === 0) {
|
|
border = this.self.unitizeBox((border === true) ? 1 : border);
|
|
domStyle.setProperty('border-width', border, 'important');
|
|
}
|
|
else {
|
|
domStyle.removeProperty('border-top-width');
|
|
domStyle.removeProperty('border-right-width');
|
|
domStyle.removeProperty('border-bottom-width');
|
|
domStyle.removeProperty('border-left-width');
|
|
}
|
|
},
|
|
|
|
setLengthValue: function(name, value) {
|
|
var domStyle = this.dom.style;
|
|
|
|
if (value === null) {
|
|
domStyle.removeProperty(name);
|
|
return this;
|
|
}
|
|
|
|
if (typeof value == 'number') {
|
|
value = value + 'px';
|
|
}
|
|
|
|
domStyle.setProperty(name, value, 'important');
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the visibility of the element (see details). If the `visibilityMode` is set to `Element.DISPLAY`, it will use
|
|
* the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the `visibility` property.
|
|
* @param {Boolean} visible Whether the element is visible.
|
|
* @return {Ext.Element} this
|
|
*/
|
|
setVisible: function(visible) {
|
|
var mode = this.getVisibilityMode(),
|
|
method = visible ? 'removeCls' : 'addCls';
|
|
|
|
switch (mode) {
|
|
case this.VISIBILITY:
|
|
this.removeCls(['x-hidden-display', 'x-hidden-offsets']);
|
|
this[method]('x-hidden-visibility');
|
|
break;
|
|
|
|
case this.DISPLAY:
|
|
this.removeCls(['x-hidden-visibility', 'x-hidden-offsets']);
|
|
this[method]('x-hidden-display');
|
|
break;
|
|
|
|
case this.OFFSETS:
|
|
this.removeCls(['x-hidden-visibility', 'x-hidden-display']);
|
|
this[method]('x-hidden-offsets');
|
|
break;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
getVisibilityMode: function() {
|
|
var dom = this.dom,
|
|
mode = Ext.dom.Element.data(dom, 'visibilityMode');
|
|
|
|
if (mode === undefined) {
|
|
Ext.dom.Element.data(dom, 'visibilityMode', mode = this.DISPLAY);
|
|
}
|
|
|
|
return mode;
|
|
},
|
|
|
|
/**
|
|
* Use this to change the visibility mode between {@link #VISIBILITY}, {@link #DISPLAY} or {@link #OFFSETS}.
|
|
*/
|
|
setVisibilityMode: function(mode) {
|
|
this.self.data(this.dom, 'visibilityMode', mode);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Shows this element.
|
|
* Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
|
|
*/
|
|
show: function() {
|
|
var dom = this.dom;
|
|
if (dom) {
|
|
dom.style.removeProperty('display');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Hides this element.
|
|
* Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
|
|
*/
|
|
hide: function() {
|
|
this.dom.style.setProperty('display', 'none', 'important');
|
|
},
|
|
|
|
setVisibility: function(isVisible) {
|
|
var domStyle = this.dom.style;
|
|
|
|
if (isVisible) {
|
|
domStyle.removeProperty('visibility');
|
|
}
|
|
else {
|
|
domStyle.setProperty('visibility', 'hidden', 'important');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* This shared object is keyed by style name (e.g., 'margin-left' or 'marginLeft'). The
|
|
* values are objects with the following properties:
|
|
*
|
|
* * `name` (String) : The actual name to be presented to the DOM. This is typically the value
|
|
* returned by {@link #normalize}.
|
|
* * `get` (Function) : A hook function that will perform the get on this style. These
|
|
* functions receive "(dom, el)" arguments. The `dom` parameter is the DOM Element
|
|
* from which to get the style. The `el` argument (may be `null`) is the Ext.Element.
|
|
* * `set` (Function) : A hook function that will perform the set on this style. These
|
|
* functions receive "(dom, value, el)" arguments. The `dom` parameter is the DOM Element
|
|
* from which to get this style. The `value` parameter is the new value for the style. The
|
|
* `el` argument (may be `null`) is the Ext.Element.
|
|
*
|
|
* The `this` pointer is the object that contains `get` or `set`, which means that
|
|
* `this.name` can be accessed if needed. The hook functions are both optional.
|
|
* @private
|
|
*/
|
|
styleHooks: {},
|
|
|
|
// @private
|
|
addStyles: function(sides, styles) {
|
|
var totalSize = 0,
|
|
sidesArr = sides.match(this.wordsRe),
|
|
i = 0,
|
|
len = sidesArr.length,
|
|
side, size;
|
|
for (; i < len; i++) {
|
|
side = sidesArr[i];
|
|
size = side && parseInt(this.getStyle(styles[side]), 10);
|
|
if (size) {
|
|
totalSize += Math.abs(size);
|
|
}
|
|
}
|
|
return totalSize;
|
|
},
|
|
|
|
/**
|
|
* Checks if the current value of a style is equal to a given value.
|
|
* @param {String} style property whose value is returned.
|
|
* @param {String} value to check against.
|
|
* @return {Boolean} `true` for when the current value equals the given value.
|
|
*/
|
|
isStyle: function(style, val) {
|
|
return this.getStyle(style) == val;
|
|
},
|
|
|
|
getStyleValue: function(name) {
|
|
return this.dom.style.getPropertyValue(name);
|
|
},
|
|
|
|
/**
|
|
* Normalizes `currentStyle` and `computedStyle`.
|
|
* @param {String} prop The style property whose value is returned.
|
|
* @return {String} The current value of the style property for this element.
|
|
*/
|
|
getStyle: function(prop) {
|
|
var me = this,
|
|
dom = me.dom,
|
|
hook = me.styleHooks[prop],
|
|
cs, result;
|
|
|
|
if (dom == document) {
|
|
return null;
|
|
}
|
|
if (!hook) {
|
|
me.styleHooks[prop] = hook = { name: Ext.dom.Element.normalize(prop) };
|
|
}
|
|
if (hook.get) {
|
|
return hook.get(dom, me);
|
|
}
|
|
|
|
cs = window.getComputedStyle(dom, '');
|
|
|
|
// why the dom.style lookup? It is not true that "style == computedStyle" as
|
|
// well as the fact that 0/false are valid answers...
|
|
result = (cs && cs[hook.name]); // || dom.style[hook.name];
|
|
|
|
// WebKit returns rgb values for transparent, how does this work n IE9+
|
|
// if (!supportsTransparentColor && result == 'rgba(0, 0, 0, 0)') {
|
|
// result = 'transparent';
|
|
// }
|
|
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Wrapper for setting style properties, also takes single object parameter of multiple styles.
|
|
* @param {String/Object} property The style property to be set, or an object of multiple styles.
|
|
* @param {String} [value] The value to apply to the given property, or `null` if an object was passed.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
setStyle: function(prop, value) {
|
|
var me = this,
|
|
dom = me.dom,
|
|
hooks = me.styleHooks,
|
|
style = dom.style,
|
|
valueFrom = Ext.valueFrom,
|
|
name, hook;
|
|
|
|
// we don't promote the 2-arg form to object-form to avoid the overhead...
|
|
if (typeof prop == 'string') {
|
|
hook = hooks[prop];
|
|
|
|
if (!hook) {
|
|
hooks[prop] = hook = { name: Ext.dom.Element.normalize(prop) };
|
|
}
|
|
value = valueFrom(value, '');
|
|
|
|
if (hook.set) {
|
|
hook.set(dom, value, me);
|
|
} else {
|
|
style[hook.name] = value;
|
|
}
|
|
}
|
|
else {
|
|
for (name in prop) {
|
|
if (prop.hasOwnProperty(name)) {
|
|
hook = hooks[name];
|
|
|
|
if (!hook) {
|
|
hooks[name] = hook = { name: Ext.dom.Element.normalize(name) };
|
|
}
|
|
|
|
value = valueFrom(prop[name], '');
|
|
|
|
if (hook.set) {
|
|
hook.set(dom, value, me);
|
|
}
|
|
else {
|
|
style[hook.name] = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return me;
|
|
},
|
|
|
|
/**
|
|
* Returns the offset height of the element.
|
|
* @param {Boolean} [contentHeight] `true` to get the height minus borders and padding.
|
|
* @return {Number} The element's height.
|
|
*/
|
|
getHeight: function(contentHeight) {
|
|
var dom = this.dom,
|
|
height = contentHeight ? (dom.clientHeight - this.getPadding("tb")) : dom.offsetHeight;
|
|
return height > 0 ? height : 0;
|
|
},
|
|
|
|
/**
|
|
* Returns the offset width of the element.
|
|
* @param {Boolean} [contentWidth] `true` to get the width minus borders and padding.
|
|
* @return {Number} The element's width.
|
|
*/
|
|
getWidth: function(contentWidth) {
|
|
var dom = this.dom,
|
|
width = contentWidth ? (dom.clientWidth - this.getPadding("lr")) : dom.offsetWidth;
|
|
return width > 0 ? width : 0;
|
|
},
|
|
|
|
/**
|
|
* Gets the width of the border(s) for the specified side(s)
|
|
* @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
|
|
* passing `'lr'` would get the border **l**eft width + the border **r**ight width.
|
|
* @return {Number} The width of the sides passed added together
|
|
*/
|
|
getBorderWidth: function(side) {
|
|
return this.addStyles(side, this.borders);
|
|
},
|
|
|
|
/**
|
|
* Gets the width of the padding(s) for the specified side(s).
|
|
* @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
|
|
* passing `'lr'` would get the padding **l**eft + the padding **r**ight.
|
|
* @return {Number} The padding of the sides passed added together.
|
|
*/
|
|
getPadding: function(side) {
|
|
return this.addStyles(side, this.paddings);
|
|
},
|
|
|
|
/**
|
|
* More flexible version of {@link #setStyle} for setting style properties.
|
|
* @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form `{width:"100px"}`, or
|
|
* a function which returns such a specification.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
applyStyles: function(styles) {
|
|
if (styles) {
|
|
var dom = this.dom,
|
|
styleType, i, len;
|
|
|
|
if (typeof styles == 'function') {
|
|
styles = styles.call();
|
|
}
|
|
styleType = typeof styles;
|
|
if (styleType == 'string') {
|
|
styles = Ext.util.Format.trim(styles).split(this.styleSplitRe);
|
|
for (i = 0, len = styles.length; i < len;) {
|
|
dom.style[Ext.dom.Element.normalize(styles[i++])] = styles[i++];
|
|
}
|
|
}
|
|
else if (styleType == 'object') {
|
|
this.setStyle(styles);
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Returns the size of the element.
|
|
* @param {Boolean} [contentSize] `true` to get the width/size minus borders and padding.
|
|
* @return {Object} An object containing the element's size:
|
|
* @return {Number} return.width
|
|
* @return {Number} return.height
|
|
*/
|
|
getSize: function(contentSize) {
|
|
var dom = this.dom;
|
|
return {
|
|
width: Math.max(0, contentSize ? (dom.clientWidth - this.getPadding("lr")) : dom.offsetWidth),
|
|
height: Math.max(0, contentSize ? (dom.clientHeight - this.getPadding("tb")) : dom.offsetHeight)
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Forces the browser to repaint this element.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
repaint: function() {
|
|
var dom = this.dom;
|
|
this.addCls(Ext.baseCSSPrefix + 'repaint');
|
|
setTimeout(function() {
|
|
Ext.fly(dom).removeCls(Ext.baseCSSPrefix + 'repaint');
|
|
}, 1);
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
|
|
* then it returns the calculated width of the sides (see {@link #getPadding}).
|
|
* @param {String} [sides] Any combination of 'l', 'r', 't', 'b' to get the sum of those sides.
|
|
* @return {Object/Number}
|
|
*/
|
|
getMargin: function(side) {
|
|
var me = this,
|
|
hash = {t: "top", l: "left", r: "right", b: "bottom"},
|
|
o = {},
|
|
key;
|
|
|
|
if (!side) {
|
|
for (key in me.margins) {
|
|
o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
|
|
}
|
|
return o;
|
|
} else {
|
|
return me.addStyles.call(me, side, me.margins);
|
|
}
|
|
},
|
|
|
|
translate: function() {
|
|
var transformStyleName = 'webkitTransform' in document.createElement('div').style ? 'webkitTransform' : 'transform';
|
|
|
|
return function(x, y, z) {
|
|
this.dom.style[transformStyleName] = 'translate3d(' + (x || 0) + 'px, ' + (y || 0) + 'px, ' + (z || 0) + 'px)';
|
|
}
|
|
}()
|
|
});
|
|
|
|
//<deprecated product=touch since=2.0>
|
|
Ext.dom.Element.addMembers({
|
|
/**
|
|
* Returns the dimensions of the element available to lay content out in.
|
|
*
|
|
* If the element (or any ancestor element) has CSS style `display: none`, the dimensions will be zero.
|
|
*
|
|
* Example:
|
|
*
|
|
* var vpSize = Ext.getBody().getViewSize();
|
|
*
|
|
* // all Windows created afterwards will have a default value of 90% height and 95% width
|
|
* Ext.Window.override({
|
|
* width: vpSize.width * 0.9,
|
|
* height: vpSize.height * 0.95
|
|
* });
|
|
* // To handle window resizing you would have to hook onto onWindowResize.
|
|
*
|
|
* @deprecated 2.0.0
|
|
* @return {Object} Object describing `width` and `height`:
|
|
* @return {Number} return.width
|
|
* @return {Number} return.height
|
|
*/
|
|
getViewSize: function() {
|
|
//<debug warn>
|
|
Ext.Logger.deprecate("Ext.dom.Element.getViewSize() is deprecated", this);
|
|
//</debug>
|
|
|
|
var doc = document,
|
|
dom = this.dom;
|
|
|
|
if (dom == doc || dom == doc.body) {
|
|
return {
|
|
width: Element.getViewportWidth(),
|
|
height: Element.getViewportHeight()
|
|
};
|
|
}
|
|
else {
|
|
return {
|
|
width: dom.clientWidth,
|
|
height: dom.clientHeight
|
|
};
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Returns `true` if the value of the given property is visually transparent. This
|
|
* may be due to a 'transparent' style value or an rgba value with 0 in the alpha
|
|
* component.
|
|
* @deprecated 2.0.0
|
|
* @param {String} prop The style property whose value is to be tested.
|
|
* @return {Boolean} `true` if the style property is visually transparent.
|
|
*/
|
|
isTransparent: function(prop) {
|
|
//<debug warn>
|
|
Ext.Logger.deprecate("Ext.dom.Element.isTransparent() is deprecated", this);
|
|
//</debug>
|
|
|
|
var value = this.getStyle(prop);
|
|
|
|
return value ? this.transparentRe.test(value) : false;
|
|
},
|
|
|
|
|
|
/**
|
|
* Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
|
|
* @deprecated 2.0.0
|
|
* @param {String/String[]} className The CSS class to add, or an array of classes.
|
|
* @return {Ext.dom.Element} this
|
|
*/
|
|
radioCls: function(className) {
|
|
//<debug warn>
|
|
Ext.Logger.deprecate("Ext.dom.Element.radioCls() is deprecated", this);
|
|
//</debug>
|
|
|
|
var cn = this.dom.parentNode.childNodes,
|
|
v;
|
|
className = Ext.isArray(className) ? className : [className];
|
|
for (var i = 0, len = cn.length; i < len; i++) {
|
|
v = cn[i];
|
|
if (v && v.nodeType == 1) {
|
|
Ext.fly(v, '_internal').removeCls(className);
|
|
}
|
|
}
|
|
return this.addCls(className);
|
|
}
|
|
});
|
|
//</deprecated>
|