1

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.

James A Mohler
  • 11,060
  • 15
  • 46
  • 72
Mo Ali
  • 11
  • 4
  • sounds like a race condition. To verify its a race condition, put that function in a setTimeout for 3 seconds. See if that fixes the issue. From there you might have to looking in to some type of dependency management like require js. – im_benton Oct 30 '14 at 17:32

1 Answers1

0

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 );
    }
});
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • unfortunately with testing it turns out that even with your code still the same error. even when i used this plugin [HERE](https://github.com/rgrove/lazyload) to dynamically load css and execute the code after loading is finished the same error still happening. I don't know what is the reason ??? – Mo Ali Oct 31 '14 at 15:02
  • Do you get any errors in the console when it happens? Issues loading the CSS, etc.? (Does the CSS get loaded?) It almost sounds like some kind of rate-limiting or overactive DDoS prevention. – T.J. Crowder Oct 31 '14 at 15:05
  • no i get no errors. i also tried to make it as a function and used setTimeout inside with a check for empty value of the array to repeat the code every 10 ms untill it gets a value for the array but i get infinite loop. i'm stuck – Mo Ali Oct 31 '14 at 17:13
  • it is a strange situation even with $(window).load it give me the same result as above i wonder what could be the reason ?? – Mo Ali Oct 31 '14 at 17:47