【问题标题】:How to determine if CSS has been loaded?如何判断 CSS 是否已经加载?
【发布时间】:2012-05-19 04:55:07
【问题描述】:

如何断言页面的 CSS 已成功加载并在 Watin 2.1 中应用其样式?

【问题讨论】:

标签: css watin


【解决方案1】:

在做了一些研究并写下我的答案后,我偶然发现了this link,它解释了您需要了解的有关 CSS 的所有信息、加载时间以及如何检查它。

提供的链接很好地解释了它,事实上,我正在添加一些引用以供将来参考。
如果你很好奇,我的答案将是 #2 和一个变体#4。

When is a stylesheet really loaded?

...

除此之外,让我们看看这里有什么。

// my callback function 
// which relies on CSS being loaded function
CSSDone() {
    alert('zOMG, CSS is done');
};

// load me some stylesheet 
var url = "http://tools.w3clubs.com/pagr/1.sleep-1.css",
    head = document.getElementsByTagName('head')[0],
    link = document.createElement('link');

link.type = "text/css"; 
link.rel = "stylesheet";
link.href = url;

// MAGIC 
// call CSSDone() when CSS arrives
head.appendChild(link);

魔术部分的选项,从简单到可笑排序

  1. 收听link.onload
  2. 收听link.addEventListener('load')
  3. 收听link.onreadystatechange
  4. setTimeout 并检查 document.styleSheets 中的更改
  5. setTimeout 并检查您创建的特定元素的样式是否发生了变化,但使用新 CSS 设置样式

第五个选项太疯狂了,假设你可以控制 CSS 的内容,所以忘了它。另外,它会在超时时检查当前样式,这意味着它将刷新回流队列并且可能会很慢。 CSS 到达越慢,回流越多。所以,真的,算了吧。

那么如何实现魔法呢?

// MAGIC 

// #1   
link.onload = function () {
    CSSDone('onload listener');
};   

// #2   
if (link.addEventListener) {
    link.addEventListener('load', function() {
        CSSDone("DOM's load event");
    }, false);   
};   

// #3   
link.onreadystatechange = function() {
    var state = link.readyState;
    if (state === 'loaded' || state === 'complete') {
        link.onreadystatechange = null;
        CSSDone("onreadystatechange");
    }   
};

// #4   
var cssnum = document.styleSheets.length;
var ti = setInterval(function() {
    if (document.styleSheets.length > cssnum) {
        // needs more work when you load a bunch of CSS files quickly
        // e.g. loop from cssnum to the new length, looking
        // for the document.styleSheets[n].href === url
        // ...

        // FF changes the length prematurely :(
        CSSDone('listening to styleSheets.length change');
        clearInterval(ti);
    }   
}, 10);

// MAGIC ends

【讨论】:

  • 检查我的答案,它指的是文章@ShowScripter 链接到的重要后续更新。
【解决方案2】:

@ShadowScripter 对文章进行了更新。据称,新方法适用于所有浏览器,包括 FF。

var style = document.createElement('style');
style.textContent = '@import "' + url + '"';

var fi = setInterval(function() {
  try {
    style.sheet.cssRules; // <--- MAGIC: only populated when file is loaded
    CSSDone('listening to @import-ed cssRules');
    clearInterval(fi);
  } catch (e){}
}, 10);  

document.getElementsByTagName('head')[0].appendChild(style);

【讨论】:

    【解决方案3】:

    页面加载后,您可以验证某些元素的样式,如下所示:

    var style = browser.Div(Find.ByClass("class")).Style;
    Assert.That(Style.Display, Is.StringContaining("none"));
    Assert.That(Style.FontSize, Is.EqualTo("10px"));
    

    等等……

    【讨论】:

    • 好的,但这只是问题的一部分。这仅验证样式是否已应用,而不是所有样式均已有效加载。例如,如何确保给定的背景图像已作为样式的一部分加载?检查样式会说样式有背景图片,但是如何验证该图片是否已加载并正在显示?
    • 您可以验证元素属性等...可见性测试只能通过眼睛来完成。如果您对此有解决方案,我会很高兴知道答案:)
    【解决方案4】:

    由于浏览器兼容性可能会有所不同,并且未来新的浏览器标准可能会发生变化,因此我建议将 onload 侦听器和添加 CSS 到样式表中相结合,这样您就可以在 HTML 元素 z-index 更改时进行侦听,如果您是使用单个样式表。否则,使用下面的函数为每个样式添加一个新的元标记。

    将以下内容添加到您正在加载的 CSS 文件中:

    #*(insert a unique id for he current link tag)* {
        z-index: 0
    }
    

    将以下内容添加到您的脚本中:

    function whencsslinkloads(csslink, whenload ){
        var intervalID = setInterval(
            function(){
                if (getComputedStyle(csslink).zIndex !== '0') return;
                clearInterval(intervalID);
                csslink.onload = null;
                whenload();
            },
            125 // check for if it has loaded 8 times a second
        );
        csslink.onload = function(){
            clearInterval(intervalID);
            csslink.onload = null;
            whenload();
        }
    }
    

    示例

    index.html:

    <!doctype html>
    <html>
        <head>
            <link rel=stylesheet id="EpicStyleID" href="the_style.css" />
            <script async href="script.js"></script>
        </head>
        <body>
            CSS Loaded: <span id=result>no</span>
        </body>
    </html>
    

    script.js:

    function whencsslinkloads(csslink, whenload ){
        var intervalID = setInterval(
            function(){
                if (getComputedStyle(csslink).zIndex !== '0') return;
                clearInterval(intervalID);
                csslink.onload = null;
                whenload();
            },
            125 // check for if it has loaded 8 times a second
        );
        csslink.onload = function(){
            clearInterval(intervalID);
            csslink.onload = null;
            whenload();
        }
    }
    /*************************************/
    whencsslinkloads(
        document.getElementById('EpicStyleID'),
        function(){
            document.getElementById('result').innerHTML = '<font color=green></font>'
        }
    )
    

    the_style.css

    #EpicStyleID {
        z-index: 0
    }
    

    请不要让您的脚本同步加载(没有async 属性),这样您就可以捕获链接的onload 事件。还有更好的方法,比如上面的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多