<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>The source code</title>
|
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
|
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
|
<style type="text/css">
|
.highlight { display: block; background-color: #ddd; }
|
</style>
|
<script type="text/javascript">
|
function highlight() {
|
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
|
}
|
</script>
|
</head>
|
<body onload="prettyPrint(); highlight();">
|
<pre class="prettyprint lang-js">// @tag dom,core
|
<span id='Ext-dom-Element_style'>/**
|
</span> */
|
Ext.define('Ext.dom.Element_style', {
|
override: 'Ext.dom.Element'
|
},
|
function() {
|
|
var Element = this,
|
view = document.defaultView,
|
adjustDirect2DTableRe = /table-row|table-.*-group/,
|
INTERNAL = '_internal',
|
HIDDEN = 'hidden',
|
HEIGHT = 'height',
|
WIDTH = 'width',
|
ISCLIPPED = 'isClipped',
|
OVERFLOW = 'overflow',
|
OVERFLOWX = 'overflow-x',
|
OVERFLOWY = 'overflow-y',
|
ORIGINALCLIP = 'originalClip',
|
DOCORBODYRE = /#document|body/i,
|
// This reduces the lookup of 'me.styleHooks' by one hop in the prototype chain. It is
|
// the same object.
|
styleHooks, verticalStyleHooks90, verticalStyleHooks270,
|
edges, k, edge, borderWidth;
|
|
if (!view || !view.getComputedStyle) {
|
Element.prototype.getStyle = function (property, inline) {
|
var me = this,
|
dom = me.dom,
|
multiple = typeof property != 'string',
|
hooks = me.styleHooks,
|
prop = property,
|
props = prop,
|
len = 1,
|
isInline = inline,
|
camel, domStyle, values, hook, out, style, i;
|
|
if (multiple) {
|
values = {};
|
prop = props[0];
|
i = 0;
|
if (!(len = props.length)) {
|
return values;
|
}
|
}
|
|
if (!dom || dom.documentElement) {
|
return values || '';
|
}
|
|
domStyle = dom.style;
|
|
if (inline) {
|
style = domStyle;
|
} else {
|
style = dom.currentStyle;
|
|
// fallback to inline style if rendering context not available
|
if (!style) {
|
isInline = true;
|
style = domStyle;
|
}
|
}
|
|
do {
|
hook = hooks[prop];
|
|
if (!hook) {
|
hooks[prop] = hook = { name: Element.normalize(prop) };
|
}
|
|
if (hook.get) {
|
out = hook.get(dom, me, isInline, style);
|
} else {
|
camel = hook.name;
|
|
// In some cases, IE6 will throw Invalid Argument exceptions for properties
|
// like fontSize (/examples/tabs/tabs.html in 4.0 used to exhibit this but
|
// no longer does due to font style changes). There is a real cost to a try
|
// block, so we avoid it where possible...
|
if (hook.canThrow) {
|
try {
|
out = style[camel];
|
} catch (e) {
|
out = '';
|
}
|
} else {
|
// EXTJSIV-5657 - In IE9 quirks mode there is a chance that VML root element
|
// has neither `currentStyle` nor `style`. Return '' this case.
|
out = style ? style[camel] : '';
|
}
|
}
|
|
if (!multiple) {
|
return out;
|
}
|
|
values[prop] = out;
|
prop = props[++i];
|
} while (i < len);
|
|
return values;
|
};
|
}
|
|
Element.override({
|
getHeight: function(contentHeight, preciseHeight) {
|
var me = this,
|
hidden = me.isStyle('display', 'none'),
|
height,
|
floating;
|
|
if (hidden) {
|
return 0;
|
}
|
|
height = me.dom.offsetHeight;
|
|
// IE9/10 Direct2D dimension rounding bug
|
if (Ext.supports.Direct2DBug) {
|
floating = me.adjustDirect2DDimension(HEIGHT);
|
if (preciseHeight) {
|
height += floating;
|
}
|
else if (floating > 0 && floating < 0.5) {
|
height++;
|
}
|
}
|
|
if (contentHeight) {
|
height -= me.getBorderWidth("tb") + me.getPadding("tb");
|
}
|
|
return (height < 0) ? 0 : height;
|
},
|
|
getWidth: function(contentWidth, preciseWidth) {
|
var me = this,
|
dom = me.dom,
|
hidden = me.isStyle('display', 'none'),
|
rect, width, floating;
|
|
if (hidden) {
|
return 0;
|
}
|
|
// Gecko will in some cases report an offsetWidth that is actually less than the width of the
|
// text contents, because it measures fonts with sub-pixel precision but rounds the calculated
|
// value down. Using getBoundingClientRect instead of offsetWidth allows us to get the precise
|
// subpixel measurements so we can force them to always be rounded up. See
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=458617
|
// Rounding up ensures that the width includes the full width of the text contents.
|
if (preciseWidth && Ext.supports.BoundingClientRect) {
|
rect = dom.getBoundingClientRect();
|
// IE9 is the only browser that supports getBoundingClientRect() and
|
// uses a filter to rotate the element vertically. When a filter
|
// is used to rotate the element, the getHeight/getWidth functions
|
// are not inverted (see setVertical).
|
width = (me.vertical && !Ext.isIE9 && !Ext.supports.RotatedBoundingClientRect) ?
|
(rect.bottom - rect.top) : (rect.right - rect.left);
|
} else {
|
width = dom.offsetWidth;
|
}
|
|
// IE9/10 Direct2D dimension rounding bug: https://sencha.jira.com/browse/EXTJSIV-603
|
// there is no need make adjustments for this bug when the element is vertically
|
// rotated because the width of a vertical element is its rotated height
|
if (Ext.supports.Direct2DBug && !me.vertical) {
|
// get the fractional portion of the sub-pixel precision width of the element's text contents
|
floating = me.adjustDirect2DDimension(WIDTH);
|
if (preciseWidth) {
|
width += floating;
|
}
|
// IE9 also measures fonts with sub-pixel precision, but unlike Gecko, instead of rounding the offsetWidth down,
|
// it rounds to the nearest integer. This means that in order to ensure that the width includes the full
|
// width of the text contents we need to increment the width by 1 only if the fractional portion is less than 0.5
|
else if (floating > 0 && floating < 0.5) {
|
width++;
|
}
|
}
|
|
if (contentWidth) {
|
width -= me.getBorderWidth("lr") + me.getPadding("lr");
|
}
|
|
return (width < 0) ? 0 : width;
|
},
|
|
setWidth: function(width, animate) {
|
var me = this;
|
width = me.adjustWidth(width);
|
if (!animate || !me.anim) {
|
me.dom.style.width = me.addUnits(width);
|
}
|
else {
|
if (!Ext.isObject(animate)) {
|
animate = {};
|
}
|
me.animate(Ext.applyIf({
|
to: {
|
width: width
|
}
|
}, animate));
|
}
|
return me;
|
},
|
|
setHeight : function(height, animate) {
|
var me = this;
|
|
height = me.adjustHeight(height);
|
if (!animate || !me.anim) {
|
me.dom.style.height = me.addUnits(height);
|
}
|
else {
|
if (!Ext.isObject(animate)) {
|
animate = {};
|
}
|
me.animate(Ext.applyIf({
|
to: {
|
height: height
|
}
|
}, animate));
|
}
|
|
return me;
|
},
|
|
applyStyles: function(style) {
|
Ext.DomHelper.applyStyles(this.dom, style);
|
return this;
|
},
|
|
setSize: function(width, height, animate) {
|
var me = this;
|
|
if (Ext.isObject(width)) { // in case of object from getSize()
|
animate = height;
|
height = width.height;
|
width = width.width;
|
}
|
|
width = me.adjustWidth(width);
|
height = me.adjustHeight(height);
|
|
if (!animate || !me.anim) {
|
me.dom.style.width = me.addUnits(width);
|
me.dom.style.height = me.addUnits(height);
|
}
|
else {
|
if (animate === true) {
|
animate = {};
|
}
|
me.animate(Ext.applyIf({
|
to: {
|
width: width,
|
height: height
|
}
|
}, animate));
|
}
|
|
return me;
|
},
|
|
getViewSize : function() {
|
var me = this,
|
dom = me.dom,
|
isDoc = DOCORBODYRE.test(dom.nodeName),
|
ret;
|
|
// If the body, use static methods
|
if (isDoc) {
|
ret = {
|
width : Element.getViewWidth(),
|
height : Element.getViewHeight()
|
};
|
} else {
|
ret = {
|
width : dom.clientWidth,
|
height : dom.clientHeight
|
};
|
}
|
|
return ret;
|
},
|
|
getSize: function(contentSize) {
|
return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
|
},
|
|
// TODO: Look at this
|
|
// private ==> used by Fx
|
adjustWidth : function(width) {
|
var me = this,
|
isNum = (typeof width == 'number');
|
|
if (isNum && me.autoBoxAdjust && !me.isBorderBox()) {
|
width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
|
}
|
return (isNum && width < 0) ? 0 : width;
|
},
|
|
// private ==> used by Fx
|
adjustHeight : function(height) {
|
var me = this,
|
isNum = (typeof height == "number");
|
|
if (isNum && me.autoBoxAdjust && !me.isBorderBox()) {
|
height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
|
}
|
return (isNum && height < 0) ? 0 : height;
|
},
|
|
<span id='Ext-dom-Element-method-getColor'> /**
|
</span> * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like `#fff`) and valid values
|
* are convert to standard 6 digit hex color.
|
* @param {String} attr The css attribute
|
* @param {String} defaultValue The default value to use when a valid color isn't found
|
* @param {String} [prefix] defaults to #. Use an empty string when working with
|
* color anims.
|
*/
|
getColor : function(attr, defaultValue, prefix) {
|
var v = this.getStyle(attr),
|
color = prefix || prefix === '' ? prefix : '#',
|
h, len, i=0;
|
|
if (!v || (/transparent|inherit/.test(v))) {
|
return defaultValue;
|
}
|
if (/^r/.test(v)) {
|
v = v.slice(4, v.length - 1).split(',');
|
len = v.length;
|
for (; i<len; i++) {
|
h = parseInt(v[i], 10);
|
color += (h < 16 ? '0' : '') + h.toString(16);
|
}
|
} else {
|
v = v.replace('#', '');
|
color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
|
}
|
return(color.length > 5 ? color.toLowerCase() : defaultValue);
|
},
|
|
<span id='Ext-dom-Element-method-setOpacity'> /**
|
</span> * Set the opacity of the element
|
* @param {Number} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
|
* @param {Boolean/Object} [animate] a standard Element animation config object or `true` for
|
* the default animation (`{duration: 350, easing: 'easeIn'}`)
|
* @return {Ext.dom.Element} this
|
*/
|
setOpacity: function(opacity, animate) {
|
var me = this;
|
|
if (!me.dom) {
|
return me;
|
}
|
|
if (!animate || !me.anim) {
|
me.setStyle('opacity', opacity);
|
}
|
else {
|
if (typeof animate != 'object') {
|
animate = {
|
duration: 350,
|
easing: 'ease-in'
|
};
|
}
|
|
me.animate(Ext.applyIf({
|
to: {
|
opacity: opacity
|
}
|
}, animate));
|
}
|
return me;
|
},
|
|
<span id='Ext-dom-Element-method-clearOpacity'> /**
|
</span> * Clears any opacity settings from this element. Required in some cases for IE.
|
* @return {Ext.dom.Element} this
|
*/
|
clearOpacity : function() {
|
return this.setOpacity('');
|
},
|
|
<span id='Ext-dom-Element-method-adjustDirect2DDimension'> /**
|
</span> * @private
|
* Returns 1 if the browser returns the subpixel dimension rounded to the lowest pixel.
|
* @return {Number} 0 or 1
|
*/
|
adjustDirect2DDimension: function(dimension) {
|
var me = this,
|
dom = me.dom,
|
display = me.getStyle('display'),
|
inlineDisplay = dom.style.display,
|
inlinePosition = dom.style.position,
|
originIndex = dimension === WIDTH ? 0 : 1,
|
currentStyle = dom.currentStyle,
|
floating;
|
|
if (display === 'inline') {
|
dom.style.display = 'inline-block';
|
}
|
|
dom.style.position = display.match(adjustDirect2DTableRe) ? 'absolute' : 'static';
|
|
// floating will contain digits that appears after the decimal point
|
// if height or width are set to auto we fallback to msTransformOrigin calculation
|
|
// Use currentStyle here instead of getStyle. In some difficult to reproduce
|
// instances it resets the scrollWidth of the element
|
floating = (parseFloat(currentStyle[dimension]) || parseFloat(currentStyle.msTransformOrigin.split(' ')[originIndex]) * 2) % 1;
|
|
dom.style.position = inlinePosition;
|
|
if (display === 'inline') {
|
dom.style.display = inlineDisplay;
|
}
|
|
return floating;
|
},
|
|
<span id='Ext-dom-Element-method-clip'> /**
|
</span> * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
|
* @return {Ext.dom.Element} this
|
*/
|
clip : function() {
|
var me = this,
|
data = (me.$cache || me.getCache()).data,
|
style;
|
|
if (!data[ISCLIPPED]) {
|
data[ISCLIPPED] = true;
|
style = me.getStyle([OVERFLOW, OVERFLOWX, OVERFLOWY]);
|
data[ORIGINALCLIP] = {
|
o: style[OVERFLOW],
|
x: style[OVERFLOWX],
|
y: style[OVERFLOWY]
|
};
|
me.setStyle(OVERFLOW, HIDDEN);
|
me.setStyle(OVERFLOWX, HIDDEN);
|
me.setStyle(OVERFLOWY, HIDDEN);
|
}
|
return me;
|
},
|
|
<span id='Ext-dom-Element-method-unclip'> /**
|
</span> * Return clipping (overflow) to original clipping before {@link #clip} was called
|
* @return {Ext.dom.Element} this
|
*/
|
unclip : function() {
|
var me = this,
|
data = (me.$cache || me.getCache()).data,
|
clip;
|
|
if (data[ISCLIPPED]) {
|
data[ISCLIPPED] = false;
|
clip = data[ORIGINALCLIP];
|
if (clip.o) {
|
me.setStyle(OVERFLOW, clip.o);
|
}
|
if (clip.x) {
|
me.setStyle(OVERFLOWX, clip.x);
|
}
|
if (clip.y) {
|
me.setStyle(OVERFLOWY, clip.y);
|
}
|
}
|
return me;
|
},
|
|
<span id='Ext-dom-Element-method-boxWrap'> /**
|
</span> * Wraps the specified element with a special 9 element markup/CSS block that renders by default as
|
* a gray container with a gradient background, rounded corners and a 4-way shadow.
|
*
|
* This special markup is used throughout Ext when box wrapping elements ({@link Ext.button.Button},
|
* {@link Ext.panel.Panel} when {@link Ext.panel.Panel#frame frame=true}, {@link Ext.window.Window}).
|
* The markup is of this form:
|
*
|
* Ext.dom.Element.boxMarkup =
|
* '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div>
|
* <div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div>
|
* <div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';
|
*
|
* Example usage:
|
*
|
* // Basic box wrap
|
* Ext.get("foo").boxWrap();
|
*
|
* // You can also add a custom class and use CSS inheritance rules to customize the box look.
|
* // 'x-box-blue' is a built-in alternative -- look at the related CSS definitions as an example
|
* // for how to create a custom box wrap style.
|
* Ext.get("foo").boxWrap().addCls("x-box-blue");
|
*
|
* @param {String} [class='x-box'] A base CSS class to apply to the containing wrapper element.
|
* Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
|
* so if you supply an alternate base class, make sure you also supply all of the necessary rules.
|
* @return {Ext.dom.Element} The outermost wrapping element of the created box structure.
|
*/
|
boxWrap : function(cls) {
|
cls = cls || Ext.baseCSSPrefix + 'box';
|
var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + Ext.String.format(Element.boxMarkup, cls) + "</div>"));
|
Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
|
return el;
|
},
|
|
<span id='Ext-dom-Element-method-getComputedHeight'> /**
|
</span> * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
|
* when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
|
* if a height has not been set using CSS.
|
* @return {Number}
|
*/
|
getComputedHeight : function() {
|
var me = this,
|
h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
|
if (!h) {
|
h = parseFloat(me.getStyle(HEIGHT)) || 0;
|
if (!me.isBorderBox()) {
|
h += me.getFrameWidth('tb');
|
}
|
}
|
return h;
|
},
|
|
<span id='Ext-dom-Element-method-getComputedWidth'> /**
|
</span> * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
|
* when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
|
* if a width has not been set using CSS.
|
* @return {Number}
|
*/
|
getComputedWidth : function() {
|
var me = this,
|
w = Math.max(me.dom.offsetWidth, me.dom.clientWidth);
|
|
if (!w) {
|
w = parseFloat(me.getStyle(WIDTH)) || 0;
|
if (!me.isBorderBox()) {
|
w += me.getFrameWidth('lr');
|
}
|
}
|
return w;
|
},
|
|
<span id='Ext-dom-Element-method-getFrameWidth'> /**
|
</span> * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
|
* for more information about the sides.
|
* @param {String} sides
|
* @return {Number}
|
*/
|
getFrameWidth : function(sides, onlyContentBox) {
|
return (onlyContentBox && this.isBorderBox()) ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
|
},
|
|
<span id='Ext-dom-Element-method-addClsOnOver'> /**
|
</span> * Sets up event handlers to add and remove a css class when the mouse is over this element
|
* @param {String} className The class to add
|
* @param {Function} [testFn] A test function to execute before adding the class. The passed parameter
|
* will be the Element instance. If this functions returns false, the class will not be added.
|
* @param {Object} [scope] The scope to execute the testFn in.
|
* @return {Ext.dom.Element} this
|
*/
|
addClsOnOver : function(className, testFn, scope) {
|
var me = this,
|
dom = me.dom,
|
hasTest = Ext.isFunction(testFn);
|
|
me.hover(
|
function() {
|
if (hasTest && testFn.call(scope || me, me) === false) {
|
return;
|
}
|
Ext.fly(dom, INTERNAL).addCls(className);
|
},
|
function() {
|
Ext.fly(dom, INTERNAL).removeCls(className);
|
}
|
);
|
return me;
|
},
|
|
<span id='Ext-dom-Element-method-addClsOnFocus'> /**
|
</span> * Sets up event handlers to add and remove a css class when this element has the focus
|
* @param {String} className The class to add
|
* @param {Function} [testFn] A test function to execute before adding the class. The passed parameter
|
* will be the Element instance. If this functions returns false, the class will not be added.
|
* @param {Object} [scope] The scope to execute the testFn in.
|
* @return {Ext.dom.Element} this
|
*/
|
addClsOnFocus : function(className, testFn, scope) {
|
var me = this,
|
dom = me.dom,
|
hasTest = Ext.isFunction(testFn);
|
|
me.on("focus", function() {
|
if (hasTest && testFn.call(scope || me, me) === false) {
|
return false;
|
}
|
Ext.fly(dom, INTERNAL).addCls(className);
|
});
|
me.on("blur", function() {
|
Ext.fly(dom, INTERNAL).removeCls(className);
|
});
|
return me;
|
},
|
|
<span id='Ext-dom-Element-method-addClsOnClick'> /**
|
</span> * Sets up event handlers to add and remove a css class when the mouse is down and then up on this element (a click effect)
|
* @param {String} className The class to add
|
* @param {Function} [testFn] A test function to execute before adding the class. The passed parameter
|
* will be the Element instance. If this functions returns false, the class will not be added.
|
* @param {Object} [scope] The scope to execute the testFn in.
|
* @return {Ext.dom.Element} this
|
*/
|
addClsOnClick : function(className, testFn, scope) {
|
var me = this,
|
dom = me.dom,
|
hasTest = Ext.isFunction(testFn);
|
|
me.on("mousedown", function() {
|
if (hasTest && testFn.call(scope || me, me) === false) {
|
return false;
|
}
|
Ext.fly(dom, INTERNAL).addCls(className);
|
var d = Ext.getDoc(),
|
fn = function() {
|
Ext.fly(dom, INTERNAL).removeCls(className);
|
d.removeListener("mouseup", fn);
|
};
|
d.on("mouseup", fn);
|
});
|
return me;
|
},
|
|
<span id='Ext-dom-Element-method-getStyleSize'> /**
|
</span> * Returns the dimensions of the element available to lay content out in.
|
*
|
* getStyleSize utilizes prefers style sizing if present, otherwise it chooses the larger of offsetHeight/clientHeight and
|
* offsetWidth/clientWidth. To obtain the size excluding scrollbars, use getViewSize.
|
*
|
* Sizing of the document body is handled at the adapter level which handles special cases for IE and strict modes, etc.
|
*
|
* @return {Object} Object describing width and height.
|
* @return {Number} return.width
|
* @return {Number} return.height
|
*/
|
getStyleSize : function() {
|
var me = this,
|
d = this.dom,
|
isDoc = DOCORBODYRE.test(d.nodeName),
|
s ,
|
w, h;
|
|
// If the body, use static methods
|
if (isDoc) {
|
return {
|
width : Element.getViewWidth(),
|
height : Element.getViewHeight()
|
};
|
}
|
|
s = me.getStyle([HEIGHT, WIDTH], true); //seek inline
|
// Use Styles if they are set
|
if (s.width && s.width != 'auto') {
|
w = parseFloat(s.width);
|
if (me.isBorderBox()) {
|
w -= me.getFrameWidth('lr');
|
}
|
}
|
// Use Styles if they are set
|
if (s.height && s.height != 'auto') {
|
h = parseFloat(s.height);
|
if (me.isBorderBox()) {
|
h -= me.getFrameWidth('tb');
|
}
|
}
|
// Use getWidth/getHeight if style not set.
|
return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
|
},
|
|
statics: {
|
selectableCls: Ext.baseCSSPrefix + 'selectable',
|
unselectableCls: Ext.baseCSSPrefix + 'unselectable'
|
},
|
|
<span id='Ext-dom-Element-method-selectable'> /**
|
</span> * Enable text selection for this element (normalized across browsers)
|
* @return {Ext.Element} this
|
*/
|
selectable : function() {
|
var me = this;
|
|
// We clear this property for all browsers, not just Opera. This is so that rendering templates don't need to
|
// condition on Opera when making elements unselectable.
|
me.dom.unselectable = '';
|
|
me.removeCls(Element.unselectableCls);
|
me.addCls(Element.selectableCls);
|
|
return me;
|
},
|
|
<span id='Ext-dom-Element-method-unselectable'> /**
|
</span> * Disables text selection for this element (normalized across browsers)
|
* @return {Ext.dom.Element} this
|
*/
|
unselectable : function() {
|
// The approach used to disable text selection combines CSS, HTML attributes and DOM events. Importantly the
|
// strategy is designed to be expressible in markup, so that elements can be rendered unselectable without
|
// needing modifications post-render. e.g.:
|
//
|
// <div class="x-unselectable" unselectable="on"></div>
|
//
|
// Changes to this method may need to be reflected elsewhere, e.g. ProtoElement.
|
var me = this;
|
|
// The unselectable property (or similar) is supported by various browsers but Opera is the only browser that
|
// doesn't support any of the other techniques. The problem with it is that it isn't inherited by child
|
// elements. Theoretically we could add it to all children but the performance would be terrible. In certain
|
// key locations (e.g. panel headers) we add unselectable="on" to extra elements during rendering just for
|
// Opera's benefit.
|
if (Ext.isOpera) {
|
me.dom.unselectable = 'on';
|
}
|
|
// In Mozilla and WebKit the CSS properties -moz-user-select and -webkit-user-select prevent a selection
|
// originating in an element. These are inherited, which is what we want.
|
//
|
// In IE we rely on a listener for the selectstart event instead. We don't need to register a listener on the
|
// individual element, instead we use a single listener and rely on event propagation to listen for the event at
|
// the document level. That listener will walk up the DOM looking for nodes that have either of the classes
|
// x-selectable or x-unselectable. This simulates the CSS inheritance approach.
|
//
|
// IE 10 is expected to support -ms-user-select so the listener may not be required.
|
me.removeCls(Element.selectableCls);
|
me.addCls(Element.unselectableCls);
|
|
return me;
|
},
|
|
<span id='Ext-dom-Element-method-setVertical'> /**
|
</span> * Changes this Element's state to "vertical" (rotated 90 or 270 degrees).
|
* This involves inverting the getters and setters for height and width,
|
* and applying hooks for rotating getters and setters for border/margin/padding.
|
* (getWidth becomes getHeight and vice versa), setStyle and getStyle will
|
* also return the inverse when height or width are being operated on.
|
*
|
* @param {Number} angle the angle of rotation - either 90 or 270
|
* @param {String} cls an optional css class that contains the required
|
* styles for switching the element to vertical orientation. Omit this if
|
* the element already contains vertical styling. If cls is provided,
|
* it will be removed from the element when {@link #setHorizontal} is called.
|
* @private
|
*/
|
setVertical: function(angle, cls) {
|
var me = this,
|
proto = Element.prototype,
|
hooks;
|
|
me.vertical = true;
|
if (cls) {
|
me.addCls(me.verticalCls = cls);
|
}
|
|
me.setWidth = proto.setHeight;
|
me.setHeight = proto.setWidth;
|
if (!Ext.isIE9m) {
|
// In browsers that use CSS3 transforms we must invert getHeight and
|
// get Width. In IE9 and below no adjustment is needed because we use
|
// a BasicImage filter to rotate the element and the element's
|
// offsetWidth and offsetHeight are automatically inverted.
|
me.getWidth = proto.getHeight;
|
me.getHeight = proto.getWidth;
|
}
|
|
// Switch to using the appropriate vertical style hooks
|
me.styleHooks = (angle === 270) ?
|
Element.prototype.verticalStyleHooks270 : Element.prototype.verticalStyleHooks90;
|
},
|
|
<span id='Ext-dom-Element-method-setHorizontal'> /**
|
</span> * Removes "vertical" state from this element (reverses everything done
|
* by {@link #setVertical}).
|
* @private
|
*/
|
setHorizontal: function() {
|
var me = this,
|
cls = me.verticalCls;
|
|
delete me.vertical;
|
if (cls) {
|
delete me.verticalCls;
|
me.removeCls(cls);
|
}
|
|
// delete the inverted methods and revert to inheriting from the prototype
|
delete me.setWidth;
|
delete me.setHeight;
|
if (!Ext.isIE9m) {
|
delete me.getWidth;
|
delete me.getHeight;
|
}
|
|
// revert to inheriting styleHooks from the prototype
|
delete me.styleHooks;
|
}
|
});
|
|
Element.prototype.styleHooks = styleHooks = Ext.dom.AbstractElement.prototype.styleHooks;
|
|
// When elements are rotated 80 or 270 degrees, their border, margin and padding hooks
|
// need to be rotated as well.
|
Element.prototype.verticalStyleHooks90 = verticalStyleHooks90 = Ext.Object.chain(Element.prototype.styleHooks);
|
Element.prototype.verticalStyleHooks270 = verticalStyleHooks270 = Ext.Object.chain(Element.prototype.styleHooks);
|
|
verticalStyleHooks90.width = { name: 'height' };
|
verticalStyleHooks90.height = { name: 'width' };
|
verticalStyleHooks90['margin-top'] = { name: 'marginLeft' };
|
verticalStyleHooks90['margin-right'] = { name: 'marginTop' };
|
verticalStyleHooks90['margin-bottom'] = { name: 'marginRight' };
|
verticalStyleHooks90['margin-left'] = { name: 'marginBottom' };
|
verticalStyleHooks90['padding-top'] = { name: 'paddingLeft' };
|
verticalStyleHooks90['padding-right'] = { name: 'paddingTop' };
|
verticalStyleHooks90['padding-bottom'] = { name: 'paddingRight' };
|
verticalStyleHooks90['padding-left'] = { name: 'paddingBottom' };
|
verticalStyleHooks90['border-top'] = { name: 'borderLeft' };
|
verticalStyleHooks90['border-right'] = { name: 'borderTop' };
|
verticalStyleHooks90['border-bottom'] = { name: 'borderRight' };
|
verticalStyleHooks90['border-left'] = { name: 'borderBottom' };
|
|
verticalStyleHooks270.width = { name: 'height' };
|
verticalStyleHooks270.height = { name: 'width' };
|
verticalStyleHooks270['margin-top'] = { name: 'marginRight' };
|
verticalStyleHooks270['margin-right'] = { name: 'marginBottom' };
|
verticalStyleHooks270['margin-bottom'] = { name: 'marginLeft' };
|
verticalStyleHooks270['margin-left'] = { name: 'marginTop' };
|
verticalStyleHooks270['padding-top'] = { name: 'paddingRight' };
|
verticalStyleHooks270['padding-right'] = { name: 'paddingBottom' };
|
verticalStyleHooks270['padding-bottom'] = { name: 'paddingLeft' };
|
verticalStyleHooks270['padding-left'] = { name: 'paddingTop' };
|
verticalStyleHooks270['border-top'] = { name: 'borderRight' };
|
verticalStyleHooks270['border-right'] = { name: 'borderBottom' };
|
verticalStyleHooks270['border-bottom'] = { name: 'borderLeft' };
|
verticalStyleHooks270['border-left'] = { name: 'borderTop' };
|
|
if (Ext.isIE7m) {
|
styleHooks.fontSize = styleHooks['font-size'] = {
|
name: 'fontSize',
|
canThrow: true
|
};
|
|
styleHooks.fontStyle = styleHooks['font-style'] = {
|
name: 'fontStyle',
|
canThrow: true
|
};
|
|
styleHooks.fontFamily = styleHooks['font-family'] = {
|
name: 'fontFamily',
|
canThrow: true
|
};
|
}
|
|
// override getStyle for border-*-width
|
if (Ext.isIEQuirks || Ext.isIE && Ext.ieVersion <= 8) {
|
function getBorderWidth (dom, el, inline, style) {
|
if (style[this.styleName] == 'none') {
|
return '0px';
|
}
|
return style[this.name];
|
}
|
|
edges = ['Top','Right','Bottom','Left'];
|
k = edges.length;
|
|
while (k--) {
|
edge = edges[k];
|
borderWidth = 'border' + edge + 'Width';
|
|
styleHooks['border-'+edge.toLowerCase()+'-width'] = styleHooks[borderWidth] = {
|
name: borderWidth,
|
styleName: 'border' + edge + 'Style',
|
get: getBorderWidth
|
};
|
}
|
}
|
|
// The following hack is needed to support padding on dom elements with display:table.
|
// It was added because at one point auto layout's "outerCt" element had padding applied
|
// to it. The padding is now appplied to the innerCt which is display:table-cell, so this
|
// hack is not currently needed.
|
//if (Ext.isIE9 && Ext.isStrict) {
|
// // In IE9, getComputedStyle always returns 0px for padding if the element has
|
// // "display:table", so we use currentStyle instead.
|
// var names = {
|
// padding: 'padding',
|
// paddingTop: 'padding-top',
|
// paddingRight: 'padding-right',
|
// paddingBottom: 'padding-bottom',
|
// paddingLeft: 'padding-left'
|
// },
|
// createHook = function(name, camelCaseName) {
|
// styleHooks[name] = styleHooks[camelCaseName] = {
|
// name: name,
|
// get: function(dom) {
|
// return dom.currentStyle[name];
|
// }
|
// }
|
// },
|
// camelCaseName;
|
//
|
// for (camelCaseName in names) {
|
// createHook(names[camelCaseName], camelCaseName);
|
// }
|
//}
|
|
// Element.unselectable relies on this listener to prevent selection in IE. Some other browsers support the event too
|
// but it is only strictly required for IE. In WebKit this listener causes subtle differences to how the browser handles
|
// the non-selection, e.g. whether or not the mouse cursor changes when attempting to select text.
|
Ext.getDoc().on('selectstart', function(ev, dom) {
|
var doc = document.documentElement,
|
selectableCls = Element.selectableCls,
|
unselectableCls = Element.unselectableCls,
|
tagName = dom && dom.tagName;
|
|
tagName = tagName && tagName.toLowerCase();
|
|
// Element.unselectable is not really intended to handle selection within text fields and it is important that
|
// fields inside menus or panel headers don't inherit the unselectability. In most browsers this is automatic but in
|
// IE 9 the selectstart event can bubble up from text fields so we have to explicitly handle that case.
|
if (tagName === 'input' || tagName === 'textarea') {
|
return;
|
}
|
|
// Walk up the DOM checking the nodes. This may be 'slow' but selectstart events don't fire very often
|
while (dom && dom.nodeType === 1 && dom !== doc) {
|
var el = Ext.fly(dom);
|
|
// If the node has the class x-selectable then stop looking, the text selection is allowed
|
if (el.hasCls(selectableCls)) {
|
return;
|
}
|
|
// If the node has class x-unselectable then the text selection needs to be stopped
|
if (el.hasCls(unselectableCls)) {
|
ev.stopEvent();
|
return;
|
}
|
|
dom = dom.parentNode;
|
}
|
});
|
|
});
|
|
Ext.onReady(function () {
|
var opacityRe = /alpha\(opacity=(.*)\)/i,
|
trimRe = /^\s+|\s+$/g,
|
hooks = Ext.dom.Element.prototype.styleHooks;
|
|
// Ext.supports flags are not populated until onReady...
|
hooks.opacity = {
|
name: 'opacity',
|
afterSet: function(dom, value, el) {
|
if (el.isLayer) {
|
el.onOpacitySet(value);
|
}
|
}
|
};
|
if (!Ext.supports.Opacity && Ext.isIE) {
|
Ext.apply(hooks.opacity, {
|
get: function (dom) {
|
var filter = dom.style.filter,
|
match, opacity;
|
if (filter.match) {
|
match = filter.match(opacityRe);
|
if (match) {
|
opacity = parseFloat(match[1]);
|
if (!isNaN(opacity)) {
|
return opacity ? opacity / 100 : 0;
|
}
|
}
|
}
|
return 1;
|
},
|
set: function (dom, value) {
|
var style = dom.style,
|
val = style.filter.replace(opacityRe, '').replace(trimRe, '');
|
|
style.zoom = 1; // ensure dom.hasLayout
|
|
// value can be a number or '' or null... so treat falsey as no opacity
|
if (typeof(value) == 'number' && value >= 0 && value < 1) {
|
value *= 100;
|
style.filter = val + (val.length ? ' ' : '') + 'alpha(opacity='+value+')';
|
} else {
|
style.filter = val;
|
}
|
}
|
});
|
}
|
// else there is no work around for the lack of opacity support. Should not be a
|
// problem given that this has been supported for a long time now...
|
});
|
</pre>
|
</body>
|
</html>
|