Does anyone know a way, via JavaScript, that I can either clear Safari's bfcache, or force it to reload rather that used a cached version of a page?
I have a web application that is running tests, and there is JavaScript which monitors a countdown (a timeout):
timeoutId = window.setInterval(function () {
timeoutRemaining--;
if (timeoutRemaining <= 0) {
location.href = myTimeoutLocation;
}
}, timeoutInterval);
This all works fine until I get to myTimeoutLocation. The behavior is that, if a user clicks the back button, the test should continue. However, when navigating back, I find that IE and Chrome reload the page, but Firefox and Safari are showing the cached page. I need to make sure that a cached page is NEVER shown. I can fix this problem in Firefox by adding:
window.onunload = function () { };
to my script, but that hasn't worked in Safari since Safari 5.x (as far as I can tell). I found another solution:
window.addEventListener("pageshow", function(evt){
if(evt.persisted){
setTimeout(function(){
window.location.reload();
},10);
}
}, false);
This worked to an extent... The problem I have now is that even with the above code, I am receiving a dialog box: ... which I'm apparently not allowed to embed. The dialog says that in order to display the page, information must be sent to the server, with the appropriate confirm or deny buttons. I did try setting forceGet to true, but that did not solve the problem with the dialog appearing. I should mention that clicking Resend has the desired effect.
Non-embedded image of dialog
And yes, I realize the image is of Firefox, not Safari.
In case it makes any difference (even though this is a JavaScript question), the site is coded in .NET/MVC4 and is hosted in IIS.
Thank you in advance for any help/thoughts/information/pointers in the right direction.
Related
I can't find a way to execute a script when a page is reached via the browser's BACK button or key command. (Background: I need to know if a page was opened using the browser's BACK button or key command. Then I could check for a stored sessionStorage varible and trigger some appropriate stuff).
If, for example, I put this into my page code
<script>
$(document).ready(function() {
alert("YES!");
/* in the real situation: do something */
})
</script>
, the alert will be displayed when I load the page via a link or by opening it directly by typing its URL into the address bar.
But this alert will not appear when I come to that page via the BACK button.
I tried the same using $(window).on("load", function() {... and $(window).on("navigate", function () {... - no success either...
EDIT / ADDITION:
I just realized that browsers behave differently in this respect: Chrome, Opera, IE and Firefox Windows will reload the page correctly (and trigger document.ready() and onload() events) , but Firefox Mac and Safari will not - they load the whole page from cache without triggering document.ready() or onload(). (I haven't tried mobile browsers yet)
So i searched for solutions avoiding the cached content, but what I've found and tried so far (which is a lot!) hasn't worked either...
after reading lots of posts and trying the solutions in there and narrowing the thing down to a browser issue, I discovered this answer, which forces the page to be reloaded also in Safari (and apparently also Firefox/Mac):
https://stackoverflow.com/a/13123626/5641669
Essentially, this jQuery code reloads the page in its original state when coming there via the back button on Safari, which also allows to trigger any desired script on pageload:
$(window).bind("pageshow", function(event) {
if (event.originalEvent.persisted) {
window.location.reload()
}
});
I have seen related questions on StackOverflow, but none of the suggestions are working for me. I need browsers to reload a page from the server every time it is displayed, including if the user got there by pressing the Back button. It seems like browsers obey caching rules for everything except the base document. This happens in current versions of Safari and Firefox (as of Dec 2013), verified by packet capture.
The pages in my application are used to edit a database record. At the top of the source files are a couple lines of PHP to store a lock indicating that the record is being edited. Other users cannot edit the same record while the lock exists. The pages have a window unload handler that uses AJAX in non-async mode to release the lock. (There's more to the locking mechanism, but those are the relevant pieces.) When the user returns to the page via Back button, the server-side code is never executed.
I have tried including a header:
Cache-Control: no-cache, must-revalidate
Safari's inspector shows the header was received and processed, but it still does not re-retrieve the page.
I have tried setting a handler to check whether the page's state was maintained:
window.onpageshow = function(event) {
if (event.persisted) {
window.location.reload();
}
};
The if condition never matches: event.persisted is always false.
The annoying part is that this appears to be technically correct. According to the relevant part of the HTML5 spec, since the page registers an unload listener the browser should never try to maintain page state. And it doesn't! When the user presses the back button, the browser is "replaying" the entire page load sequence, including the ready event. It repeats any AJAX calls where the prior results were not cached. The only thing it refuses to actually reload from the server is the main document itself.
How do I get it to reload the main document?
Quick answer:
No you can't... the Back button is even more aggressive and different of a cache than the others. Some insight:
Why is Google Chrome going to the server on pushState?
https://github.com/nickhsharp/prefetchNightmare
That said... a GET request (the browser loading it) shouldn't "do" anything to the server... if anything you should do that lock setting part via an AJAX on the page start... the inverse of how you remove it using AJAX on the done part.
The browsers are pretty clear on their reasons for the crazy BACK/FORWARD caches and you're not going to be able to force their hands on this one.
Adding this code to my HTML works just fine for me:
<input id="isOld" type="hidden" />
<script>
onload = function () {
var el = document.getElementById('isOld');
if (el.value) {
el.value = '';
location.reload();
}
el.value = true;
};
</script>
The code assigns a value to the hidden input that will remain after the back button is clicked in which case the page is force refreshed.
And here's a stripped down version of the above:
<input id="isOld" type="hidden" />
<script>
setTimeout(function () {
var el = document.getElementById('alwaysFetch');
el.value = el.value ? location.reload() : true;
}, 0);
</script>
This time we no longer rely on the onload event which might conflict with other code elsewhere.
There is HTML5 has History API https://developer.mozilla.org/en-US/docs/Web/API/History
Perhaps you may try that.
Nick Sharp's answer is correct - you are trying to find a solution to a problem you've created by the way you've built the application. There are some potential solutions: Optimistic locking mostly works - but bind the session id not the user id. Alternatively you could rebuild it modelling it along the lines of a thick client application - where all the interaction is mediated by javascript within a single HTML page load.
I have an aspx page with JS calling window.location.reload(true) to force refresh a page when a function is called.
This appears to work a few times, with the page reloading as expected, but gets to a scenario where the function is called (i.e. alert in the function is visible) but the reload does not occur. I've also tried setting window.location with the same outcome - it works 2 or 3 times then fails.
This does not occur in Firefox (16), but is happening in different versions of IE (7 & 9)
Using Fiddler to monitor the browser traffic, all is as expected when the reload is working, but there is no traffic reported when the reload stops, suggesting the browser is not sending the request to the server? The IE window does go blank with the loading spinner spinning, but eventually IE displays the error page:
Internet Explorer cannot display the webpage
Most likely causes:
You are not connected to the Internet.
The website is encountering problems.
There might be a typing error in the address.
This appears to lock the browser. Trying to hit another website results in the same output in Fiddler (nothing). Opening a new IE window means I am able to hit the site with no problems.
This was initially causing a problem updating UpdatePanels via __doPostBack so this JS reload of the page was seen as a quick workaround, but this does not seem to be the case.
I would tend to think this is server related, but I have been unable to replicate the issue in Firefox. This does however unfortunately have to work in IE.
Any ideas much appreciated!
JS snippet below (though this is pretty simple stuff)
function ReloadWindow() {
alert(window.location); // Can see this alert, even when page fails to reload
window.location.reload(true);
}
This question already has answers here:
Prevent safari loading from cache when back button is clicked
(8 answers)
Closed 4 years ago.
The issue I've found is very similar to this question, except that Safari on desktops seems to have resolved the issue. Essentially, the issue is this: when a client is browsing on mobile safari and the page executes a javascript function on pageA.html, then navigate to pageB.html, then press the back button to go back to pageA.html, the javascript function won't run when the client pressed the back button to come back to pageA.html. It will skip the javascript call.
I've tried the solutions mentioned in the link above, but nothing seems to work for mobile Safari. Has anyone else encountered this bug? How did you handle it?
This 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.
window.onpageshow = function(event) {
if (event.persisted) {
alert("From back / forward cache.");
}
};
For some reason jQuery does not have this property in the event. You can find it from original event though.
$(window).bind("pageshow", function(event) {
if (event.originalEvent.persisted) {
alert("From back / forward cache.");
}
});
Quick solution to these problem is to reload the page when back button is pressed. This however nullifies any positive effect back / forward cache would give.
window.onpageshow = function(event) {
if (event.persisted) {
window.location.reload()
}
};
As a sidenote, you can see lot of pages offering using empty onunload handler as solution. This has not worked since iOS5.
$(window).bind("unload", function() { });
I know this is not recommended, but I need it because I have an iframe inside the page who has the actual content and I want that when the users hits refresh button, iframe reloads not entire page.
I know I have to call onunload / onbeforeunload event, but I don't want to ask me if I want to leave the window, just don't.
Is that possible? I've got handled the F5 key, but I like to prevent refreshing from button too.
UPDATE: I wrote this 5 years ago, browsers do different stuff now, you can still use this for testing your browser set, but your experience may vary from my old research.
Experimenting using jQuery, because I'm lazy.
Theoretically, preventing the default behavior should stop the event from doing whatever it is supposed to do. It doesn't work with the events in my example and has different results in different browsers. I put the Math.random() in to determine if the page has been reloaded or not. Because different browsers do different things, I highly recommend NOT using this in a production environment.
<body>
<p></p>
<script type="text/javascript">
$('p').append(Math.random());
$(window).bind({
beforeunload: function(ev) {
ev.preventDefault();
},
unload: function(ev) {
ev.preventDefault();
}
});
</script>
</body>
Using CTRL-R or F5 or Reload Button:
Safari: Does nothing
Chrome: Does nothing
Opera 10 & 11: Does nothing
Firefox 7.x: Shows a special prompt with two buttons:
Stay on Page - Does not reload page
Leave Page - Reloads the page
IE7 & IE8: Shows a prompt with two buttons:
OK - Reloads the page
Cancel - Does not reload the page
IE9: Shows a prompt with two buttons:
Leave this page - reloads
Stay on this page - does not reload
Firefox Prompt (you can tell I tested it on a Mac)
IE7 & IE8 Prompt
IE9 Prompt
In closing:
Yes, I did not test IE6, I deleted my VM which had it installed, I don't have a VM with IE10 beta installed, so you're out of luck on that too.
You might also experiment with cancelBubble and stopPropagation or maybe return false; might reveal something useful. I'm down with Jordan's reply that you shouldn't be trying to override the defaults, so I'm concluding my experiment here.
Returning false in an onsubmit event prevents the form from being submitted and stays in the same page without any user interaction..
For example..
when a form having input field is empty and submitted this javascript check for validation and returns accordingly..
If false is returned nothing is done(i.e. page is not refreshed or redirected)..
If the validation is ok and if true is returned the form action is performed..
function validateForm(Str) {
mystring=document.getElementById('inputid').value;
if(!mystring.match(/\S/)){
alert ('Please Enter a String.Field cannot be empty');
return false;
}else{
return true;
}
}