├── README.md
├── demo.html
└── fontdetect.js
/README.md:
--------------------------------------------------------------------------------
1 | # FontDetect
2 |
3 | Detect if the specific fonts are installed, and add classes to the `html` element.
4 |
5 | Inspired by:
6 |
7 | - http://jsdo.it/mayuki/qAvH
8 | - https://plus.google.com/113463921353776506005/posts/Yf1xtgKchFm
9 |
10 | ## Usage
11 |
12 |
13 |
14 |
30 |
31 | Result:
32 |
33 |
34 |
35 | ## Browser support
36 |
37 | - Does not support IE 8 and below
38 |
--------------------------------------------------------------------------------
/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | FontDetect
7 |
15 |
16 |
17 |
18 |
19 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/fontdetect.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * FontDetect v0.1.1
3 | * https://github.com/terkel/fontdetect
4 | *
5 | * Copyright (c) 2014 Takeru Suzuki - http://terkel.jp/
6 | * Licensed under the MIT license - http://opensource.org/licenses/MIT
7 | */
8 | var FontDetect = FontDetect || (function () {
9 |
10 | 'use strict';
11 |
12 | var style = document.createElement('style'),
13 | fontDataWOFF2 = 'data:application/font-woff2;base64,d09GMgABAAAAAAKIAA8AAAAABgQAAAIuAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP0ZGVE0cGiAGYACCUggEEQgKVHIBNgIkAxALCgAEIAWDXAc5P3dlYmYGGxAFyB6SVKCABKlAERUgUKUFz8uavn8wALxOFwfMqjRmYaemieJZWGDH8c2EJh7+u//9PjPTxSiKf9/lf07jhKMIQiqi73sYTwj/zzX9IkXvk5wfSuS6NCpso4nuDQeUmGE6AJq5td1rDz+KiZhJDRHZY0iIlwECPJQcPgO81LyeyN/1D+YgEAYJABQhZKE0t0DNvtigK2k99QNN+Ak5kxlmgM4/1HPsa6VcqEM2ar4b1efGhIJag4AabSlyppkq2lLNCgSEdAJ0Zmstc1J/VS0hDU+fJPMjXqD44yrqNaU1QGpdvFYDCPgJCICgnAbWgSa0EqyHar3Xi0GmW+Dm07juv7YCnArL9Zm/xn/mqZ/+ddOqEuZU/UL05Jm/n/w4i7j7BIS95Yp3V3jxT3r24czUPGiCTNImtlouqK+an9zojN9SWotJTJC7LDi06d0KiIByVuwLcqWKEggyUEOhsAxI2gaQTWRD0eGElot5aHR8w504f9wDe8S89Z7pRjUDZsxaM2/MiFGLDFNkLITVY6aNqGDXaahsXjLJY56DlR2tRXo06dMKcWSahcU3n5HpNWRe2ZjhSUMp066LUUeEzKgZiyYT05aHI1Z5XDnFY8JQf9Uwq0ljvDLJkhOXz5clU4G1yj5DvIZVyUVbi6lImwEhYsiVSx0KZcpMlqyVLJkWE9lqZw91mbNkzLx5QybPdeH/pUz+NA1JotJrRibXZkcd/kvTY3YqryanzPMr',
14 | fontDataWOFF = 'data:application/font-woff;base64,d09GRgABAAAAAAREAA8AAAAABgQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABWAAAABwAAAAcbNveqkdERUYAAAF0AAAAHQAAACAAMQAET1MvMgAAAZQAAABDAAAAYGVJZyBjbWFwAAAB2AAAAEcAAAFSACIEFmN2dCAAAAIgAAAABAAAAAQAIQJ5Z2FzcAAAAiQAAAAIAAAACP//AANnbHlmAAACLAAAAFQAAABUPaWWPmhlYWQAAAKAAAAAMAAAADYBLgvpaGhlYQAAArAAAAAcAAAAJAUUAyVobXR4AAACzAAAABAAAAAQCTwAIWxvY2EAAALcAAAACgAAAAoAVABUbWF4cAAAAugAAAAfAAAAIABIADluYW1lAAADCAAAAQUAAAHc+4lFanBvc3QAAAQQAAAAKwAAADlLkh2id2ViZgAABDwAAAAGAAAABrO3VDIAAAABAAAAAMw9os8AAAAA0EXXpQAAAADQWGQ1eNpjYGRgYOADYgkGEGBiYARCZiBmAfMYAARrADYAAAB42mNgZn7BOIGBlYGFqYspgoGBwRtCM8YxGDHqAPlAKewg1Dvcj8GBgZfBkVnhvwXDCeYXDCeAwoxIShQYGAEA7AotAHjaY2BgYGaAYBkGRgYQ8AHyGMF8FgYDIM0BhExgGV4Gx///kViM/7/+PwTVBQaMbAxwLiNIDxMDKmBkIAyYGYY0AAAwHgk2AAAhAnkAAAAB//8AAgACACEAAAEqApoAAwAHAC6xAQAvPLIHBADtMrEGBdw8sgMCAO0yALEDAC88sgUEAO0ysgcGAfw8sgECAO0yMxEhESczESMhAQnox8cCmv1mIQJYAHjaY2BkYGAA4vlljjfj+W2+MsgzvwCKMFyISDGF04pAJVpMs4BcDgYmkCgAKfgJT3jaY2BkYGB+8d8CRDIAAaMWAyMDKmABAFs2Az8BbAAhA+gAAAPoAAAAAAAAAAAAKgAqACoAKgAAeNpjYGRgYGBh4GBgYgABEMnIABJzYNADCQAABIEAggB42m2PzUrDQBRGT0ws6MJV6cJV6MKFYGnTWrVdCeJG/MGi3QlWrA2mraZRdOPz6SP4Cj6E9JvJEGqRYcK5X+49uQHW+cDHC9aAqm7OHoGqnFfYYMuxzzYtxwFlbhyv8kbquKT8x/EnFX4df1H3yjl/+2x6R9wx5Yl3TcY8MCIjZCye6cRMlB1S55J70QsJt+psUFNmTpcrTuhzJjJ9O0udJguXsmtVqbVP5Q//2C7oKTG8mI7UmdlNJ7wWEzX27NuxrI9ymp6h0kTmAZFo1959mqoO/t2vr2qgKWPOCvOp2+xc3zRpSNu+a9CRKdKzaf8rsnu2OC7mezzLHcucypzMAcGmPvcAAAB42mNgYgCD/1sZjBiwARYGBkYmRmYGFbb0nMqCDEP20rxMAwMDFwCFRwaaAAABVDKztgAA',
15 | fontDataTTF = 'data:application/x-font-ttf;base64,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',
16 | styleText = '@font-face{font-family:A0;src:' +
17 | 'url(' + fontDataWOFF2 + ')format("woff2"),' +
18 | 'url(' + fontDataWOFF + ')format("woff"),' +
19 | 'url(' + fontDataTTF + ')format("truetype")}',
20 | testNode = document.createElement('span');
21 |
22 | if (typeof style.appendChild !== 'function') {
23 | return {
24 | test: function () {
25 | return this;
26 | }
27 | };
28 | }
29 |
30 | style.id = 'fontdetect-style';
31 | style.appendChild(document.createTextNode(styleText));
32 | document.head.appendChild(style);
33 |
34 | testNode.id = 'fontdetect-test';
35 | testNode.style.fontFamily = 'A0';
36 | testNode.style.height = 0;
37 | testNode.style.overflow = 'hidden';
38 | testNode.style.position = 'absolute';
39 | testNode.style.visibility = 'hidden';
40 | testNode.appendChild(document.createTextNode('A'));
41 | document.body.appendChild(testNode);
42 |
43 | return {
44 | test: test
45 | };
46 |
47 | function test (slug, familyName) {
48 |
49 | var testInterval = setInterval(detect, 16),
50 | testTimeout = setTimeout(function () {
51 | clearInterval(testInterval);
52 | }, 4096);
53 |
54 | detect();
55 |
56 | function detect () {
57 |
58 | var test = false,
59 | key,
60 | i,
61 | len;
62 |
63 | if (testNode.offsetWidth === 0) {
64 | clearInterval(testInterval);
65 | clearTimeout(testTimeout);
66 | if (typeof slug === 'object') {
67 | for (key in slug) {
68 | FontDetect.test(key, slug[key]);
69 | }
70 | } else {
71 | if (Object.prototype.toString.call(familyName) === '[object Array]') {
72 | len = familyName.length;
73 | for (i = 0; i < len; i++) {
74 | if (isFontAvailable(familyName[i])) {
75 | test = true;
76 | break;
77 | }
78 | }
79 | } else {
80 | if (familyName === undefined) {
81 | familyName = slug;
82 | slug = slug.toLowerCase().replace(/\s/g, '');
83 | }
84 | test = isFontAvailable(familyName);
85 | }
86 | document.documentElement.className += (test? ' ': ' no-') + slug;
87 | FontDetect[slug] = test;
88 | }
89 | }
90 | }
91 |
92 | function isFontAvailable (fontName) {
93 | var result;
94 | testNode.style.fontFamily = '"' + fontName + '",A0';
95 | result = testNode.offsetWidth > 0;
96 | testNode.style.fontFamily = 'A0';
97 | return result;
98 | }
99 |
100 | return this;
101 | }
102 | }());
103 |
--------------------------------------------------------------------------------