history.back() does not update location.hash in Chrome/FireFox - javascript

I tried to build a JS script that would change the location of the page, to go back until a specific hash location is found:
var StopAtThisHash ='#';
var CurrentHash = window.location.hash;
var continueLoop = true;
while ((window.history.length>0) && (continueLoop))
{
window.history.back();
var NowWeAreAtHash = window.location.hash; //this never changes in Chrome
//actually, always seems to: CurrentHash == NowWeAreAtHash;
if(NowWeAreAtHash == StopAtThisHash)
continueLoop= false;
}
Weird enough, in Chrome and FF, the window.location.hash is not changed after back().. neither is the length of history decreased by 1 as I expected. The loop runs indefinitely, and the browser hangs up.
In IE 9 this seems to run as intended.
Any workarounds around this?

function goBackHome () {
goBackToHash(''); // Assume the home is without hash. You can use '#'.
}
function goBackToHash(hash) {
setTimeout(function () {
if (window.location.hash == hash) return;
history.back();
goBackToHash(hash);
}, 0);
}
To overcome the problem of while loop, I tried use setTimeout, but this is usually goes further than expected... Waiting for a perfect solution.
I think there is a delay between history.back() and when window.location.hash is changed.
Another workaround is to keep the hashes in JS so that you can figure out how many steps is needed in history.go(N).

Seems that window.history.back(), window.history.forward() and window.history.go() does not changes history, just navigates back and forth. If back() would change length of history then you would not be able to forward().
As workaround I would suggest to loop over window.history with for from last to first instead of while.

Related

Change content in iframe without reloading page with AJAX and Jquery [duplicate]

I would like to reload an <iframe> using JavaScript. The best way I found until now was set the iframe’s src attribute to itself, but this isn’t very clean. Any ideas?
document.getElementById('some_frame_id').contentWindow.location.reload();
be careful, in Firefox, window.frames[] cannot be indexed by id, but by name or index
document.getElementById('iframeid').src = document.getElementById('iframeid').src
It will reload the iframe, even across domains!
Tested with IE7/8, Firefox and Chrome.
Note: As mentioned by #user85461, this approach doesn't work if the iframe src URL has a hash in it (e.g. http://example.com/#something).
If using jQuery, this seems to work:
$('#your_iframe').attr('src', $('#your_iframe').attr('src'));
Appending an empty string to the src attribute of the iFrame also reloads it automatically.
document.getElementById('id').src += '';
window.frames['frameNameOrIndex'].location.reload();
Because of the same origin policy, this won't work when modifying an iframe pointing to a different domain. If you can target newer browsers, consider using HTML5's Cross-document messaging. You view the browsers that support this feature here: http://caniuse.com/#feat=x-doc-messaging.
If you can't use HTML5 functionality, then you can follow the tricks outlined here: http://softwareas.com/cross-domain-communication-with-iframes. That blog entry also does a good job of defining the problem.
I've just come up against this in chrome and the only thing that worked was removing and replacing the iframe. Example:
$(".iframe_wrapper").find("iframe").remove();
var iframe = $('<iframe src="' + src + '" frameborder="0"></iframe>');
$.find(".iframe_wrapper").append(iframe);
Pretty simple, not covered in the other answers.
Simply replacing the src attribute of the iframe element was not satisfactory in my case because one would see the old content until the new page is loaded. This works better if you want to give instant visual feedback:
var url = iframeEl.src;
iframeEl.src = 'about:blank';
setTimeout(function() {
iframeEl.src = url;
}, 10);
A refinement on yajra's post ... I like the thought, but hate the idea of browser detection.
I rather take ppk's view of using object detection instead of browser detection,
(http://www.quirksmode.org/js/support.html),
because then you're actually testing the capabilities of the browser and acting accordingly, rather than what you think the browser is capable of at that time. Also doesn't require so much ugly browser ID string parsing, and doesn't exclude perfectly capable browsers of which you know nothing about.
So, instead of looking at navigator.AppName, why not do something like this, actually testing for the elements you use? (You could use try {} blocks if you want to get even fancier, but this worked for me.)
function reload_message_frame() {
var frame_id = 'live_message_frame';
if(window.document.getElementById(frame_id).location ) {
window.document.getElementById(frame_id).location.reload(true);
} else if (window.document.getElementById(frame_id).contentWindow.location ) {
window.document.getElementById(frame_id).contentWindow.location.reload(true);
} else if (window.document.getElementById(frame_id).src){
window.document.getElementById(frame_id).src = window.document.getElementById(frame_id).src;
} else {
// fail condition, respond as appropriate, or do nothing
alert("Sorry, unable to reload that frame!");
}
}
This way, you can go try as many different permutations as you like or is necessary, without causing javascript errors, and do something sensible if all else fails. It's a little more work to test for your objects before using them, but, IMO, makes for better and more failsafe code.
Worked for me in IE8, Firefox (15.0.1), Chrome (21.0.1180.89 m), and Opera (12.0.2) on Windows.
Maybe I could do even better by actually testing for the reload function, but that's enough for me right now. :)
for new url
location.assign("http:google.com");
The assign() method loads a new document.
reload
location.reload();
The reload() method is used to reload the current document.
Another solution.
const frame = document.getElementById("my-iframe");
frame.parentNode.replaceChild(frame.cloneNode(), frame);
Now to make this work on chrome 66, try this:
const reloadIframe = (iframeId) => {
const el = document.getElementById(iframeId)
const src = el.src
el.src = ''
setTimeout(() => {
el.src = src
})
}
In IE8 using .Net, setting the iframe.src for the first time is ok,
but setting the iframe.src for the second time is not raising the page_load of the iframed page.
To solve it i used iframe.contentDocument.location.href = "NewUrl.htm".
Discover it when used jQuery thickBox and tried to reopen same page in the thickbox iframe.
Then it just showed the earlier page that was opened.
Use reload for IE and set src for other browsers. (reload does not work on FF)
tested on IE 7,8,9 and Firefox
if(navigator.appName == "Microsoft Internet Explorer"){
window.document.getElementById('iframeId').contentWindow.location.reload(true);
}else {
window.document.getElementById('iframeId').src = window.document.getElementById('iframeId').src;
}
If you using Jquery then there is one line code.
$('#iframeID',window.parent.document).attr('src',$('#iframeID',window.parent.document).attr('src'));
and if you are working with same parent then
$('#iframeID',parent.document).attr('src',$('#iframeID',parent.document).attr('src'));
Using self.location.reload() will reload the iframe.
<iframe src="https://vivekkumar11432.wordpress.com/" width="300" height="300"></iframe>
<br><br>
<input type='button' value="Reload" onclick="self.location.reload();" />
<script type="text/javascript">
top.frames['DetailFrame'].location = top.frames['DetailFrame'].location;
</script>
If all of the above doesn't work for you:
window.location.reload();
This for some reason refreshed my iframe instead of the whole script. Maybe because it is placed in the frame itself, while all those getElemntById solutions work when you try to refresh a frame from another frame?
Or I don't understand this fully and talk gibberish, anyways this worked for me like a charm :)
Have you considered appending to the url a meaningless query string parameter?
<iframe src="myBaseURL.com/something/" />
<script>
var i = document.getElementsById("iframe")[0],
src = i.src,
number = 1;
//For an update
i.src = src + "?ignoreMe=" + number;
number++;
</script>
It won't be seen & if you are aware of the parameter being safe then it should be fine.
Reload from inside Iframe
If your app is inside an Iframe you can refresh it with replacing the location href:
document.location.href = document.location.href
If you tried all of the other suggestions, and couldn't get any of them to work (like I couldn't), here's something you can try that may be useful.
HTML
<a class="refresh-this-frame" rel="#iframe-id-0">Refresh</a>
<iframe src="" id="iframe-id-0"></iframe>
JS
$('.refresh-this-frame').click(function() {
var thisIframe = $(this).attr('rel');
var currentState = $(thisIframe).attr('src');
function removeSrc() {
$(thisIframe).attr('src', '');
}
setTimeout (removeSrc, 100);
function replaceSrc() {
$(thisIframe).attr('src', currentState);
}
setTimeout (replaceSrc, 200);
});
I initially set out to try and save some time with RWD and cross-browser testing. I wanted to create a quick page that housed a bunch of iframes, organized into groups that I would show/hide at will. Logically you'd want to be able to easily and quickly refresh any given frame.
I should note that the project I am working on currently, the one in use in this test-bed, is a one-page site with indexed locations (e.g. index.html#home). That may have had something to do with why I couldn't get any of the other solutions to refresh my particular frame.
Having said that, I know it's not the cleanest thing in the world, but it works for my purposes. Hope this helps someone. Now if only I could figure out how to keep the iframe from scrolling the parent page each time there's animation inside iframe...
EDIT:
I realized that this doesn't "refresh" the iframe like I'd hoped it would. It will reload the iframe's initial source though. Still can't figure out why I couldn't get any of the other options to work..
UPDATE:
The reason I couldn't get any of the other methods to work is because I was testing them in Chrome, and Chrome won't allow you to access an iframe's content (Explanation: Is it likely that future releases of Chrome support contentWindow/contentDocument when iFrame loads a local html file from local html file?) if it doesn't originate from the same location (so far as I understand it). Upon further testing, I can't access contentWindow in FF either.
AMENDED JS
$('.refresh-this-frame').click(function() {
var targetID = $(this).attr('rel');
var targetSrc = $(targetID).attr('src');
var cleanID = targetID.replace("#","");
var chromeTest = ( navigator.userAgent.match(/Chrome/g) ? true : false );
var FFTest = ( navigator.userAgent.match(/Firefox/g) ? true : false );
if (chromeTest == true) {
function removeSrc() {
$(targetID).attr('src', '');
}
setTimeout (removeSrc, 100);
function replaceSrc() {
$(targetID).attr('src', targetSrc);
}
setTimeout (replaceSrc, 200);
}
if (FFTest == true) {
function removeSrc() {
$(targetID).attr('src', '');
}
setTimeout (removeSrc, 100);
function replaceSrc() {
$(targetID).attr('src', targetSrc);
}
setTimeout (replaceSrc, 200);
}
if (chromeTest == false && FFTest == false) {
var targetLoc = (document.getElementById(cleanID).contentWindow.location).toString();
function removeSrc() {
$(targetID).attr('src', '');
}
setTimeout (removeSrc, 100);
function replaceSrc2() {
$(targetID).attr('src', targetLoc);
}
setTimeout (replaceSrc2, 200);
}
});
For debugging purposes one could open the console, change the execution context to the frame that he wants refreshed, and do document.location.reload()
I had a problem with this because I didnt use a timeout to give the page time to update, I set the src to '', and then set it back to the original url, but nothing happened:
function reload() {
document.getElementById('iframe').src = '';
document.getElementById('iframe').src = url;
}
but it didnt reload the site, because it is single threaded, the first change doesnt do anything, because that function is still taking up the thread, and then it sets it back to the original url, and I guess chrome doesnt reload because preformance or whatever, so you need to do:
function setBack() {
document.getElementById('iframe').src = url;
}
function reload() {
document.getElementById('iframe').src = '';
setTimeout(setBack,100);
}
if the setTimeout time is too short, it doesnt work, so if its not working, try set it to 500 or something and see if it works then.
this was in the latest version of chrome at the time of writing this.
This way avoids adding history to some browsers (an unneeded overhead). In the body section put:
<div id='IF'>
<iframe src='https://www.wolframalpha.com/input?i=Memphis%20TN%20Temperature'
style="width:5in; height:6in" // or whatever you want in your Iframe
title'Temperature'></iframe>
</div>
Then in some JAVASCRIPT you may have a function like:
function UPdate() { // Iframe
T1=document.getElementById('IF')
T2=T1.innerHTML
T1.innerHTML=T2
}

How to reload an iframe in Javascript? [duplicate]

I would like to reload an <iframe> using JavaScript. The best way I found until now was set the iframe’s src attribute to itself, but this isn’t very clean. Any ideas?
document.getElementById('some_frame_id').contentWindow.location.reload();
be careful, in Firefox, window.frames[] cannot be indexed by id, but by name or index
document.getElementById('iframeid').src = document.getElementById('iframeid').src
It will reload the iframe, even across domains!
Tested with IE7/8, Firefox and Chrome.
Note: As mentioned by #user85461, this approach doesn't work if the iframe src URL has a hash in it (e.g. http://example.com/#something).
If using jQuery, this seems to work:
$('#your_iframe').attr('src', $('#your_iframe').attr('src'));
Appending an empty string to the src attribute of the iFrame also reloads it automatically.
document.getElementById('id').src += '';
window.frames['frameNameOrIndex'].location.reload();
Because of the same origin policy, this won't work when modifying an iframe pointing to a different domain. If you can target newer browsers, consider using HTML5's Cross-document messaging. You view the browsers that support this feature here: http://caniuse.com/#feat=x-doc-messaging.
If you can't use HTML5 functionality, then you can follow the tricks outlined here: http://softwareas.com/cross-domain-communication-with-iframes. That blog entry also does a good job of defining the problem.
I've just come up against this in chrome and the only thing that worked was removing and replacing the iframe. Example:
$(".iframe_wrapper").find("iframe").remove();
var iframe = $('<iframe src="' + src + '" frameborder="0"></iframe>');
$.find(".iframe_wrapper").append(iframe);
Pretty simple, not covered in the other answers.
Simply replacing the src attribute of the iframe element was not satisfactory in my case because one would see the old content until the new page is loaded. This works better if you want to give instant visual feedback:
var url = iframeEl.src;
iframeEl.src = 'about:blank';
setTimeout(function() {
iframeEl.src = url;
}, 10);
A refinement on yajra's post ... I like the thought, but hate the idea of browser detection.
I rather take ppk's view of using object detection instead of browser detection,
(http://www.quirksmode.org/js/support.html),
because then you're actually testing the capabilities of the browser and acting accordingly, rather than what you think the browser is capable of at that time. Also doesn't require so much ugly browser ID string parsing, and doesn't exclude perfectly capable browsers of which you know nothing about.
So, instead of looking at navigator.AppName, why not do something like this, actually testing for the elements you use? (You could use try {} blocks if you want to get even fancier, but this worked for me.)
function reload_message_frame() {
var frame_id = 'live_message_frame';
if(window.document.getElementById(frame_id).location ) {
window.document.getElementById(frame_id).location.reload(true);
} else if (window.document.getElementById(frame_id).contentWindow.location ) {
window.document.getElementById(frame_id).contentWindow.location.reload(true);
} else if (window.document.getElementById(frame_id).src){
window.document.getElementById(frame_id).src = window.document.getElementById(frame_id).src;
} else {
// fail condition, respond as appropriate, or do nothing
alert("Sorry, unable to reload that frame!");
}
}
This way, you can go try as many different permutations as you like or is necessary, without causing javascript errors, and do something sensible if all else fails. It's a little more work to test for your objects before using them, but, IMO, makes for better and more failsafe code.
Worked for me in IE8, Firefox (15.0.1), Chrome (21.0.1180.89 m), and Opera (12.0.2) on Windows.
Maybe I could do even better by actually testing for the reload function, but that's enough for me right now. :)
for new url
location.assign("http:google.com");
The assign() method loads a new document.
reload
location.reload();
The reload() method is used to reload the current document.
Another solution.
const frame = document.getElementById("my-iframe");
frame.parentNode.replaceChild(frame.cloneNode(), frame);
Now to make this work on chrome 66, try this:
const reloadIframe = (iframeId) => {
const el = document.getElementById(iframeId)
const src = el.src
el.src = ''
setTimeout(() => {
el.src = src
})
}
In IE8 using .Net, setting the iframe.src for the first time is ok,
but setting the iframe.src for the second time is not raising the page_load of the iframed page.
To solve it i used iframe.contentDocument.location.href = "NewUrl.htm".
Discover it when used jQuery thickBox and tried to reopen same page in the thickbox iframe.
Then it just showed the earlier page that was opened.
Use reload for IE and set src for other browsers. (reload does not work on FF)
tested on IE 7,8,9 and Firefox
if(navigator.appName == "Microsoft Internet Explorer"){
window.document.getElementById('iframeId').contentWindow.location.reload(true);
}else {
window.document.getElementById('iframeId').src = window.document.getElementById('iframeId').src;
}
If you using Jquery then there is one line code.
$('#iframeID',window.parent.document).attr('src',$('#iframeID',window.parent.document).attr('src'));
and if you are working with same parent then
$('#iframeID',parent.document).attr('src',$('#iframeID',parent.document).attr('src'));
Using self.location.reload() will reload the iframe.
<iframe src="https://vivekkumar11432.wordpress.com/" width="300" height="300"></iframe>
<br><br>
<input type='button' value="Reload" onclick="self.location.reload();" />
<script type="text/javascript">
top.frames['DetailFrame'].location = top.frames['DetailFrame'].location;
</script>
If all of the above doesn't work for you:
window.location.reload();
This for some reason refreshed my iframe instead of the whole script. Maybe because it is placed in the frame itself, while all those getElemntById solutions work when you try to refresh a frame from another frame?
Or I don't understand this fully and talk gibberish, anyways this worked for me like a charm :)
Have you considered appending to the url a meaningless query string parameter?
<iframe src="myBaseURL.com/something/" />
<script>
var i = document.getElementsById("iframe")[0],
src = i.src,
number = 1;
//For an update
i.src = src + "?ignoreMe=" + number;
number++;
</script>
It won't be seen & if you are aware of the parameter being safe then it should be fine.
Reload from inside Iframe
If your app is inside an Iframe you can refresh it with replacing the location href:
document.location.href = document.location.href
If you tried all of the other suggestions, and couldn't get any of them to work (like I couldn't), here's something you can try that may be useful.
HTML
<a class="refresh-this-frame" rel="#iframe-id-0">Refresh</a>
<iframe src="" id="iframe-id-0"></iframe>
JS
$('.refresh-this-frame').click(function() {
var thisIframe = $(this).attr('rel');
var currentState = $(thisIframe).attr('src');
function removeSrc() {
$(thisIframe).attr('src', '');
}
setTimeout (removeSrc, 100);
function replaceSrc() {
$(thisIframe).attr('src', currentState);
}
setTimeout (replaceSrc, 200);
});
I initially set out to try and save some time with RWD and cross-browser testing. I wanted to create a quick page that housed a bunch of iframes, organized into groups that I would show/hide at will. Logically you'd want to be able to easily and quickly refresh any given frame.
I should note that the project I am working on currently, the one in use in this test-bed, is a one-page site with indexed locations (e.g. index.html#home). That may have had something to do with why I couldn't get any of the other solutions to refresh my particular frame.
Having said that, I know it's not the cleanest thing in the world, but it works for my purposes. Hope this helps someone. Now if only I could figure out how to keep the iframe from scrolling the parent page each time there's animation inside iframe...
EDIT:
I realized that this doesn't "refresh" the iframe like I'd hoped it would. It will reload the iframe's initial source though. Still can't figure out why I couldn't get any of the other options to work..
UPDATE:
The reason I couldn't get any of the other methods to work is because I was testing them in Chrome, and Chrome won't allow you to access an iframe's content (Explanation: Is it likely that future releases of Chrome support contentWindow/contentDocument when iFrame loads a local html file from local html file?) if it doesn't originate from the same location (so far as I understand it). Upon further testing, I can't access contentWindow in FF either.
AMENDED JS
$('.refresh-this-frame').click(function() {
var targetID = $(this).attr('rel');
var targetSrc = $(targetID).attr('src');
var cleanID = targetID.replace("#","");
var chromeTest = ( navigator.userAgent.match(/Chrome/g) ? true : false );
var FFTest = ( navigator.userAgent.match(/Firefox/g) ? true : false );
if (chromeTest == true) {
function removeSrc() {
$(targetID).attr('src', '');
}
setTimeout (removeSrc, 100);
function replaceSrc() {
$(targetID).attr('src', targetSrc);
}
setTimeout (replaceSrc, 200);
}
if (FFTest == true) {
function removeSrc() {
$(targetID).attr('src', '');
}
setTimeout (removeSrc, 100);
function replaceSrc() {
$(targetID).attr('src', targetSrc);
}
setTimeout (replaceSrc, 200);
}
if (chromeTest == false && FFTest == false) {
var targetLoc = (document.getElementById(cleanID).contentWindow.location).toString();
function removeSrc() {
$(targetID).attr('src', '');
}
setTimeout (removeSrc, 100);
function replaceSrc2() {
$(targetID).attr('src', targetLoc);
}
setTimeout (replaceSrc2, 200);
}
});
For debugging purposes one could open the console, change the execution context to the frame that he wants refreshed, and do document.location.reload()
I had a problem with this because I didnt use a timeout to give the page time to update, I set the src to '', and then set it back to the original url, but nothing happened:
function reload() {
document.getElementById('iframe').src = '';
document.getElementById('iframe').src = url;
}
but it didnt reload the site, because it is single threaded, the first change doesnt do anything, because that function is still taking up the thread, and then it sets it back to the original url, and I guess chrome doesnt reload because preformance or whatever, so you need to do:
function setBack() {
document.getElementById('iframe').src = url;
}
function reload() {
document.getElementById('iframe').src = '';
setTimeout(setBack,100);
}
if the setTimeout time is too short, it doesnt work, so if its not working, try set it to 500 or something and see if it works then.
this was in the latest version of chrome at the time of writing this.
This way avoids adding history to some browsers (an unneeded overhead). In the body section put:
<div id='IF'>
<iframe src='https://www.wolframalpha.com/input?i=Memphis%20TN%20Temperature'
style="width:5in; height:6in" // or whatever you want in your Iframe
title'Temperature'></iframe>
</div>
Then in some JAVASCRIPT you may have a function like:
function UPdate() { // Iframe
T1=document.getElementById('IF')
T2=T1.innerHTML
T1.innerHTML=T2
}

How to know if there is a previous page [duplicate]

I want using JavaScript to see if there is history or not, I mean if the back button is available on the browser or not.
Short answer: You can't.
Technically there is an accurate way, which would be checking the property:
history.previous
However, it won't work. The problem with this is that in most browsers this is considered a security violation and usually just returns undefined.
history.length
Is a property that others have suggested...
However, the length doesn't work completely because it doesn't indicate where in the history you are. Additionally, it doesn't always start at the same number. A browser not set to have a landing page, for example, starts at 0 while another browser that uses a landing page will start at 1.
Most of the time a link is added that calls:
history.back();
or
history.go(-1);
and it's just expected that if you can't go back then clicking the link does nothing.
There is another way to check - check the referrer. The first page usually will have an empty referrer...
if (document.referrer == "") {
window.close()
} else {
history.back()
}
My code let the browser go back one page, and if that fails it loads a fallback url. It also detect hashtags changes.
When the back button wasn't available, the fallback url will be loaded after 500 ms, so the browser has time enough to load the previous page. Loading the fallback url right after window.history.go(-1); would cause the browser to use the fallback url, because the js script didn't stop yet.
function historyBackWFallback(fallbackUrl) {
fallbackUrl = fallbackUrl || '/';
var prevPage = window.location.href;
window.history.go(-1);
setTimeout(function(){
if (window.location.href == prevPage) {
window.location.href = fallbackUrl;
}
}, 500);
}
Here is how i did it.
I used the 'beforeunload' event to set a boolean. Then I set a timeout to watch if the 'beforeunload' fired.
var $window = $(window),
$trigger = $('.select_your_link'),
fallback = 'your_fallback_url';
hasHistory = false;
$window.on('beforeunload', function(){
hasHistory = true;
});
$trigger.on('click', function(){
window.history.go(-1);
setTimeout(function(){
if (!hasHistory){
window.location.href = fallback;
}
}, 200);
return false;
});
Seems to work in major browsers (tested FF, Chrome, IE11 so far).
There is a snippet I use in my projects:
function back(url) {
if (history.length > 2) {
// if history is not empty, go back:
window.History.back();
} else if (url) {
// go to specified fallback url:
window.History.replaceState(null, null, url);
} else {
// go home:
window.History.replaceState(null, null, '/');
}
}
FYI: I use History.js to manage browser history.
Why to compare history.length to number 2?
Because Chrome's startpage is counted as first item in the browser's history.
There are few possibilities of history.length and user's behaviour:
User opens new empty tab in the browser and then runs a page. history.length = 2 and we want to disable back() in this case, because user will go to empty tab.
User opens the page in new tab by clicking a link somewhere before. history.length = 1 and again we want to disable back() method.
And finally, user lands at current page after reloading few pages. history.length > 2 and now back() can be enabled.
Note: I omit case when user lands at current page after clicking link from external website without target="_blank".
Note 2: document.referrer is empty when you open website by typing its address and also when website uses ajax to load subpages, so I discontinued checking this value in the first case.
this seems to do the trick:
function goBackOrClose() {
window.history.back();
window.close();
//or if you are not interested in closing the window, do something else here
//e.g.
theBrowserCantGoBack();
}
Call history.back() and then window.close(). If the browser is able to go back in history it won't be able to get to the next statement. If it's not able to go back, it'll close the window.
However, please note that if the page has been reached by typing a url, then firefox wont allow the script to close the window.
Be careful with window.history.length because it also includes entries for window.history.forward()
So you may have maybe window.history.length with more than 1 entries, but no history back entries.
This means that nothing happens if you fire window.history.back()
You can't directly check whether the back button is usable. You can look at history.length>0, but that will hold true if there are pages ahead of the current page as well. You can only be sure that the back button is unusable when history.length===0.
If that's not good enough, about all you can do is call history.back() and, if your page is still loaded afterwards, the back button is unavailable! Of course that means if the back button is available, you've just navigated away from the page. You aren't allowed to cancel the navigation in onunload, so about all you can do to stop the back actually happening is to return something from onbeforeunload, which will result in a big annoying prompt appearing. It's not worth it.
In fact it's normally a Really Bad Idea to be doing anything with the history. History navigation is for browser chrome, not web pages. Adding “go back” links typically causes more user confusion than it's worth.
history.length is useless as it does not show if user can go back in history.
Also different browsers uses initial values 0 or 1 - it depends on browser.
The working solution is to use $(window).on('beforeunload' event, but I'm not sure that it will work if page is loaded via ajax and uses pushState to change window history.
So I've used next solution:
var currentUrl = window.location.href;
window.history.back();
setTimeout(function(){
// if location was not changed in 100 ms, then there is no history back
if(currentUrl === window.location.href){
// redirect to site root
window.location.href = '/';
}
}, 100);
Building on the answer here and here. I think, the more conclusive answer is just to check if this is a new page in a new tab.
If the history of the page is more than one, then we can go back to the page previous to the current page. If not, the tab is a newly opened tab and we need to create a new tab.
Differently, to the answers linked, we are not checking for a referrer as a new tab will still have a referrer.
if(1 < history.length) {
history.back();
}
else {
window.close();
}
This work for me using react but can work in another case; when history is in the first page (you cannot go back) window.history.state will be null, so if you want to know if you can navigate back you only need:
if (window.history.state == null) {
//you cannot go back
}
Documentation:
The History.state property returns a value representing the state at
the top of the history stack. This is a way to look at the state
without having to wait for a popstate event.
I was trying to find a solution and this is the best i could get (but works great and it's the easiest solution i've found even here).
In my case, i wanted to go back on history with an back button, but if the first page the user opened was an subpage of my app, it would go back to the main page.
The solution was, as soon the app is loaded, i just did an replace on the history state:
history.replaceState( {root: true}, '', window.location.pathname + window.location.hash)
This way, i just need to check history.state.root before go back. If true, i make an history replace instead:
if(history.state && history.state.root)
history.replaceState( {root: true}, '', '/')
else
history.back()
I came up with the following approach. It utilizes the onbeforeunload event to detect whether the browser starts leaving the page or not. If it does not in a certain timespan it'll just redirect to the fallback.
var goBack = function goBack(fallback){
var useFallback = true;
window.addEventListener("beforeunload", function(){
useFallback = false;
});
window.history.back();
setTimeout(function(){
if (useFallback){ window.location.href = fallback; }
}, 100);
}
You can call this function using goBack("fallback.example.org").
There is another near perfect solution, taken from another SO answer:
if( (1 < history.length) && document.referrer ) {
history.back();
}
else {
// If you can't go back in history, you could perhaps close the window ?
window.close();
}
Someone reported that it does not work when using target="_blank" but it seems to work for me on Chrome.
the browser has back and forward button. I come up a solution on this question. but It will affect browser forward action and cause bug with some browsers.
It works like that: If the browser open a new url, that has never opened, the history.length will be grow.
so you can change hash like
location.href = '#__transfer__' + new Date().getTime()
to get a never shown url, then history.length will get the true length.
var realHistoryLength = history.length - 1
but, It not always work well, and I don't known why ,especially the when url auto jump quickly.
I am using window.history in Angular for the FAQ on my site.
Whenever the user wants to exit the FAQ they can click the exit button (next to the back button)
My logic for this "exit" strategy is based on the entry ID and then just go back the number of states till that state.
So on enter:
enterState: { navigationId:number } = {navigationId: 1}
constructor() {
this.enterState = window.history.state
}
pretent the user navigates through the faq
And then, when the user clicks the exit button, read the current state and calculate your delta:
exitFaq() {
// when user started in faq, go back to first state, replace it with home and navigate
if (this.enterState.navigationId === 1) {
window.history.go((window.history.state.navigationId - 1) * -1)
this.router.navigateByUrl('/')
// non-angular
// const obj = {Title: 'Home', Url: '/'}
// window.history.replaceState(obj, obj.Title, obj.Url)
} else {
window.history.go(this.enterState.navigationId - window.history.state.navigationId - 1)
}
}
As you can see, I also use a fallback for when the user started in the faq, in that case the state.navigationId is 1 and we want to route back, replace the first state and show the homepage (For this I'm using the Angular router, but you can use history.replaceState as well when you handle your own routes)
For reference:
history.go
history.state
history.replaceState
Angular.router.navigateByUrl
This might help:
const prev = window.location.pathname;
window.history.back();
setTimeout(() => {
if (prev === window.location.pathname) {
// Do something else ...
}
}, 1000);
I'm using Angular, I need to check if there is history, trigger location.back(), else redirect to parent route.
Solution from https://stackoverflow.com/a/69572533/18856708 works well.
constructor(
private activatedRoute: ActivatedRoute,
private router: Router,
private location: Location,
}
...
back(): void {
if (window.history.state === null) {
this.router.navigate(['../'], { relativeTo: this.activatedRoute });
return;
}
this.location.back();
}
This is my solution:
function historyBack() {
console.log('back');
window.history.back() || window.history.go(-1);
if (!window.history.length) window.close();
var currentUrl = window.location.href;
setTimeout(function(){
// if location was not changed in 100 ms, then there is no history back
if(current === window.location.href){
console.log('History back is empty!');
}
}, 100);
}
function historyForward() {
console.log('forward');
window.history.forward() || window.history.go(+1);
var current = window.location.href;
setTimeout(function(){
// if location was not changed in 100 ms, then there is no history forward
if(current === window.location.href){
console.log('History forward is empty!');
}
}, 100);
}
The following solution will navigate back AND will tell if the navigation occurred or not:
async function goBack() {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => reject('nowhere to go'), 100);
window.history.back();
const onBack = () => {
window.removeEventListener('beforeunload', onBack);
window.removeEventListener('popstate', onBack);
clearTimeout(timer);
resolve(true);
};
window.addEventListener('beforeunload', onBack);
window.addEventListener('popstate', onBack);
});
}
// usage
await goBack().catch(err => console.log('failed'));
How it works:
Try to navigate back
Add event listeners that will trigger on navigation to another website or to another page on the same site (SPA website, etc.)
If above events didn't occur in 100ms, deduce that there's nowhere to go back to
Notice that goBack() is an async function.
var fallbackUrl = "home.php";
if(history.back() === undefined)
window.location.href = fallbackUrl;
I am using a bit of PHP to achieve the result. It's a bit rusty though. But it should work.
<?php
function pref(){
return (isset($_SERVER['HTTP_REFERER'])) ? true : '';
}
?>
<html>
<body>
<input type="hidden" id="_pref" value="<?=pref()?>">
<button type="button" id="myButton">GoBack</button>
<!-- Include jquery library -->
<script>
if (!$('#_pref').val()) {
$('#myButton').hide() // or $('#myButton').remove()
}
</script>
</body>
</html>
var func = function(){ console.log("do something"); };
if(document.referrer.includes(window.location.hostname) && history.length-1 <= 1){
func();
}
else{
const currentUrl = window.location.href;
history.back();
setTimeout(function(){
currentUrl === window.location.href && func();
}, 100);
}
I found a JQuery solution that actually works
window.history.length == 1
This works on Chrome, Firefox, and Edge.
You can use the following piece of JQuery code that worked for me on the latest versions of all of the above 3 browsers if you want to hide or remove a back button on your developed web page when there is no window history.
$(window).load(function() {
if (window.history.length == 1) {
$("#back-button").remove();
}
})
Solution
'use strict';
function previousPage() {
if (window.location.pathname.split('/').filter(({ length }) => length > 0).length > 0) {
window.history.back();
}
}
Explaination
window.location.pathname will give you the current URI. For instance https://domain/question/1234/i-have-a-problem will give /question/1234/i-have-a-problem. See the documentation about window.location for more informations.
Next, the call to split() will give us all fragments of that URI. so if we take our previous URI, we will have something like ["", "question", "1234", "i-have-a-problem"]. See the documentation about String.prototype.split() for more informations.
The call to filter() is here to filter out the empty string generated by the backward slash. It will basically return only the fragment URI that have a length greater than 1 (non-empty string). So we would have something like ["question", "1234", "i-have-a-question"]. This could have been writen like so:
'use strict';
window.location.pathname.split('/').filter(function(fragment) {
return fragment.length > 0;
});
See the documentation about Array.prototype.filter() and the Destructuring assignment for more informations.
Now, if the user tries to go back while being on https://domain/, we wont trigger the if-statement, and so wont trigger the window.history.back() method so the user will stay in our website. This URL will be equivalent to [] which has a length of 0, and 0 > 0 is false. Hence, silently failing. Of course, you can log something or have another action if you want.
'use strict';
function previousPage() {
if (window.location.pathname.split('/').filter(({ length }) => length > 0).length > 0) {
window.history.back();
} else {
alert('You cannot go back any further...');
}
}
Limitations
Of course, this solution wont work if the browser do not support the History API. Check the documentation to know more about it before using this solution.
I'm not sure if this works and it is completely untested, but try this:
<script type="text/javascript">
function goBack() {
history.back();
}
if (history.length > 0) { //if there is a history...
document.getElementsByTagName('button')[].onclick="goBack()"; //assign function "goBack()" to all buttons onClick
} else {
die();
}
</script>
And somewhere in HTML:
<button value="Button1"> //These buttons have no action
<button value="Button2">
EDIT:
What you can also do is to research what browsers support the back function (I think they all do) and use the standard JavaScript browser detection object found, and described thoroughly, on this page. Then you can have 2 different pages: one for the "good browsers" compatible with the back button and one for the "bad browsers" telling them to go update their browser
Check if window.history.length is equal to 0.

Clear browser history

I wrote the following code to clear the browser history and it's working correctly in Internet Explorer but it does not work in Mozilla Firefox. How can I solve this problem?
<script language="JavaScript">
function DisablingBackFunctionality()
{
var URL;
var i ;
var QryStrValue;
URL=window.location.href ;
i=URL.indexOf("?");
QryStrValue=URL.substring(i+1);
if (QryStrValue!='X')
{
window.location.href="http://localhost:8085/FruitShop/";
}
}
</script>
I'm writing this code in <header> section.
Do NOT try to break the back button
Instead on the page you want not to return to use location.replace(url)
Also your code can be vastly simplified - but be aware it does not CLEAR the history. You cannot clear the history, only keep a page from getting into the history or as you try, break the back button
function DisablingBackFunctionality() {
// get the query string including ?
var passed =window.location.search;
// did we receive ?X
if (passed && passed.substring(1) =="X") {
// if so, replace the page in the browser (overwriting this page in the history)
window.location.replace("http://localhost:8085/FruitShop/");
}
}

What’s the best way to reload / refresh an iframe?

I would like to reload an <iframe> using JavaScript. The best way I found until now was set the iframe’s src attribute to itself, but this isn’t very clean. Any ideas?
document.getElementById('some_frame_id').contentWindow.location.reload();
be careful, in Firefox, window.frames[] cannot be indexed by id, but by name or index
document.getElementById('iframeid').src = document.getElementById('iframeid').src
It will reload the iframe, even across domains!
Tested with IE7/8, Firefox and Chrome.
Note: As mentioned by #user85461, this approach doesn't work if the iframe src URL has a hash in it (e.g. http://example.com/#something).
If using jQuery, this seems to work:
$('#your_iframe').attr('src', $('#your_iframe').attr('src'));
Appending an empty string to the src attribute of the iFrame also reloads it automatically.
document.getElementById('id').src += '';
window.frames['frameNameOrIndex'].location.reload();
Because of the same origin policy, this won't work when modifying an iframe pointing to a different domain. If you can target newer browsers, consider using HTML5's Cross-document messaging. You view the browsers that support this feature here: http://caniuse.com/#feat=x-doc-messaging.
If you can't use HTML5 functionality, then you can follow the tricks outlined here: http://softwareas.com/cross-domain-communication-with-iframes. That blog entry also does a good job of defining the problem.
I've just come up against this in chrome and the only thing that worked was removing and replacing the iframe. Example:
$(".iframe_wrapper").find("iframe").remove();
var iframe = $('<iframe src="' + src + '" frameborder="0"></iframe>');
$.find(".iframe_wrapper").append(iframe);
Pretty simple, not covered in the other answers.
Simply replacing the src attribute of the iframe element was not satisfactory in my case because one would see the old content until the new page is loaded. This works better if you want to give instant visual feedback:
var url = iframeEl.src;
iframeEl.src = 'about:blank';
setTimeout(function() {
iframeEl.src = url;
}, 10);
A refinement on yajra's post ... I like the thought, but hate the idea of browser detection.
I rather take ppk's view of using object detection instead of browser detection,
(http://www.quirksmode.org/js/support.html),
because then you're actually testing the capabilities of the browser and acting accordingly, rather than what you think the browser is capable of at that time. Also doesn't require so much ugly browser ID string parsing, and doesn't exclude perfectly capable browsers of which you know nothing about.
So, instead of looking at navigator.AppName, why not do something like this, actually testing for the elements you use? (You could use try {} blocks if you want to get even fancier, but this worked for me.)
function reload_message_frame() {
var frame_id = 'live_message_frame';
if(window.document.getElementById(frame_id).location ) {
window.document.getElementById(frame_id).location.reload(true);
} else if (window.document.getElementById(frame_id).contentWindow.location ) {
window.document.getElementById(frame_id).contentWindow.location.reload(true);
} else if (window.document.getElementById(frame_id).src){
window.document.getElementById(frame_id).src = window.document.getElementById(frame_id).src;
} else {
// fail condition, respond as appropriate, or do nothing
alert("Sorry, unable to reload that frame!");
}
}
This way, you can go try as many different permutations as you like or is necessary, without causing javascript errors, and do something sensible if all else fails. It's a little more work to test for your objects before using them, but, IMO, makes for better and more failsafe code.
Worked for me in IE8, Firefox (15.0.1), Chrome (21.0.1180.89 m), and Opera (12.0.2) on Windows.
Maybe I could do even better by actually testing for the reload function, but that's enough for me right now. :)
for new url
location.assign("http:google.com");
The assign() method loads a new document.
reload
location.reload();
The reload() method is used to reload the current document.
Another solution.
const frame = document.getElementById("my-iframe");
frame.parentNode.replaceChild(frame.cloneNode(), frame);
Now to make this work on chrome 66, try this:
const reloadIframe = (iframeId) => {
const el = document.getElementById(iframeId)
const src = el.src
el.src = ''
setTimeout(() => {
el.src = src
})
}
In IE8 using .Net, setting the iframe.src for the first time is ok,
but setting the iframe.src for the second time is not raising the page_load of the iframed page.
To solve it i used iframe.contentDocument.location.href = "NewUrl.htm".
Discover it when used jQuery thickBox and tried to reopen same page in the thickbox iframe.
Then it just showed the earlier page that was opened.
Use reload for IE and set src for other browsers. (reload does not work on FF)
tested on IE 7,8,9 and Firefox
if(navigator.appName == "Microsoft Internet Explorer"){
window.document.getElementById('iframeId').contentWindow.location.reload(true);
}else {
window.document.getElementById('iframeId').src = window.document.getElementById('iframeId').src;
}
If you using Jquery then there is one line code.
$('#iframeID',window.parent.document).attr('src',$('#iframeID',window.parent.document).attr('src'));
and if you are working with same parent then
$('#iframeID',parent.document).attr('src',$('#iframeID',parent.document).attr('src'));
Using self.location.reload() will reload the iframe.
<iframe src="https://vivekkumar11432.wordpress.com/" width="300" height="300"></iframe>
<br><br>
<input type='button' value="Reload" onclick="self.location.reload();" />
<script type="text/javascript">
top.frames['DetailFrame'].location = top.frames['DetailFrame'].location;
</script>
If all of the above doesn't work for you:
window.location.reload();
This for some reason refreshed my iframe instead of the whole script. Maybe because it is placed in the frame itself, while all those getElemntById solutions work when you try to refresh a frame from another frame?
Or I don't understand this fully and talk gibberish, anyways this worked for me like a charm :)
Have you considered appending to the url a meaningless query string parameter?
<iframe src="myBaseURL.com/something/" />
<script>
var i = document.getElementsById("iframe")[0],
src = i.src,
number = 1;
//For an update
i.src = src + "?ignoreMe=" + number;
number++;
</script>
It won't be seen & if you are aware of the parameter being safe then it should be fine.
Reload from inside Iframe
If your app is inside an Iframe you can refresh it with replacing the location href:
document.location.href = document.location.href
If you tried all of the other suggestions, and couldn't get any of them to work (like I couldn't), here's something you can try that may be useful.
HTML
<a class="refresh-this-frame" rel="#iframe-id-0">Refresh</a>
<iframe src="" id="iframe-id-0"></iframe>
JS
$('.refresh-this-frame').click(function() {
var thisIframe = $(this).attr('rel');
var currentState = $(thisIframe).attr('src');
function removeSrc() {
$(thisIframe).attr('src', '');
}
setTimeout (removeSrc, 100);
function replaceSrc() {
$(thisIframe).attr('src', currentState);
}
setTimeout (replaceSrc, 200);
});
I initially set out to try and save some time with RWD and cross-browser testing. I wanted to create a quick page that housed a bunch of iframes, organized into groups that I would show/hide at will. Logically you'd want to be able to easily and quickly refresh any given frame.
I should note that the project I am working on currently, the one in use in this test-bed, is a one-page site with indexed locations (e.g. index.html#home). That may have had something to do with why I couldn't get any of the other solutions to refresh my particular frame.
Having said that, I know it's not the cleanest thing in the world, but it works for my purposes. Hope this helps someone. Now if only I could figure out how to keep the iframe from scrolling the parent page each time there's animation inside iframe...
EDIT:
I realized that this doesn't "refresh" the iframe like I'd hoped it would. It will reload the iframe's initial source though. Still can't figure out why I couldn't get any of the other options to work..
UPDATE:
The reason I couldn't get any of the other methods to work is because I was testing them in Chrome, and Chrome won't allow you to access an iframe's content (Explanation: Is it likely that future releases of Chrome support contentWindow/contentDocument when iFrame loads a local html file from local html file?) if it doesn't originate from the same location (so far as I understand it). Upon further testing, I can't access contentWindow in FF either.
AMENDED JS
$('.refresh-this-frame').click(function() {
var targetID = $(this).attr('rel');
var targetSrc = $(targetID).attr('src');
var cleanID = targetID.replace("#","");
var chromeTest = ( navigator.userAgent.match(/Chrome/g) ? true : false );
var FFTest = ( navigator.userAgent.match(/Firefox/g) ? true : false );
if (chromeTest == true) {
function removeSrc() {
$(targetID).attr('src', '');
}
setTimeout (removeSrc, 100);
function replaceSrc() {
$(targetID).attr('src', targetSrc);
}
setTimeout (replaceSrc, 200);
}
if (FFTest == true) {
function removeSrc() {
$(targetID).attr('src', '');
}
setTimeout (removeSrc, 100);
function replaceSrc() {
$(targetID).attr('src', targetSrc);
}
setTimeout (replaceSrc, 200);
}
if (chromeTest == false && FFTest == false) {
var targetLoc = (document.getElementById(cleanID).contentWindow.location).toString();
function removeSrc() {
$(targetID).attr('src', '');
}
setTimeout (removeSrc, 100);
function replaceSrc2() {
$(targetID).attr('src', targetLoc);
}
setTimeout (replaceSrc2, 200);
}
});
For debugging purposes one could open the console, change the execution context to the frame that he wants refreshed, and do document.location.reload()
I had a problem with this because I didnt use a timeout to give the page time to update, I set the src to '', and then set it back to the original url, but nothing happened:
function reload() {
document.getElementById('iframe').src = '';
document.getElementById('iframe').src = url;
}
but it didnt reload the site, because it is single threaded, the first change doesnt do anything, because that function is still taking up the thread, and then it sets it back to the original url, and I guess chrome doesnt reload because preformance or whatever, so you need to do:
function setBack() {
document.getElementById('iframe').src = url;
}
function reload() {
document.getElementById('iframe').src = '';
setTimeout(setBack,100);
}
if the setTimeout time is too short, it doesnt work, so if its not working, try set it to 500 or something and see if it works then.
this was in the latest version of chrome at the time of writing this.
This way avoids adding history to some browsers (an unneeded overhead). In the body section put:
<div id='IF'>
<iframe src='https://www.wolframalpha.com/input?i=Memphis%20TN%20Temperature'
style="width:5in; height:6in" // or whatever you want in your Iframe
title'Temperature'></iframe>
</div>
Then in some JAVASCRIPT you may have a function like:
function UPdate() { // Iframe
T1=document.getElementById('IF')
T2=T1.innerHTML
T1.innerHTML=T2
}

Categories