Element.extend({
        getDimensions: function(options) {
                options = $merge({computeSize: false},options);
                var dim = {};
                function getSize(el, options){
                        if(options.computeSize) dim = el.getComputedSize(options);
                        else {
                                dim.width = el.getSize().size.x;
                                dim.height = el.getSize().size.y;
                        }
                        return dim;
                }
                try {
                        dim = getSize(this, options);
                }catch(e){}
                if(this.getStyle('display') == 'none'){
                        var before = {};
                        ['visibility', 'display', 'position'].each(function(style){
                                before[style] = this.style[style]||'';
                        }, this);
                        this.setStyles({
                                visibility: 'hidden',
                                display: 'block',
                                position:'absolute'
                        });
                        dim = getSize(this, options);
                        this.setStyles(before);
                }
                return $merge(dim, {x: dim.width, y: dim.height});
        },
        getComputedSize: function(options){
                options = $merge({
                        styles: ['padding','border'],
                        plains: {height: ['top','bottom'], width: ['left','right']},
                        mode: 'both'
                }, options);
                var size = {width: 0,height: 0};
                switch (options.mode){
                        case 'vertical':
                                delete size.width;
                                delete options.plains.width;
                                break;
                        case 'horizontal':
                                delete size.height;
                                delete options.plains.height;
                                break;
                }
                var getStyles = [];
                $each(options.plains, function(plain, key){
                        plain.each(function(edge){
                                options.styles.each(function(style){
                                        getStyles.push((style=="border")?style+'-'+edge+'-'+'width':style+'-'+edge);
                                });
                        });
                });
                var styles = this.getStyles.apply(this, getStyles);
                var subtracted = [];
                $each(options.plains, function(plain, key){
                        size['total'+key.capitalize()] = 0;
                        size['computed'+key.capitalize()] = 0;
                        plain.each(function(edge){
                                size['computed'+edge.capitalize()] = 0;
                                getStyles.each(function(style,i){
                                        if(style.test(edge)) {
                                                styles[style] = styles[style].toInt();
                                                if(isNaN(styles[style]))styles[style]=0;
                                                size['total'+key.capitalize()] = size['total'+key.capitalize()]+styles[style];
                                                size['computed'+edge.capitalize()] = size['computed'+edge.capitalize()]+styles[style];
                                        }
                                        if(style.test(edge) && key!=style && 
                                                (style.test('border') || style.test('padding')) && !subtracted.test(style)) {
                                                subtracted.push(style);
                                                size['computed'+key.capitalize()] = size['computed'+key.capitalize()]-styles[style];
                                        }
                                });
                        });
                });
                if($chk(size.width)) {
                        size.width = size.width+this.offsetWidth+size.computedWidth;
                        size.totalWidth = size.width + size.totalWidth;
                        delete size.computedWidth;
                }
                if($chk(size.height)) {
                        size.height = size.height+this.offsetHeight+size.computedHeight;
                        size.totalHeight = size.height + size.totalHeight;
                        delete size.computedHeight;
                }
                return $merge(styles, size);
        }
});

