Обработка <? Xml-stylesheet> похожа на <link rel = "stylesheet">?
Во время исследования преимуществ и недостатков присоединения CSS с <?xml-stylesheet>
Обрабатывая инструкцию, я столкнулся с некоторыми проблемами.
Предположим, у нас есть простой документ XHTML (который поставляется с application/xhtml+xml
Тип MIME и просмотр в веб-браузере):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>A sample XHTML document</title>
<script type="application/javascript" src="/script.js"></script>
</head>
<body>
<h1>A heading</h1>
</body>
</html>
Тогда у нас есть внешний файл CSS (пусть он будет назван style.css
и положить в корневой каталог):
h1 { color: red; }
Во-первых, в script.js
, Я динамически присоединяю этот CSS с link
элемент:
const link = document.createElement('link');
Object.entries({rel: 'stylesheet', type: 'text/css', href: '/style.css'})
.forEach(([name, value]) => link.setAttribute(name, value));
document.head.appendChild(link);
Затем сценарий ожидает, пока таблица стилей не завершит загрузку и не достигнет ее. sheet
имущество:
link.addEventListener('load', function() {
const stylesheet = link.sheet;
});
После этого скрипт может манипулировать этой таблицей стилей, например:
stylesheet.cssRules.item(0).style.color = 'green'; // modify an existing rule
stylesheet.insertRule('body { background: #ffc; }', 1); // insert a new rule
Но сейчас я не могу понять, возможны ли такие же манипуляции, если таблица стилей прикреплена к <?xml-stylesheet>
инструкция по обработке:
const pi = document.createProcessingInstruction('xml-stylesheet',
'href="/style.css" type="text/css"');
document.insertBefore(pi, document.documentElement);
Во-первых, ИП, похоже, не имеет load
событие, поэтому сценарий не может знать, когда таблица стилей готова. Во-вторых, нет ничего подобного sheet
собственности, поэтому вы не можете позвонить pi.sheet
чтобы достичь таблицы стилей.
Есть ли способ преодолеть эти трудности и перейти от сценария к таблице стилей, связанной с <?xml-stylesheet>
ЧИСЛО ПИ?
1 ответ
Во-первых, кажется, что в PI нет события загрузки, поэтому сценарий не может знать, когда таблица стилей готова.
Ты можешь использовать PerformanceObserver
проверить запрошенные и загруженные ресурсы. Итерирует узлы document
, проверить .nodeType
7
или же .nodeType
8
, как ProcessingInstruction
узел может иметь comment
.nodeType
, Получить "resource"
свойство из записей производительности. парсить .nodeValue
отфильтрованного узла для URL в href="URL"
проверьте, равно ли значение "resource"
ввода производительности, затем проверьте, если .styleSheet
.href
значение равно проанализированному URL, а если проанализированный URL равен записи производительности "resource"
стоимость имущества. Если true
итерация .cssRules
или же .rules
из styleSheet
загружен в ProcessingInstruction
узел.
window.onload = () => {
let resource;
const observer = new PerformanceObserver((list, obj) => {
for (let entry of list.getEntries()) {
for (let [key, prop] of Object.entries(entry.toJSON())) {
if (key === "name") {
resource = prop;
var nodes = document.childNodes;
_nodes: for (let node of nodes) {
if (node.nodeType === 7 || node.nodeType === 8
&& node.nodeValue === pi.nodeValue) {
let url = node.baseURI
+ node.nodeValue.match(/[^href="][a-z0-9/.]+/i)[0];
if (url === resource) {
observer.disconnect();
// use `setTimeout` here for
// low RAM, busy CPU, many processes running
let stylesheets = node.rootNode.styleSheets;
for (let xmlstyle of stylesheets) {
if (xmlstyle.href === url && url === resource) {
let rules = (xmlstyle["cssRules"] || xmlstyle["rules"]);
for (let rule of rules) {
// do stuff
console.log(rule, rule.cssText, rule.style, xmlstyle);
break _nodes;
}
}
}
}
}
}
}
}
}
});
observer.observe({
entryTypes: ["resource"]
});
const pi = document.createProcessingInstruction('xml-stylesheet',
'href="style.css" type="text/css"');
document.insertBefore(pi, document.documentElement);
}
plnkr http://plnkr.co/edit/uXfSzu0dMDCOfZbsdA7n?p=preview
Вы также можете использовать MutationObserver
, setTimeout()
обрабатывать
недостаточно оперативной памяти, загружен процессор, запущено много процессов
window.onload = function() {
let observer = new MutationObserver(function(mutations) {
console.log(mutations)
for (let mutation of mutations) {
for (let node of mutation.addedNodes) {
if (node.nodeName === "xml-stylesheet") {
let url = node.baseURI
+ node.nodeValue.match(/[^href="][a-z0-9/.]+/i)[0];
setTimeout(function() {
for (let style of document.styleSheets) {
if (style.href === url) {
observer.disconnect();
// do stuff
console.log(style)
}
}
// adjust `duration` to compensate for device
// low RAM, busy CPU, many processes running
}, 500)
}
}
}
});
observer.observe(document, {
childList: true
});
const pi = document.createProcessingInstruction('xml-stylesheet',
'href="style.css" type="text/css"');
document.insertBefore(pi, document.documentElement);
}
plnkr http://plnkr.co/edit/AI4QZiBUx6f1Kmc5qNG9?p=preview
В качестве альтернативы используйте XMLHttpRequest()
или же fetch()
запросить .css
файл, создать и добавить <style>
элемент к document
, делать вещи с текстом ответа, установить .textContent
из style
элемент для корректировки css
текст.