DOMContentLoaded not working in Safari App Extension

I am trying to run JavaScript only after the page has loaded, and according to here, I should use DOMContentLoaded. However, it does not seem to work.

This is my content.js file:
Code Block
function runOnStart() {
    document.addEventListener('DOMContentLoaded', function(e) {
        document.body.style.background = "rgb(20, 20, 20)";
        document.html.style.background = "rgb(20, 20, 20)";
      
        var divElements = document.body.getElementsByTagName('div');
        for(var i = 0; i < divElements.length; i++) {
            let elem = divElements[i];
            elem.style.background = "rgba(255, 255, 255, 0.05)";
        }
    });
}
runOnStart();


If I take the code outside of the event listener, it runs fine, but a lot of the elements haven't loaded in yet so it doesn't work as it should.

The function is definitely running, but the event listener simply doesn't work. I appreciate any help you can give!
Answered by Frameworks Engineer in 615985022
This sounds like a bug. Can you send us a bug report via Feedback Assistant?
Accepted Answer
This sounds like a bug. Can you send us a bug report via Feedback Assistant?
What version of Xcode and Safari are you using?

I can confirm that in Xcode 11.0 and Safari 13.0.1 that your content scripts "works" and I am not experiencing the the issue you describe. However, I have not tested in newer versions of Safari or Xcode.

What is document.html? Are you trying to target the html element?

You should probably use document.documentElement - that line of your code is throwing an error.
Hey everyone! I have figured out a work-around to the issue. It appears that a lot of the time, the DOMContentLoaded event would fire before the event listener got called.

This workaround worked for me:
Code Block
function runOnStart() {
// Run your code here
}
if(document.readyState !== 'loading') {
    runOnStart();
}
else {
    document.addEventListener('DOMContentLoaded', function () {
        runOnStart()
    });
}


It checks to see if DOMContentLoaded has already been fired (hence the document is no longer loading), and if so, run the code. If it has not been fired yet, then the listener is initialized.

@JakeShort your solution helped me! I couldn't figure out why my JS events were not triggering ONLY on iOS. Even on the iOS Simulator it was working, but only on my iPhone things were not working.

Thank you!!

Please make safari abosolute

Still not fixed on Xcode 14 and iOS Safari 16.

I am running macOS Sonoma and can confirm that this is still not fixed in Safari 17

That workaround that JakeShort mentioned is a good best practice to have in all of your extensions.

There is a chance that your extension will be injected into a page after DOMContentLoaded has already happened and your script should be able to handle that case.

To check this, you can check document.readyState when your content script runs. If the state is interactive or complete, then the DOMContentLoaded event has already fired and you should just run the code directly.

Is it still an issue? if not, which Safari version has fixed it? thanks

DOMContentLoaded not working in Safari App Extension
 
 
Q