PageSourceSearch

https://boutrosfonts.com/squelettes/js/fontdetect.js

js boutrosfonts.com collected 2026-10-03 19:56:30 UTC 9,397 bytes, 244 lines download raw bytes

1/**
2 * FontDetect - A simple library to detect if an internal font is present or an external font got loaded.
3 * Updated by Ahmad Azimi: Add some functionality to support other languages, for example Farsi (Persian).
4 * 
5 * TO USE:
6 *     Include this file. If desired, you can load this file after the BODY.
7 *
8 *     After you load the fonts you want to test, call either of these methods:
9 *
10 *         // Checks that the font is loaded now.
11 *         isLoaded = FontDetect.isFontLoaded(fontname);
12 *
13 *         // Polls for the font getting loaded and calls a callback when it does.
14 *         FontDetect.onFontLoaded(fontname, callback [, {onFail: xxx, msInterval: yyy, msTimeout: zzz}]);
15 *
16 *     Note: For externally loaded fonts, you may have to wait for more than a second to get a reliable
17 *     answer. Internal browser fonts can be detected immediately.
18 *
19 *         // Determines which font in the font stack is being used for a given element.
20 *         fontname = FontDetect.whichFont(element); // DOM element, or can be a $(expression) if jQuery is loaded
21 *
22 * @author     Jennifer Simonds
23 * @copyright  2014 Jennifer Simonds
24 * @license    MIT License http://opensource.org/licenses/MIT
25 */
26FontDetect = function()
27{
28    // The private parts
29    var _isInitialized = false;
30    var _aFallbackFonts = ['serif', 'sans-serif', 'monospace', 'cursive', 'fantasy'];
31    var span = null;
32	var eLang = 'en';
33	var aChars = {
34		'en': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
35		'fa': 'ابپتجچحخدذرزسشصضططعغفقکگلمنوهی'
36	};
37
38    function _init ()
39    {
40        if (_isInitialized)
41        {	return;
42        }
43
44        _isInitialized = true;
45
46        var body = document.body;
47        var firstChild = document.body.firstChild;
48
49        var div = document.createElement('div');
50        div.id = 'fontdetectHelper';
51        span = document.createElement('span');
52        span.innerText = aChars[eLang];
53        div.appendChild(span);
54
55        body.insertBefore(div,firstChild);
56
57        div.style.position   = 'absolute';
58        div.style.visibility = 'hidden';
59        div.style.top        = '-200px';
60        div.style.left       = '-100000px';
61        div.style.width      = '100000px';
62        div.style.height     = '200px';
63        div.style.fontSize   = '200px';
64    }
65
66
67    function _getCss (p_element, p_cssStyle)
68    {
69        // First check if p_element is a DOM element.
70        if (p_element instanceof Element)
71        {   return window.getComputedStyle(p_element).getPropertyValue(p_cssStyle);
72        }
73
74        // If jQuery's loaded, use that.
75        else if (window.jQuery)
76        {   return $(p_element).css(p_cssStyle);
77        }
78
79        else // p_element might be a jQuery expression & caller was expecting jQuery to be loaded,
80             // or else some other parameter error...
81        {   return '';
82        }
83    }
84
85
86    // The public interface
87    return {
88        /**
89         * Polls 10 times/second until a font gets loaded or until it times out. (Default = 2 secs) It
90         * calls a callback on load, & optionally calls another function if it times out without loading.
91         *
92         * NOTE: You must specify at least one callback - for success or failure.
93         *
94         * @param string		The font name to check for.
95         * @param function		The function to call if it gets loaded within the timeout period.
96         * @param options		An optional object with named parameters:
97         *     @param eLang        Which font language to use. Default = 'en'.
98         *     @param onFail       The function to call if the font doesn't load within the timeout period.
99         *     @param msInterval   How many milliseconds for the polling interval. Default = 100.
100         *     @param msTimeout    How many milliseconds until we time out & call onFail. Default = 2000.
101         */
102        onFontLoaded: function (p_cssFontName, p_onLoad, p_onFail, p_options)
103        {
104            if (!p_cssFontName)
105            {	return;
106            }
107
108            // Our hashtable of optional params.
109            var msInterval = (p_options && p_options.msInterval) ? p_options.msInterval : 100;
110            var msTimeout  = (p_options && p_options.msTimeout) ? p_options.msTimeout : 2000;
111            var param1 = (p_options && p_options.param1) ? p_options.param1 : false;
112            var param2 = (p_options && p_options.param2) ? p_options.param2 : false;
113			// Since the language to use is an enum, check if the language they pass in is defined in aChars.
114			eLang = (p_options && p_options.eLang && p_options.eLang in aChars) ? p_options.eLang : 'en';
115
116            if (!p_onLoad && !p_onFail)
117            {	// Caller must specify at least one callback.
118                return;
119            }
120
121            if (!_isInitialized)
122            {	_init ();
123            }
124
125            if (this.isFontLoaded(p_cssFontName))
126            {	// It's already here, so no need to poll.
127                if (p_onLoad)
128                {	p_onLoad(p_cssFontName,param1,param2);
129                }
130                return;
131            }
132
133            // At this point we know the font hasn't loaded yet. Add it to the list of fonts to monitor.
134
135            // Set up an interval using msInterval. The callback calls isFontLoaded(), & if true
136            // it closes the interval & calls p_onLoad, else if the current time has timed out
137            // it closes the interval & calls onFail if there is one.
138            var outerThis = this;
139            var utStart = new Date().getTime();
140            var idInterval = setInterval (
141                function()
142                {
143                    if (outerThis.isFontLoaded(p_cssFontName))
144                    {	// It's now loaded.
145                        clearInterval (idInterval);
146						if (p_onLoad)
147						{
148							p_onLoad(p_cssFontName,param1,param2);
149						}
150                        return;
151                    }
152                    else
153                    {	// Still not loaded.
154                        var utNow = new Date().getTime();
155                        if ((utNow - utStart) > msTimeout)
156                        {
157                            clearInterval (idInterval);
158                            if (p_onFail)
159                            {	p_onFail(p_cssFontName);
160                            }
161                        }
162                    }
163                },
164                msInterval
165            );
166        },
167
168
169        /**
170         * Determines if a font has gotten loaded.
171         *
172         * @param string		The font name to check for.
173         *
174         * @returns bool		true if it's loaded, else false if the browser had to use a fallback font.
175         */
176        isFontLoaded: function (p_cssFontName)
177        {
178            var wThisFont = 0;
179            var wPrevFont = 0;
180
181            if (!_isInitialized)
182            {	_init ();
183            }
184
185            for(var ix = 0; ix < _aFallbackFonts.length; ++ix)
186            {
187                span.style.fontFamily = '"' + p_cssFontName + '",' + _aFallbackFonts[ix];
188                wThisFont = span.offsetWidth;
189                if (ix > 0 && wThisFont != wPrevFont)
190                {// This iteration's font was different than the previous iteration's font, so it must
191                //  have fallen back on a generic font. So our font must not exist.
192                    return false;
193                }
194
195                wPrevFont = wThisFont;
196            }
197
198            // The widths were all the same, therefore the browser must have rendered the text in the same
199            // font every time. So unless all the generic fonts are identical widths (highly unlikely), it
200            // couldn't have fallen back to a generic font. It's our font.
201            return true;
202        },
203
204
205        /**
206         * Determines which font is being used for a given element.
207         *
208         * @param string/object		The element to examine. If it's a string, it's a jQuery selector. If it's
209         *							an object, it's taken as a DOM element.
210         *
211         * @returns string			The name of the font that's being used - either one of the fonts
212         *							listed in the element's font-family css value, or null.
213         */
214        whichFont: function (p_element)
215        {
216            var sStack = _getCss(p_element, 'font-family');
217            var aStack = sStack.split(',');
218
219            var sFont = aStack.shift();
220            while (sFont)
221            {
222                // Trim the fontname of any spaces or quotes.
223                sFont = sFont.replace(/^\s*['"]?\s*([^'"]*)\s*['"]?\s*$/, '$1');
224
225                // If it's a default fallback font, trap it here.
226                for (var ix=0; ix < _aFallbackFonts.length; ix++)
227                {
228                    if (sFont == _aFallbackFonts[ix])
229                    {return sFont;
230                    }
231                }
232
233                // It must be a custom font name. Check it.
234                if (this.isFontLoaded(sFont))
235                {	return sFont;
236                }
237
238                sFont = aStack.shift();
239            }
240
241            return null;
242        }
243    };
244}();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.