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.
19 // local style camelizing for speed
20 var ELEMENT = Ext.Element,
21 supports = Ext.supports,
22 view = document.defaultView,
23 opacityRe = /alpha\(opacity=(.*)\)/i,
24 trimRe = /^\s+|\s+$/g,
27 adjustDirect2DTableRe = /table-row|table-.*-group/,
28 INTERNAL = '_internal',
39 ISCLIPPED = 'isClipped',
40 OVERFLOW = 'overflow',
41 OVERFLOWX = 'overflow-x',
42 OVERFLOWY = 'overflow-y',
43 ORIGINALCLIP = 'originalClip',
44 // special markup used throughout Ext when box wrapping elements
45 borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
46 paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
47 margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
50 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>';
52 // These property values are read from the parentNode if they cannot be read
54 ELEMENT.inheritedProps = {
60 Ext.override(ELEMENT, {
65 // private ==> used by Fx
66 adjustWidth : function(width) {
68 isNum = (typeof width == 'number');
70 if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
71 width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
73 return (isNum && width < 0) ? 0 : width;
76 // private ==> used by Fx
77 adjustHeight : function(height) {
79 isNum = (typeof height == "number");
81 if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
82 height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
84 return (isNum && height < 0) ? 0 : height;
89 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
90 * @param {String/String[]} className The CSS classes to add separated by space, or an array of classes
91 * @return {Ext.Element} this
93 addCls : function(className){
96 space = ((me.dom.className.replace(trimRe, '') == '') ? "" : " "),
98 if (className === undefined) {
101 // Separate case is for speed
102 if (Object.prototype.toString.call(className) !== '[object Array]') {
103 if (typeof className === 'string') {
104 className = className.replace(trimRe, '').split(spacesRe);
105 if (className.length === 1) {
106 className = className[0];
107 if (!me.hasCls(className)) {
108 me.dom.className += space + className;
111 this.addCls(className);
115 for (i = 0, len = className.length; i < len; i++) {
117 if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
122 me.dom.className += space + cls.join(" ");
129 * Removes one or more CSS classes from the element.
130 * @param {String/String[]} className The CSS classes to remove separated by space, or an array of classes
131 * @return {Ext.Element} this
133 removeCls : function(className){
135 i, idx, len, cls, elClasses;
136 if (className === undefined) {
139 if (Object.prototype.toString.call(className) !== '[object Array]') {
140 className = className.replace(trimRe, '').split(spacesRe);
142 if (me.dom && me.dom.className) {
143 elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
144 for (i = 0, len = className.length; i < len; i++) {
146 if (typeof cls == 'string') {
147 cls = cls.replace(trimRe, '');
148 idx = Ext.Array.indexOf(elClasses, cls);
150 Ext.Array.erase(elClasses, idx, 1);
154 me.dom.className = elClasses.join(" ");
160 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
161 * @param {String/String[]} className The CSS class to add, or an array of classes
162 * @return {Ext.Element} this
164 radioCls : function(className){
165 var cn = this.dom.parentNode.childNodes,
167 className = Ext.isArray(className) ? className : [className];
168 for (i = 0, len = cn.length; i < len; i++) {
170 if (v && v.nodeType == 1) {
171 Ext.fly(v, '_internal').removeCls(className);
174 return this.addCls(className);
178 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
179 * @param {String} className The CSS class to toggle
180 * @return {Ext.Element} this
183 toggleCls : Ext.supports.ClassList ?
184 function(className) {
185 this.dom.classList.toggle(Ext.String.trim(className));
188 function(className) {
189 return this.hasCls(className) ? this.removeCls(className) : this.addCls(className);
193 * Checks if the specified CSS class exists on this element's DOM node.
194 * @param {String} className The CSS class to check for
195 * @return {Boolean} True if the class exists, else false
198 hasCls : Ext.supports.ClassList ?
199 function(className) {
203 className = className.split(spacesRe);
204 var ln = className.length,
206 for (; i < ln; i++) {
207 if (className[i] && this.dom.classList.contains(className[i])) {
214 return className && (' ' + this.dom.className + ' ').indexOf(' ' + className + ' ') != -1;
218 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
219 * @param {String} oldClassName The CSS class to replace
220 * @param {String} newClassName The replacement CSS class
221 * @return {Ext.Element} this
223 replaceCls : function(oldClassName, newClassName){
224 return this.removeCls(oldClassName).addCls(newClassName);
227 isStyle : function(style, val) {
228 return this.getStyle(style) == val;
232 * Normalizes currentStyle and computedStyle.
233 * @param {String} property The style property whose value is returned.
234 * @return {String} The current value of the style property for this element.
237 getStyle : function() {
238 return view && view.getComputedStyle ?
241 v, cs, out, display, cleaner;
246 prop = ELEMENT.normalize(prop);
247 out = (v = el.style[prop]) ? v :
248 (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
250 // Ignore cases when the margin is correctly reported as 0, the bug only shows
252 if(prop == 'marginRight' && out != '0px' && !supports.RightMargin){
253 cleaner = ELEMENT.getRightMarginFixCleaner(el);
254 display = this.getStyle('display');
255 el.style.display = 'inline-block';
256 out = view.getComputedStyle(el, '').marginRight;
257 el.style.display = display;
261 if(prop == 'backgroundColor' && out == 'rgba(0, 0, 0, 0)' && !supports.TransparentColor){
270 if (el == document) {
273 prop = ELEMENT.normalize(prop);
276 if (prop == 'opacity') {
277 if (el.style.filter.match) {
278 m = el.style.filter.match(opacityRe);
280 var fv = parseFloat(m[1]);
282 return fv ? fv / 100 : 0;
289 // the try statement does have a cost, so we avoid it unless we are
292 return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
296 return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
298 // in some cases, IE6 will throw Invalid Argument for properties
299 // like fontSize (see in /examples/tabs/tabs.html).
302 if (!ELEMENT.inheritedProps[prop]) {
307 // this is _not_ perfect, but we can only hope that the style we
308 // need is inherited from a parentNode. If not and since IE won't
309 // give us the info we need, we are never going to be 100% right.
315 msg: 'Failed to get ' + this.dom.id + '.currentStyle.' + prop
323 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
324 * are convert to standard 6 digit hex color.
325 * @param {String} attr The css attribute
326 * @param {String} defaultValue The default value to use when a valid color isn't found
327 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
330 getColor : function(attr, defaultValue, prefix){
331 var v = this.getStyle(attr),
332 color = prefix || prefix === '' ? prefix : '#',
335 if(!v || (/transparent|inherit/.test(v))) {
339 Ext.each(v.slice(4, v.length -1).split(','), function(s){
341 color += (h < 16 ? '0' : '') + h.toString(16);
344 v = v.replace('#', '');
345 color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
347 return(color.length > 5 ? color.toLowerCase() : defaultValue);
351 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
352 * @param {String/Object} property The style property to be set, or an object of multiple styles.
353 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
354 * @return {Ext.Element} this
356 setStyle : function(prop, value){
363 if (typeof prop === 'string') {
368 for (style in prop) {
369 if (prop.hasOwnProperty(style)) {
370 value = Ext.value(prop[style], '');
371 if (style == 'opacity') {
372 me.setOpacity(value);
375 me.dom.style[ELEMENT.normalize(style)] = value;
383 * Set the opacity of the element
384 * @param {Number} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
385 * @param {Boolean/Object} animate (optional) a standard Element animation config object or <tt>true</tt> for
386 * the default animation (<tt>{duration: .35, easing: 'easeIn'}</tt>)
387 * @return {Ext.Element} this
389 setOpacity: function(opacity, animate) {
399 style = me.dom.style;
401 if (!animate || !me.anim) {
402 if (!Ext.supports.Opacity) {
403 opacity = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')': '';
404 val = style.filter.replace(opacityRe, '').replace(trimRe, '');
407 style.filter = val + (val.length > 0 ? ' ': '') + opacity;
410 style.opacity = opacity;
414 if (!Ext.isObject(animate)) {
420 me.animate(Ext.applyIf({
432 * Clears any opacity settings from this element. Required in some cases for IE.
433 * @return {Ext.Element} this
435 clearOpacity : function(){
436 var style = this.dom.style;
437 if(!Ext.supports.Opacity){
438 if(!Ext.isEmpty(style.filter)){
439 style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
442 style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
449 * Returns 1 if the browser returns the subpixel dimension rounded to the lowest pixel.
450 * @return {Number} 0 or 1
452 adjustDirect2DDimension: function(dimension) {
455 display = me.getStyle('display'),
456 inlineDisplay = dom.style['display'],
457 inlinePosition = dom.style['position'],
458 originIndex = dimension === 'width' ? 0 : 1,
461 if (display === 'inline') {
462 dom.style['display'] = 'inline-block';
465 dom.style['position'] = display.match(adjustDirect2DTableRe) ? 'absolute' : 'static';
467 // floating will contain digits that appears after the decimal point
468 // if height or width are set to auto we fallback to msTransformOrigin calculation
469 floating = (parseFloat(me.getStyle(dimension)) || parseFloat(dom.currentStyle.msTransformOrigin.split(' ')[originIndex]) * 2) % 1;
471 dom.style['position'] = inlinePosition;
473 if (display === 'inline') {
474 dom.style['display'] = inlineDisplay;
481 * Returns the offset height of the element
482 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
483 * @return {Number} The element's height
485 getHeight: function(contentHeight, preciseHeight) {
488 hidden = Ext.isIE && me.isStyle('display', 'none'),
489 height, overflow, style, floating;
491 // IE Quirks mode acts more like a max-size measurement unless overflow is hidden during measurement.
492 // We will put the overflow back to it's original value when we are done measuring.
493 if (Ext.isIEQuirks) {
495 overflow = style.overflow;
496 me.setStyle({ overflow: 'hidden'});
499 height = dom.offsetHeight;
501 height = MATH.max(height, hidden ? 0 : dom.clientHeight) || 0;
503 // IE9 Direct2D dimension rounding bug
504 if (!hidden && Ext.supports.Direct2DBug) {
505 floating = me.adjustDirect2DDimension('height');
509 else if (floating > 0 && floating < 0.5) {
515 height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
518 if (Ext.isIEQuirks) {
519 me.setStyle({ overflow: overflow});
529 * Returns the offset width of the element
530 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
531 * @return {Number} The element's width
533 getWidth: function(contentWidth, preciseWidth) {
536 hidden = Ext.isIE && me.isStyle('display', 'none'),
537 rect, width, overflow, style, floating, parentPosition;
539 // IE Quirks mode acts more like a max-size measurement unless overflow is hidden during measurement.
540 // We will put the overflow back to it's original value when we are done measuring.
541 if (Ext.isIEQuirks) {
543 overflow = style.overflow;
544 me.setStyle({overflow: 'hidden'});
547 // Fix Opera 10.5x width calculation issues
548 if (Ext.isOpera10_5) {
549 if (dom.parentNode.currentStyle.position === 'relative') {
550 parentPosition = dom.parentNode.style.position;
551 dom.parentNode.style.position = 'static';
552 width = dom.offsetWidth;
553 dom.parentNode.style.position = parentPosition;
555 width = Math.max(width || 0, dom.offsetWidth);
557 // Gecko will in some cases report an offsetWidth that is actually less than the width of the
558 // text contents, because it measures fonts with sub-pixel precision but rounds the calculated
559 // value down. Using getBoundingClientRect instead of offsetWidth allows us to get the precise
560 // subpixel measurements so we can force them to always be rounded up. See
561 // https://bugzilla.mozilla.org/show_bug.cgi?id=458617
562 } else if (Ext.supports.BoundingClientRect) {
563 rect = dom.getBoundingClientRect();
564 width = rect.right - rect.left;
565 width = preciseWidth ? width : Math.ceil(width);
567 width = dom.offsetWidth;
570 width = MATH.max(width, hidden ? 0 : dom.clientWidth) || 0;
572 // IE9 Direct2D dimension rounding bug
573 if (!hidden && Ext.supports.Direct2DBug) {
574 floating = me.adjustDirect2DDimension('width');
578 else if (floating > 0 && floating < 0.5) {
584 width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
587 if (Ext.isIEQuirks) {
588 me.setStyle({ overflow: overflow});
598 * Set the width of this Element.
599 * @param {Number/String} width The new width. This may be one of:<div class="mdetail-params"><ul>
600 * <li>A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels).</li>
601 * <li>A String used to set the CSS width style. Animation may <b>not</b> be used.
603 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
604 * @return {Ext.Element} this
606 setWidth : function(width, animate){
608 width = me.adjustWidth(width);
609 if (!animate || !me.anim) {
610 me.dom.style.width = me.addUnits(width);
613 if (!Ext.isObject(animate)) {
616 me.animate(Ext.applyIf({
626 * Set the height of this Element.
628 // change the height to 200px and animate with default configuration
629 Ext.fly('elementId').setHeight(200, true);
631 // change the height to 150px and animate with a custom configuration
632 Ext.fly('elId').setHeight(150, {
633 duration : .5, // animation will have a duration of .5 seconds
634 // will change the content to "finished"
635 callback: function(){ this.{@link #update}("finished"); }
638 * @param {Number/String} height The new height. This may be one of:<div class="mdetail-params"><ul>
639 * <li>A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels.)</li>
640 * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
642 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
643 * @return {Ext.Element} this
645 setHeight : function(height, animate){
647 height = me.adjustHeight(height);
648 if (!animate || !me.anim) {
649 me.dom.style.height = me.addUnits(height);
652 if (!Ext.isObject(animate)) {
655 me.animate(Ext.applyIf({
665 * Gets the width of the border(s) for the specified side(s)
666 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
667 * passing <tt>'lr'</tt> would get the border <b><u>l</u></b>eft width + the border <b><u>r</u></b>ight width.
668 * @return {Number} The width of the sides passed added together
670 getBorderWidth : function(side){
671 return this.addStyles(side, borders);
675 * Gets the width of the padding(s) for the specified side(s)
676 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
677 * passing <tt>'lr'</tt> would get the padding <b><u>l</u></b>eft + the padding <b><u>r</u></b>ight.
678 * @return {Number} The padding of the sides passed added together
680 getPadding : function(side){
681 return this.addStyles(side, paddings);
685 * Store the current overflow setting and clip overflow on the element - use <tt>{@link #unclip}</tt> to remove
686 * @return {Ext.Element} this
692 if(!data(dom, ISCLIPPED)){
693 data(dom, ISCLIPPED, true);
694 data(dom, ORIGINALCLIP, {
695 o: me.getStyle(OVERFLOW),
696 x: me.getStyle(OVERFLOWX),
697 y: me.getStyle(OVERFLOWY)
699 me.setStyle(OVERFLOW, HIDDEN);
700 me.setStyle(OVERFLOWX, HIDDEN);
701 me.setStyle(OVERFLOWY, HIDDEN);
707 * Return clipping (overflow) to original clipping before <tt>{@link #clip}</tt> was called
708 * @return {Ext.Element} this
715 if(data(dom, ISCLIPPED)){
716 data(dom, ISCLIPPED, false);
717 clip = data(dom, ORIGINALCLIP);
719 me.setStyle(OVERFLOW, clip.o);
722 me.setStyle(OVERFLOWX, clip.x);
725 me.setStyle(OVERFLOWY, clip.y);
732 addStyles : function(sides, styles){
734 sidesArr = sides.match(wordsRe),
736 len = sidesArr.length,
738 for (; i < len; i++) {
740 size = side && parseInt(this.getStyle(styles[side]), 10);
742 totalSize += MATH.abs(size);
751 * More flexible version of {@link #setStyle} for setting style properties.
752 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
753 * a function which returns such a specification.
754 * @return {Ext.Element} this
756 applyStyles : function(style){
757 Ext.DomHelper.applyStyles(this.dom, style);
762 * Returns an object with properties matching the styles requested.
763 * For example, el.getStyles('color', 'font-size', 'width') might return
764 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
765 * @param {String} style1 A style name
766 * @param {String} style2 A style name
767 * @param {String} etc.
768 * @return {Object} The style object
770 getStyles : function(){
772 len = arguments.length,
775 for(; i < len; ++i) {
776 style = arguments[i];
777 styles[style] = this.getStyle(style);
783 * <p>Wraps the specified element with a special 9 element markup/CSS block that renders by default as
784 * a gray container with a gradient background, rounded corners and a 4-way shadow.</p>
785 * <p>This special markup is used throughout Ext when box wrapping elements ({@link Ext.button.Button},
786 * {@link Ext.panel.Panel} when <tt>{@link Ext.panel.Panel#frame frame=true}</tt>, {@link Ext.window.Window}). The markup
787 * is of this form:</p>
789 Ext.Element.boxMarkup =
790 '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div>
791 <div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div>
792 <div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';
794 * <p>Example usage:</p>
797 Ext.get("foo").boxWrap();
799 // You can also add a custom class and use CSS inheritance rules to customize the box look.
800 // 'x-box-blue' is a built-in alternative -- look at the related CSS definitions as an example
801 // for how to create a custom box wrap style.
802 Ext.get("foo").boxWrap().addCls("x-box-blue");
804 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element
805 * (defaults to <tt>'x-box'</tt>). Note that there are a number of CSS rules that are dependent on
806 * this name to make the overall effect work, so if you supply an alternate base class, make sure you
807 * also supply all of the necessary rules.
808 * @return {Ext.Element} The outermost wrapping element of the created box structure.
810 boxWrap : function(cls){
811 cls = cls || Ext.baseCSSPrefix + 'box';
812 var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + Ext.String.format(ELEMENT.boxMarkup, cls) + "</div>"));
813 Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
818 * Set the size of this Element. If animation is true, both width and height will be animated concurrently.
819 * @param {Number/String} width The new width. This may be one of:<div class="mdetail-params"><ul>
820 * <li>A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels).</li>
821 * <li>A String used to set the CSS width style. Animation may <b>not</b> be used.
822 * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>
824 * @param {Number/String} height The new height. This may be one of:<div class="mdetail-params"><ul>
825 * <li>A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels).</li>
826 * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
828 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
829 * @return {Ext.Element} this
831 setSize : function(width, height, animate){
833 if (Ext.isObject(width)) { // in case of object from getSize()
835 height = width.height;
838 width = me.adjustWidth(width);
839 height = me.adjustHeight(height);
840 if(!animate || !me.anim){
841 // Must touch some property before setting style.width/height on non-quirk IE6,7, or the
842 // properties will not reflect the changes on the style immediately
843 if (!Ext.isIEQuirks && (Ext.isIE6 || Ext.isIE7)) {
846 me.dom.style.width = me.addUnits(width);
847 me.dom.style.height = me.addUnits(height);
850 if (animate === true) {
853 me.animate(Ext.applyIf({
864 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
865 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
866 * if a height has not been set using CSS.
869 getComputedHeight : function(){
871 h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
873 h = parseFloat(me.getStyle('height')) || 0;
874 if(!me.isBorderBox()){
875 h += me.getFrameWidth('tb');
882 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
883 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
884 * if a width has not been set using CSS.
887 getComputedWidth : function(){
889 w = Math.max(me.dom.offsetWidth, me.dom.clientWidth);
892 w = parseFloat(me.getStyle('width')) || 0;
893 if(!me.isBorderBox()){
894 w += me.getFrameWidth('lr');
901 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
902 for more information about the sides.
903 * @param {String} sides
906 getFrameWidth : function(sides, onlyContentBox){
907 return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
911 * Sets up event handlers to add and remove a css class when the mouse is over this element
912 * @param {String} className
913 * @return {Ext.Element} this
915 addClsOnOver : function(className){
919 Ext.fly(dom, INTERNAL).addCls(className);
922 Ext.fly(dom, INTERNAL).removeCls(className);
929 * Sets up event handlers to add and remove a css class when this element has the focus
930 * @param {String} className
931 * @return {Ext.Element} this
933 addClsOnFocus : function(className){
936 me.on("focus", function(){
937 Ext.fly(dom, INTERNAL).addCls(className);
939 me.on("blur", function(){
940 Ext.fly(dom, INTERNAL).removeCls(className);
946 * 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)
947 * @param {String} className
948 * @return {Ext.Element} this
950 addClsOnClick : function(className){
952 this.on("mousedown", function(){
953 Ext.fly(dom, INTERNAL).addCls(className);
954 var d = Ext.getDoc(),
956 Ext.fly(dom, INTERNAL).removeCls(className);
957 d.removeListener("mouseup", fn);
965 * <p>Returns the dimensions of the element available to lay content out in.<p>
966 * <p>If the element (or any ancestor element) has CSS style <code>display : none</code>, the dimensions will be zero.</p>
967 * example:<pre><code>
968 var vpSize = Ext.getBody().getViewSize();
970 // all Windows created afterwards will have a default value of 90% height and 95% width
971 Ext.Window.override({
972 width: vpSize.width * 0.9,
973 height: vpSize.height * 0.95
975 // To handle window resizing you would have to hook onto onWindowResize.
978 * getViewSize utilizes clientHeight/clientWidth which excludes sizing of scrollbars.
979 * To obtain the size including scrollbars, use getStyleSize
981 * Sizing of the document body is handled at the adapter level which handles special cases for IE and strict modes, etc.
984 getViewSize : function(){
987 isDoc = (dom == Ext.getDoc().dom || dom == Ext.getBody().dom),
988 style, overflow, ret;
990 // If the body, use static methods
993 width : ELEMENT.getViewWidth(),
994 height : ELEMENT.getViewHeight()
997 // Else use clientHeight/clientWidth
1000 // IE 6 & IE Quirks mode acts more like a max-size measurement unless overflow is hidden during measurement.
1001 // We will put the overflow back to it's original value when we are done measuring.
1002 if (Ext.isIE6 || Ext.isIEQuirks) {
1004 overflow = style.overflow;
1005 me.setStyle({ overflow: 'hidden'});
1008 width : dom.clientWidth,
1009 height : dom.clientHeight
1011 if (Ext.isIE6 || Ext.isIEQuirks) {
1012 me.setStyle({ overflow: overflow });
1019 * <p>Returns the dimensions of the element available to lay content out in.<p>
1021 * getStyleSize utilizes prefers style sizing if present, otherwise it chooses the larger of offsetHeight/clientHeight and offsetWidth/clientWidth.
1022 * To obtain the size excluding scrollbars, use getViewSize
1024 * Sizing of the document body is handled at the adapter level which handles special cases for IE and strict modes, etc.
1027 getStyleSize : function(){
1031 isDoc = (d == doc || d == doc.body),
1035 // If the body, use static methods
1038 width : ELEMENT.getViewWidth(),
1039 height : ELEMENT.getViewHeight()
1042 // Use Styles if they are set
1043 if(s.width && s.width != 'auto'){
1044 w = parseFloat(s.width);
1045 if(me.isBorderBox()){
1046 w -= me.getFrameWidth('lr');
1049 // Use Styles if they are set
1050 if(s.height && s.height != 'auto'){
1051 h = parseFloat(s.height);
1052 if(me.isBorderBox()){
1053 h -= me.getFrameWidth('tb');
1056 // Use getWidth/getHeight if style not set.
1057 return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
1061 * Returns the size of the element.
1062 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
1063 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
1065 getSize : function(contentSize){
1066 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
1070 * Forces the browser to repaint this element
1071 * @return {Ext.Element} this
1073 repaint : function(){
1075 this.addCls(Ext.baseCSSPrefix + 'repaint');
1076 setTimeout(function(){
1077 Ext.fly(dom).removeCls(Ext.baseCSSPrefix + 'repaint');
1083 * Enable text selection for this element (normalized across browsers)
1084 * @return {Ext.Element} this
1086 selectable : function() {
1088 me.dom.unselectable = "off";
1089 // Prevent it from bubles up and enables it to be selectable
1090 me.on('selectstart', function (e) {
1091 e.stopPropagation();
1094 me.applyStyles("-moz-user-select: text; -khtml-user-select: text;");
1095 me.removeCls(Ext.baseCSSPrefix + 'unselectable');
1100 * Disables text selection for this element (normalized across browsers)
1101 * @return {Ext.Element} this
1103 unselectable : function(){
1105 me.dom.unselectable = "on";
1107 me.swallowEvent("selectstart", true);
1108 me.applyStyles("-moz-user-select:-moz-none;-khtml-user-select:none;");
1109 me.addCls(Ext.baseCSSPrefix + 'unselectable');
1115 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
1116 * then it returns the calculated width of the sides (see getPadding)
1117 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
1118 * @return {Object/Number}
1120 getMargin : function(side){
1122 hash = {t:"top", l:"left", r:"right", b: "bottom"},
1127 for (key in me.margins){
1128 o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
1132 return me.addStyles.call(me, side, me.margins);