Is there a way to make the user's back button on their browser, call a javascript function instead of going back a page?
You can't override the behaviour that if a user follows a link to your page, clicking Back will take them off it again.
But you can make JavaScript actions on your page add entries into the history as though they were clicks to new pages, and control what happens with Back and Forward in the context of those clicks.
There are JavaScript libraries to help with this, with Really Simple History being a popular example.
yes, you can. Use this js:
(function(window, location) {
history.replaceState(null, document.title, location.pathname+"#!/stealingyourhistory");
history.pushState(null, document.title, location.pathname);
window.addEventListener("popstate", function() {
if(location.hash === "#!/stealingyourhistory") {
history.replaceState(null, document.title, location.pathname);
setTimeout(function(){
location.replace("http://www.programadoresweb.net/");
},0);
}
}, false);
}(window, location));
That will redirect your back button to the location.replace you specify
I think this will do the trick.
you can write your custom code to execute on browser back button click inside onpopstate function.
This works in HTML5.
window.onpopstate = function() {
alert("clicked back button");
}; history.pushState({}, '');
I assume you wish to create a one-page application that doesn't reload the website as the user navigates, and hence you want to negate the back button's native functionality and replace it with your own. This can also be useful in mobile web-apps where using the back button inside apps is common to close an in-app window for example. To achieve this without a library, you need to:
1st. Throughout your application modify the window's location.hash instead of the location.href (which is what tags will do by default). For example, your buttons could fire on click events that modify the location.hash like this:
button.addEventListener('click', function (event) {
// Prevent default behavior on <a> tags
event.preventDefault()
// Update how the application looks like
someFunction()
// Update the page's address without causing a reload
window.location.hash = '#page2'
})
Do this with every button or tag you have that would otherwise redirect to a different page and cause a reload.
2nd. Load this code so that you can run a function every time the page history changes (both back and forward). Instead of the switch that I used in this example, you can use an if and check for other states, even states and variables not related to location.hash. You can also replace any conditional altogether and just run a function every time the history changes.
window.onpopstate = function() {
switch(location.hash) {
case '#home':
backFromHome()
break
case '#login':
backFromLogin()
break
default:
defaultBackAnimation()
}
}
This will work until the user reaches the first page they opened from your website, then it will go back to new tab, or whatever website they were in before. This can't be prevented and the teams that develop browsers are patching hacks that allow this, if a user wants to exit your website by going back, they expect the browser to do that.
If you are creating a one-page web application, where your html body has different sections and you want to nevigate through back button to the previous section you were. This answer will help you.
Where your website sections are differentiated by #. Such as:
your-web-address.com/#section-name
Just follow a few steps:
Add a class and a id in every section in you html body. Here it is ".section"
<section class="section" id="section-name">...</section>
Add two CSS class in your linked css (e.g., style.css) file to your html (e.g., index.html) file such:
.section .hide {
display: none;
}
.section .active{
dislplay: block;
}
Add this JavaScript function in you linked .js (e.g., main.js) file to your html file.
window.onpopstate = function () {
if (location.hash !== "") {
const hash = location.hash;
// Deactivating existing active 'section'
document.querySelector(".section.active").classList.add("hide");
document.querySelector(".section.active").classList.remove("active");
// Activating new 'section'
document.querySelector(hash).classList.add("active");
document.querySelector(hash).classList.remove("hide");
}
}
Related
On the footer of the website I'm working on, I have links to different pages, and in one case, 2 links to the same page with a different hash in the url ,like this :
<a href="http://example.com/mypage#test>Test</a>
<a href="http://example.com/mypage#test2>Test2</a>
These hashes are not true anchors, they reflect some actions the user takes (namely showing/hiding some content).
If I come from another page, I navigate without any problem. However, if I am already on "mypage", then the hash changes, but nothing happens. The browser detects and anchor change and thus tries to navigate to the anchor.
That's fair enough, but I want my user to be actually redirected to "http://example.com/mypage#test2", as if he copy-pasted it himself in the address bar. How can I achieve that ?
I could use the hashchange event but it would make it complicated to manage the rest of the javascript, so I wonder if there is a simpler way to do it.
You have a very simple solution if you are using jQuery:
$(window).on('hashchange', function() {
//code
});
Check out this: On - window.location.hash - Change?
Also this MDN documentation.
Use the location.hash property of the window object to find out what the anchor is. To detect a change in the hash, with plain javascript, just use the onhashchange event.
window.onhashchange = new function() {
window.location.replace("http://example.com/mypage" + window.location.hash);
});
I have a site that uses AJAX to dynamically load content into a div.
The links to do so are anchors with href="#" and an onclick event to trigger the AJAX.
This leaves me without a history when I click back, so if I load one page, then another and click back, it does nothing.
A basic version of the code is this:
<script type="text/javascript">
function loadXMLDoc(url)
{
<!-- Load XML Script here. -->
}
</script>
</head>
<body>
<div id="myDiv">
<!-- Target div. -->
</div>
Click Me.
Click Me.
Click Me.
</body>
What I would like to know is, can I give each link a different "#" and then use a popstate handler to call the appropriate event, so if I click link 1, 2 and then 3 and then start hitting the back button, it'll go back to 2 and then 1 etc..
I was going to use history.js and start using pushstate in the loadXML script but I think the whole manipulating history thing is a bit dirty and unreliable.
Am I thinking on the right lines or is there a better way?
Currently all my links just use "#" so that it pops back to the top of the page when loading more content but I'd like to be able to go back if possible.
Any help would be great.
Browser saves hashtags to history properly. Just add hashtag #1 to this question page, hit enter, change it to #2, hit enter, change it to #3, hit enter. Now click back button, and you'll see hash changes from #3 to #2. I recommend to change only hash itself on link click and react on page hash change and page load events.
function react() {
var hash = window.location.hash.replace("#", "");
loadXMLDoc(hash + ".txt");
};
document.body.onload = function() {
react();
window.onhashchange = react;
};
Click me
Click me
Click me
Please note that onhashchange event does not supported by old IE. The only way to deal with it if you want is to define timer with setInterval and check hashes equality.
Try to use combination of LocalStorage and HistoryAPI.
When you load XMLDoc store it in LocatStorage, when back is pressed - load data from storage, not from web.
A bit code above.
/* Handling history.back added */
window.onpopstate = function(event) {
yourHandleBackFunction(event.state);
};
function yourHandleBackFunction(renderTs) {
/*Check TS and load from localStorage if needed*/
};
I've the following link:
I
And this use the following javascript:
function showGallery(){
if(window.location.hash) {
$('#gallery').fadeIn('fast');
var hash = window.location.hash.substring(1);
alert(hash);
} else {
}
}
So it only show the gallery when in the URL is a hashtag. But when i click on the link, nothing happens. When i click it twice, the gallery fade in.
So the link first make the javascript, and i doesn't work 'cause there is no hashtag in the URL and after that, it perform the href and insert the Hashtag in the URL.
How can i do that?
My Target:
When i click on a link, it open a gallery. To know which gallery i must open, i insert in the URL a Hashtag. Here i want to display the HDR album. And i also want, if my site get opend with a hashtag, it should display the gallery.!
Is there also a another, easier or cleaner way to make it?
Hope you understand what i want.
For modern browsers, you can bind your Javascript code to the onhashchange event. Links will be without Javascript:
I
And the Javascript is run whenever the hash has changed:
function locationHashChanged() {
if (location.hash === "#HDR") {
$('#gallery').fadeIn('fast');
}
}
window.onhashchange = locationHashChanged;
Have you tried a setTimeout call to delay the onclick event?
Like this:
I
You can simplify this quite considerably, it is not good practice to use the href for other things than pure navigation.
<a onClick="showGallery('HDR')">I</a>
And then:
function showGallery(name){
if(name) {
$('#gallery').fadeIn('fast');
alert(name);
} else {
}
}
If you want to run showGallery() without following the link, the correct code is this:
I
By keeping the href the user still sees the destination in the status bar and navigation still works for clients without Javascript (i.e. Google). By returning false in the event handler, you prevent the browser from following the link.
In showGallery(), you can then show the gallery and add '#HDR' to the location.hash.
You don't need to verify the window's hash, because on first click you don't have any hash in the address bar. The functionality will only apply on the second click.
What you can do is this:
gallery 1
function showGallery(galid){
var linkhash = $('#' + galid).attr('href').substring(1);
alert(linkhash);
$('#gallery' + linkhash).fadeIn('fast');
}
I have a menu that loads a new html file in a div. The loading is done by a click event attached to the menu's <a> tags. The loading works well and I add the new load to the history by constructing a new href with a hash tag.
But when I use the back button, the URL is updated correct in the browsers address field, but the page is never loaded. If I focus the address field and press enter it loads.
This is the javascript located in the mypage.html header.
<script type="text/javascript">
$(document).ready(function() {
// replace menu link click
$(".right-menu a").live('click', function(ev) {
ev.preventDefault();
ev.stopPropagation();
window.location.href = $(this).attr('href');
$("#content-right").load('mypage'+window.location.hash.substring(1)+'.html');
return false;
});
// If page loads, load the content area according to the hash.
var hrtag = window.location.hash.substring(1);
if(hrtag=="")
hrtag='about';
$("#content-right").load('mypage'+hrtag+'.html');
window.location.hash = hrtag;
});
</script>
This is the menu
<ul class="right-menu">
<li>About</li>
<li>Screens</li>
<li>License</li>
<li>Download</li>
<li>Donate</li>
</ul>
If I load the page as mypage.html, the javascript will append the hash #about and load the div id "content-right" with mypageabout.html
If I click the menu, for example download, it will load the div id "content-right" with mypagedownload.html
In both cases, the window.location will be set to the hash version of the page, mypage.html#about and mypage.html#download to register them in the history.
If i click the menu in the following order; license, about, screens and then click the browser's back button, the address field will show; mypage.html#about, mypage.html#license but it will NOT load the pages!?!
The URLs are obviously in the history, but they don't load.
Any clue to what might be wrong here?
// Thanks
EDIT - The solution
Thanks to Andres Gallo's article I came up with this solution:
<script type="text/javascript">
$(document).ready(function() {
// Make sure the page always load #about
LoadIDWithURL('#content-right','myPageAbout.html');
window.addEventListener('hashchange',function() {
if (window.location.hash != "") {
// We have a hash, use it!
LoadIDWithURL('#content-right','MyPage'+window.location.hash.substring(1)+'.html');
} else {
// We do not have a hash, force page reload!
window.history.go(0);
}
});
});
// Load the targetID with the URL loadURL.
function LoadIDWithURL(targetID,loadURL) {
$(targetID).load(loadURL);
}
</script>
I wrote a very detailed article on this exact topic. It explains how to build exactly what you are trying to do.
Furthermore my article also explains how you can pass parameters in your links to have javascript do special things
Here is a link to the article http://andresgallo.com/2012/06/08/ajaxifying-the-web-the-easy-way/
The best method is to attach your functionality to your hashchanges rather than to you click events. This allows any changes in history to take advantage of your javascript functionalities.
This is normal behaviour when navigating between pages which differ only in their hash. You have two options:
Use the hashchange event, or an emulation of it, to detect when the user changes the hash by navigation back or forward and update the page appropriately
Use the HTML5 history API.
you can try with hashchange
$(function(){
$(window).hashchange(function(){
// some event
})
})
Say I'm on a page called /example#myanchor1 where myanchor is an anchor in the page.
I'd like to link to /example#myanchor2, but force the page to reload while doing so.
The reason is that I run js to detect the anchor from the url at the page load.
The problem (normally expected behavior) here though, is that the browser just sends me to that specific anchor on the page without reloading the page.
How would I go about doing so? JS is OK.
I would suggest monitoring the anchor in the URL to avoid a reload, that's pretty much the point of using anchors for control-flow. But still here goes. I'd say the easiest way to force a reload using a simple anchor-link would be to use
where in place of $random insert a random number (assuming "dummy" is not interpreted server side). I'm sure there's a way to reload the page after setting the anchor, but it's probably more difficult then simply reacting to the anchor being set and do the stuff you need at that point.
Then again, if you reload the page this way, you can just put myanchor2 as a query parameter instead, and render your stuff server side.
Edit
Note that the link above will reload in all circumstances, if you only need to reload if you're not already on the page, you need to have the dummy variable be more predictable, like so
I would still recommend just monitoring the hash though.
Simple like that
#hardcore
an example
Another way to do that is to set the url, and use window.location.reload() to force the reload.
<a href="/example#myanchor2"
onclick="setTimeout(location.reload.bind(location), 1)">
</a>
Basically, the setTimeout delays the reload. As there is no return false in the onclick, the href is performed. The url is then changed by the href and only after that is the page reloaded.
No need for jQuery, and it is trivial.
My favorite solution, inspired by another answer is:
myanchor2
href link will not be followed so you can use your own preference, for example: "" or "#".
Even though I like the accepted answer I find this more elegant as it doesn't introduce a foreign parameter. And both #Qwerty's and #Stilltorik's answers were causing the hash to disappear after reload for me.
What's the point of using client-side JS if you're going to keep reloading the page all the time anyways? It might be a better idea to monitor the hash for changes even when the page is not reloading.
This page has a hash monitor library and a jQuery plugin to go with it.
If you really want to reload the page, why not use a query string (?foo) instead of a hash?
Another option that hasn't been mentioned yet is to bind event listeners (using jQuery for example) to the links that you care about (might be all of them, might not be) and get the listener to call whatever function you use.
Edit after comment
For example, you might have this code in your HTML:
example1
example2
example3
Then, you could add the following code to bind and respond to the links:
<script type="text/javascript">
$('a.myHash').click(function(e) {
e.preventDefault(); // Prevent the browser from handling the link normally, this stops the page from jumping around. Remove this line if you do want it to jump to the anchor as normal.
var linkHref = $(this).attr('href'); // Grab the URL from the link
if (linkHref.indexOf("#") != -1) { // Check that there's a # character
var hash = linkHref.substr(linkHref.indexOf("#") + 1); // Assign the hash to a variable (it will contain "myanchor1" etc
myFunctionThatDoesStuffWithTheHash(hash); // Call whatever javascript you use when the page loads and pass the hash to it
alert(hash); // Just for fun.
}
});
</script>
Note that I'm using the jQuery class selector to select the links I want to 'monitor', but you can use whatever selector you want.
Depending on how your existing code works, you may need to either modify how/what you pass to it (perhaps you will need to build a full URL including the new hash and pass that across - eg. http://www.example.com/example#myanchor1), or modify the existing code to accept what you pass to it from you new code.
Here's something like what I did (where "anc" isn't used for anything else):
And onload:
window.onload = function() {
var hash = document.location.hash.substring(1);
if (hash.length == 0) {
var anc = getURLParameter("anc");
if (anc != null) {
hash = document.location.hash = anc;
}
}
}
The getURLParameter function is from here
If you need to reload the page using the same anchor and expect the browser to return to that anchor, it won't. It will return to the user's previous scroll position.
Setting a random anchor, overwriting it and then reloading seems to fix it. Not entirely sure why.
var hash = window.location.hash;
window.location.hash = Math.random();
window.location.hash = hash;
window.location.reload();
Try this its help for me
<a onclick="location.href='link.html'">click me</a>
In your anchor tag instead of
click me
As suggested in another answer, monitoring the hash is also an option. I ended up solving it like this so it required minimal code changes. If I had asked the original question, I believe I would have loved to see this option fully explained.
The added benefit is that it allows for additional code for either of the situations (hash changed or page loaded). It also allows you to call the hash change code manually with a custom hash. I used jQuery because it makes the hash change detection a piece of cake.
Here goes!
Move all the code that fires when a hash is detected into a separate independent function:
function openHash(hash) {
// hashy code goes here
return false; // optional: prevents triggering href for onclick calls
}
Then detect your hash for both scenarios like so:
// page load
$(function () {
if(typeof location.hash != typeof undefined) {
// here you can add additional code to trigger only on page load
openHash(location.hash);
}
});
// hash change
$(window).on('hashchange', function() {
// here you can add additional code to trigger only on hash change
openHash(location.hash);
});
And you can also call the code manually now like
Magic
Hope this helps anyone!
Try this by adding simple question mark:
Going to Anchor2 with Refresh