Posts Tagged ‘style’

Butterfish
by Butterfish

Cross-browser getStyle with ease

Posted in Swell

As Element is one of the most important components, we wanted to be able to manipulate DOM, CSS and everything related to content manipulation. Our main goal is to make the user write a minimum of code while keeping the smallest codebase possible (yes, we are DRY hard fervents).

To achieve this challenging goal, we made a batch system that allows us to run a specific function without modifying it several times over given arguments.

So, to put it in a more comprehensive manner, by simply writing this snippet of code:

foo: function() {
    var _fn = function(arg) {
        return this.domEl.id + arg+ 'bar';
    }
 
    return _delegate.call(this, _fn, arguments);
}

If you execute $(‘foo’, ‘bar’, ‘baz’).foo(‘baz’); you’ll get ['foobazbar', 'barbazbar', 'bazbazbar'].
The _delegate method loops through the internal elements stack and executes on each element the given _fn.


getStyle at work

Another thing worth mentioning is the normalization process done backwards by getStyle, as properties may differ between browsers, which one should we choose? currentStyle or getComputedStyle? usually you would use chained if statements to address each possibility.

This is where our approach clearly gives better results by keeping trace of native properties  (e.g. under currentStyle “float” would be “styleFloat”, and getComputedStyle, “cssFloat”) as well as providing an abstraction layer for getting/setting values.

var _styleExceptions = {
    'CURRENT_STYLE' : {
        'float' : 'styleFloat',
        'opacity' : 'filter',
        'border' : null
    },
    'DEFAULT_VIEW'  : {
        'float' : 'cssFloat',
        'border' : null
    }
};
 
getStyle : function() {
    var _fn = function(style) {
        var _method = this._domEl.currentStyle ? { o : this._domEl.currentStyle, type : 'CURRENT_STYLE' } : { o : document.defaultView.getComputedStyle(this._domEl, null), type : 'DEFAULT_VIEW' };
 
        var _exceptions = new Swell.Core.Hashtable().inject(_styleExceptions[_method.type]);
        _exceptions.defineGetter(function(key, val, arg) {
            var _oStyle = arg.o,
                _isCurrentStyle = (arg.type === 'CURRENT_STYLE') ? true : false;
            switch(key) {
                case 'opacity':
                    if (_isCurrentStyle) {
                        return /opacity\s?=\s?([0-9]+)/.exec(_oStyle[val])[1]/100;
                    }
                case 'border':
                    return [_oStyle['borderTopWidth'], _oStyle['borderRightWidth'], _oStyle['borderBottomWidth'], _oStyle['borderLeftWidth']];
                default:
                    return _oStyle[val];
            }
        }, _method);
 
        if (_exceptions.exists(style)) {
            return _exceptions.get(style);
        }
 
        return _method.o[style];
    }
    return _delegate.call(this, _fn, arguments);
}

For example retrieving the opacity value without worrying about the browser.

    <div id="foo" style="filter:alpha(opacity=50);"></div>
    <script type="text/javascript">
        $('foo').getStyle('opacity'); // returns 0.5
    </script>