WKWebView document.onvisibilitychange event not always being fired. Need to detect page changes reliability from WKUserScript

I need to prepare an object when the user navigates to a new page in WKWebView and refresh UI. I run a WKUserScript on behalf of the user to do this.

I'm using the readystatechange event listener to detect initial page load. I'm also listening to the visibilitychange event to refresh UI if the DOM is already loaded on a "Go back" or "Go Forward" action.

document.addEventListener('visibilitychange', () => {
   //do whatever if the DOM is already loaded and if we are visible.
});

document.addEventListener('readystatechange', (event) =>
{
          //do whatever when page is loaded
});

On certain websites however I noticed that neither of these events are being fired when I navigate -goForward: and -goBack:

I'm not sure why. My WKUserScript is in WKContentWorld.defaultClientWorld so it shouldn't be interfering with the javascript of the page. Is there another JS event I'm missing?

I could pick up the changed URL on the native code side but it would be nice to keep this all contained within the WKUserScript as this UI is for the "webview" and the native code shouldn't have to be bothered with having to patch in the additional glue. Is there another DOM event I need to listen to? I tried listening to window's pageshow but that didn't work. Also experimented a bit with the window's popstate event but no luck.

Replies

So after some research it appears that there is no javascript event to detect url changes. So the javascript code I have won't work for "web apps" that modify an already loaded DOM and change the URL programmatically.

Listening for pageshow and popstate should both be valid solutions here.

One other thing to try that could help understanding the issue is: What if you did inject your JS using pageWorld instead of defaultContentWorld? Does that make it work?

If pageWorld makes this work, it would be great to know the feedback request you file so we can improve that. But if it still doesn't work, we'd simply need to see more details of what you've implemented to diagnose further.

  • Thanks a lot for your reply!

    I seem to be getting better results listening for the window's onpageshow instead of the document.visibilitychange (and checking the visibility state of the document in the event handler to see if its visible) so I think I'm going to remove the document visibilitychange listener and replace it with pageshow.

Add a Comment

So after some research it appears that there is no javascript event to detect url changes. So the javascript code I have won't work for "web apps" that modify an already loaded DOM and change the URL programmatically.

Usually a combination of onhashchange and onstatechange will capture all the ways JS programmatically changes the apparent URL without loading a new document.

Both those aren't relevant for the back/forward cases.

Thanks again for your replies!

So after some research it appears that there is no javascript event to detect url changes. So the javascript code I have won't work for "web apps" that modify an already loaded DOM and change the URL programmatically.

Usually a combination of onhashchange and onstatechange will capture all the ways JS programmatically changes the apparent URL without loading a new document. Both those aren't relevant for the back/forward cases.

I heard about onhashchange but I can't seem to find documentation for a onstatechange event? It is my understanding that onhashchange won't pick up url changes in all cases? Being able to run a script after a "page change" in a reliable fashion is surprisingly complex.