0

How to determine when document has loaded(or is loading) after loading external css?

Normal page has loaded and complete at first time(with using document.onreadystatechange or document.readyStage), but after time script will call function to place a new stylesheet CSS into HTML for changing a background or images. During change stylesheet, document has still stage complete. Stage never has been changed after calling function? Why?

Timeline(example):

  1. Visit one page : localhost/index.html
  2. Document has stage loading
  3. Document has stage complete
  4. User was trying to change a theme, at this time stage hasnt been changed yet.

UPDATE: Without jQuery:)

UPDATE: Example problem with using one image:

<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 

    <script>
        document.onreadystatechange = function(){
            console.log(document.readyState);
        };
        function checkDocumentState(){
            console.log(document.readyState);
            return setTimeout(function(){ 
                checkDocumentState();
            }, 1000);
        }
        checkDocumentState();
    </script>
</head>
<body>
    <img src="" onclick="this.setAttribute('src','http://i.imgur.com/uRBtadp.jpg')" style="width:50px; height:50px; background-color:gray; " /> Press empty image and open new image.
</body>
</html>

enter image description here

FOUND ANSWER: How can I tell when a CSS background image has loaded? Is an event fired?

But hopeless .. lack of universality...

Community
  • 1
  • 1
machei
  • 337
  • 2
  • 16
  • 1
    "loaded" and "loading" are not the same. once it's done, it's done. you can probably monitor the dynamic link tag somehow. – dandavis Dec 02 '14 at 03:11
  • what are you trying to do that's a problem? – dandavis Dec 02 '14 at 03:21
  • Get changes from document state ;) State "complete" should be back to "loading", because of big images are gonna to load. I am trying to determine it, and page shows up as "loading page". U can understand it? – machei Dec 02 '14 at 03:23
  • readyState will never roll backwards. once complete, you'll have to monitor your own resources individually. in short, after onload(), loading state is more complex than a single global value can indicate... – dandavis Dec 02 '14 at 07:47
  • U can place example code? How to monitor all resources from CSS, which are needed to view. (font-face and background-image) – machei Dec 02 '14 at 14:10

3 Answers3

0

CSS is called after DOM elements are populated. This is why in the days of dial up internet, the page would load all funky looking, and then all of a sudden start to develop into the desired page bit by bit. I would suggest using Jquery instead, where you could use the following code to be able to ensure the document is fully loaded and the CSS is already implemented

$document.ready(function() {
//Insert Code here
}

Hope that helps

Tyler Lazenby
  • 409
  • 5
  • 27
  • CSS linked in the head is loaded and parsed BEFORE html is layedout – dandavis Dec 02 '14 at 03:12
  • I beg to differ dandavis. The html is what the browser will have on hand first, and start populating it first. http://stackoverflow.com/questions/6500141/do-external-stylesheets-get-loaded-before-the-html – Tyler Lazenby Dec 02 '14 at 03:15
  • layout. the page will not be _shown_ until css is ready, so the showing of un-styled content you describe can not happen. unless you import a sheet from the end of the body... – dandavis Dec 02 '14 at 03:19
  • $document.ready(function(){}) - is once time called by document state complete. But after state complete i wanna place new stylesheet, state must be changed to loading(or loaded) because images are gonna to load. http://www.w3schools.com/jsref/prop_doc_readystate.asp – machei Dec 02 '14 at 03:22
  • jQuery is a bit overhead for this, don't you think? – Sterling Archer Dec 02 '14 at 03:52
  • I am using jQuery too, but isn't the most tool for it based on document stage. – machei Dec 02 '14 at 04:01
  • You've got a point there about Jquery being overboard. Listen to them, not me. – Tyler Lazenby Dec 02 '14 at 04:36
0

Answering the question, how to determine the document has loaded after dynamically loading a css file depends upon the different browser vendors out there. There is not a single sure shot way for all the browsers, but lets tackle the problem one by one for each of these browsers.

Preface

var url = "path_to_some_stylesheet.css",
    head = document.getElementsByTagName('head')[0];
    link = document.createElement('link');

link.type = "text/css";
link.rel = "stylesheet"
link.href = url;
head.appendChild(link);

Once that appending is done:

  • Internet Explorer : fires readystatechange and load.
  • Opera : fires load event via onload.
  • Chrome : Doesnt fire an event but increments document.styesheets.length only after the file has arrived.
  • Firefox: I was not able to reliably get anything other than mozAfterPaint.
MIdhun Krishna
  • 1,739
  • 1
  • 13
  • 31
  • 1
    I know about document.stylesheets and onLoad, problem is how to determine all files, which are really loading by placing new css (example: body{background-image:url("new_image.png")}). – machei Dec 02 '14 at 14:00
0

I wrote this code, what i wanted and worked for me:

window.engineLoading = {images_count:0, images_loaded_count:0, fonts_count:0, fonts_loaded_count:0 };
document.querySelector("a").onclick = function(){ // first elemnet a
    var before_stylesheets_length = document.styleSheets.length;
    var before_fonts_size = document.fonts.size;

    document.fonts.onloadingerror = function(a){
        window.engineLoading.fonts_loaded_count++;
    }               
    document.fonts.onloading = function(a){
        window.engineLoading.fonts_count++;
    }       
    document.fonts.onloadingdone = function(a){
        window.engineLoading.fonts_loaded_count++;
    }

    var head= document.getElementsByTagName('head')[0];
    var style= document.createElement('link');
    style.rel= 'stylesheet';
    style.setAttribute("href","./new_style.css");
    style.onload = function(){
        for(i=before_stylesheets_length; i<document.styleSheets.length; i++){
            var rules = document.styleSheets[i].rules;
            for(q=0; q<rules.length; q++){
                var styles = rules[q].style;
                for(s=0; s<styles.length; s++){
                    console.log(styles[s]);
                    if((styles[s] == "background-image" || styles[s] == "background") && styles.backgroundImage.length > 0){
                        window.engineLoading.images_count++;
                        var body= document.getElementsByTagName('body')[0];
                        var image = document.createElement('img');
                        var url = styles.backgroundImage;
                        url = url.replace(/^url\(["']?/, '').replace(/["']?\)$/, '');
                        image.src = url;
                        image.width = 0;
                        image.height = 0;
                        image.setAttribute("class","pace-load-style");
                        image.onload = function(e){
                            console.log(e);
                            window.engineLoading.images_loaded_count++;
                        };
                        image.onerror = function(e){
                            window.engineLoading.images_laoded_count++;
                        }
                        body.appendChild(image);
                        break;
                    }
                }
            }
        }
    };
    style.onerror = function(){};
    head.appendChild(style);


    setTimeout(function(){ 
        checkCurrentState();
    }, 1000);
    return false;
};

    function checkCurrentState(){
        if(window.engineLoading.images_count == window.engineLoading.images_loaded_count && window.engineLoading.fonts_count == window.engineLoading.fonts_loaded_count){
            console.log("loaded"); return true;
        }console.log("still loading...");
    return  setTimeout(function(){ 
            checkCurrentState();
        }, 1000);
    };

UPDATE: Scipt has bug on localfile because of empty rule. CSSRules is empty I don't worry about it , and no need fix it.

UPDATE: Mozilla Firefox hasnt reference document.fonts.

Community
  • 1
  • 1
machei
  • 337
  • 2
  • 16