Search code examples
javascriptjquerycssfont-face

Reading @font-face css in javascript/jquery IE vs Chrome and FF


I'm trying to read into a javascript variable, the CSS of a (local) stylesheet containing @font-face. I managed to make it work in FF en Chrome, but not in IE or Safari.

This is my routine (see also jsfiddle -- try it in different browsers)

function getFonts (obj, doc) {
    // Makes a list of the cssText of all @font-face items.
    var o = obj || {},
    sheets = doc.styleSheets,
    i = sheets.length, j, rules;

    while( 0 <= --i ){
        rules = sheets[i].rules || sheets[i].cssRules || [];
        j = rules.length;

        while( 0 <= --j ){
            // Alternatives for the if below:
            // - (worked only in Chrome): if ( rule[j].constructor.name === 'CSSFontFaceRule' )
            // - if ( rule[j].style.cssText && rule[j].style.cssText.match('src:') )
            // IE just gives NO [object CSSFontFaceRule] !!!
            if( rules[j].toString() == "[object CSSFontFaceRule]" ) {
                // rule.style.fontFamily works in Chrome chrome; Not in FF. For IE I don't know yet.
                fontFamily = rules[j].style.fontFamily || rules[j].style.cssText.match(/font-family\s*:\s*([^;\}]*)\s*[;}]/i)[1]

                // To prevent duplicates we use the cssText as key 
                o[ fontFamily ] = o[ fontFamily ] || {} ;
                o[ fontFamily ][rules[j].style.cssText] = rules[j].style.cssText ;
            }
        }
    }
    return o;
}

I have Googled for hours, but I just don't understand it. The rules that IE finds just are NEVER of the type CSSFontFaceRule. Am I missing something?

I got the code from somewhere online and altered it so that it works on FF too (only worked on Chrome). Anybody? I know the CSSFontFaceRule Object exists in IE. But how do you get it?

PS. I am on Windows and cannot test on (recent) Safari; only on iPad and it doesn't work there either.


Solution

  • Reverse the order of your check for sheets[i].rules and sheets[i].cssRules - IE matches both, but the CSSFontFaceRule are only found in the latter (tested in IE9+).

    http://jsfiddle.net/clintioo/zbpe518k/1/

    function getFonts (obj, doc) {
        // Maakt een lijst met de css van alle @font-face items.
        var o = obj || {},
        sheets = doc.styleSheets,
        rule = null,
        i = sheets.length, j;
    
        while( 0 <= --i ){
            rules = sheets[i].cssRules || sheets[i].rules || [];
            j = rules.length;
    
            while( 0 <= --j ){
                // Alternatives for the if below:
                // - if ( rule[j].style.cssText && rule[j].style.cssText.match('src:') )
                // - (worked only in Chrome): if ( rule[j].constructor.name === 'CSSFontFaceRule' )
                // IE just gives NO [object CSSFontFaceRule] !!!
                if( rules[j].toString() == "[object CSSFontFaceRule]" ) {
                    // rule.style.fontFamily works in Chrome chrome; Not in FF. For IE I don't know yet.
                    fontFamily = rules[j].style.fontFamily || rules[j].style.cssText.match(/font-family\s*:\s*([^;\}]*)\s*[;}]/i)[1]
    
                    // To prevent duplicates we use the cssText as key 
                    o[ fontFamily ] = o[ fontFamily ] || {} ;
                    o[ fontFamily ][rules[j].style.cssText] = rules[j].style.cssText ;
                }
            }
        }
        return o;
    }
    
    console.log(getFonts(null, document));