Applying the getComputedStyle fix for IE to my code ... 'null' is null or not a object

4.7k views Asked by At

Following to this problem I had. I'm trying to apply the following fix to get getComputedStyle to work with IE8 (and -) in the code I use for jQuery isotope. But I still get an error message. Any help would be greatly appreciated.

I get 'null' is null or not a object error message with IE-Tester. The website is http://www.gablabelle.com/

    $(document).ready(function(){
        var layoutI = 0;
        var $container = $("#stream");
        var $window = $(window);
//getComputedStyle fix for IE ?
        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;
            }
        };
        function reLayout(){
// getComputedStyle is used here
            var mediaQueryId = getComputedStyle( document.body, ':after' ).getPropertyValue('content');
            // fix for firefox, remove double quotes
            var mediaQueryId = mediaQueryId.replace( /"/g, '' );
            // console.log( mediaQueryId );
            var windowSize = $window.width();
            var masonryOpts;
            // update sizing options 
            switch ( mediaQueryId ) {
                case 'bigger' :
                    masonryOpts = {
                        columnWidth: 270,
                        gutterWidth: 30
                    };
                break;
                case 'big' :
                    masonryOpts = {
                        columnWidth: 220,
                        gutterWidth: 20
                    };
                break;
                case 'medium' :
                    masonryOpts = {
                        columnWidth: 166,
                        gutterWidth: 20
                    };
                break;
                case 'small' :
                    masonryOpts = {
                        columnWidth: $container.width() / 2,
                        gutterWidth: 0
                    };  
                break;
            };
            $container.isotope({
                resizable: false, // disable resizing by default, we'll trigger it manually
                itemSelector : "article.post",
                animationEngine: "best-available",
                masonry: masonryOpts,
                onLayout: function() {
                //  console.log('layout!' + (layoutI++) )
                    forceLoad();
                    setTimeout(function(){
                        html_height = $container.height();
                        $("#sidebar").height(html_height - masonryOpts.gutterWidth);
                    }, 500);
                }
            });
        };
        // start up isotope with default settings
        $container.imagesLoaded( function(){
            reLayout();
            $window.smartresize( reLayout );
        });
2

There are 2 answers

0
Gab On BEST ANSWER

Following @Nelson 's logic I decided to add the value I wanted to catch using jQuery instead of CSS to make sure it was in the DOM and can be manipulated.

jQuery:

$(document).ready(function(){
    var layoutI = 0;
    var $container = $("#stream");
    var $window = $(window);
    function windowSizeMe(){
        var windowSize = $window.width();
        if (windowSize > 1199) {
            $("#switch").attr("data-content", "bigger");
        } else if (windowSize < 1200 && windowSize > 979) {
            $("#switch").attr("data-content", "big");
        } else if (windowSize < 768) {
            $("#switch").attr("data-content", "small");
        } else {
            $("#switch").attr("data-content", "medium");
        };
    }; 
    function reLayout(){
        windowSizeMe(); 
        var mediaQueryId = $("#switch").attr("data-content");
        console.log(mediaQueryId);
        // fix for firefox, remove double quotes
        var mediaQueryId = mediaQueryId.replace( /"/g, '' );
        var masonryOpts;
        // update sizing options 
        switch ( mediaQueryId ) {
            case 'bigger' :
                masonryOpts = {
                    columnWidth: 270,
                    gutterWidth: 30
                };
            break;
            case 'big' :
                masonryOpts = {
                    columnWidth: 220,
                    gutterWidth: 20
                };
            break;
            case 'medium' :
                masonryOpts = {
                    columnWidth: 166,
                    gutterWidth: 20
                };
            break;
            case 'small' :
                masonryOpts = {
                    columnWidth: $container.width() / 2,
                    gutterWidth: 0
                };  
            break;
        };
        $container.isotope({
            resizable: false, // disable resizing by default, we'll trigger it manually
            itemSelector : "article.post",
            animationEngine: "best-available",
            masonry: masonryOpts,
            onLayout: function() {
            //  console.log('layout!' + (layoutI++) )
                forceLoad();
                setTimeout(function(){
                    html_height = $container.height();
                    $("#sidebar").height(html_height - masonryOpts.gutterWidth);
                }, 500);
            }
        });
    };
    // start up isotope with default settings
    $container.imagesLoaded( function(){
        reLayout();
        $window.smartresize( reLayout );
    });
});

HTML (can be added anywhere):

<span id="switch"></span>

CSS (I don't think the media queries part is mandatory since we set this up in jquery):

#switch {
    display: none;
}
/**** Media queries ****/
@media (max-width: 767px) {
    #switch:after {
        content: attr(data-content) "small";
    }
}
@media (min-width: 768px) and (max-width: 979px) {
    #switch:after {
        content: attr(data-content) "medium";
    }
}
@media (min-width: 980px) and (max-width: 1199px) {
    #switch:after {
        content: attr(data-content) "big";
    }
}
@media (min-width: 1200px) {
    #switch:after {
        content: attr(data-content) "bigger";
    }
}
2
Nelson On

It seems IE8 currentStyle object does not carry information about the content css property, I tested it in your webpage printing all currentStyle info like so:

for(var i in document.body.currentStyle) {
      console.log(i + ' : ' + document.body.currentStyle[i] );
} 

and the content property is not present, that is why getPropertyValue() returns null in your following line:

var mediaQueryId = getComputedStyle( document.body, ':after' ).getPropertyValue('content');

and in the next line it calls .replace() on that null object and hence the error you are getting.

You need to get the content value some other way, currently you are printing if after body with body:after css, I don't know why you do that, you could try to print it to an invisible element inside your body, and later retrieve it from there.. like so:

CSS:

@media (min-width: 1200px) {
    #hid:after {
        content: 'bigger';
    }
...
...

your #hid element could be anywhere in your page like:

<span id="hid" style="display:none"></span>

and then your reLayout() function would retrieve it like so:

function reLayout(){
// getComputedStyle is used here
            var mediaQueryId = $('#hid').html();
            // fix for firefox, remove double quotes
            var mediaQueryId = mediaQueryId.replace( /"/g, '' );
...
...

so doing this way you don't need your IE fix at all, which anyway does not work for the content property.