Comment revenir à la feuille de style locale (pas le script) si CDN échoue

je crée un lien vers la feuille de style Mobile jQuery sur un CDN et j'aimerais revenir à ma version locale de la feuille de style si le CDN échoue. Pour les scripts, la solution est bien connue:

<!-- Load jQuery and jQuery mobile with fall back to local server -->
<script src="http://code.jquery.com/jquery-1.6.3.min.js"></script>
<script type="text/javascript">
  if (typeof jQuery == 'undefined') {
    document.write(unescape("%3Cscript src='jquery-1.6.3.min.js'%3E"));
  }
</script>

je voudrais faire quelque chose de similaire pour une feuille de style:

<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.css" />

Je ne suis pas sûr si une approche similaire peut être réalisée parce que je ne suis pas sûr si le navigateur bloque de la même manière lors de la liaison d'un script comme il le fait lors du chargement d'un script (peut-être est-il possible de charger une feuille de style dans une étiquette de script et de l'injecter ensuite dans la page) ?

alors ma question Est: Comment puis-je m'assurer qu'une feuille de style est chargée localement si un CDN échoue ?

98
demandé sur Salman A 2011-09-12 07:56:58

11 réponses

N'a pas été testé sur plusieurs navigateurs, mais je pense que ça va marcher. Il faudra que ce soit après avoir chargé jquery, ou vous devrez le réécrire en Javascript simple.

<script type="text/javascript">
$.each(document.styleSheets, function(i,sheet){
  if(sheet.href=='http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.css') {
    var rules = sheet.rules ? sheet.rules : sheet.cssRules;
    if (rules.length == 0) {
      $('<link rel="stylesheet" type="text/css" href="path/to/local/jquery.mobile-1.0b3.min.css" />').appendTo('head');
    }
 }
})
</script>
58
répondu katy lavallee 2011-10-16 04:32:54

en supposant que vous utilisez le même CDN pour css et jQuery, pourquoi ne pas faire un seul test et tout attraper??

<link href="//ajax.googleapis.com/ajax/libs/jqueryui/1/themes/start/jquery-ui.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script type="text/javascript">
    if (typeof jQuery == 'undefined') {
        document.write(unescape('%3Clink rel="stylesheet" type="text/css" href="../../Content/jquery-ui-1.8.16.custom.css" /%3E'));
        document.write(unescape('%3Cscript type="text/javascript" src="/jQuery/jquery-1.6.4.min.js" %3E%3C/script%3E'));
        document.write(unescape('%3Cscript type="text/javascript" src="/jQuery/jquery-ui-1.8.16.custom.min.js" %3E%3C/script%3E'));
    }
</script>
28
répondu Mike Wills 2011-09-19 16:04:38

je suppose que la question Est de déterminer si une feuille de style est chargée ou non. Une approche possible est la suivante:

1) Ajouter une règle spéciale à la fin de votre fichier CSS, comme:

#foo { display: none !important; }

2) Ajouter le div correspondant dans votre HTML:

<div id="foo"></div>

3) sur le document prêt, vérifier si #foo est visible ou non. Si la feuille de style a été chargée, elle ne sera pas visible.

Démo ici -- loads thème jQuery-ui smoothness; aucune règle n'est ajoutée à la feuille de style.

27
répondu Salman A 2016-10-13 07:16:28

cet article suggère quelques solutions pour le bootstrap css http://eddmann.com/posts/providing-local-js-and-css-resources-for-cdn-fallbacks /

alternativement cela fonctionne pour fontawesome

<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<script>
    (function($){
        var $span = $('<span class="fa" style="display:none"></span>').appendTo('body');
        if ($span.css('fontFamily') !== 'FontAwesome' ) {
            // Fallback Link
            $('head').append('<link href="/css/font-awesome.min.css" rel="stylesheet">');
        }
        $span.remove();
    })(jQuery);
</script>
6
répondu dc2009 2014-12-10 15:25:08

Vous pourrait être en mesure de tester l'existence de la feuille de style dans document.styleSheets .

var rules = [];
if (document.styleSheets[1].cssRules)
    rules = document.styleSheets[i].cssRules
else if (document.styleSheets[i].rules)
    rule= document.styleSheets[i].rules

Test pour quelque chose de spécifique au fichier CSS que vous utilisez.

3
répondu Stefan Kendall 2011-09-12 04:15:09

voici une extension à la réponse de katy lavallee. J'ai tout emballé dans une syntaxe jQuery auto-exécutable pour prévenir les collisions variables et lancer le script sur dom ready. J'ai aussi rendu le script non spécifique à un seul lien. C'est-à-dire que tout lien de feuille de style avec un attribut url "data-fallback" sera automatiquement analysé. Vous n'avez pas à coder l'url dans ce script comme avant.

http://jsfiddle.net/skibulk/jnfgyrLt /

<link rel="stylesheet" type="text/css" href="broken-link.css" data-fallback="broken-link2.css">

.

(function($){
    var links = {};

    $( "link[data-fallback]" ).each( function( index, link ) {
        links[link.href] = link;
    });

    $.each( document.styleSheets, function(index, sheet) {
        if(links[sheet.href]) {
            var rules = sheet.rules ? sheet.rules : sheet.cssRules;
            if (rules.length == 0) {
                link = $(links[sheet.href]);
                link.attr( 'href', link.attr("data-fallback") );
            }
        }
    });
})(jQuery);
3
répondu skibulk 2014-10-15 12:33:01

voulez-vous vraiment suivre cette route javascript pour charger CSS en cas de défaillance D'un CDN?

Je n'ai pas pensé à toutes les implications de performance à travers, mais vous allez perdre le contrôle de quand le CSS est chargé et en général pour la performance de charge de page, CSS est la première chose que vous voulez télécharger après le HTML.

pourquoi ne pas gérer cela au niveau de l'infrastructure-mapper votre propre nom de domaine sur le CDN, lui donner un TTL court, surveiller les fichiers sur le CDN (par exemple en utilisant Watchmouse ou autre chose), si le CDN échoue, changez le DNS en site de sauvegarde.

D'autres options qui pourraient aider sont" cache forever " sur le contenu statique, mais il n'y a aucune garantie que le navigateur les conservera bien sûr ou en utilisant l'app-cache.

en réalité comme quelqu'un l'a dit au sommet, si votre CDN n'est pas fiable obtenir un nouveau

Andy

2
répondu Andy Davies 2011-09-17 07:00:32

regardez ces fonctions:

$.ajax({
    url:'CSS URL HERE',
    type:'HEAD',
    error: function()
    {
        AddLocalCss();
    },
    success: function()
    {
        //file exists
    }
});

et voici la version JavaScript vanille:

function UrlExists(url)
{
    var http = new XMLHttpRequest();
    http.open('HEAD', url, false);
    http.send();
    return http.status!=404;
}
if (!UrlExists('CSS URL HERE') {
AddLocalCss();
}

Maintenant, l'effectif de la fonction:

function AddLocalCss(){
document.write('<link rel="stylesheet" type="text/css" href=" LOCAL CSS URL HERE">')
}

assurez-vous que AddLocalCss est appelé dans la tête.

vous pourriez également envisager d'utiliser l'une des façons suivantes expliquée dans cette réponse :

de la Charge à l'aide d'AJAX

$.get(myStylesLocation, function(css)
{
   $('<style type="text/css"></style>')
      .html(css)
      .appendTo("head");
});

charge créée dynamiquement

$('<link rel="stylesheet" type="text/css" href="'+myStylesLocation+'" >')
   .appendTo("head");
Load using dynamically-created <style>

$('<style type="text/css"></style>')
    .html('@import url("' + myStylesLocation + '")')
    .appendTo("head");

ou

$('<style type="text/css">@import url("' + myStylesLocation + '")</style>')
    .appendTo("head");
1
répondu Community 2017-05-23 12:10:06

on pourrait utiliser onerror pour cela:

<link rel="stylesheet" href="cdn.css" onerror="this.onerror=null;this.href='local.css';" />

le this.onerror=null; est d'éviter les boucles sans fin dans le cas où le repli lui-même n'est pas disponible. Mais il pourrait également être utilisé pour plusieurs issues.

cependant, cela ne fonctionne actuellement que dans Firefox et Chrome.

0
répondu Jan 2018-09-07 13:33:37

j'utiliserais probablement quelque chose comme yepnope.js

yepnope([{
  load: 'http:/­/ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js',
  complete: function () {
    if (!window.jQuery) {
      yepnope('local/jquery.min.js');
    }
  }
}]);

tiré de the readme.

-1
répondu Ben Schwarz 2011-09-17 05:15:41
//(load your cdn lib here first)

<script>window.jQuery || document.write("<script src='//me.com/path/jquery-1.x.min.js'>\x3C/script>")</script>
-7
répondu crazy4groovy 2012-03-29 10:31:39