/**
* @class Ext.core.Element
*/
(function(){
Ext.core.Element.boxMarkup = '';
// local style camelizing for speed
var supports = Ext.supports,
view = document.defaultView,
opacityRe = /alpha\(opacity=(.*)\)/i,
trimRe = /^\s+|\s+$/g,
spacesRe = /\s+/,
wordsRe = /\w/g,
INTERNAL = '_internal',
PADDING = 'padding',
MARGIN = 'margin',
BORDER = 'border',
LEFT = '-left',
RIGHT = '-right',
TOP = '-top',
BOTTOM = '-bottom',
WIDTH = '-width',
MATH = Math,
HIDDEN = 'hidden',
ISCLIPPED = 'isClipped',
OVERFLOW = 'overflow',
OVERFLOWX = 'overflow-x',
OVERFLOWY = 'overflow-y',
ORIGINALCLIP = 'originalClip',
// special markup used throughout Ext when box wrapping elements
borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
data = Ext.core.Element.data;
Ext.override(Ext.core.Element, {
/**
* TODO: Look at this
*/
// private ==> used by Fx
adjustWidth : function(width) {
var me = this;
var 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;
var isNum = (typeof height == "number");
if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
}
return (isNum && height < 0) ? 0 : height;
},
/**
* Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
* @param {String/Array} className The CSS class to add, or an array of classes
* @return {Ext.core.Element} this
*/
addCls : function(className){
var me = this,
i,
len,
v,
cls = [];
// Separate case is for speed
if (!Ext.isArray(className)) {
if (typeof className == 'string' && !this.hasCls(className)) {
me.dom.className += " " + className;
}
}
else {
for (i = 0, len = className.length; i < len; i++) {
v = className[i];
if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
cls.push(v);
}
}
if (cls.length) {
me.dom.className += " " + cls.join(" ");
}
}
return me;
},
/**
* Removes one or more CSS classes from the element.
* @param {String/Array} className The CSS class to remove, or an array of classes
* @return {Ext.core.Element} this
*/
removeCls : function(className){
var me = this,
i,
idx,
len,
cls,
elClasses;
if (!Ext.isArray(className)){
className = [className];
}
if (me.dom && me.dom.className) {
elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
for (i = 0, len = className.length; i < len; i++) {
cls = className[i];
if (typeof cls == 'string') {
cls = cls.replace(trimRe, '');
idx = Ext.Array.indexOf(elClasses, cls);
if (idx != -1) {
elClasses.splice(idx, 1);
}
}
}
me.dom.className = elClasses.join(" ");
}
return me;
},
/**
* Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
* @param {String/Array} className The CSS class to add, or an array of classes
* @return {Ext.core.Element} this
*/
radioCls : function(className){
var cn = this.dom.parentNode.childNodes,
v,
i,
len;
className = Ext.isArray(className) ? className : [className];
for (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);
},
/**
* 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.core.Element} this
*/
toggleCls : Ext.supports.ClassList ?
function(className) {
this.dom.classList.toggle(Ext.String.trim(className));
return this;
} :
function(className) {
return this.hasCls(className) ? this.removeCls(className) : this.addCls(className);
},
/**
* Checks if the specified CSS class exists on this element's DOM node.
* @param {String} className The CSS class to check for
* @return {Boolean} True if the class exists, else false
*/
hasCls : Ext.supports.ClassList ?
function(className) {
var className = className.split(spacesRe),
ln = className.length,
i = 0;
for (; i < ln; i++) {
if (className[i] && this.dom.classList.contains(className[i])) {
return true;
}
}
return false;
} :
function(className){
return className && (' ' + this.dom.className + ' ').indexOf(' ' + className + ' ') != -1;
},
/**
* 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} oldClassName The CSS class to replace
* @param {String} newClassName The replacement CSS class
* @return {Ext.core.Element} this
*/
replaceCls : function(oldClassName, newClassName){
return this.removeCls(oldClassName).addCls(newClassName);
},
isStyle : function(style, val) {
return this.getStyle(style) == val;
},
/**
* Normalizes currentStyle and computedStyle.
* @param {String} property The style property whose value is returned.
* @return {String} The current value of the style property for this element.
*/
getStyle : function(){
return view && view.getComputedStyle ?
function(prop){
var el = this.dom,
v,
cs,
out,
display;
if(el == document){
return null;
}
prop = Ext.core.Element.normalize(prop);
out = (v = el.style[prop]) ? v :
(cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
// Ignore cases when the margin is correctly reported as 0, the bug only shows
// numbers larger.
if(prop == 'marginRight' && out != '0px' && !supports.RightMargin){
display = this.getStyle('display');
el.style.display = 'inline-block';
out = view.getComputedStyle(el, '').marginRight;
el.style.display = display;
}
if(prop == 'backgroundColor' && out == 'rgba(0, 0, 0, 0)' && !supports.TransparentColor){
out = 'transparent';
}
return out;
} :
function(prop){
var el = this.dom,
m,
cs;
if (el == document) {
return null;
}
if (prop == 'opacity') {
if (el.style.filter.match) {
m = el.style.filter.match(opacityRe);
if(m){
var fv = parseFloat(m[1]);
if(!isNaN(fv)){
return fv ? fv / 100 : 0;
}
}
}
return 1;
}
prop = Ext.core.Element.normalize(prop);
return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
};
}(),
/**
* 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 (optional) defaults to #. Use an empty string when working with
* color anims.
*/
getColor : function(attr, defaultValue, prefix){
var v = this.getStyle(attr),
color = prefix === 'undefined' ? prefix : '#',
h;
if(!v || (/transparent|inherit/.test(v))) {
return defaultValue;
}
if(/^r/.test(v)){
Ext.each(v.slice(4, v.length -1).split(','), function(s){
h = parseInt(s, 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);
},
/**
* 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 (optional) The value to apply to the given property, or null if an object was passed.
* @return {Ext.core.Element} this
*/
setStyle : function(prop, value){
var tmp, style;
if (!Ext.isObject(prop)) {
tmp = {};
tmp[prop] = value;
prop = tmp;
}
for (style in prop) {
if (prop.hasOwnProperty(style)) {
value = Ext.value(prop[style], '');
if (style == 'opacity') {
this.setOpacity(value);
} else {
this.dom.style[Ext.core.Element.normalize(style)] = value;
}
}
}
return this;
},
/**
* Set the opacity of the element
* @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
* @param {Boolean/Object} animate (optional) a standard Element animation config object or true for
* the default animation ({duration: .35, easing: 'easeIn'})
* @return {Ext.core.Element} this
*/
setOpacity : function(opacity, animate){
var me = this,
s = me.dom.style;
if(!animate || !me.anim){
if(!Ext.supports.Opacity){
opacity = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '';
val = s.filter.replace(opacityRe, '').replace(trimRe, '');
s.zoom = 1;
s.filter = val + (val.length > 0 ? ' ' : '') + opacity;
}else{
s.opacity = opacity;
}
}else{
if (!Ext.isObject(animate)) {
animate = {
duration: 350,
easing: 'ease-in'
};
}
me.animate(Ext.applyIf({
to: {
opacity: opacity
}
}, animate));
}
return me;
},
/**
* Clears any opacity settings from this element. Required in some cases for IE.
* @return {Ext.core.Element} this
*/
clearOpacity : function(){
var style = this.dom.style;
if(!Ext.supports.Opacity){
if(!Ext.isEmpty(style.filter)){
style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
}
}else{
style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
}
return this;
},
/**
* Returns the offset height of the element
* @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
* @return {Number} The element's height
*/
getHeight : function(contentHeight){
var me = this,
dom = me.dom,
hidden = Ext.isIE && me.isStyle('display', 'none'),
h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;
h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
return h < 0 ? 0 : h;
},
/**
* Returns the offset width of the element
* @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
* @return {Number} The element's width
*/
getWidth : function(contentWidth){
var me = this,
dom = me.dom,
hidden = Ext.isIE && me.isStyle('display', 'none'),
w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
return w < 0 ? 0 : w;
},
/**
* Set the width of this Element.
* @param {Mixed} 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.
*
* @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
* @return {Ext.core.Element} this
*/
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;
},
/**
* Set the height of this Element.
*
// change the height to 200px and animate with default configuration
Ext.fly('elementId').setHeight(200, true);
// change the height to 150px and animate with a custom configuration
Ext.fly('elId').setHeight(150, {
duration : .5, // animation will have a duration of .5 seconds
// will change the content to "finished"
callback: function(){ this.{@link #update}("finished"); }
});
*
* @param {Mixed} 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.
*
* @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
* @return {Ext.core.Element} this
*/
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;
},
/**
* 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 left width + the border right width.
* @return {Number} The width of the sides passed added together
*/
getBorderWidth : function(side){
return this.addStyles(side, 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 left + the padding right.
* @return {Number} The padding of the sides passed added together
*/
getPadding : function(side){
return this.addStyles(side, paddings);
},
/**
* Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
* @return {Ext.core.Element} this
*/
clip : function(){
var me = this,
dom = me.dom;
if(!data(dom, ISCLIPPED)){
data(dom, ISCLIPPED, true);
data(dom, ORIGINALCLIP, {
o: me.getStyle(OVERFLOW),
x: me.getStyle(OVERFLOWX),
y: me.getStyle(OVERFLOWY)
});
me.setStyle(OVERFLOW, HIDDEN);
me.setStyle(OVERFLOWX, HIDDEN);
me.setStyle(OVERFLOWY, HIDDEN);
}
return me;
},
/**
* Return clipping (overflow) to original clipping before {@link #clip} was called
* @return {Ext.core.Element} this
*/
unclip : function(){
var me = this,
dom = me.dom,
clip;
if(data(dom, ISCLIPPED)){
data(dom, ISCLIPPED, false);
clip = data(dom, ORIGINALCLIP);
if(o.o){
me.setStyle(OVERFLOW, o.o);
}
if(o.x){
me.setStyle(OVERFLOWX, o.x);
}
if(o.y){
me.setStyle(OVERFLOWY, o.y);
}
}
return me;
},
// private
addStyles : function(sides, styles){
var totalSize = 0,
sidesArr = sides.match(wordsRe),
side,
size,
i,
len = sidesArr.length;
for (i = 0; i < len; i++) {
side = sidesArr[i];
size = side && parseInt(this.getStyle(styles[side]), 10);
if (size) {
totalSize += MATH.abs(size);
}
}
return totalSize;
},
margins : margins,
/**
* 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.core.Element} this
*/
applyStyles : function(style){
Ext.core.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 styles = {},
i = 0,
len = arguments.length,
style;
for(; i < len; ++i) {
style = arguments[i];
styles[style] = this.getStyle(style);
}
return styles;
},
/**
* 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.core.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 (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.core.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", "" + Ext.String.format(Ext.core.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:
* - 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 {Mixed} 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.
*
* @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
* @return {Ext.core.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 {
if (!Ext.isObject(animate)) {
animate = {};
}
me.animate(Ext.applyIf({
to: {
width: width,
height: height
}
}, animate));
}
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 = parseFloat(me.getStyle('height')) || 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 = parseFloat(this.getStyle('width')) || 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.core.Element} this
*/
addClsOnOver : function(className){
var dom = this.dom;
this.hover(
function(){
Ext.fly(dom, INTERNAL).addCls(className);
},
function(){
Ext.fly(dom, INTERNAL).removeCls(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.core.Element} this
*/
addClsOnFocus : function(className){
var dom = this.dom;
this.on("focus", function(){
Ext.fly(dom, INTERNAL).addCls(className);
});
this.on("blur", function(){
Ext.fly(dom, INTERNAL).removeCls(className);
});
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.core.Element} this
*/
addClsOnClick : function(className){
var dom = this.dom;
this.on("mousedown", function(){
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 this;
},
/**
* 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.
*
*
* getViewSize utilizes clientHeight/clientWidth which excludes sizing of scrollbars.
* To obtain the size including scrollbars, use getStyleSize
*
* Sizing of the document body is handled at the adapter level which handles special cases for IE and strict modes, etc.
*/
getViewSize : function(){
var doc = document,
d = this.dom,
isDoc = (d == doc || d == doc.body);
// If the body, use static methods
if (isDoc) {
return {
width : Ext.core.Element.getViewWidth(),
height : Ext.core.Element.getViewHeight()
};
// Else use clientHeight/clientWidth
} else {
return {
width : d.clientWidth,
height : d.clientHeight
};
}
},
/**
* 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.
*/
getStyleSize : function(){
var me = this,
w, h,
doc = document,
d = this.dom,
isDoc = (d == doc || d == doc.body),
s = d.style;
// If the body, use static methods
if (isDoc) {
return {
width : Ext.core.Element.getViewWidth(),
height : Ext.core.Element.getViewHeight()
};
}
// 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)};
},
/**
* 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.core.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;
},
/**
* Disables text selection for this element (normalized across browsers)
* @return {Ext.core.Element} this
*/
unselectable : function(){
this.dom.unselectable = "on";
return this.swallowEvent("selectstart", true).
applyStyles("-moz-user-select:none;-khtml-user-select:none;").
addCls(Ext.baseCSSPrefix + '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}
*/
getMargin : 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]] = parseFloat(me.getStyle(me.margins[key])) || 0;
}
return o;
} else {
return me.addStyles.call(me, side, me.margins);
}
}
});
})();