This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the javascript category.
Last Updated: 2024-11-23
I had the following code that was supposed to attach the PayPal button for payments, but didn't work:
function attachPayments() {
attachAsyncScript(
`https://www.paypal.com/sdk/js?${serializeGetParamsObj(getParams)}`
)
document.addEventListener("DOMContentLoaded", attachPaypalButton)
}
document.addEventListener("DOMContentLoaded", attachPayments)
The issue was that DOMContentLoaded
only ever fires once, and it had already fired
by the time the code reached the inside of the attachPayments
function and
executed the part that attached another DOMContentLoaded
event for
attachPaypalButton
.
You can confirm this with a simpler example: Open up Chrome Tools for a web page that has already loaded and enter the following into the JavaScript console:
document.addEventListener("DOMContentLoaded", () => console.log("fired"))
You will not see "fired" logged - i.e. adding this listener does nothing if the event has already been fired. (You might imagine it would execute the code immediately because the DOMContentLoaded has already fired - but this does not seem to be the behavior).
I could trigger the code not on global DOM initialization, but rather on the
loading of the specific script
element I was interested in:
// Attach script is a custom function that returns a reference to a script tag
attachScript(`https://www.paypal.com/sdk/js?${serializeGetParamsObj(getParams)}`).
// We attach the custom code to this script tag's `onload`
onload = () => attachPaypalButton(finalizeUrl)
Look at document.readyState
. If it says "interactive" then the DOMContentLoaded
event
has already fired. It could be either loading
or interactive
or complete
. Thus your code
should check for both if (document.readyState != "loading")
In the Chrome Dev Tools console you can set breakpoints on events - e.g. Event Listener Breakpoints
monitorEvents
, e.g. monitorEvents(document.body, "click")