J'ai besoin de vérifier (en Javascript) si un fichier CSS est chargé et, si ce n'est pas le cas, de le charger. jQuery est parfait.
Comment fonctionne le crossbrowser document.styleSheets
?
J'ai besoin de vérifier (en Javascript) si un fichier CSS est chargé et, si ce n'est pas le cas, de le charger. jQuery est parfait.
Vérifiez simplement si un <link>
existe avec l'élément href
avec l'URL de votre fichier CSS :
if (!$("link[href='http://stackoverflow.com/path/to.css']").length)
$('<link href="http://stackoverflow.com/path/to.css" rel="stylesheet">').appendTo("head");
La méthode JS est également simple, en utilisant la fonction collection document.styleSheets :
function loadCSSIfNotAlreadyLoadedForSomeReason () {
var ss = document.styleSheets;
for (var i = 0, max = ss.length; i < max; i++) {
if (ss[i].href == "/path/to.css")
return;
}
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = "/path/to.css";
document.getElementsByTagName("head")[0].appendChild(link);
}
loadCSSIfNotAlreadyLoadedForSomeReason();
J'ai compris que la question était "comment vérifier si un fichier css est chargé ou non" plutôt que "comment vérifier si le fichier css est chargé ou non". <link>
élément existe". Le site <link>
peut exister (et le chemin d'accès peut aussi être correct) mais cela ne signifie pas que le fichier css a été chargé avec succès. Donc, en reformulant la question : si un fichier css n'est pas chargé (problèmes de communication avec le serveur cdn par exemple), comment charger un fichier css (local) (fallback) à la place ?
@JFK : cela mérite probablement sa propre question sur Stack Overflow. Il y a le load
y error
mais ils ne sont pas largement pris en charge (IE et Safari ne les prennent pas en charge, selon MDN). Je me pencherais probablement sur l'option document.styleSheets
Vous pouvez vérifier le nombre de règles dans chaque feuille de style de la collection, si c'est le cas. 0
alors il n'a probablement pas réussi à se charger.
Je devais juste écrire quelque chose comme ça et je voulais le partager. Celui-ci est préparé pour de multiples cas.
var styles = document.styleSheets;
for (var i = 0; i < styles.length; i++) {
// checking if there is a request for template.css
if (styles[i].href.match("template")) {
console.log("(Iteration: " + i + ") Request for template.css is found.");
// checking if the request is not successful
// when it is successful .cssRules property is set to null
if (styles[i].cssRules != null && styles[i].cssRules.length == 0) {
console.log("(Iteration: " + i + ") Request for template.css failed.");
// fallback, make your modification
// since the request failed, we don't need to iterate through other stylesheets
break;
} else {
console.log("(Iteration: " + i + ") Request for template.css is successful.");
// template.css is loaded successfully, we don't need to iterate through other stylesheets
break;
}
}
// if there isn't a request, we fallback
// but we need to fallback when the iteration is done
// because we don't want to apply the fallback each iteration
// it's not like our css file is the first css to be loaded
else if (i == styles.length-1) {
console.log("(Iteration: " + i + ") There is no request for template.css.");
// fallback, make your modification
}
}
Version TL;DR
var styles = document.styleSheets;
for (var i = 0; i < styles.length; i++) {
if (styles[i].href.match("css-file-name-here")) {
if (styles[i].cssRules != null && styles[i].cssRules.length == 0) {
// request for css file failed, make modification
break;
}
} else if (i == styles.length-1) {
// there is no request for the css file, make modification
}
}
Mise à jour : Comme ma réponse a reçu quelques upvotes et que cela m'a amené à réviser le code, j'ai décidé de le mettre à jour.
// document.styleSheets holds the style sheets from LINK and STYLE elements
for (var i = 0; i < document.styleSheets.length; i++) {
// Checking if there is a request for the css file
// We iterate the style sheets with href attribute that are created from LINK elements
// STYLE elements don't have href attribute, so we ignore them
// We also check if the href contains the css file name
if (document.styleSheets[i].href && document.styleSheets[i].href.match("/template.css")) {
console.log("There is a request for the css file.");
// Checking if the request is unsuccessful
// There is a request for the css file, but is it loaded?
// If it is, the length of styleSheets.cssRules should be greater than 0
// styleSheets.cssRules contains all of the rules in the css file
// E.g. b { color: red; } that's a rule
if (document.styleSheets[i].cssRules.length == 0) {
// There is no rule in styleSheets.cssRules, this suggests two things
// Either the browser couldn't load the css file, that the request failed
// or the css file is empty. Browser might have loaded the css file,
// but if it's empty, .cssRules will be empty. I couldn't find a way to
// detect if the request for the css file failed or if the css file is empty
console.log("Request for the css file failed.");
// There is a request for the css file, but it failed. Fallback
// We don't need to check other sheets, so we break;
break;
} else {
// If styleSheets.cssRules.length is not 0 (>0), this means
// rules from css file is loaded and the request is successful
console.log("Request for the css file is successful.");
break;
}
}
// If there isn't a request for the css file, we fallback
// But only when the iteration is done
// Because we don't want to apply the fallback at each iteration
else if (i == document.styleSheets.length - 1) {
// Fallback
console.log("There is no request for the css file.");
}
}
TL;DR
for (var i = 0; i < document.styleSheets.length; i++) {
if (document.styleSheets[i].href && document.styleSheets[i].href.match("/template.css")) {
if (document.styleSheets[i].cssRules.length == 0) {
// Fallback. There is a request for the css file, but it failed.
break;
}
} else if (i == document.styleSheets.length - 1) {
// Fallback. There is no request for the css file.
}
}
Dans Firefox, si le code CSS n'a pas encore été analysé, l'appel à la fonction cssRules
échouera avec l'erreur InvalidAccessError : Un paramètre ou une opération n'est pas pris en charge par l'objet sous-jacent. .
Il existe une solution de contournement pour Firefox ici phpied.com/Quand une feuille de style est vraiment chargée ? .
Quelque chose comme ceci fera l'affaire (en utilisant jQuery) :
function checkStyleSheet(url){
var found = false;
for(var i = 0; i < document.styleSheets.length; i++){
if(document.styleSheets[i].href==url){
found=true;
break;
}
}
if(!found){
$('head').append(
$('<link rel="stylesheet" type="text/css" href="' + url + '" />')
);
}
}
Un moyen : utiliser document.getElementsByTagName("link")
itérer sur chacun et vérifier si son href
est égal au fichier CSS que vous vérifiez.
Autre possibilité : si vous savez qu'une règle CSS n'est définie que dans ce fichier, vérifiez si cette règle s'applique vraiment, par exemple si l'arrière-plan d'un élément est vraiment rouge.
var links = document.getElementsByTagName('link');
var file = 'my/file.css';
var found = false;
for ( var i in links )
{
if ( links[i].type == 'text/css' && file == links[i].href ) {
found = true; break;
}
}
if ( !( found ) ) {
var styles = document.getElementsByTagName('style');
var regexp = new RegExp('/\@import url\("?' + file + '"?\);/');
for ( var i in styles )
{
if ( styles[i].src == file ) {
found = true; break;
} else if ( styles[i].innerHTML.match(regexp) ) {
found = true; break;
}
}
}
if ( !( found ) ) {
var elm = document.createElement('link');
elm.href = file;
document.documentElement.appendChild(elm);
}
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.