6

已经有一个类似的帖子,但我觉得它不能很好地回答我的特定问题。

我想检查外部样式表是否已加载。例如,如果它受到网络问题的阻碍,那么我想知道并加载一个后备。这是作为 jQuery 主题 CSS 的 CDN 的后备方案,但我希望这最终不会专门针对这一点,因为我使用的其他外部 CSS 我也想应用它。

  • 参考link元素将在页面上,因此对于头部中存在的链接元素的模式匹配是不可接受的。
  • 我没有能力更改样式表中的 CSS,因此添加虚拟 CSS 是不可接受的。
  • 由于我无法控制外部样式表中的 CSS,因此依赖 CSS 中的现有类是脆弱的,所以如果有其他解决方案,我更愿意。
  • 使用超时是唯一的方法吗?我应该设置多长时间?我应该选择什么事件来测量时间?
  • 我更喜欢纯 javascript,然后是 jQuery,但其他 javascript 框架的答案将被接受,因为它们无疑会对某人有所帮助。

编辑:一个新的想法。如果样式表是通过 AJAX 加载的,并且检查了状态码会怎样?这是一个可行的选择,有人知道吗?


这是我目前拥有的脚本:

<script type="text/javascript">
  var cdn = 'http://code.jquery.com/ui/1.10.1/themes/black-tie/jquery-ui.min.css';
  var ss = document.styleSheets;
  for (var i = 0, max = ss.length; i < max; i++) {
    var sheet = ss[i];
    var rules = sheet.rules ? sheet.rules : sheet.cssRules;
    if (sheet.href == cdn) {
      if ( rules == null || rules.length == 0) {
        var link = document.createElement("link");
        link.rel = "stylesheet";      
        link.href = '/js/jquery-ui/1.10.1/themes/black-tie/jquery-ui.min.css';
        document.getElementsByTagName("head")[0].appendChild(link);  
      }
      break;
    }  
  }
</script>

我在使用控制台(Chrome v25.0.1364.172)时发现,即使样式表是从 CDN 加载的,document.styleSheets[x].rules也是null. 我不确定我是否在控制台中正确访问它,也许还有另一个我应该使用或反对的功能?

CSSStyleSheet {rules: null, cssRules: null, ownerRule: null, media: MediaList, title: null…}
cssRules: null
disabled: false
href: "http://code.jquery.com/ui/1.10.1/themes/black-tie/jquery-ui.min.css"
media: MediaList
ownerNode: link
ownerRule: null
parentStyleSheet: null
rules: null
title: null
type: "text/css"
__proto__: CSSStyleSheet

如果有人可以帮助我找到如何检查样式表是否已加载,那将非常有帮助并且非常感谢。

4

1 回答 1

5

笔记:

请参阅rack-jquery_ui-themes 库的 github 存储库中的生产代码。忽略常量的所有插值和大写符号,如:THEME,它们在别处被替换。想象一下它是原始的 javascript。

什么有效

非常感谢 Brian 在对我的问题的评论中提供了主要的灵感来源。

<meta id='rack-jquery-ui-themes-fallback-beacon' />
<script type="text/javascript">
  var meta = $("#rack-jquery-ui-themes-fallback-beacon");
  meta.addClass("ui-icon");
  if ( meta.css('width') != "16px" ) {
    $('<link rel="stylesheet" type="text/css" href="/js/jquery-ui/#{JQueryUI::JQUERY_UI_VERSION}/themes/:THEME/#{JQUERY_UI_THEME_FILE}" />').appendTo('head');
  }
  meta.remove();
</script>

添加一个元标记,然后从 jQuery UI 样式表应用一个 CSS 类,然后检查它是否已更改,如果没有则添加回退链接,然后删除元标记。

我们在头部使用元标记而不是在正文中使用 div是有原因的。大多数 CSS 文件都包含在头部的链接元素中。如果检查它是否加载的脚本在此之后立即出现,因为它在头部的上下文中,所以身体还没有被加载到 DOM 中。在该上下文中访问 document.body 将导致 null ref 错误。

什么没用

使用 AJAX 发出 HEAD 请求并检查状态:

<script type="text/javascript">
  $.ajax({
    type: "HEAD",
    url: ':CDNURL',
    success: function(css,status) {
      // do nothing
    },
    error: function(xhr,status,error) {
      var link = document.createElement("link");
      link.rel = "stylesheet";     
      link.href = ':FALLBACK_URL';
      document.getElementsByTagName("head")[0].appendChild(link); 
    }
  });
</script>

我发现这是一个潜在的安全威胁,所以浏览器不会允许它。

检查 DOM 的样式表规则:

<script type="text/javascript">
  var has_jquery_rules = false;
  var i = document.styleSheets.length - 1;
  while (i >= 0 ) {
    var sheet = document.styleSheets[i];
    if(sheet.href == ":CDNURL/ui/#{JQueryUI::JQUERY_UI_VERSION}/themes/:THEME/jquery-ui.min.css") {
      var rules = sheet.rules ? sheet.rules : sheet.cssRules;
      has_jquery_rules = rules.length == 0 ? false : true;
      break; // end the loop.
    }
    has_jquery_rules = false;
    i--;
  }
  if ( has_jquery_rules == false ) {
    $('<link rel="stylesheet" type="text/css" href="/js/jquery-ui/#{JQueryUI::JQUERY_UI_VERSION}/themes/:THEME/#{JQUERY_UI_THEME_FILE}" />').appendTo('head');
  }
</script>

这也不起作用,因为某些(全部?)浏览器阻止访问由外部样式表添加的规则。

于 2013-08-06T22:39:59.727 回答