1

I am trying to write a Chrome extension that modifies the appearance of tweets on Twitter.

window.addEventListener('load', myMain, false)

function myMain() {
  console.log(document.getElementsByTagName('article'))
  console.log(document.getElementsByTagName('article').length)
  for (const article of document.getElementsByTagName('article')) {
    console.log('print something if this code is ever reached')
    console.log(article)
  }
}

Produces the following output: enter image description here

Hence console.log(document.getElementsByTagName('article')) retrieves every articles element, but the HTMLCollection CANNOT be iterated over.

I have seen other StackOverflow threads that suggest that the script must run after the page has loaded (e.g.: Iterate over HTMLCollection in custom element, HTMLCollection appearing in console with many elements but has length 0). But Twitter seems to be forever loading, so that solution does not work here. Is there any way to retrieve the content of document.getElementsByTagName('article') given that the Javascript is clearly retrieving something in order to be able to print it to the console?

James Shapiro
  • 4,805
  • 3
  • 31
  • 46
  • "*`console.log(document.getElementsByTagName('article'))` retrieves every articles element*" - no it doesn't, see [Is Chrome's JavaScript console lazy about evaluating arrays?](https://stackoverflow.com/q/4057440/1048572). As you can see, when the code runs the list has length 0. The answers on the questions you found are accurate. – Bergi May 30 '21 at 23:54
  • "*But Twitter seems to be forever loading*" - they're probably loading the elements lazily using js, so they don't exist on `DOMContentLoaded` either. You can use a mutation observer to recognise them being added to the DOM. What's the [actual problem](https://meta.stackexchange.com/q/66377) you're trying to solve? – Bergi May 30 '21 at 23:59
  • @Bergi I stated the actual problem I'm trying to solve in the first sentence of this question: "modify the appearance of tweets on Twitter." More specifically, for each Tweet, add a new button to the Tweet. Mutation Observer may be my best bet. – James Shapiro May 31 '21 at 00:02
  • Ah right. Neither CSS nor event delegation will help you to add a button. (Or, they might, but mutation observer is probably simpler) – Bergi May 31 '21 at 00:04

1 Answers1

0

The reason is that HTMLCollection does not behave completely like an Array, which means that doing:

for (const element of HTMLCollection){
  console.log(element)
}

Does not actually return element of that collection, but the HTMLCollection itself. To get to the element, you need to do any flavor of following:

for (let i = 0; i < HTMLCollection.length; i++) {
  console.log(HTMLCollection[i]);
}

In other words you need to address element by it's index.

MalwareMoon
  • 788
  • 1
  • 2
  • 13