如何确定CSS是否已加载?

时间:2023-01-02 23:59:14

How can i Assert that the CSS for a page has successfully loaded and applied its styles in Watin 2.1?

我怎么能断言页面的CSS已经成功加载并在Watin 2.1中应用了它的样式?

4 个解决方案

#1


22  

After doing some research and writing up my answer, I stumbled upon this link that explains everything you need to know about CSS, when it is loaded and how you can check for it.

在做了一些研究并写了我的答案之后,我偶然发现了这个链接,它解释了你需要知道的关于CSS的所有内容,加载时以及如何检查它。

The link provided explains it so well, in fact, that I'm adding some quotes from it for future reference.
If you're curious, my answer was going to be #2 and a variation of #4.

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

When is a stylesheet really loaded?

...

...

With that out of the way, let's see what we have here.

有了这个,让我们看看我们在这里有什么。

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

Options for the magic part, sorted from nice-and-easy to ridiculous

神奇部分的选项,从简单到易于分类排序

  1. listen to link.onload
  2. 听link.onload
  3. listen to link.addEventListener('load')
  4. 听link.addEventListener('load')
  5. listen to link.onreadystatechange
  6. 听link.onreadystatechange
  7. setTimeout and check for changes in document.styleSheets
  8. setTimeout并检查document.styleSheets中的更改
  9. setTimeout and check for changes in the styling of a specific element you create but style with the new CSS
  10. setTimeout并检查您创建的特定元素样式的更改,但使用新CSS检查样式

5th option is too crazy and assumes you have control over the content of the CSS, so forget it. Plus it checks for current styles in a timeout meaning it will flush the reflow queue and can be potentially slow. The slower the CSS to arrive, the more reflows. So, really, forget it.

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

So how about implementing the magic?

那么实施魔术怎么样?

// 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

#2


6  

There has been an update to the article lined to by @ShadowScripter. The new method purportedly works in all browsers, including FF.

@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


2  

After page load you can verify the style on some of your elements something like this:

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

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

And etc...

等等...

#4


0  

Since browser compatibility can vary, and new future browser standards subject to change, I would recommend a combination of the onload listener and adding CSS to the style sheet so you can listen for when the HTML elements z-index changes if you are using a single style sheet. Otherwise, use the function below with a new meta tag for each style.

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

Add the following to the CSS file that you are loading:

将以下内容添加到要加载的CSS文件中:

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

Add the following to your script:

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

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

Example

index.html:

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:

的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

the_style.css

#EpicStyleID {
    z-index: 0
}

PLEASE do not make your script load synchronously (without the async attribute) just so you can capture the link's onload event. There are better ways, like the method above.

请不要同步加载脚本(没有async属性),以便捕获链接的onload事件。有更好的方法,如上面的方法。

#1


22  

After doing some research and writing up my answer, I stumbled upon this link that explains everything you need to know about CSS, when it is loaded and how you can check for it.

在做了一些研究并写了我的答案之后,我偶然发现了这个链接,它解释了你需要知道的关于CSS的所有内容,加载时以及如何检查它。

The link provided explains it so well, in fact, that I'm adding some quotes from it for future reference.
If you're curious, my answer was going to be #2 and a variation of #4.

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

When is a stylesheet really loaded?

...

...

With that out of the way, let's see what we have here.

有了这个,让我们看看我们在这里有什么。

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

Options for the magic part, sorted from nice-and-easy to ridiculous

神奇部分的选项,从简单到易于分类排序

  1. listen to link.onload
  2. 听link.onload
  3. listen to link.addEventListener('load')
  4. 听link.addEventListener('load')
  5. listen to link.onreadystatechange
  6. 听link.onreadystatechange
  7. setTimeout and check for changes in document.styleSheets
  8. setTimeout并检查document.styleSheets中的更改
  9. setTimeout and check for changes in the styling of a specific element you create but style with the new CSS
  10. setTimeout并检查您创建的特定元素样式的更改,但使用新CSS检查样式

5th option is too crazy and assumes you have control over the content of the CSS, so forget it. Plus it checks for current styles in a timeout meaning it will flush the reflow queue and can be potentially slow. The slower the CSS to arrive, the more reflows. So, really, forget it.

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

So how about implementing the magic?

那么实施魔术怎么样?

// 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

#2


6  

There has been an update to the article lined to by @ShadowScripter. The new method purportedly works in all browsers, including FF.

@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


2  

After page load you can verify the style on some of your elements something like this:

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

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

And etc...

等等...

#4


0  

Since browser compatibility can vary, and new future browser standards subject to change, I would recommend a combination of the onload listener and adding CSS to the style sheet so you can listen for when the HTML elements z-index changes if you are using a single style sheet. Otherwise, use the function below with a new meta tag for each style.

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

Add the following to the CSS file that you are loading:

将以下内容添加到要加载的CSS文件中:

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

Add the following to your script:

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

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

Example

index.html:

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:

的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

the_style.css

#EpicStyleID {
    z-index: 0
}

PLEASE do not make your script load synchronously (without the async attribute) just so you can capture the link's onload event. There are better ways, like the method above.

请不要同步加载脚本(没有async属性),以便捕获链接的onload事件。有更好的方法,如上面的方法。