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:
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 div
s doesn’t exactly represent the order of comments on the screen. Instead, they seem to be placed by an attribute called translate3d
:
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:
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);">
Advertisement
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.