Why "document.styleSheets" returns empty value after each 3 to 5 browser refreshes?

728 Views Asked by At

What I want to achieve is to make the user define specific stylesheets to be processed by a JavaScript file i wrote and here is the code i used to get the specified stylesheets :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="sheet-1.css">
    <link rel="stylesheet" href="sheet-2.css">
    <link rel="stylesheet" href="sheet-3.css">
    <!-- other css files -->

    <style>
        /* inline styles */
    </style>

</head>
<body>

    <script src="jquery-2.1.1.min.js"></script>
    <!-- some plugins -->

    <script>
        jQuery(document).ready(function($) {

            // user specified stylesheets
            var watchedStyleSheetsNames = [ 'sheet-1.css', 'sheet-2.css', 'sheet-3.css' ]

            var allSheets    = document.styleSheets,
                targetSheets = [];

            for ( var i = watchedStyleSheetsNames.length - 1; i >= 0; i--) {
                Object.keys( allSheets ).forEach ( function (j) {
                    if( allSheets[j].href && allSheets[j].href.indexOf( watchedStyleSheetsNames[i] ) !== -1 ) {
                        targetSheets.push(allSheets[j]);
                    }

                });            

            };

            // result
            console.log( 'Watched Stylesheets Array : ' + targetSheets );

        });
    </script>
</body>
</html>



The problem is everything works just fine with the first time page load and then after 3 to 5 refreshes the array of targetSheets returns empty value which obviously ruins everything done after that then after refreshing another time I get the expected value and so on. I tried with all browsers, cleared my cache the same thing happens again and again. here is an image of what i get in my console:

https://www.dropbox.com/s/ipnc20hcdr3d6wl/01.png?dl=0

I tested my code online & locally using wamp server with the latest versions of all browsers. So what causes this problem and how can I fix it ?

Thanks for your time.

Edit

I found the answer it was because implementing prefixfree plugin which remove the link nodes and then reinsert the processed css in style tags.

1

There are 1 best solutions below

4
On

You're looking for the stylesheets from within a jQuery ready handler. The whole point of a jQuery ready handler is that it fires after the HTML has been parsed but before all the dependencies have been downloaded and evaluated. So apparently sometimes, your code runs before the stylesheets have been loaded.

You'll want to wait until the stylesheets have been loaded. The only way I know of to check whether a linked stylesheet has been loaded is to load it dynamically, looking the load event before setting the href. There may be other ways, that's just the only one I know.

In your case, for instance, you could remove the <link> elements from the markup and do this:

jQuery(document).ready(function($) {

    // user specified stylesheets
    var watchedSheets = [
        { name: 'sheet-1.css' },
        { name: 'sheet-2.css' },
        { name: 'sheet-3.css' }
    ];
    var completed = 0;
    var head = document.querySelector('head');

    watchedSheets.forEach(function(sheet, index) {
        var link = document.createElement('link');
        link.onload  = function() {
            sheet.loaded = true;
            ++completed;
            if (completed === watchedSheets.length) {
                done();
            }
        };
        link.onerror = function() {
            sheet.error = true;
            ++completed;
            if (completed === watchedSheets.length) {
                done();
            }
        };
        link.rel = "styleshet";
        link.href = sheet.name;
        head.appendChild(link);
    });

    function done() {
        var allSheets    = document.styleSheets,
            targetSheets = [];

        Object.keys( allSheets ).forEach ( function (j) {
            var sheet = watchedSheets[j];
            if( !sheet.error && allSheets[j].href && allSheets[j].href.indexOf( sheet.name ) !== -1 ) {
                targetSheets.push(allSheets[j]);
            }
        });            

        // result
        console.log( 'Watched Stylesheets Array : ' + targetSheets );
    }
});