I am working on a Chrome extension, which can sort the videos of a website. For example, I search for a word `stackoverflow’ and many videos appear there, but these videos do not have the number of comments displayed in the search result, you have to open this video and get the number of comments. And this is my problem, I actually managed to do something similar, I can get the number of comments but it’s not working properly
const property = message.property;
const videos = Array.from(document.querySelectorAll("." + sortikContainer));
const parent = videos[0].parentNode;
originalOrder = Array.from(parent.children); // Store the original order
const savedURL = window.location.href; // Save the current URL
if (videos.length > 0) {
const visitedVideos = {}; // Object to store visited video URLs
const videoObjects = []; // Array to store video objects
const commentCounts = new Map(); // Map to store comment counts for each video URL
const openAndPrintVideoContent = async () => {
for (const video of videos) {
const videoUrl = video.getAttribute("src");
if (!visitedVideos[videoUrl]) {
visitedVideos[videoUrl] = true; // Mark video as visited
await new Promise((resolve) => {
const videoTriggerElement = video.querySelector(".tiktok-18e9va3-DivContainer");
videoTriggerElement.click(); // Open video
waitForElm('[data-e2e="browse-comment-count"]').then((commentCountElement) => {
if (commentCountElement && commentCountElement.textContent.trim() !== "") {
const commentCount = parseFloat(commentCountElement.textContent);
commentCounts.set(videoUrl, commentCount); // Store the comment count for the video URL
}
const closeButton = video.querySelector('[data-e2e="browse-close"]');
if (closeButton) {
closeButton.click();
resolve();
}
});
});
// Return to the list of videos by restoring the saved URL
history.pushState(null, null, savedURL);
}
}
sortVideosByComments(); // Sort videos by comments
console.log("Video Objects:", videoObjects); // Print video objects
};
const sortVideosByComments = () => {
const sortedVideos = videos.sort((a, b) => {
const commentCountA = commentCounts.get(a.getAttribute("src")) || 0;
const commentCountB = commentCounts.get(b.getAttribute("src")) || 0;
console.log("A=>" + commentCountA);
console.log("B=>" + commentCountB);
return commentCountB - commentCountA; // Sort by comment count in descending order
});
sortedVideos.forEach((video) => {
const parent = video.parentNode;
parent.prepend(video);
});
console.log("Videos sorted by comments");
// Build video object and add it to the array
sortedVideos.forEach((video) => {
const videoObject = {
url: video.getAttribute("href"),
commentCount: commentCounts.get(video.getAttribute("src")) || 0,
html: video.outerHTML,
};
videoObjects.push(videoObject);
});
};
openAndPrintVideoContent().then(() => {
console.log("Printing completed");
});
} else {
console.log("No video elements found");
sendResponse({ success: false, videoCounts: [] });
}
function waitForElm(selector) {
return new Promise((resolve) => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver((mutations) => {
if (document.querySelector(selector)) {
resolve(document.querySelector(selector));
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
});
}
This code returns the number of comments, but it also changes the URL in Chrome, and then takes me away from the page where I’m sorting, is there any other way I can do what I’m looking for?
2
Answers
use mutator to wait until element exists this way ou can be sure that the comments are loaded after
when the element is present you can get the comments count safely
example of mutator to wait until element exists :
To use it:
you can also find other functions that use timeout if the comments page are not loaded proprely
usage
Try this solution it look working for me but you need to rework this code to be most performant because if it is for commercial use you need to add a reject to your promise when waiting for element and if it is not found (caused by network failure…) you can set comment count to 0 or reschedule the url
wait for element with reject
Example call:
finally note that i trigger click for this element :