When does PageTransitionEvent.persisted evaluate to true? - javascript

I'm trying to detect if my current page is loaded from cache or is a fresh copy.
I have the onPageShow callback registered on my body tag.
I can see it being triggered, but I cannot produce a circumstance where the event.persisted is actually true.
I've even put firefox in offline mode and I see the response being fetched from cache on the network tab but event.persisted is still false.

Umm I can confirm var isCached = performance.getEntriesByType("navigation")[0].transferSize === 0; this does work on Chrome. Worth trying out.
Also as other suggested you might wanna look at this example How can I use JavaScript to detect if I am on a cached page

From google books
This works in mozilla perfectly.
Try the below code
<meta http-equiv="Cache-control" content="public">
...
<body onpageshow="onShow(event)" onpagehide="onHide(event)">
<div >
<a href='/new.html' >Next page</a>
</div>
<script>
function onShow(event) {
if (event.persisted) {
alert('Persisted...');
}
}
function onHide(event) {
if(event.persisted) {
alert("Persisted")
}
}
</script>
</body>
Add any code in new.html. Blank page is also fine
Then use the browser back. You'll get the alert persisted
Note:
Use a domain or ngrok . Cache doesn't work in local
Reload wont trigger persisted. I tried only with page show/hide
I'am skipping the alternative answers to find cache or not

IE11 does have window.performance.getEntriesByType('navigation') but doesn't have transferSize. However, it seems to leave out connectEnd if the page comes from browser cache.
Extending on #subhendu-kundu s answer, this should also work on IE11
<script>
window.addEventListener('pageshow', function(event) {
if (window.performance) {
var navEntries = window.performance.getEntriesByType('navigation');
if (navEntries.length > 0 && typeof navEntries[0].transferSize !== 'undefined') {
if (navEntries[0].transferSize === 0) {
// From cache
}
} else if (navEntries.length > 0) {
// IE11 seems to leave this completely if loaded from bfCache
if (!navEntries[0].connectEnd) {
// From cache
}
}
}
});
</script>

I don't know if i understood your question correctly, you want to check if the page that is loaded is from disk/memory cache or a fresh one. Please comment below if i understood it wrong.
I'm trying to detect if my current page is loaded from cache or is a
fresh copy.
For this you can open the developer tools of your browser and check the network tab, if the page is loaded from cache it will show indication (from cache).
Chrome supports this out of the box but for fire fox i think you should install web-developer plugin : https://addons.mozilla.org/en-US/firefox/addon/web-developer/

Well one thing I can suggest to disable the cache in the browser and check the size of the fetched code chunk. For the same you can disable the cache from browser itself..(I am just suggesting my views).

Related

location.href in IE & Edge

Having issues getting my one page web application to work in Internet Explorer and Edge. It works perfectly fine in other browsers.
The issue that I'm having is that I can't seem to get the navigation to work.
I've tried the following:
location.href = '#quickQuiz'
location.href = '/#quickQuiz'
window.location.href = '#quickQuiz'
window.location.href = '/#quickQuiz'
document.location.href = '/#quickQuiz'
document.location.href = '#quickQuiz'
function goHere(where) { window.location = where; return false; }
location.hash = '#quickQuiz'
location.hash = '/#quickQuiz'
All of them works perfectly fine on other browsers. What am I doing wrong?
http://www.snabbteori.se if you wanna see it for yourself.
EDIT1: Additional code
The item in my navigation menu looks like the following:
<li data-icon="info"><a id="teoriNav">Teori</a></li>
And then I check for a click event on it. I know that it's possible to just put href="#teori in there, but I am just using this one as an example, there are other links where I need to perform AJAX calls too, this one doesn't need it though just to verify there isn't something wrong with my AJAX calls causing it.
$(document).delegate('#teoriNav', 'click', function () {
location.hash('#teori');');
});
I've also tried this but doesn't work:
$('#teoriNav').click( function() {
location.hash('#teori');
});
EDIT2: Updates
I believe I've fixed all jQuery errors and some other issues. The only thing I'm getting in the Internet Explorer console is:
HTML1300: Navigation occured.
DOM7011: The code on this page disabled back and forward caching.
And then when I click on the button I get output which I wrote which confirms it registers my click on the button. But still it won't navigate.
EDIT3: Ugly temporary fix
It works after doing a page reload after navigating.
var isIE = /*#cc_on!#*/false || !!document.documentMode;
var isEdge = !isIE && !!window.StyleMedia;
if(isEdge || isIE)
location.reload();
But I hate the fact that the site has to reload, and if someone has a real fix for this I would really appreciate it...
Edge has an issue with links if your code is not propper. You should check your console for any errors, This is most likely.
We will need more information from your side to help you further.
Post your HTML and your Javascript (just relating to this area of problem)
and we can then better help you.
I sagest fixing your jQuery errors first and trying again.
Ok my Browser test have given me a variation of 30-60 error relating to jQuery across Mac to Win. These will need to be addressed.
You also have a XSS issue that needs to be resolved. You have HTTPS from facebook but then HTTP on your website, These will need to match.

jquery cookie , still set after clear browser history

I'm using a simple script to show a popup with a checkbox to not show it again, and it works just fine, and it works perfectly to delete the cookie via the script.
My problem is that if i delete the cookies in IE11 (company browser), the cookie is still set!
So what am i missing? Is the cookie stored somewhere other than the standard directory when using jquery.cookie.js ?
I want to be able to see the popup by delete the cookie locally.
My code for reference:
<script type="text/javascript">
$("#Cookiehandler").change(function() {
if(this.checked) {
$.cookie('the_cookie', 'no');
}
});
window.jQuery(document).ready(function() {
if($.cookie('the_cookie') == null) {
$.fancybox.open('#popup_box');
}
else {
// placeholder
}
});
//$.removeCookie("the_cookie");
//alert( $.cookie("the_cookie") );
</script>
Best regards,
Marcus
I think the best way might be for you to have an administrative page with a script that deletes the cookie and just to visit that page whenever you want the cookie to be killed. That's a browser-independent method and you don't have to worry about where the cookie was stored, nor do you have to worry about doing it from a bunch of different browsers manually. Just visit the admin page from some or all of your browsers and it's done...for those browsers...while leaving the other ones alone unless you browse the kill page from them too.

JavaScript - bfcache/pageshow event - event.persisted always set to false?

In a standard Java / SpringMVC / JSP / jQuery web-app, I'm trying to detect a "Back" (or history.go(-1)) event, in order to refresh (AJAX) a summary component/panel content when I return to a page (where we can change the backend data that is displayed by the summary component).
I tried the following in JavaScript (following some posts on StackExchange re how to achieve this):
<script type="text/javascript">
$(document).ready(function() {
window.onpageshow = function(event) {
console.log("Event:");
console.dir(event);
if (event.persisted) {
alert("non-jQuery - back to page - loaded from bfcache");
} else {
alert("non-jQuery - loaded page from server");
}
};
$(window).on("pageshow", function(event){
console.log("Event:");
console.dir(event);
if (event.originalEvent.persisted) {
alert("jquery - back to page - loaded from bfcache");
} else {
alert("jquery - loaded page from server");
}
});
});
</script>
I am running OpenSUSE Linux and have tried this with FireFox and Chrome (latest versions), but every time the event's persisted attribute is set to false (I can see this in the JavaScript console and by the alerts that pop-up from the above code). By every time, I mean, regardless of whether it was loaded from the server or shown again via the Back button (or a 'Back' link).
My intention was to make an AJAX call to reload the summary component/panel with the updated data from the server if the page was showing via the Back button or history.go(-1) call.
I also tried setting an unload handler (that does nothing) to prevent the page from being put into the bfcache but it still seems to be showing a bf-cached version and the event.persisted (or event.originalEvent.persisted) is set to false.
Is this property managed correctly on Linux? Am I doing something stupid in my code? Any help or ideas would be much appreciated, thanks!
I have found hidden input buttons are not a reliable solution since they may hold the wrong value when the user navigates back to the page and then hits refresh. Some browsers (Firefox) retain input values on refresh so every time the user hits refresh it will refresh again since the input button holds the wrong value. This is a typical scenario for forums (user views a topic, hits the back button to go back to the list of topics, and may continue to hit refresh to check if there are new topics).
As noted by Grégoire Clermont, event.persisted is buggy in chrome (and IE) and this still hasn't been fixed for either browser as of Feb 2017. The good news is you can rely on window.performance.navigation.type == 2 for chrome and IE. Ironically Firefox is unreliable for the latter but it shouldn't matter since it is reliable for event.persisted. The following code worked for me:
if (document.addEventListener) {
window.addEventListener('pageshow', function (event) {
if (event.persisted || window.performance &&
window.performance.navigation.type == 2)
{
location.reload();
}
},
false);
}
Update 2022:
Because window.performance.navigation.type is deprecated (ref: MDN), I updated the code to do the same thing:
if (document.addEventListener) {
window.addEventListener('pageshow', function (event) {
if (event.persisted || performance.getEntriesByType("navigation")[0].type === 'back_forward') {
location.reload();
}
},
false);
}
This appears to be a bug in Chrome (also present in IE11).
I have found the following workaround:
<input type="hidden" id="cacheTest"></input>
<script>
var input = document.querySelector('#cacheTest')
if (input.value === "") {
// the page has been loaded from the server,
// equivalent of persisted == false
}
else {
// the page has been loaded from the cache,
// equivalent of persisted == true
}
// change the input value so that we can detect
// if the page is reloaded from cache later
input.value = "some value"
</script>
This exploits the fact that in most browsers, when the page is loaded from the cache, form fields values are also conserved.
I know this is a bit late but this works for me:
window.onpageshow = function(e) {
if (e.persisted) {
alert("Page shown");
window.location.reload();
}
};
I don't think you need it in the document ready function, just use vanilla as above.

Prevent safari loading from cache when back button is clicked

Got an issue with safari loading old youtube videos when back button is clicked. I have tried adding onunload="" (mentioned here Preventing cache on back-button in Safari 5) to the body tag but it doesn't work in this case.
Is there any way to prevent safari loading from cache on a certain page?
Your problem is caused by back-forward cache. It is supposed to save complete state of page when user navigates away. When user navigates back with back button page can be loaded from cache very quickly. This is different from normal cache which only caches HTML code.
When page is loaded for bfcache onload event wont be triggered. Instead you can check the persisted property of the onpageshow event. It is set to false on initial page load. When page is loaded from bfcache it is set to true.
Kludgish solution is to force a reload when page is loaded from bfcache.
window.onpageshow = function(event) {
if (event.persisted) {
window.location.reload()
}
};
If you are using jQuery then do:
$(window).bind("pageshow", function(event) {
if (event.originalEvent.persisted) {
window.location.reload()
}
});
All of those answer are a bit of the hack. In modern browsers (safari) only on onpageshow solution work,
window.onpageshow = function (event) {
if (event.persisted) {
window.location.reload();
}
};
but on slow devices sometimes you will see for a split second previous cached view before it will be reloaded. Proper way to deal with this problem is to set properly Cache-Control on the server response to one bellow
'Cache-Control', 'no-cache, max-age=0, must-revalidate, no-store'
Yes the Safari browser does not handle back/foreward button cache the same like Firefox and Chrome does. Specially iframes like vimeo or youtube videos are cached hardly although there is a new iframe.src.
I found three ways to handle this. Choose the best for your case.
Solutions tested on Firefox 53 and Safari 10.1
1. Detect if user is using the back/foreward button, then reload whole page or reload only the cached iframes by replacing the src
if (!!window.performance && window.performance.navigation.type === 2) {
// value 2 means "The page was accessed by navigating into the history"
console.log('Reloading');
//window.location.reload(); // reload whole page
$('iframe').attr('src', function (i, val) { return val; }); // reload only iframes
}
2. reload whole page if page is cached
window.onpageshow = function (event) {
if (event.persisted) {
window.location.reload();
}
};
3. remove the page from history so users can't visit the page again by back/forward buttons
$(function () {
//replace() does not keep the originating page in the session history,
document.location.replace("/Exercises#nocache"); // clear the last entry in the history and redirect to new url
});
You can use an anchor, and watch the value of the document's location href;
Start off with http://acme.co/, append something to the location, like '#b';
So, now your URL is http://acme.co/#b, when a person hits the back button, it goes back to http://acme.co, and the interval check function sees the lack of the hash tag we set, clears the interval, and loads the referring URL with a time-stamp appended to it.
There are some side-effects, but I'll leave you to figure those out ;)
<script>
document.location.hash = "#b";
var referrer = document.referrer;
// setup an interval to watch for the removal of the hash tag
var hashcheck = setInterval(function(){
if(document.location.hash!="#b") {
// clear the interval
clearInterval(hashCheck);
var ticks = new Date().getTime();
// load the referring page with a timestamp at the end to avoid caching
document.location.href.replace(referrer+'?'+ticks);
}
},100);
</script>
This is untested but it should work with minimal tweaking.
The behavior is related to Safari's Back/Forward cache. You can learn about it on the relevant Apple documentation: http://web.archive.org/web/20070612072521/http://developer.apple.com/internet/safari/faq.html#anchor5
Apple's own fix suggestion is to add an empty iframe on your page:
<iframe style="height:0px;width:0px;visibility:hidden" src="about:blank">
this frame prevents back forward cache
</iframe>
(The previous accepted answer seems valid too, just wanted to chip in documentation and another potential fix)
I had the same issue with using 3 different anchor links to the next page. When coming back from the next page and choosing a different anchor the link did not change.
so I had
House 1
View House 2
View House 3
Changed to
House 1
View House 2
View House 3
Also used for safety:
// Javascript
window.onpageshow = function(event) {
if (event.persisted) {
window.location.reload()
}
};
// JQuery
$(window).bind("pageshow", function(event) {
if (event.originalEvent.persisted) {
window.location.reload()
}
});
None of the solutions found online to unload, reload and reload(true) singularily didn't work. Hope this helps someone with the same situation.
First of all insert field in your code:
<input id="reloadValue" type="hidden" name="reloadValue" value="" />
then run jQuery:
jQuery(document).ready(function()
{
var d = new Date();
d = d.getTime();
if (jQuery('#reloadValue').val().length == 0)
{
jQuery('#reloadValue').val(d);
jQuery('body').show();
}
else
{
jQuery('#reloadValue').val('');
location.reload();
}
});
There are many ways to disable the bfcache. The easiest one is to set an 'unload' handler. I think it was a huge mistake to make 'unload' and 'beforeunload' handlers disable the bfcache, but that's what they did (if you want to have one of those handlers and still make the bfcache work, you can remove the beforeunload handler inside the beforeunload handler).
window.addEventListener('unload', function() {})
Read more here:
https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/1.5/Using_Firefox_1.5_caching

A Firefox javascript bookmarking problem

I'm using the following JavaScript code:
<script language="JavaScript1.2" type="text/javascript">
function CreateBookmarkLink(title, url) {
if (window.sidebar) {
window.sidebar.addPanel(title, url,"");
} else if( window.external ) {
window.external.AddFavorite( url, title); }
else if(window.opera && window.print) {
return true; }
}
</script>
This will create a bookmark for Firefox and IE. But the link for Firefox will show up in the sidepanel of the browser, instead of being displayed in the main screen. I personally find this very annoying and am looking for a better solution. It is of course possible to edit the bookmark manually to have it not show up in the side panel, but that requires extra steps. I just want to be able to have people bookmark a page (that has a lot of GET information in the URL which is used to build a certain scheme) the easy way.
I'm afraid that it might not be possible to have Firefox present the page in the main screen at all (as Googling this subject resulted in practically nothing worth using), but I might have missed something. If anyone has an idea if this is possible, or if there's a workaround, I'd love to hear about it.
For Firefox no need to set any JavaScript for the bookmark an page by script, only an anchor tag with title and rel="sidebar" can do this functionality
Bookmark This Page
I have tested it on FF9 and its working fine.
When you click on the link, Firefox will open an dialog box New Bookmark and if you wish to not load this bookmark on side bar then un-check Load this bookmark in the sidebar from dialog box.
I think that's the only solution for Firefox... I have a better function for that action, it works even for Opera and shows a message for other "unsupported" browsers.
<script type="text/javascript">
function addBookmark(url,name){
if(window.sidebar && window.sidebar.addPanel) {
window.sidebar.addPanel(name,url,''); //obsolete from FF 23.
} else if(window.opera && window.print) {
var e=document.createElement('a');
e.setAttribute('href',url);
e.setAttribute('title',name);
e.setAttribute('rel','sidebar');
e.click();
} else if(window.external) {
try {
window.external.AddFavorite(url,name);
}
catch(e){}
}
else
alert("To add our website to your bookmarks use CTRL+D on Windows and Linux and Command+D on the Mac.");
}
</script>
You have a special case for
if (window.sidebar)
and then a branch for 'else' - wouldn't firefox land in the first branch and hence only add the panel?
Hojou,
It seems that is the only way to add a bookmark for Firefox. So FF needs to land in the first branch to have anything happening at all. I Googled some more but I'm really getting the idea this is impossible to properly address in FF...

Categories