0

I'm attempting to create a local fallback for font-awesome, and I'm having some issues adding the <link> tag to the <head> element when the CDN fails to load.

Expected Behavior

If the GET request to the CDN produces a status other than 200 upon page load, a link to the local version of font-awesome should be added to the <head> element.

Actual Behavior

A failed GET request to the CDN doesn't add a link to the local version of font-awesome to the <head> element.

The issue appears to be happening within the code block that starts with xmlHttp.onreadystatechange = function() {.

When I move parentElement.insertBefore(createFallback, referenceElement); outside of the xmlHttp.onreadystatechange = function() { block, the link to the local fallback gets added to the <head> element just fine. But I don't understand why it isn't working within the code block.

I'd like to be able to detect whether the CDN is down, and if so, apply a link to the local version of font-awesome. I'm not receiving any error messages in the console while viewing the page,

My code is below:

<!doctype html>
<html class="no-js" lang="">
    <head>
        <link id="fontAwesomeFallback" rel="stylesheet" href="#">
        <script>
        // Define Variables
        var createFallback = document.createElement("link");
            createFallback.type = "text/css";
            createFallback.rel = "stylesheet";
            createFallback.href = "/css/font-awesome.css";

        var referenceElement = document.getElementById("fontAwesomeFallback");
        var parentElement = referenceElement.parentNode;

        // Open Http Request
        xmlHttp = new XMLHttpRequest();
        xmlHttp.open("GET", "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css", true);
        xmlHttp.onreadystatechange = function() {
           if (xmlHttp.readyState == 4 && xmlHttp.status !== 200) {
             parentElement.insertBefore(createFallback, referenceElement);
             console.log("Local fallback appended to head element");
           }
        }
        </script>
    </head>
    <body>
    </body>
</html>

I'd really appreciate any help you all can offer!

Thanks!

2 Answers2

1

The answer is at https://stackoverflow.com/a/27404688/294577 .

But I recommend using the following code to minimize the layout reflow if you are using jQuery library.

<div id="FontAwesome_fallback" style="display:none"></div>    
<script async>(function($) {
    var $span = $('<span class="fa" style="display:none"></span>');
    $('#FontAwesome_fallback').append($span)
    var f = $span.css('fontFamily');
    if (f !== 'FontAwesome') {
      $('head').append('<link href="/css/font-awesome.css" rel="stylesheet">');
    }
    })(jQuery);
</script>

There's no worry about the createDocumentFragment as mostly supported in browsers stated in http://quirksmode.org/dom/core/#miscellaneous

Community
  • 1
  • 1
Gnought
  • 485
  • 5
  • 12
  • I avoided having to include an extra static piece of markup by just applying this idea using the body element. – Sirius_B Jan 26 '17 at 17:27
0

You can also do this all with just JavaScript by targeting the document body like so:

<script async>(function($){
    var $span = $('<span class="fa" style="display:none">`</span>').appendTo('body');
    if ($span.css('fontFamily') !== 'FontAwesome' ) {
    $('head').append('<link href="~/assets/shared/css/vendor/font-awesome-4.7.0.min.css" rel="stylesheet">');
    }
    $span.remove();
    })(window.jQuery);
</script>
Sirius_B
  • 276
  • 1
  • 2
  • 13