Chrome.tabs.onUpdated.addListener with delay

Asked

Viewed 188 times

6

I made an extension for Google Chrome that’s working. The goal is to change the color of the images' pixels on all web pages.

To do this on the pages loaded in the tabs already open, I use the following code (in background.js file):

function executeScriptsInExistingTabs(){
  chrome.windows.getAll(null, function(wins) {
    for (var j = 0; j < wins.length; ++j) {
      chrome.tabs.getAllInWindow(wins[j].id, function(tabs) {
        for (var i = 0; i < tabs.length; ++i) {
          if (tabs[i].url.indexOf("chrome://") != 0) {
            chrome.tabs.executeScript(tabs[i].id, { file: 'muda_conteudo.js' });
            chrome.browserAction.setIcon({path: "on.png", tabId:tabs[i].id});
          }
        }
      });
     }
   });
 }

To change the color, tabs that will be opened after the activation of the extension, use the following code (in the background.js file):

chrome.tabs.onUpdated.addListener(function(tabid, info, tab) {
  if (flag){
    if (info.status == "complete") {
       chrome.tabs.executeScript(tabid, {file:"muda_conteudo.js"});
       chrome.browserAction.setIcon({path: "on.png", tabId:tab.id})
    }
  }
});

Everything works perfectly, but when a new tab is opened, you first see the original images and only a few microseconds are replaced by the images recolored. I would like to correct that. Someone has an idea how to do it ?

  • 1

    The event you are using waits for the content to finish loading on the tab and then applies the script. As the operation you want to do depends on the content loaded, I don’t know if there is another way.

  • I don’t know if this works but, I think you can add a "Visible:Hidden" in the image tags, so they keep loading and you can wait for all content to finish loading to run your script and show them.

  • Thanks for the suggestion, but it won’t do in this case. The extension is prepared to work with any web page that is loaded in the browser, particularly all those that are not created by me. So I can’t define the state of the images.

1 answer

2

Like bfavaretto mentioned you only work with the images when the site is fully loaded, which make the browser draw the screen again.

What you do is remove all images while the site loads, as mentioned by Jan Cássio. To do this, you can use several strategies, one of them creating a script that defines display: none, knowing that not all pages are under your control, you can create a small Javascript function and run before the site loads completely.

(function () {
    var imagens = document.querySelectorAll("img");

    for(var i=0; i< imagens.length;i++) {
        imagens[i].style.display = "none";
    }
}());

The problem is that this script works only for the images within the tag img, in addition it can only hide the images that are already present on the page until the moment of execution, which can be a problem on websites with various elements of images. This solution should also not work when using Lazy Loading, probably you would have to call the function several times to achieve the expected result.

A more complete solution can be achieved using CSS, when defining which images should have the display: none At the very beginning of the body, when loading the pages everything should work normally. And when you finish uploading all the content, you turn the preview back on.

For example:

img{
    display: none !important; 
}

Notice the use of !important, we use this to ensure the over-writing of image properties already defined within other CSS files. By adding this CSS at the beginning of the body we can ensure that the images will not be visible.

Now to add our css style we should put at the top of the page, or inside the head right after the CSS styles of the site itself or at the beginning of the body. According to Google documentation you have to set the following in your file manifest.

"run_at": "document_start"

Done this just do something like:

function escondeImagens() {
    var conteudo   =    "<style id='fix_imagens'>img{display: none !important;}</style>";
    var head       = document.querySelector("head");
    head.innerHTML = head.innerHTML +  conteudo;
}

Remember that as your script will run before the head tag exists, if you call the function too soon nothing will happen, then you will probably have to make use of the setTimeout to ensure that the head already exists.

To display the images again to select the element with id fix_imagens and remove its contents.

var elem = document.querySelector('#fix_imagens');
elem.innerHTML = '';
  • Thank you very much :-)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.