BFcache disabled by unload events (Back-Forward cache) - javascript

(Note: FireFox only)
The Back-Forward cache is a caching system in firefox that runs when the back button is clicked. It will then simply use the DOM from the previous page that is in it's cache instead of reloading the entire page (and re-requesting files).
I'm using piwik (an analytics service), that requires a tracking code snippet to be added to the footer. Upon adding this, the back-forward cache no longer works.
It is my understanding that, if there is an unload event (or beforeunload) the bfcache is automatically disabled. This is likely what is happening here.
Is there anything I can add to make the BFCache work anyway?
To make matters worse, I cannot add any custom code below the piwik code. That one is always last.
I added the code displayed below to try and remove any unload events that are registered, but the BFcache is still not working.
$(window).unbind('beforeunload');
$(window).unbind('unload');
window.onbeforeunload = null;
window.onunload = null;
I also tried:
function UnloadHandler() {
window.removeEventListener('unload', UnloadHandler, false);
}
window.addEventListener('unload', UnloadHandler, false);
$(window).unload(function () { $(window).unbind('unload'); });
but this too does not work.
I have placed some samples online. Remember to test this with Firefox:
this one shows a working BFcache (you will get an different alert based on whether or not the back button was clicked)
http://users.telenet.be/prullen/bfcache/a.html
Loaded piwik, BFCache no longer works
http://users.telenet.be/prullen/bfcache/b.html
Loaded piwik, tried to unset onload event, but still not working
http://users.telenet.be/prullen/bfcache/c.html
Using unloadhandler
http://users.telenet.be/prullen/bfcache/d.html
Suggestions by #roasted
http://users.telenet.be/prullen/bfcache/e.html
http://users.telenet.be/prullen/bfcache/f.html
More information about BFCache:
https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching
You can see another demo of the behavior here:
http://www.twmagic.com/misc/cache.html
If you add dom elements, and click the first link, then return - the dom elements are still there. However, if you add an onload or beforeunload event that is not the case. Again, test this in firefox.
Any ideas?

In order to enable BFCache you need to remove beforeunload event listener. It should be the same listener which was added by Piwik code, otherwise removeEventListener will do nothing.
That listener is unreachable outside of the Piwik's source, so one does not simply remove it.
But, if you have a possibility to insert code before the Piwik, you can try to override addEventListener, track added handlers and expose function to remove all tracked handlers at once.

Related

Chrome popstate not firing on Back Button if no user interaction

I'm trying to use "pushState" and the "popstate" event to trap Back button navigation, however, while the popstate event triggers correctly in Firefox, it doesn't trigger in Chrome (Version 76.0.3809.87 (Official Build) (64-bit)) if there is no user interaction.
From testing, it looks like the popstate event only gets triggered if the user interacts with the page (ie. clicks somewhere on the document). So if you load the page without interacting and hit Back, the popstate function is not called.
I've added a Fiddle to showcase this: https://jsfiddle.net/0xwvLndu/
To test the Fiddle in Chrome, just click the link and hit the Back button. You'll see no alert. Then click the link again but this time click anywhere on the Fiddle document and then hit the Back button, the alert is then triggered.
I found a discussion on the Chromium forum that may relate to this quirk, and perhaps this has been implemented to prevent abuse of history entries - https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/OCS7g72HtyI and https://github.com/WICG/interventions/issues/21#issuecomment-425609246
If this is the case, does it mean that popstate cannot be relied on anymore to trap Back button actions, and if so, is there a work around solution?
Below is an example of what I've been testing with:
window.addEventListener('load', function() {
history.pushState(null, null, document.URL);
});
window.addEventListener('popstate', function(event) {
alert('test');
});
I expected the alert to be triggered on Back Button regardless of user interaction, but this does not happen in Chrome.
Try adding a setTimeout of 0
window.onpopstate = () => setTimeout(alert.bind(window, "Pop"), 0);
When writing functions that process popstate event it is important to take into account that properties like window.location will already reflect the state change (if it affected the current URL), but document might still not. If the goal is to catch the moment when the new document state is already fully in place, a zero-delay setTimeout() method call should be used to effectively put its inner callback function that does the processing at the end of the browser event loop: window.onpopstate = () => setTimeout(doSomeThing, 0);
Content is taken from
https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event
On a sidenote it is advised not to use this as browsers may remove this any time.
As others suggested in comment, this should be by design of browser software to prevent hijacking of its default back button behavior.

Can I "catch" a redirect executed by a script, with javascript eventListeners?

I have an HTML page that includes only a script tag, I don't control the script and I can't change it (so I can't fire my custom event for example).
The script ends with a redirect (using window.location).
Is there a way to add a new script to the page that will listen to the page events and "catch" the redirect (actually it's better for me to catch the new loaded document)?
Something like:
window.addEventListener('redirected', function() {
// do staff
});
(I know there is no "redirected" event, it's just for the example).
It's very important to make it clear that the redirect isn't caused by an anchor click or back/forward button click, so I can't use events like click or popstate.
You might want to look at the onpagehide event or the onunload event, both of which occur when the user navigates away from the page.
However, if you wish to interfere or prevent the redirection itself, onbeforeunload is what you want.
Just take a look at :
unload function w3school or mozilla developper network
beacon function for sending a final XMLHttpRequest

Check if the link results in reloading the page

I develope a chrome extension; with a content script I inject some code in the page. What I want is an event that triggers if the current tab is going to update.
I tried to catch the click event of an a-element and it does work in somehow 80% of all cases. I already check if it's an anchor, but there are still many links which don't reload the page or forward to another.
$('a', document).click(function (e) {
// ...
});
So, what I want is described in the following three steps:
Event: the page is going to reload
prevent it from reloading, execute some code
trigger reloading the page afterwards
Depending on your requirements, have you considered listening to beforeunload event? It's fired when the page is about to unload (also including refresh the current page).

How can I force scripts to finish before leaving the page (in webkit browsers)?

This already works well in FireFox, IE and Opera, but in Chrome and Safari this is a problem. I have an onClick event function on links that leaves the page. These functions send requests to various tracking services to record the exit link.
I have tested this by removing the href attribute in the link. When it's removed, the link is tracked. When the link is active (and leads away from the page) the link is not tracked. This is only the case in Chrome and Safari.
I was hoping there was some non-extreme way of forcing the browser to finish the script before leaving the page. (By extreme I mean f.inst. removing the href attribute using javascript and manually redirecting the browser after tracking is complete)
jQuery is already loaded in this project, so it'd be great if it had a solution.
Thanks for any and all advice
Google analytics _trackPageView does not offer a callback so you have no easy way to get a success callback, then proceed to your next page. There is a callback though on _trackEvent, and that's triggered each time some GA event occurs. You can try this and listen for it like so (make sure to put your href's back into your links - this depends on that being there, plus you'll get graceful degradation):
$(".myLinkClass").click(function(e){
e.preventDefault();
var link = $(this).attr('href');
pageTracker._trackPageview('/outbound/'+link);
if (pageTracker._trackEvent("Outbound", "URL", link)) {
window.location = link;
}
});

What tool can I use to find out what JavaScript events are being called when leaving a web page?

I have a set of pages that have tons of JavaScript on it: Table sorting, AJAX calls, autocomplete, dynamically hiding and displaying areas of the page, etc... The problem that I am seeing is when the data on said page gets large a delay (browser freezes) is noticed when leaving the page. This delay happens when the user clicks away, closes the browser, or executes a form submit. I want to see if the problem is caused by JavaScript. What tool could I use to find out? Firebug doesn't seem to work in this scenario.
The only place unload is mentioned in the codebase is in jquery.js and ui.tabs.js (jquery ui)
Are there any onunload event handlers attached (to body, window, form etc.)? If so, it would be a good starting point to investigate.
[Edit]: Apparently jQuery runs a loop unbinding all the events attached to every element. This is to prevent memory leaks in IE (created due to event handler closures referencing the element they are listening to). This could create a delay if your DOM is very complex.
Can you try commenting this portion out in jQuery code and see if that is causing the problem?
[Edit 2]: The window unload seems to have been improved in newer versions of jQuery (1.3+). What version are you using?
Inline Code Finder is a firefox addin (well, really it's a firebug addin) that shows you visually what events are attached where and when they're invoked.

Categories