JQuery: загрузка css по запросу + обратный вызов, если выполняется
Я хочу загрузить файлы CSS по требованию (например, запустив HTTP-запрос XML, который возвращает загружаемые файлы CSS), например style1.css, style2.css..
Так есть ли способ в jQuery (или плагин) к этому?
- массовая загрузка нескольких файлов + добавление всех этих CSS файлов в DOM
- после завершения загрузки: запуск обратного вызова (например, оповещение "все таблицы стилей загружены!");
Идея заключается в следующем: загрузка html
через xmlhttp
, загрузка +adding необходимых css файлов, а затем - после того, как что-либо закончено, отобразить этот html
.
любая идея?
Thanx!
Ответы
Ответ 1
Как загрузить несколько файлов CSS с обратным вызовом по запросу
Обратите внимание, что без разрешения xdomain $.get будет загружать только локальные файлы
РАБОЧАЯ ДЕМО
$.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);
Ответ 2
Ответ, данный @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();
});
}
});
Ответ 3
Вот как я его загрузил:
$(document).ready( function() {
var css = jQuery("<link>");
css.attr({
rel: "stylesheet",
type: "text/css",
href: "path/to/file/style.css"
});
$("head").append(css);
});
Ответ 4
Решение может быть улучшено немного, я думаю... Прежде всего, когда вы используете эти строки кода:
...
$.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');
...
Но если вам нужно делать больше вещей (например, загружать файл script), получая эти css 'перед вызовом функции обратного вызова, я думаю, что лучший подход для этого будет использовать promises вместо решения 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 занимает некоторое время для загрузки, функция обратного вызова не будет выполняться до тех пор, пока все из них не будут восстановлены.
Ответ 5
Вы пытаетесь достичь ленивой загрузки ваших ресурсов.
Существуют различные плагины для обработки такого поведения.
Я могу назвать это два:
Два фрагмента со страницы плагинов, чтобы показать его:
Плагины 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();
Ответ 6
Если вы хотите, чтобы это было динамически (читай: по требованию), вы можете изменить ответ Whit на loadCssFile()
и вызвать его с файлом, который вы хотите загрузить.
function loadCssFile(pathToFile) {
var css = jQuery("<link>");
css.attr({
rel: "stylesheet",
type: "text/css",
href: pathToFile
});
$("head").append(css);
}
Ответ 7
Если вы хотите загрузить несколько файлов 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);
Ответ 8
ЭТО НЕ ТРЕБУЕТ ЗАГРУЗИТЬ ФАЙЛ 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);
Он не загружает запрошенный файл более одного раза, что требует статического хранения содержимого CSS в заголовке. Но это имеет смысл, учитывая, что загрузка/оценка JavaScript отличается от того, как стилизация доступна для браузера для рендеринга.
$.getCss('path/to/css/file.css')
.done(function(){
console.log("Worked");
})
.fail(function(){
console.log("Failed");
});
До сих пор я тестировал его с Chrome, IE и Firefox. Кажется, все работает нормально.