Can I fetch the value of a non-standard CSS property via Javascript?

Solution 1:

Modern browsers will just throw away any invalid css. However, you can use the content property since it only has effect with :after, :before etc. You can store JSON inside it:

#someElement {
    content: '{"foo": "bar"}';
}

Then use code like this to retrieve it:

var CSSMetaData = function() {

    function trimQuotes( str ) {
         return str.replace( /^['"]/, "" ).replace( /["']$/, "" );   
    }

    function fixFirefoxEscape( str ) {
        return str.replace( /\\"/g, '"' );
    }

    var forEach = [].forEach,
        div = document.createElement("div"),
        matchesSelector = div.webkitMatchesSelector ||
                          div.mozMatchesSelector ||
                          div.msMatchesSelector ||
                          div.oMatchesSelector ||
                          div.matchesSelector,
        data = {};

    forEach.call( document.styleSheets, function( styleSheet ) {
        forEach.call( styleSheet.cssRules, function( rule ) {
            var content = rule.style.getPropertyValue( "content" ),
                obj;

            if( content ) {
                content = trimQuotes(content);
                try {
                   obj = JSON.parse( content );
                }
                catch(e) {
                    try {

                        obj = JSON.parse( fixFirefoxEscape( content ) );
                    }
                    catch(e2) {
                        return ;
                    }

                }
                data[rule.selectorText] = obj;
            }
        });

    });


    return {

        getDataByElement: function( elem ) {
            var storedData;
            for( var selector in data ) {
                if( matchesSelector.call( elem, selector ) ) {
                    storedData = data[selector];
                    if( storedData ) return storedData;

                }
            }

            return null;
        }
    };

}();
var obj = CSSMetaData.getDataByElement( document.getElementById("someElement"));
console.log( obj.foo ); //bar

Note, this is only for modern browsers. Demo: http://jsfiddle.net/xFjZp/3/

Solution 2:

Firefox does not carry over tags, attributes or CSS styles it does not understand from the code to the DOM. That is by design. Javascript only has access to the DOM, not the code. So no, there is no way to access a property from javascript that the browser itself does not support.

Solution 3:

By reading in the Stylesheet info in IE, you CAN get these "bogus" properties, but only in IE that I'm aware of.

var firstSS = document.styleSheets[0];
var firstSSRule = firstSS.rules[0];
if(typeof(firstSSRule.style.bar) != 'undefined'){
  alert('value of [foo] is: ' + firstSSRule.style.bar);
} else {
  alert('does not have [foo] property');
}

Its ugly code, but you get the picture.

Solution 4:

I too have some pages that work wonderfully in MSIE, but have lots of info in styles and style sheets. So I'm thinking about workarounds. One thing Firefox does allow, mercifully, is putting inline attributes into the DOM. So here's a partial strategy:

  1. Replace each inline style in the html document with a corresponding "nStyle", e.g., <span class="cls1" nStyle="color:red; nref:#myid; foo:bar"> ... </span>

  2. When the page is loaded, do the following with each element node: (a) copy the value of the nStyle attribute into the tag's cssText, and at the same time (b) convert the nonstandard attributes into an easier format, so that, e.g., node.getAttribute('nStyle') becomes the object {"nref":"#myid", "foo":"bar"}.

  3. Write a "calculatedStyle" function that gets either the style or the nStyle, depending on what's available.

Writing a rough parser for style sheets might enable a similar strategy for them, but I have a question: How do I get over the hurdle of reading the style sheet without censorship from Firefox?