Skip to content
Advertisement

How to get elements in order that are placed via translate3d

I am building a Chrome extension that interacts with Youtube comments visible on the screen in my Youtube backend. I want the extension to traverse the list of comments and highlight them one by one like so:

enter image description here

I get the comments on the screen in the following way:

return document.querySelectorAll(".ytcp-comment-thread .style-scope.ytcp-comments-section #comment")[currentIndex]

and then maintain currentIndex to know at what element I am currently at.

This works for the first couple of comments but then it starts highlighting the wrong comment. After inspecting the page, I noticed that the order of the comment divs doesn’t exactly represent the order of comments on the screen. Instead, they seem to be placed by an attribute called translate3d:

enter image description here

How can I accurately traverse all of these comments on the screen?

Edit: Here is an example of how Youtube puts the last comments of the page (loaded lazily) at the top of the HTML elements:

enter image description here

And as code:

<div class="ytcp-comment-thread style-scope ytcp-comments-section" style="transform: translate3d(0px, 11596px, 0px);">

<div class="ytcp-comment-thread style-scope ytcp-comments-section" style="transform: translate3d(0px, 11800px, 0px);">

<div class="ytcp-comment-thread style-scope ytcp-comments-section" style="transform: translate3d(0px, 12004px, 0px);">

<div class="style-scope ytcp-comments-section" style="transform: translate3d(0px, 12208px, 0px);">

<div class="ytcp-comment-thread style-scope ytcp-comments-section" style="transform: translate3d(0px, 980px, 0px);">

<div class="ytcp-comment-thread style-scope ytcp-comments-section" style="transform: translate3d(0px, 1184px, 0px);">

Answer

Taking the given code (which is just part of a longer list and hence there are gaps in the layout) we can go through sorting the elements in terms of their y translations.

The sorted array has entries of the form [i, y] where i is the index within the collection of children of #items and y is the px value of the translation.

To illustrate that the sorting has produced the order in which the comments are to be highlighted a setTimeout function highlights them in turn. This is not likely to be what you want to do – it is here just as a simple demo:

const items = document.querySelector('#items').children;
let arr = [];
for (let i = 0; i < items.length; i++) {
  arr.push([i, Number(items[i].style.transform.split('translate3d(0px, ')[1].split('px')[0])]);
}
let sortedArr = arr.sort(function(a, b) {
  return a[1] - b[1];
});
let next = 0;
setInterval(function() {
  if (next > 0) {
    items[sortedArr[next - 1][0]].classList.remove('hilite');
  }
  items[sortedArr[next][0]].classList.add('hilite');
  if (next < (arr.length - 1)) next++;
}, 5000);
.hilite {
  background-color: yellow;
}
<div id="items">
  <div class="ytcp-comment-thread style-scope ytcp-comments-section" style="transform: translate3d(0px, 11596px, 0px);">content 11596</div>

  <div class="ytcp-comment-thread style-scope ytcp-comments-section" style="transform: translate3d(0px, 11800px, 0px);">content 11800</div>

  <div class="ytcp-comment-thread style-scope ytcp-comments-section" style="transform: translate3d(0px, 12004px, 0px);">content 12004</div>

  <div class="style-scope ytcp-comments-section" style="transform: translate3d(0px, 12208px, 0px);">content 12208</div>

  <div class="ytcp-comment-thread style-scope ytcp-comments-section" style="transform: translate3d(0px, 980px, 0px);">content 980</div>

  <div class="ytcp-comment-thread style-scope ytcp-comments-section" style="transform: translate3d(0px, 1184px, 0px);">content 1184</div>
</div>

Don’t forget to scroll down (quite a way) to see the highlighting happening.

Advertisement