Динамически загружайте таблицу стилей CSS и ждите ее загрузки

У меня есть скрипт, где я загружаю таблицу стилей CSS при нажатии кнопки, как это:

link = "<link class='listcss' rel='stylesheet' href='http://....list.css'>";
$("head").append(link);

Затем мне нужно сделать некоторые расчеты на основе свойств ширины и высоты CSS:

function CSSDone(){
            if($(window).width()>640){
                $(".grid-item").css({"height":$(".grid-item").width()*0.2});
                $(".grid_item_img").css({"height":$(".grid-item").width()*0.2});
            console.log("a");
            }else{
                $(".grid-item").css({"height":$(".grid-item").width()*0.33});
                $(".grid_item_img").css({"height":$(".grid-item").width()*0.33});
            console.log("b");       
            }
        }
        CSSDone();

Однако, если я запускаю CSSDone(); Сразу после добавления таблицы стилей вычисления выполняются до загрузки CSS. Я искал в Интернете как сумасшедший, но все, что я пробовал, не работает:

Я пробовал эти варианты: 1) Не работает:

link.onload = function () {
    CSSDone();
}

2) не работает:

    if (link.addEventListener) {
      link.addEventListener('load', function() {
        CSSDone();
      }, false);
    }

3) не работает:

    link.onreadystatechange = function() {
      var state = link.readyState;
      if (state === 'loaded' || state === 'complete') {
        link.onreadystatechange = null;
        CSSDone();
      }
    };

4) не работает:

    $(window).load(function () {
        CSSDone();
    });

5) не работает:

    $(window).bind("load", function() {
        CSSDone();
    });

Поверь мне. Ничего не работает......


Один обходной путь:

Я загружаю CSS в DOM и немедленно удаляю его снова с помощью jQuery. Таким образом, при добавлении ссылки на голову позже, это достаточно быстро.

2 ответа

Решение

Вам нужно вставить link узел в голове, а затем прикрепить onload событие к этому. В вашем коде ссылка на строку. Смотрите пример кода ниже о том, как реализовать то, что вы хотите.

var link = document.createElement('link');
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.onload = function(){ CSSDone(); }
link.setAttribute("href", 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css');
document.getElementsByTagName("head")[0].appendChild(link);

jsfiddle

Чтобы обойти условия гонки при динамической вставке ссылки на таблицу стилей, а затем полагаясь на эти вычисления:

function downloadCSS(url) {
    function insertCss(code) {
        var style = document.createElement('style');
        style.type = 'text/css';
        style.innerHTML = code;
        document.querySelector("head").appendChild(style);
    }

    return new Promise(async (resolve, reject) => {
        try {
            let src = await axios.get(url);
            insertCss(src.data);
        } catch (e) {
            return reject(e);
        }

        requestAnimationFrame(function () {
            resolve();
        });
    });
}

(async function setup() {
    try {
        await downloadCSS('https://myapp.com/style.css');        
    } catch (e) {
        return reject(e);
    }
    
    //rest of code
})();

Я использую библиотеку axios для HTTP-запросов, но вы можете использовать все, что захотите.

Идея состоит в том, что вы ждете обещание downloadCSS, которое загружает URL-адрес вашего CSS, затем вставляет код как стиль, а не элемент ссылки, затем в следующем кадре выполняется обещание и продолжается оттуда.

Используя jQuery:

var head = $('head');
var link = $('<link>')
    .attr('rel', 'stylesheet')
    .attr('type', 'text/css')
    .attr('href', url)
                        .on('load', callback)
                        .on('error', error)
                       .appendTo(head);

Вы можете попробовать это, я верю.. включить CSSDone() код в $("head").append(link)обратный звонок

$(document).ready(function(){
$('.btn').on('click', function(){
link = "<link class='listcss' rel='stylesheet' href='/list.css'>";
        $("head").append(link, function(){
        if($(window).width()>640){
                $(".grid-item").css({"height":$(".grid-item").width()*0.2});
                $(".grid_item_img").css({"height":$(".grid-item").width()*0.2});
            console.log("a");
            }else{
                $(".grid-item").css({"height":$(".grid-item").width()*0.33});
                $(".grid_item_img").css({"height":$(".grid-item").width()*0.33});
            console.log("b");       
            }

        }); // append link

        }); // button click
}); // document ready
Другие вопросы по тегам