I've recently started working on a chrome extension which has to wait for a YouTube page to load before adding a button at a certain place in the already existing code.
I've used getElementById() to get the element, but most of the time my page doesn't have time to fully load that the script already finished.
I've checked many topics regarding this issue and stumbled across window.addEventListener('load', submitAction); which doesn't actually waits for the whole page to load, or at least it doesn't look like it. When I try to print the output of the getElementById()'s output, the result is null.
I've been trying to use other kind of event listeners, using it on document and not on window, trying to wait for DOMContentLoaded as it looks like it's also waiting for the document to fully load but nothing actually waits for the whole page to load.
The most optimal thing I would like to do would be that the page loads, when the element I am looking for loads, I simply grab it, create a button, append it and it seamlessly appears in the page without any latency.
Am I doing something wrong here?*
Here's a sample of my code :
manifest.json :
{
"name": "Name",
"description": "Description.",
"version": "1.0",
"manifest_version": 2,
"permissions": [
"activeTab"
],
"content_scripts": [
{
"matches": ["https://*.youtube.com/c/*"],
"js": ["content-script.js"],
"run_at": "document_idle"
}
],
"background": {
"scripts": ["background.js"],
"persistent": false
}
}
background.js :
chrome.tabs.onUpdated.addListener( function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
window.onload = function() {
chrome.tabs.executeScript({
file: "content-script.js"
});
}
}
})
content-script.js :
window.addEventListener('load', submitAction);
function submitAction()
{
var youtubeName = document.getElementById("channel-name")
console.log("========================")
console.log(youtubeName)
console.log("========================")
}
CodePudding user response:
Attaching your code to the document-idle, which is the latest run-at value, will fire immediately after window.load event fires:
The browser chooses a time to inject scripts between "document_end" and immediately after the window.onload event fires
If the DOM gets hydrated (or mutated) with elements post load, like what seemingly happens on Youtube, then the element will not exist at the time of that event firing.
I would suggest using a different method, like a mutation observer, rather than a traditional event listener.
Example:
const callback = function(mutationsList, observer) {
for (const mutation of mutationsList) {
if (mutation.target.id === "channel-name") {
console.log("Element found:", document.getElementById("channel-name"));
// disconnect the observer
observer.disconnect();
// element exists, run your code below
}
}
};
const observer = new MutationObserver(callback);
observer.observe(document.body, {childList: true, subtree: true });
The snippet above watches the dom for mutations and when a mutation occurs that has a target with the id of channel-name, it executes code. In the example above, I disconnect the observer (which you may or may not want to do) and then I log the element.
CodePudding user response:
Maybe it doesn't help, but try adding "defer" to your script tags:
<script defer src="script_file_name.js"></script>
defer makes your .js files to wait for the whole HTML to finish parsing.
