10

I'm trying to write a Javascript function inside a Java GWT code that gets the value of the following styles

"direction", "fontFamily", "fontSize", "fontSizeAdjust", "fontStyle", "fontWeight", "letterSpacing", "lineHeight", "padding", "textAlign", "textDecoration", "textTransform", "wordSpacing"

The getComputedStyle was useful in all browsers except IE8 which doesn't support such function as I understand

I looked at the posts about smiler subject here but all of them failed to get one of the above styles

smiler subject posts 1, 2.

Here is my initial solution without the IE8 special case

public static native String getStyleProperty(Element element, String style) /*-{
        if (element.currentStyle) {
            return element.currentStyle[style];
        } else if (window.getComputedStyle) {
            return window.getComputedStyle(element, null).getPropertyValue(
                    style);
        }
    }-*/;

Any suggestions for a good getComputedStyle replacement function for IE8 ?

Community
  • 1
  • 1
montss
  • 454
  • 5
  • 18

5 Answers5

8

Look over here: http://snipplr.com/view/13523/

The code:

if (!window.getComputedStyle) {
    window.getComputedStyle = function(el, pseudo) {
        this.el = el;
        this.getPropertyValue = function(prop) {
            var re = /(\-([a-z]){1})/g;
            if (prop == 'float') prop = 'styleFloat';
            if (re.test(prop)) {
                prop = prop.replace(re, function () {
                    return arguments[2].toUpperCase();
                });
            }
            return el.currentStyle[prop] ? el.currentStyle[prop] : null;
        }
        return this;
    }
}

Example:

window.onload = function() {
    var compStyle = window.getComputedStyle(document.getElementById('test'), "");

    alert(compStyle.getPropertyValue("color"));
    alert(compStyle.getPropertyValue("float"));
    alert(compStyle.getPropertyValue("background-color"));
}
Alex
  • 11,115
  • 12
  • 51
  • 64
Niels
  • 48,601
  • 4
  • 62
  • 81
  • 1
    Instead of using `this` the return value should be a newly created object. Now it assigns the `el` and `getPropertyValue` properties to the window object and subsequent calls to `window.getComputedStyle` will override them. (Also a minor nitpick: both the `{1}` in the regular expression and the if statement testing if the regular expression matches are unnecessary) – gwk Feb 18 '15 at 12:36
  • You declared the second argument, `pseudo`, but don’t do anything with it. How do I get the computed style of pseudo elements? – Raphael Schweikert Nov 11 '15 at 13:43
5

Here is the solution. It is based on this Trick, but then I've expanded it in case to resolve two problems.

First problem is that borderTopWidth (left,bottom,right) in el.currentStyle returns as adjective - 'thin', 'medium', 'thick' - or 'none'. The Trick will return exception.

And second problem - some values will not be calculated correctly. Such as opacity and some else. You can check it by yourself by applying this Trick-method to all the properties:

var _style = el.currentStyle;
for (var key in _style) {
      /// here is the Trick.....
}

At last, here is my solution, based on assumption, that I know all the properties I want to get by this function:

if (!window.getComputedStyle) window.getComputedStyle = function(el){
    var __style = el.currentStyle,
        _style = {};
    for (var i in __style) {
        _style[i] = __style[i]; 
    }

    // IE8 returns border widths as adjectives
    if (style.indexOf("border") === 0)
        switch (_style[style]) {
            case "thin":
                _style[style] = 2;
                break;
            case "medium":
                _style[style] = 4;
                break;
            case "thick":
                _style[style] = 6;
                break;
            default:
                _style[style] = 0;
        }

    // based on http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291        
    var leftCopy = el.style.left;
    var runtimeLeftCopy = el.runtimeStyle.left;
    // some properties, that I want to use
    _styleParams = {
        left : 1,
        right : 1,
        top : 1,
        bottom : 1,
        width : 1,
        height : 1,
        borderLeftWidth : 1,
        borderRightWidth : 1,
        borderTopWidth : 1,
        borderBottomWidth : 1,
        paddingLeft : 1,
        paddingRight : 1,
        paddingTop : 1,
        paddingBottom : 1,
        marginLeft : 1,
        marginRight : 1,
        marginTop : 1,
        marginBottom : 1
    }
    for (var key in _styleParams) {             
        el.runtimeStyle.left = el.currentStyle.left;            
        el.style.left = _style[key];                        
        _style[key] = el.style.pixelLeft;
        el.style.left = leftCopy;
        el.runtimeStyle.left = runtimeLeftCopy;             
    }


    // opacity for IE8
    if (_style.filter.match('alpha')) {
        _style.opacity = _style.filter.substr(14);
        _style.opacity = parseInt(_style.opacity.substring(0, _style.opacity.length-1)) / 100;
    } else {
        _style.opacity = 1;
    }}
Maksim Slepov
  • 81
  • 1
  • 4
2

Here is more complete polyfill for IE8/getComputedStyle which should handle all cases:

https://github.com/jonathantneal/Polyfills-for-IE8/blob/master/getComputedStyle.js

Goran.it
  • 5,991
  • 2
  • 23
  • 25
  • Any Idea how I can put this code inside a Java GWT code like my code in the question above? – montss Feb 16 '14 at 09:47
  • Well I'm not familiar with Java/GWT but you should be able to include that file in the < head > section of the page ( jsp if you use that ) – Goran.it Feb 16 '14 at 11:49
1

I used a similar method to my original solution with an additional case to handle inline styles, also the way to check if the current document support the getComputedStyle is a bit different it checks in the document.defaultView instead of the window itself, here is the full function

public static native String getStyleProperty(Element el, String prop) /*-{
        var computedStyle;
        if (document.defaultView && document.defaultView.getComputedStyle) { // standard (includes ie9)
            computedStyle = document.defaultView.getComputedStyle(el, null)[prop];

        } else if (el.currentStyle) { // IE older
            computedStyle = el.currentStyle[prop];

        } else { // inline style
            computedStyle = el.style[prop];
        }
        return computedStyle;

    }-*/;

source

montss
  • 454
  • 5
  • 18
1

The best solution I've found so far was from another answer here: https://stackoverflow.com/a/17890142/3672465. It's a standalone version of the jQuery curCSS() code; you may need to adjust it to suit your needs (as Maksim notes in his answer). Here's a compact version of the IE 8 portion, if you just want something to drop in.

if( !window.getComputedStyle && document.documentElement.currentStyle ){
    function getStyles( elem ){ return elem.currentStyle; };
    function curCSS( elem, name, computed ){
        var rnum = /^([+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|))(?!px)[a-z%]+$/i;
        var t = 'left', l, rs, rsL, c = computed || getStyles( elem ), 
            r = c ? c[ name ] : undefined, s = elem.style;
        if( r == null && s && s[ name ] ){ r = s[ name ]; }
        if( rnum.test( r ) && !/^(top|right|bottom|left)$/.test( name ) ){
            l = s[t]; rs = elem.runtimeStyle; rsL = rs && rs[t]; 
            if( rsL ){ rs[t] = elem.currentStyle[t]; } 
            s[t] = name === 'fontSize' ? '1em' : r; r = s.pixelLeft + 'px'; 
            s[t] = l; if( rsL ){ rs[t] = rsL; }
        }
        return r === '' ? 'auto' : r;
    };
}
Community
  • 1
  • 1
Beejor
  • 8,606
  • 1
  • 41
  • 31