JQuery: загрузка CSS по требованию + обратный вызов, если сделано - PullRequest
30 голосов
/ 17 августа 2010

Я хочу загрузить файлы CSS по требованию (например, запустив HTTP-запрос XML, который возвращает загружаемые файлы CSS), например style1.css , style2.css ..

Так есть ли способ в jQuery (или плагин) к этому?

  • массовая загрузка нескольких файлов + добавление всех этих CSS-файлов в DOM
  • при завершении загрузки: запуск обратного вызова (например, предупреждение «все таблицы стилей загружены!»);

Идея такова: загрузка html через xmlhttp, загрузка + добавление требуется css-файлы, затем - после того, как что-либо закончено, покажите, что html.

есть идеи?

Thanx!

Ответы [ 8 ]

23 голосов
/ 25 июля 2013

Как загрузить несколько файлов CSS с обратным вызовом по запросу Примечание: без разрешений xdomain $ .get будет загружать только локальные файлы

WORKING DEMO
Обратите внимание, что текст«все загруженные CSS» появляются после загрузки, но до применения CSS.Возможно, для преодоления этого потребуется другой обходной путь.

$.extend({
    getManyCss: function(urls, callback, nocache){
        if (typeof nocache=='undefined') nocache=false; // default don't refresh
        $.when.apply($,
            $.map(urls, function(url){
                if (nocache) url += '?_ts=' + new Date().getTime(); // refresh? 
                return $.get(url, function(){                    
                    $('<link>', {rel:'stylesheet', type:'text/css', 'href':url}).appendTo('head');                    
                });
            })
        ).then(function(){
            if (typeof callback=='function') callback();
        });
    },
});

Использование

var cssfiles=['https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css', 'https://stackpath.bootstrapcdn.com/bootswatch/4.3.1/cerulean/bootstrap.min.css'];

$.getManyCss(cssfiles, function(){
    // do something, e.g.
    console.log('all css loaded');
});

для принудительного обновления файлов CSS добавить true

$.getManyCss(cssfiles, function(){
    // do something, e.g.
    console.log('all css loaded');
}, true);
9 голосов
/ 16 сентября 2014

Ответ, данный @ Popnoodles , неверен, потому что обратный вызов не выполняется после загрузки всех элементов, а скорее, когда цикл $ .each завершен. Причина в том, что операция $.each не возвращает отложенный объект (что ожидается $.when).

Вот исправленный пример:

$.extend({
    getCss: function(urls, callback, nocache){
        if (typeof nocache=='undefined') nocache=false; // default don't refresh
        $.when.apply($,
            $.map(urls, function(url){
                if (nocache) url += '?_ts=' + new Date().getTime(); // refresh? 
                return $.get(url, function(){                    
                    $('<link>', {rel:'stylesheet', type:'text/css', 'href':url}).appendTo('head');                    
                });
            })
        ).then(function(){
            if (typeof callback=='function') callback();
        });
    }
});
7 голосов
/ 17 августа 2010

Вот как бы я его загрузил:

$(document).ready( function() {
    var css = jQuery("<link>");
    css.attr({
      rel:  "stylesheet",
      type: "text/css",
      href: "path/to/file/style.css"
    });
    $("head").append(css);
});
2 голосов
/ 29 сентября 2016

Решение можно немного улучшить, я думаю ... Прежде всего, когда вы используете следующие строки кода:

...
$.get(url, function(){                    
    $('<link>', {rel:'stylesheet', type:'text/css', 'href':url}).appendTo('head');
});
...

Вы действительно делаете 2 вызова для получения css: сначала в самом $.get и во второй раз, когда вы добавляете <link> в head. Удаление $.get также приведет к получению CSS, но только один раз:

...
$('<link>', {rel:'stylesheet', type:'text/css', 'href':url}).appendTo('head');
...

Но если вам нужно сделать больше вещей (например, загрузить файл скрипта) при получении этих css 'перед вызовом функции обратного вызова, я думаю, что лучшим подходом для этого будет использование обещаний вместо when...then решение. Вы могли бы сделать что-то вроде этого:

var requests = []; //array which will contain every request we want to do before calling the callback function

$.map(urls, function(url) { //urls is the array of css files we want to load
    var defer = $.Deferred();
    defer.promise();

    //we add the deferred object to the requests array
    requests.push(defer);

    var cssEl = $('<link>', { rel: 'stylesheet', type: 'text/css', 'href': url });
    cssEl.appendTo('head').on("load", function() {
        defer.resolve();
    });
});

var anotherRequest = $.ajax({...}); //eg. a script file
requests.push(anotherRequest);

$.when.apply($, requests).done(function() {
    // callback when all requests are done
});

Таким образом, если для загрузки некоторых из css требуется некоторое время, функция обратного вызова не будет выполнена, пока не будут получены все из них.

1 голос
/ 14 февраля 2011

Вы пытаетесь добиться ленивой загрузки своих ресурсов.Существуют различные плагины для обработки такого рода поведения.

Я могу назвать это два:

Два фрагмента со страницы плагинов, чтобы показать его использование:

Плагины Jquery

$.plugins({ path: '/scripts/', plugins: [        
    { id:'box', js:'box.js', css:'box/styles.css', sel:'a[rel*=box]', ext:'box', fn:'box' },        
]});

jQuery(document).ready(function($){
  $('a').box();
});

Ленивый с зависимостями:

$.lazy('ui.draggable.js','draggable',{
'css':['modal.css','drag.css'],
'js':['ui.core.js']
});

// And then you use you plugins as you always do
$("#draggable").draggable();
0 голосов
/ 28 октября 2017

ЭТО НЕ ТРЕБУЕТ ЗАГРУЗИТЬ ФАЙЛ (ы) CSS БОЛЬШЕ, ЧЕМ ОДИН РАЗ

Работая от других устоявшихся ответов, мне удалось придумать это, которое похоже на jQuery.getScript():

(function($){

    $.extend({
        getCss: function(url, success) {

            if ($("head").children("style[data-url='"+url+"']").length) {
                console.warn("CSS file already loaded: "+url);
            }

            var deferred = $.Deferred(function(defer){
                $.ajax({
                    url: url
                    ,context: {defer:defer,url:url}
                    ,dataType: 'text'
                    ,cache: (function(){
                        var cache = $.ajaxSetup().cache;
                        if (cache === undefined) {cache = false;}
                        return cache;
                    })()
                })
                .then(
                    function(css, textStatus, jqXHR){
                        css = "\n\n/* CSS dynamically loaded by jQuery */\n\n"+css;
                        $('<style type="text/css" data-url="'+this.url+'">'+css+'</style>').appendTo("head");
                        this.defer.resolve(css, textStatus, jqXHR);
                    }
                    ,function(jqXHR, textStatus, errorThrown){
                        this.defer.reject(jqXHR, textStatus, errorThrown);
                    }
                );
            });
            if ($.isFunction(success)) {deferred.done(success);}
            return deferred;
        }
    });

})(jQuery);

Он не загружает запрошенный файл более одного раза, что DOES требует статического хранения содержимого CSS в заголовке. Но это имеет смысл, учитывая, что загрузка / оценка JavaScript отличается от того, как стилизация доступна в браузере для рендеринга.

$.getCss('path/to/css/file.css')
.done(function(){
    console.log("Worked");
 })
.fail(function(){
    console.log("Failed");
});

До сих пор я тестировал его с Chrome, IE и Firefox. Кажется, все работает нормально.

0 голосов
/ 17 октября 2017

Если вы хотите загрузить несколько файлов CSS, но хотите, чтобы они загружались один за другим, вы можете использовать решение ниже:

var getCss = function (url, callback) {
        $.get(url, function () {
            $('<link>', {rel: 'stylesheet', type: 'text/css', 'href': url}).appendTo('head');
            if (typeof callback == 'function') callback();
        });
    };

Определите функцию выше, затем определите массив, содержащий нужные файлы CSS

var cssfiles = ['css/pic1.css', 'css/pic2.css',
    'css/pic3.css', 'css/pic4.css', 'css/pic5.css',
    'css/pic6.css', 'css/pic7.css', 'css/pic8.css',
    'css/pic9.css'];

Затем определите функцию обратного вызова, которая будет вызывать каждый файл CSS в массиве

var callback = function (index) {
    getCss(cssfiles[index], function () {
        if (index + 1 < cssfiles.length) {
            callback(index + 1);
        }
    });
};

затем запустите функцию с первым CSS-файлом, указав его индекс

callback(0);
0 голосов
/ 17 августа 2010

Если вы хотите динамически (читай: по запросу), вы можете изменить ответ Уитта на loadCssFile() и вызвать его с файлом, который вы хотите загрузить.

function loadCssFile(pathToFile) {
    var css = jQuery("<link>");
    css.attr({
      rel:  "stylesheet",
      type: "text/css",
      href: pathToFile
    });
    $("head").append(css);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...