Francesco
Francesco

Reputation: 25239

JS: Why can't I get fonts with JS function in Firefox?

function getFonts(obj) {
        var o = obj || {},
            sheet = document.styleSheets,
            rule = null,
            i = sheet.length,
            j;
        while(0 <= --i) {
            rule = sheet[i].rules || sheet[i].cssRules || [];
            j = rule.length;
            while(0 <= --j) {
                if(rule[j].constructor.name === 'CSSFontFaceRule') {  
                    o[rule[j].style.fontFamily] = rule[j].style.src;
                };
            }
        }
        return o;
    }

It works well on Chrome... I don't understand why this JS code doesn't work in Firefox...

Upvotes: 1

Views: 106

Answers (2)

Danziger
Danziger

Reputation: 21161

EDIT:

As Bergi as pointed out in his comment and answer, you should not be checking constructor names to distinguish the different CSSRule types. Instead, you should use:

if (rule[j].type == CSSRule.FONT_FACE_RULE)

ORIGINAL ANSWER:

Some constructor names may be prefixed with 'Moz', so instead of:

if (rule[j].constructor.name === 'CSSFontFaceRule')

You should be checking:

if (rule[j].constructor.name.match(/^(Moz)?CSSFontFaceRule$/))

So that you match both 'CSSFontFaceRule' and MozCSSFontFaceRule. Also, you might get an error indicating security issues when trying to read sheet[i].rules (if the stylesheet has been loaded over HTTPS, for example), so you should add a try-catch:

function getFonts(obj) {
  var o = obj || {},
    sheet = document.styleSheets,
    rule = null,
    i = sheet.length,
    j;

  while (0 <= --i) { 
    try {
      rule = sheet[i].rules || sheet[i].cssRules || [];
    } catch(err) {
      console.error(err);
      continue;
    }
    
    j = rule.length;

    while (0 <= --j) {
      if (rule[j].constructor.name.match(/^(Moz)?CSSFontFaceRule$/)) {
        o[rule[j].style.fontFamily] = rule[j].style.src;
      }
    }
  }
  
  return o;
}

console.log(getFonts());
@font-face {
    font-family: FontName;
    src: url(font_name.woff);
}
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Tangerine">

Upvotes: 0

Bergi
Bergi

Reputation: 664185

Don't ever compare a .constructor.name to figure out the kind of object you are dealing with.

In your particular example, CSSRules can and should be distinguished by their .type. Replace the rule[j].constructor.name === 'CSSFontFaceRule' condition with

if(rule[j].type == CSSRule.FONT_FACE_RULE) {

Upvotes: 1

Related Questions