Lopol2010
Lopol2010

Reputation: 79

chrome extension content script cant get element by class

Look at screenshot:

enter image description here

  1. Iframe is minimized so you cant see any of its childs
  2. Target div displayed as child of iframe even we know fact 1.

Extension's content script

console.log( targetDiv )   // output: undefined

Google Chrome console

console.log( targetDiv )   // output: targetDiv

How is that possible? The other 'normal' elements are printed out in both cases. Can you explain me this magic half-child element?

UPDATE: this div created dynamicly setInterval fixes problem!

Upvotes: 1

Views: 3269

Answers (3)

Jeremy
Jeremy

Reputation: 11

The polling answer by dhilt indeed does work, for pages using script loading to inject DOM (e.g. if they're using some web frameworks), you'll need to poll to retrieve results.

Just adding a bit on how you could use Promises to asynchronously compute the value of something you need to do:

const yourFunction = async (
  ...
): Promise<ReturnValueType> => {
  let POLL_COUNT = 20;
  let POLL_INTERVAL_SEC = MAX_DURATION / POLL_COUNT;
  let pollingTries = 0;
  let result: ReturnValueType;

  return new Promise((resolve, reject) => {
    const timer = setInterval(() => {
      if (pollingTries >= POLL_COUNT) {
        console.log("Max poll tries reached...");
        clearTimeout(timer);
        reject(new Error("Failed to retrieve result within specified duration"));
      }
      
      pollingTries++;
      console.log(`Running poll... #${pollingTries}`);
      
      // core functionality here
  
      if (!result) {
        console.log(`No results found yet!`);
      } else {
        // Stop interval if results are found
        clearTimeout(timer);
        resolve(results);
      }
    }, POLL_INTERVAL_SEC * MS_IN_SECONDS);
  });
};

Upvotes: 0

Ajmal
Ajmal

Reputation: 544

A simple solution to this can be to run the script after the page is fully loaded. Something like:

window.onload = function() {
   // run script
};

should work fine.

However, note that the script will run after all images and css are completely loaded and parsed.

Upvotes: 0

dhilt
dhilt

Reputation: 20744

You need to make sure that your script is loaded after that element is in DOM. Try to debug it, set up the breakpoint on your console.log(targetDiv) and investigate DOM manually. This element rendering may be delayed by some inner script for example. In that case you may implement a kind of polling process to detect this element in time:

const timer = setInterval(() => {
  const myElement = document.getElementById('my-element');
  if(myElement) {
    clearTimeout(timer);
    processMyElement(myElement);
  }
}, 150);

instead of just

const myElement = document.getElementById('my-element');
processMyElement(myElement);

Upvotes: 2

Related Questions