/**
 * @class Ext.Element
 */


// special markup used throughout Ext when box wrapping elements
Ext.Element.boxMarkup = '
';

Ext.Element.addMethods(function(){
       
var INTERNAL = "_internal";
       
return {
           
/**
             * 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.Element} this
             */

            applyStyles
: function(style){
               
Ext.DomHelper.applyStyles(this.dom, style);
               
return this;
           
},

               
/**
             * Returns an object with properties matching the styles requested.
             * For example, el.getStyles('color', 'font-size', 'width') might return
             * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
             * @param {String} style1 A style name
             * @param {String} style2 A style name
             * @param {String} etc.
             * @return {Object} The style object
             */

            getStyles
: function(){
                   
var ret = {};
                   
Ext.each(arguments, function(v) {
                           ret
[v] = this.getStyle(v);
                   
},
                   
this);
                   
return ret;
           
},

                getStyleSize
: function(){
               
var me = this,
                        w
,
                        h
,
                        d
= this.dom,
                        s
= d.style;
               
if(s.width && s.width != 'auto'){
                    w
= parseInt(s.width, 10);
                   
if(me.isBorderBox()){
                       w
-= me.getFrameWidth('lr');
                   
}
               
}
               
if(s.height && s.height != 'auto'){
                    h
= parseInt(s.height, 10);
                   
if(me.isBorderBox()){
                       h
-= me.getFrameWidth('tb');
                   
}
               
}
               
return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
           
},

           
// private  ==> used by ext full
                setOverflow
: function(v){
                       
var dom = this.dom;
               
if(v=='auto' && Ext.isMac && Ext.isGecko2){ // work around stupid FF 2.0/Mac scroll bar bug
                        dom
.style.overflow = 'hidden';
                       
(function(){dom.style.overflow = 'auto';}).defer(1);
               
}else{
                        dom
.style.overflow = v;
               
}
               
},

           
/**
                *

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},
                * {@link Ext.Panel} when
{@link Ext.Panel#frame frame=true}, {@link Ext.Window}).  The markup
                * is of this form:


                *

Ext.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().addClass("x-box-blue");
                *

                * @param {String} class (optional) A base CSS class to apply to the containing wrapper element
                * (defaults to
'x-box'). 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.Element} this
                */

            boxWrap
: function(cls){
                cls
= cls || 'x-box';
               
var el = Ext.get(this.insertHtml("beforeBegin", "
" + String.format(Ext.Element.boxMarkup, cls) + "
"));        //String.format('
'+Ext.Element.boxMarkup+'
', cls)));
               
Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
               
return el;
           
},

       
/**
         * Set the size of this Element. If animation is true, both width and height will be animated concurrently.
         * @param {Mixed} width The new width. This may be one of:

         * @param {Mixed} height The new height. This may be one of:

         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
         * @return {Ext.Element} this
         */

            setSize
: function(width, height, animate){
                       
var me = this;
                       
if(Ext.isObject(width)){ // in case of object from getSize()
                            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{
                            me
.anim({width: {to: width}, height: {to: height}}, me.preanim(arguments, 2));
                       
}
                       
return me;
           
},

           
/**
             * 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
= parseInt(me.getStyle('height'), 10) || 0;
                   
if(!me.isBorderBox()){
                        h
+= me.getFrameWidth('tb');
                   
}
               
}
               
return h;
           
},

           
/**
             * 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 w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
               
if(!w){
                    w
= parseInt(this.getStyle('width'), 10) || 0;
                   
if(!this.isBorderBox()){
                        w
+= this.getFrameWidth('lr');
                   
}
               
}
               
return w;
           
},

           
/**
             * 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));
           
},

           
/**
             * Sets up event handlers to add and remove a css class when the mouse is over this element
             * @param {String} className
             * @return {Ext.Element} this
             */

            addClassOnOver
: function(className){
               
this.hover(
                   
function(){
                       
Ext.fly(this, INTERNAL).addClass(className);
                   
},
                   
function(){
                       
Ext.fly(this, INTERNAL).removeClass(className);
                   
}
               
);
               
return this;
           
},

           
/**
             * Sets up event handlers to add and remove a css class when this element has the focus
             * @param {String} className
             * @return {Ext.Element} this
             */

            addClassOnFocus
: function(className){
                   
this.on("focus", function(){
                       
Ext.fly(this, INTERNAL).addClass(className);
                   
}, this.dom);
                   
this.on("blur", function(){
                       
Ext.fly(this, INTERNAL).removeClass(className);
                   
}, this.dom);
                   
return this;
           
},

           
/**
             * 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
             * @return {Ext.Element} this
             */

            addClassOnClick
: function(className){
               
var dom = this.dom;
               
this.on("mousedown", function(){
                   
Ext.fly(dom, INTERNAL).addClass(className);
                   
var d = Ext.getDoc(),
                        fn
= function(){
                               
Ext.fly(dom, INTERNAL).removeClass(className);
                                d
.removeListener("mouseup", fn);
                           
};
                    d
.on("mouseup", fn);
               
});
               
return this;
           
},

           
/**
             * Returns the width and height of the viewport.
        *

        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.
       

             * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
             */

            getViewSize
: function(){
               
var doc = document,
                        d
= this.dom,
                        extdom
= Ext.lib.Dom,
                        isDoc
= (d == doc || d == doc.body);
               
return { width : (isDoc ? extdom.getViewWidth() : d.clientWidth),
                                 height
: (isDoc ? extdom.getViewHeight() : d.clientHeight) };
           
},

           
/**
             * Returns the size of the element.
             * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
             * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
             */

            getSize
: function(contentSize){
               
return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
           
},

           
/**
             * Forces the browser to repaint this element
             * @return {Ext.Element} this
             */

            repaint
: function(){
               
var dom = this.dom;
               
this.addClass("x-repaint");
                setTimeout
(function(){
                   
Ext.fly(dom).removeClass("x-repaint");
               
}, 1);
               
return this;
           
},

           
/**
             * Disables text selection for this element (normalized across browsers)
             * @return {Ext.Element} this
             */

            unselectable
: function(){
               
this.dom.unselectable = "on";
               
return this.swallowEvent("selectstart", true).
                                    applyStyles
("-moz-user-select:none;-khtml-user-select:none;").
                                    addClass
("x-unselectable");
           
},

           
/**
             * 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 getPadding)
             * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
             * @return {Object/Number}
             */

            getMargins
: function(side){
                   
var me = this,
                        key
,
                        hash
= {t:"top", l:"left", r:"right", b: "bottom"},
                        o
= {};

                   
if (!side) {
                       
for (key in me.margins){
                                o
[hash[key]] = parseInt(me.getStyle(me.margins[key]), 10) || 0;
               
}
                       
return o;
               
} else {
                   
return me.addStyles.call(me, side, me.margins);
               
}
           
}
   
};
}());