ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

javascript – 处理<?xml-stylesheet>类似于?

2019-07-10 23:36:54  阅读:157  来源: 互联网

标签:javascript css xhtml processing-instruction cssom


在研究使用<?xml-stylesheet>附加CSS的优缺点时处理指令,我遇到了一些问题.

假设我们有一个简单的XHTML文档(与application / xhtml xml MIME类型一起提供并在Web浏览器中查看):

<!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:

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);

首先,PI似乎没有加载事件,因此脚本无法知道样式表何时准备就绪.其次,没有像sheet属性那样,所以你不能调用pi.sheet来访问样式表.

有没有办法克服这些困难,并从脚本到与<?xml-stylesheet>相关联的样式表? PI?

解决方法:

First, PI seem not to have load event, so the script cannot know when
the stylesheet is ready.

您可以使用PerformanceObserver检查请求和加载的资源.迭代文档的节点,检查.nodeType 7或.nodeType 8,因为ProcessingInstruction节点可以有注释.nodeType.从性能条目中获取“资源”属性.在href =“URL”处解析URL的已过滤节点的.nodeValue,检查值是否等于性能条目的“资源”,然后检查.styleSheet .href值是否等于已解析的URL,以及解析的URL是否等于性能输入“资源”属性值.如果为true,则迭代在ProcessingInstruction节点处加载的styleSheet的.cssRules或.rules.

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()来处理

low RAM, busy CPU, many processes running

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>要记录的元素,用响应文本做东西,将样式元素的.textContent设置为调整后的css文本.

标签:javascript,css,xhtml,processing-instruction,cssom
来源: https://codeday.me/bug/20190710/1428855.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有