web-dev-qa-db-fra.com

Chargement dynamique de fichier css à l'aide de javascript avec callback sans jQuery

J'essaie de charger un fichier css de manière dynamique en utilisant javascript et je ne peux utiliser aucune autre bibliothèque js (par exemple, jQuery).

Le fichier css est chargé mais je n'arrive pas à obtenir un rappel pour travailler. Ci-dessous le code que j'utilise

var callbackFunc = function(){
    console.log('file loaded');     
};
var head = document.getElementsByTagName( "head" )[0];
var fileref=document.createElement("link");
    fileref.setAttribute("rel", "stylesheet");
    fileref.setAttribute("type", "text/css");
    fileref.setAttribute("href", url);

    fileref.onload  = callbackFunc;
    head.insertBefore( fileref, head.firstChild );

L'utilisation du code suivant pour ajouter une balise de script afin de charger un fichier js fonctionne et déclenche un rappel:

var callbackFunc = function(){
    console.log('file loaded');     
};

var script = document.createElement("script");

script.setAttribute("src",url);
script.setAttribute("type","text/javascript");

script.onload  = callbackFunc ;

head.insertBefore( script, head.firstChild );

Est-ce que je fais quelque chose de mal ici? Toute autre méthode qui pourrait m'aider à atteindre cet objectif serait très appréciée?

30
U.Ahmad

Malheureusement, la plupart des navigateurs modernes ne prennent pas en charge les feuilles de style avec précaution. Il y a une solution que j'ai trouvée avec un peu de googling.

Cited from: _ ​​ http://thudjs.tumblr.com/post/637855087/stylesheet-onload-or-lack-thereof

Les bases

L'implémentation la plus élémentaire de ceci peut être réalisée dans une trentaine de lignes de - code indépendant du framework - JavaScript:

function loadStyleSheet( path, fn, scope ) {
   var head = document.getElementsByTagName( 'head' )[0], // reference to document.head for appending/ removing link nodes
       link = document.createElement( 'link' );           // create the link node
   link.setAttribute( 'href', path );
   link.setAttribute( 'rel', 'stylesheet' );
   link.setAttribute( 'type', 'text/css' );

   var sheet, cssRules;
// get the correct properties to check for depending on the browser
   if ( 'sheet' in link ) {
      sheet = 'sheet'; cssRules = 'cssRules';
   }
   else {
      sheet = 'styleSheet'; cssRules = 'rules';
   }

   var interval_id = setInterval( function() {                     // start checking whether the style sheet has successfully loaded
          try {
             if ( link[sheet] && link[sheet][cssRules].length ) { // SUCCESS! our style sheet has loaded
                clearInterval( interval_id );                      // clear the counters
                clearTimeout( timeout_id );
                fn.call( scope || window, true, link );           // fire the callback with success == true
             }
          } catch( e ) {} finally {}
       }, 10 ),                                                   // how often to check if the stylesheet is loaded
       timeout_id = setTimeout( function() {       // start counting down till fail
          clearInterval( interval_id );             // clear the counters
          clearTimeout( timeout_id );
          head.removeChild( link );                // since the style sheet didn't load, remove the link node from the DOM
          fn.call( scope || window, false, link ); // fire the callback with success == false
       }, 15000 );                                 // how long to wait before failing

   head.appendChild( link );  // insert the link node into the DOM and start loading the style sheet

   return link; // return the link node;
}

Cela vous permettrait de charger une feuille de style avec une fonction de rappel onload comme ceci:

loadStyleSheet( '/path/to/my/stylesheet.css', function( success, link ) {
   if ( success ) {
      // code to execute if the style sheet was loaded successfully
   }
   else {
      // code to execute if the style sheet failed to successfully
   }
} );

Ou si vous souhaitez que votre rappel conserve son périmètre/contexte, vous pouvez procéder de la sorte:

loadStyleSheet( '/path/to/my/stylesheet.css', this.onComplete, this );
37
mVChr

Vous pouvez créer un lien css vide dans votre fichier html et lui attribuer un identifiant. par exemple

<link id="stylesheet_css" rel="stylesheet" type="text/css" href="css/dummy.css?"/>

puis appelez-le avec le nom de l'ID et changez l'attribut 'href'

5
thecodeparadox

Il y a quelque temps, j'ai créé une bibliothèque pour cela, elle s'appelle Dysel , j'espère que ça aide

Exemple: https://jsfiddle.net/sunrising/qk0ybtnb/

var googleFont = 'https://fonts.googleapis.com/css?family=Lobster';
var jquery = 'https://code.jquery.com/jquery.js';
var bootstrapCss = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css';
var bootstrapJs = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js';
var smokeCss = 'https://rawgit.com/alfredobarron/smoke/master/dist/css/smoke.min.css';
var smokeJs = 'https://rawgit.com/alfredobarron/smoke/master/dist/js/smoke.min.js';

// Push links into an array in the correct order
var extRes = [];
extRes.Push(googleFont);
extRes.Push(bootstrapCss);
extRes.Push(smokeCss);
extRes.Push(jquery);
extRes.Push(bootstrapJs);
extRes.Push(smokeJs);

// let this happen
dysel({
  links: extRes,
  callback: function() {
    alert('everything is now loaded, this is awesome!');
  }, // optional
  nocache: false, // optional
  debug: false // optional
});
5
Sunrising

Cette approche Vanilla JS fonctionne dans tous les navigateurs modernes:

let loadStyle = function(url) {
  return new Promise((resolve, reject) => {
    let link    = document.createElement('link');
    link.type   = 'text/css';
    link.rel    = 'stylesheet';
    link.onload = () => { resolve(); console.log('style has loaded'); };
    link.href   = url;

    let headScript = document.querySelector('script');
    headScript.parentNode.insertBefore(link, headScript);
  });
};

// works in IE 10, 11 and Safari/Chrome/Firefox/Edge
// add an ES6 polyfill for the Promise (or rewrite to use a callback)
4
sandstrom

Voici comment nous le faisons. En utilisant "requestAnimationFrame" (ou faites appel à un simple événement "load" si ce n'est pas le cas).

Soit dit en passant, c’est ce que recommande Google dans son manuel "Page-speed": https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery }

<script>
    function LoadCssFile(cssPath) {
        var l = document.createElement('link'); l.rel = 'stylesheet'; l.href = cssPath;
        var h = document.getElementsByTagName('head')[0]; h.parentNode.insertBefore(l, h);
    }
    var cb = function() {
        LoadCssFile('file1.css');
        LoadCssFile('file2.css');
    };
    var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
    if (raf) raf(cb);
    else window.addEventListener('load', cb);
</script>
1
Serge Shultz

yepnope.js peut charger CSS et exécuter un rappel à la fin. par exemple.

yepnope([{
  load: "styles.css",
  complete: function() {
    console.log("oooooo. shiny!");
  }
}]);
0
David Palmer