chamberlainpi
chamberlainpi

Reputation: 5241

How to load and override Google Web Fonts subsequently?

After loading one set of Google Web Fonts, how can you load a new set to override the previously loaded set (assuming the elements making use of the old fonts are going to point to the newer font-families).

The Goal is to provide a way for a designer to choose any Google Web Fonts by copying one or more identifiers (Name:Size:Charset) in a Game Configuration popup (this interacts with the game at runtime, letting the user tweak various parameters).

Example:

  1. Load Lato:900:latin.
  2. Wait for user to type in new font to load (in a text input).
  3. When the user clicks "OK", load the new Web Font(s) + trigger a new onComplete callback.

I've tried reusing the Google JS snippet, but any calls after the 1st doesn't seem to trigger the "fontloading" callback (unsure if it fails).

var loadWebFont = function(fontFamilies, onComplete) {
    //Ensure 1st argument is of Array[String] type:
    if(!_.isArray(fontFamilies)) fontFamilies = [fontFamilies];
    else fontFamilies = fontFamilies.concat();

    //Get rid of blank/null fonts:
    for(var f=fontFamilies.length; --f>=0;) {
        var theFont = fontFamilies[f];
        if(!theFont || $.trim(theFont)==="") {
            fontFamilies.splice(f, 1);
        }
    }

    //Setup the font families Object and "fontloading" callback on window object.
    var loadCount = fontFamilies.length;
    window.WebFontConfig = {
        "fontloading": function(a, b) {
            if((--loadCount)<=0) onComplete();
        },
        google: { families: fontFamilies }
    };

    //Remove previously attached WebFonts <script> tag:
    if(window._WF_SCRIPT) {
        console.log("Removing previous Google Web Fonts node: " + window._WF_SCRIPT);
        window._WF_SCRIPT.parentNode.removeChild(window._WF_SCRIPT);
        window._WF_SCRIPT = null;
    }

    console.log("Loading fonts: " + fontFamilies);

    var wf = window._WF_SCRIPT = document.createElement('script');
    wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
        '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
    wf.type = 'text/javascript';
    wf.async = 'true';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(wf, s);
};

Upvotes: 0

Views: 449

Answers (1)

chamberlainpi
chamberlainpi

Reputation: 5241

The first time the WebFont API gets loaded, the webfont.js file defines a top-level object on window.WebFont. This holds the methods for loading the fonts, DOM manipulation to add a stylesheet, and (by the looks of it) some cross-browser compatibility check.

If you attempt reloading this script again, it seems to reuse the 1st window.WebFont object and therefore disregards any new fonts you pass to it.

Solution:

Nullify the window.WebFont and its generated <script> + <link rel="stylesheet"> tags

Here's the corrections made to the above script:

window.loadWebFont = function(fontFamilies, onComplete) {
    if(window._WEBFONT_SCRIPT) {
        console.log("Removing previous Google Web Fonts elements.");
        window._WEBFONT_SCRIPT.parentNode.removeChild(window._WEBFONT_SCRIPT);
        window._WEBFONT_SCRIPT = null;

        if(window._WEBFONT_CSS) {
            window._WEBFONT_CSS.parentNode.removeChild(window._WEBFONT_CSS);
            window._WEBFONT_CSS = null;
        }
        window.WebFont = null;
    }

    if(!_.isArray(fontFamilies)) fontFamilies = [fontFamilies];
    else fontFamilies = fontFamilies.concat();
    for(var f=fontFamilies.length; --f>=0;) {
        var theFont = fontFamilies[f];
        if(!theFont || $.trim(theFont)==="") {
            fontFamilies.splice(f, 1);
        }
    }
    var loadCount = fontFamilies.length;
    window.WebFontConfig = {
        "fontloading": function(a, b) {
            if((--loadCount)<=0) {
                var css = $('link[href^="http://fonts.googleapis.com/"]');
                //Store the <link> element, not the jQuery/Zepto result
                window._WEBFONT_CSS = css[0];
                onComplete();
            }
        },
        google: { families: fontFamilies }
    };

    var wf = window._WEBFONT_SCRIPT = document.createElement('script');
    wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
        '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
    wf.type = 'text/javascript';
    wf.async = 'true';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(wf, s);
};

Upvotes: 2

Related Questions