I have a function where I scroll to the page to the top when the page loads with document.ready(). However in Chrome this function only runs when I'm on the page and I refresh it.
If I access the page by typing the link in the address bar, the function doesn't run. If I access the page from a link from another page, it also doesn't run. The only way it runs 100% of the time in Chrome is if I'm on the page and I refresh it.
However, in Safari, the function runs 100% every single time by accessing the page from a link, typing it in the address bar, on reload.
This is my code:
jQuery(document).ready(function($) {
if (location.hash) { // do the test straight away
window.scrollTo(0, 0); // execute it straight away
setTimeout(function() {
window.scrollTo(0, 0); // run it a bit later also for browser compatibility
}, 1);
//location.reload();
}
});
This actually also works in Safari without putting it in document.ready() but then again not in Chrome.
Does anybody know what causes this and if this is possible to fix?
I've had this problem before and it was extremely frustrating.
Just increase the setTimeout delay time 20ms or more then 20ms, it may be because of 1ms is too short time of interval.
$(document).ready(function() {
if (location.hash) {
window.scrollTo(0, 0);
setTimeout(function() {window.scrollTo(0, 0);}, 20);
}
});
Related
I just updated to chrome version 32.0.1700.76 m and I am now noticing that hashchange seem to act weird. sometimes it work, sometimes it doesn't.
I have the following code on my homepage and I haven't changed the code in a few months. worked fine a few days ago(before I updated to latest chrome version):
$(window).on('hashchange', function () {
var page = location.hash.slice(1);
$('[data-page]').addClass('hidden');
$('[data-page=' + page + ']').css('z-index', '0');
$('#1st-row').children().eq(0).css('z-index', '1');
$('#1st-row').children().eq(1).css('margin-left', '-200px');
$('[data-page=' + page + ']').removeClass('hidden');
$('#1st-row').children().eq(1).animate(
{ 'margin-left':'0px' }, 1000);
$(':checkbox').checkbox('check');
$('#debug').attr('value', 'true');
});
I figured something wasn't working as it should when I redesigned my site so i changed it a bit:
$(window).on('hashchange', function () {
var page = location.hash.slice(1);
$('[data-page=' + page + ']').slideDown();
});
but it's still not working.
I have to reload the page several times, go to the site again(ctrl+l -> enter), reload a few more times and then it magically works. it won't work a second time though... I have to refresh and reload the page/site a few more times before it decides to let hashchange work.
you can test it at lingonsorbet.se.
just add #advanced to the url and a box should appear to the right. works fine in firefox and ie.
am I doing something wrong or has anyone else run into this too?
hashchange is not fired on page load
The hashchange event is only triggered when you manually change the hash or when you click an in-page anchor link (Advanced). Reloading a page without changing the hash does not trigger hashchange.
You should refactor your hash-checking code into a new function and execute it
on the hashchange event
on page load.
Consider this code:
function changeLayoutByHash() {
var page = location.hash.slice(1);
$('[data-page=' + page + ']').slideDown();
// etc.
}
$(window).bind('hashchange', changeLayoutByHash );
$(window).ready( changeLayoutByHash );
As per your question, I don't see inconsistencies in the way Chrome handles this.
If you keep reloading example.com#advanced, hashchange will not be fired. Only when you change the hash to example.com#advance (delete a character), it's registered as a changed hash.
Debugging
To find out whether or not certain events are being fired, you can always write a little console.log('hashchange fired'); into your event handlers and then (with ChromeDev Tools open) see in the console what your program does.
I see a difference between FF and Chrome (Version 22.0.1229.94 m) in this matter. FF is right (I would say).
when scrolling down a page and hitting then refreshing it, the callback of
$(window).ready(function(){
console.log( $(document).scrollTop() );
});
The console should say the amount scrolled after the window was ready, but in Chrome it's always 0
How can I show the get the amount of scrollTop in Chrome?
like some said in the comments, Chrome load the page, and then scroll it down.
Therefor when jQuery event is fired, the scroll is at 0.
You can do some work around like that :
$(document).ready(function() {
function getScroll() {
var scroll = $(window).scrollTop();
...
}
getScroll();
$(window).scroll(getScroll);
});
So in Chrome $(window).scroll(); will be fired just after the page is loaded.
EDIT: tested there http://fiddle.jshell.net/azaret/Mt65R/show/light/
Problem is that document.ready() in Chrome is executed before the browser scrolls down to the previous point and that is why you always get a zero value. A solution is provided here: Get vertical position of scrollbar for a webpage on pageload when the url contains an anchor
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
I have this little function to open/close a popup player:
function popuponclick(popup)
{
my_window = window.open("folder/player-itself.htm", popup, "width=350,height=150");
}
function closepopup()
{
my_window.close();
}
I call the functions from HTML anchors that are on each page of the site (idea is to have the player stopped/started whenever you want)...now...
it works well until i change the page, or refresh the existing one - and from then the window can't be closed anymore. Any idea where i'm wrong? Tested in FF and IE8, same behavior.
Thanks for your help.
When you reload the original window (or tab), everything about the old one is gone, blasted into the digital void, never to be seen or heard from again. The bits literally disintegrate into nothingness.
Thus, the "my_window" reference you so lovingly saved when the second window was opened is gone for good, and the "my_window" variable in the newly-loaded window contains nothing. It's name is but a mockery of the variable in the now-dead page.
The only way to deal with this situation is for the popup window to periodically check back via "window.opener" to see if its parent page has been rudely replaced by some interloper. If that happens (and the new page is from the same domain), then the popup page can restore the reference to itself in the new page's "my_window" variable.
edit — OK here's a sample. You'd put something like this in the popup page, not the launching pages:
<script>
var checkParent = setInterval(function() {
try {
if (window.opener && ('my_window' in window.opener))
window.opener.my_window = window;
}
catch (_) {
// clear the timer, since we probably won't be able to fix it now
clearInterval(checkParent);
}
}, 100);
</script>
That's probably pretty close.
When I use the back button on Firefox to reach a previously visited page, scripts on that page won't run again.
Is there any fix/workaround to have the scripts execute again when viewing the page the second time?
Please note that I have tested the same pages on Google Chrome and Internet Explorer and they work as intended.
Here are the files and the steps I used to test the problem:
(navigate to 0.html, click to get to 1.html, back button)
0.html
<html><body>
<script>
window.onload = function() { alert('window.onload alert'); };
alert('inline alert');
</script>
Click Me!
</body></html>
1.html
<html><body>
<p>Go BACK!</p>
</body></html>
Set an empty function to be called on window.onunload:
window.onunload = function(){};
e.g.
<html><body>
<script type="text/javascript">
window.onload = function() { alert('window.onload alert'); };
window.onunload = function(){};
alert('inline alert');
</script>
Click Me!
</body></html>
Source:
http://www.firefoxanswer.com/firefox/672-firefoxanswer.html (Archived Version)
When I use the back button on Firefox to reach a previously visited page, scripts on that page won't run again.
That's correct and that's a good thing.
When you hit a link in Firefox (and Safari, and Opera), it does not immediately destroy your page to go onto the next one. It keeps the page intact, merely hiding it from view. Should you hit the back button, it will then bring the old page back into view, without having to load the document again; this is much faster, resulting in smoother back/forward page transitions for the user.
This feature is called the bfcache.
Any content you added to the page during the user's previous load and use of it will still be there. Any event handlers you attached to page elements will still be attached. Any timeouts/intervals you set will still be active. So there's rarely any reason you need to know that you have been hidden and re-shown. It would be wrong to call onload or inline script code again, because any binding and content generation you did in that function would be executing a second time over the same content, with potentially disastrous results. (eg. document.write in inline script would totally destroy the page.)
The reason writing to window.onunload has an effect is that the browsers that implement bfcache have decided that — for compatibility with pages that really do need to know when they're being discarded — any page that declares an interest in knowing when onunload occurs will cause the bfcache to be disabled. That page will be loaded fresh when you go back to it, instead of fetched from the bfcache.
So if you set window.onunload= function() {};, what you're actually doing is deliberately breaking the bfcache. This will result in your pages being slow to navigate, and should not be used except as a last resort.
If you do need to know when the user leaves or comes back to your page, without messing up the bfcache, you can trap the onpageshow and onpagehide events instead:
window.onload=window.onpageshow= function() {
alert('Hello!');
};
You can check the persisted property of the pageshow event. It is set to false on initial page load. When page is loaded from cache it is set to true.
window.onpageshow = function(event) {
if (event.persisted) {
alert("From bfcache");
}
};
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 bfcache");
}
});
In my case window.onunload with an empty function didn't help (I tried to set a value for dropdown when user uses backwards button). And window.onload didn't work for other reason - it was overridden by <body onload="...">.
So I tried this using jQuery and it worked like a charm:
$(window).on('pageshow', function() { alert("I'm happy"); });
Wire in an "onunload" event that does nothing:
<html><body>
<script type="text/javascript">
window.onload = function() { alert('window.onload alert'); };
window.onunload = function(){};
alert('inline alert');
</script>
Click Me!
</body></html>
As far as i know Firefox does not fire onLoad event on back.
It should trigger onFocus instead based from this link here.
A simple way to cause a page to execute JavaScript when the user navigates back to it using browser history is the OnPopState event. We use this to pause and replay the video on our home page (https://fynydd.com).
window.onpopstate = function() {
// Do stuff here...
};
for some cases like ajax operations url change listener can be used
$(window).on('hashchange', function() {
....
});