Reputation: 6998
I'm building a Chrome Extension to add some shortcut functionality to a site I regularly work with. I've tried calling my addTypingListeners()
to bind the div with 2 inputs that I've added to the title and subtitle of the edit page I'm working on. However, I never seem to get into the document.eventListener
closure.
My Chrome Extension is run at document_idle
so the content should be loaded by the time my additional code runs. How can I get these listeners to embed on the page?
Even when I don't call addTypingListeners()
, I still see a
and b
log in the console
function addTypingListeners() {
console.log('a')
var meta = {}
document.addEventListener("DOMContentLoaded",()=>{
console.log('listeners added pre')
bind(meta, document.getElementsByTagName('title'), "title");
bind(meta, document.getElementsByTagName('subtitle'), "subtitle");
setInterval(()=>{document.getElementsByTagName('h3')[0].innerText=meta.title});
setInterval(()=>{
console.log(meta)
document.getElementsByTagName('h4')[0].innerText = meta.subtitle
});
console.log('listeners added')
})
console.log('b')
}
const start = async function() {
// var location = window.location.toString()
let slug = window.location.toString().split("/")[4]
let url = `https://example.org/${slug}?as=json`
const _ = await fetch(url)
.then(res => res.text())
.then(text => {
let obj = JSON.parse(text);
const { payload } = obj;
// Container
const root = document.getElementById('container');
var clippyContainer = document.createElement('div');
createShell(clippyContainer, name);
root.appendChild(clippyContainer);
// Inputs
const title = document.getElementsByTagName('h3')[0];
const subtitle = document.getElementsByTagName('h4')[0];
var inputDiv = document.createElement('div');
inputDiv.id = "input-div";
const titleInput = document.createElement('input');
titleInput.id = "title"
titleInput.value = title.innerText;
inputDiv.appendChild(titleInput);
const breaker = document.createElement("br")
inputDiv.appendChild(breaker);
const subtitleInput = document.createElement('input');
subtitleInput.id = "subtitle"
subtitleInput.value = subtitle.innerText;
inputDiv.appendChild(subtitleInput);
clippyContainer.appendChild(inputDiv);
inputDiv.appendChild(breaker);
// addTypingListeners() // tried here, also doesn't work
});
}
start()
.then( (_) => {
console.log('hi')
addTypingListeners()
console.log("done")
})
Upvotes: 6
Views: 2253
Reputation: 340
According to the official documentation, the order of events while a page is loading:
document_start
> DOMContentLoaded
> document_end
> load
> document_idle
.
The difference between load
and DOMContentLoaded
events is explained here as
The load event is fired when the whole page has loaded, including all dependent resources such as stylesheets and images. This is in contrast to DOMContentLoaded, which is fired as soon as the page DOM has been loaded, without waiting for resources to finish loading.
Thus, you should add the listeners without waiting for the DOMContentLoaded
event, which will never fire.
Upvotes: 1
Reputation: 1712
This is literally all the coded need besides whatever your doing to the dom.
Background.js
let slug = window.location.toString().split("/")[4]
let url = `https://example.org/${slug}?as=json`
fetch(url).then(res => res.text()).then((data) => {
chrome.tabs.sendMessage(tabId, {
message: data
});
})
Content.js
function addTypingListeners(data) {
// Update page dom
}
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.message) {
addTypingListeners(request.message);
}
});
Upvotes: 0
Reputation: 318
Probably the event DOMContentLoaded
was already fired at the point of time when you set the listener. You can check that document.readyState equals to complete
and execute the function without subscribing to the event if it already occurred. In the opposite case if the readyState
is loading
or interactive
you should set the listener as it is currently done in the attached example.
Upvotes: 1