Search code examples
javascriptdomgoogle-chromestylesheet

Why can't I detect style changes from a Chrome plugin until I call setTimeout?


Basically I'm detecting the presence of CSS that hides ads and if I find it I'd like to show a little message. However, I've found that even if all of this code is executed when the dom is loaded ($(function(){})) it still only works if I set a timeout even if the timeout is zero. Does anyone have any idea why this is happening (tested in Chrome on a Mac)

function detect(callback){

for (var x = 0; x < document.styleSheets.length; x++) {

    var rules = document.styleSheets[x].cssRules;
    for (var i = 0; i < rules.length; i++) {

           if(rules[i].style.display == 'none' && [].slice.call(rules[i].selectorText.match(/ads/ig), 0).length > 10)
           {
                return callback()
           }
    }
}
}


    // fails, the plugins css hasn't been applied yet
    detect(function(){
              $("#sorryYouDontLikeOurAds").show()
          })

    // but this works even with a timeout of zero
    setTimeout(function(){ 
          detect(function(){
              $("#sorryYouDontLikeOurAds").show()
          })
       }, 0);

Solution

  • Well, setTimeout can't take a value of 0ms as a valid delay. Most browsers will 'clamp' that delay to some minimum value. I think it's around 4-10ms depending on the browser. What is probably happening is the plugin code is executing on the $.ready loop at some point after your code runs. So then it would make sense that you would have to set some sort of timeout on it to get it to 'wait' long enough until the plugin has loaded.

    You can read more about how setTimeout works here.