In the footer of my page there a few links that point to different sections on the same page using anchor tags (# appended to the URL of the page).
This works fine, just the browser back button does not work: I cannot move back to the previous page from where I had navigated to the anchored page.
The simple question here is, is it possible to move back to previous page after navigating in the anchored page a few times? If it is then please could you suggest how?
Anchored page: the page that has several sections marked by the id attribute that can be pointed to by a URL with #anchorId at the end.
I also faced the same problem see my question anchor links referring to the page sections not working on browser refresh, back and forward
But I had to do it the way normal links work so what I did was I manually go to that section by getting the element from the hash.
$(window).on('hashchange', function ()
{
var top = $(window.location.hash).offset().top;
$(window).scrollTop(top);
});
This works for forward and back buttons.
And for refresh also you need to do the same thing. Get the element from the hash and scroll to that element manually.
History and the Back Button.
In days of old, the back button did little more that go to the previous item in the browser's history. That's changed quite a bit since then, as it keeps its own history according to a somewhat simple set of rules. Good luck digging through standards docs to find it though.
UI/UX and why NOT to change expected behaviors.
Please reference w3c's 'don't brek the back-button before you go making changes to a browser's default behavior. Its like that for a reason, following mountains of debate and defining standards.
Ultimately, this is what browsers do, and so this is what the users expect. If you begin to subvert the behavior away from user's expectations, you're likely to start pissing off your users. When buttons and links repeatedly don't behave as expected, users will often just give up and leave your site.
Prevent Default.
If you really must alter the default behavior, the using javascript would be the best way to do it:
<a href="#id" onclick="return gotoAnchor(this);">
<script>
function gotoAnchor(elm) {
window.event.returnValue = false;
var url = location.href;
location.href = elm.href;
history.replaceState(null,null,url);
return false;
}
</script>
http://www.the-art-of-web.com/javascript/remove-anchor-links/
Visit that site. Scroll to the bottom and use test the anchors. It's doing what you want.
"The following code will parse your HTML page and override the function of any links that target anchor points on the same page. The link function will be replaced with a call to the scrollIntoView method of the target element:
document.addEventListener("DOMContentLoaded", function() {
var links = document.getElementsByTagName("A");
for(var i=0; i < links.length; i++) {
if(!links[i].hash) continue;
if(links[i].origin + links[i].pathname != self.location.href) continue;
(function(anchorPoint) {
links[i].addEventListener("click", function(e) {
anchorPoint.scrollIntoView(true);
e.preventDefault();
}, false);
})(document.getElementById(links[i].hash.replace(/#/, "")));
}
}, false);
if (document.referrer == "") {
window.open("index.php");
} else {
window.history.go(-1);
return false;
}
Related
This question is sort of what i'm thinking, but has no answers.
I have successfully implemented hash navigation in my application using the following code:
$(window).on('hashchange', function () {
loadContent(location.hash.slice(1));
}).trigger('hashchange');
I use this event to download partial HTML content from the server via Ajax, and it gets called when the browser detects a change on the hash in the address bar. The addresses looks like this:
https://www.mywebsite.com/#/account/login
The problem is, when the link is the same it does not fire the hashchange event (for obvious reasons). I need to call the function loadContent to refresh the page.
For example, before I implemented hash navigation, if the user wanted to discard all the changes he made to the page, he simply clicks the same link in the system menu, or click the address bar and hit enter. Then, the browser will redirect to the same page and drop all the changes.
But now, I can't detect that. What can I do to detect those commands and call my loadContent(location.hash.slice(1)); function?
After some research, I come to conclusion that there's no way to do that. I found this question that is very close to mine, but also no useful answer, other than handling the "onclick" event on every link on the site. Not a very beautiful solution - and does not solve the functionality of hitting enter on the address bar.
I ended up with a different approach. Definitely does not solve the way I wanted, however I think that it's more elegant from code perspective and practical from user perspective. I created a keyboard shortcut to refresh the page:
function doc_keyUp(e) {
if (e.altKey && e.keyCode === 82) { // ALT + R
if (confirm("Discard changes and refresh the page?")) {
loadContent(location.hash.slice(1));
}
return false;
}
}
document.addEventListener('keyup', doc_keyUp, false);
It may a simple approach, but what if you store your current hash in a property and afterwards register a click event and check if the hash is still the same?
Here is an (untested) example. But you should get the idea.
var storedHash = document.location.hash;
// You may add a data attribute to corresponding links to not
// catch all 'a'-tags (i.e. document.querySelectorAll('a[data-nav=true]'))
var links = document.querySelectorAll('a');
for (var i in links) {
if (!links.hasOwnProperty(i)) {
continue;
}
links[i].addEventListener('click', function() {
if (document.location.hash === storedHash) {
// Here comes your logic
}
});
}
I am trying to write a Tampermonkey script to help the navigation of some of the websites I commonly browse. The goal is to be able to browse through the pagination of the page with the arrow keys (for instance, if I am on page 3, left key would go to page 2). I want to be able to search the page to ensure the Previous link exists, and if it does, click it to go to the previous page.
An example would be as follows:
<a href="www.example.com/page/2.html>Previous</a>
Instead of parsing the url to get the "2" as an integer, incrementing or decrementing as needed, and reconstructing the url, I want to find the word "Previous" and click it if it exists. How would I go about doing this? Thank you much for your time!
This is somewhat what I am looking for:
http://runnable.com/UhZCuuHhSAsoAALM/how-to-get-a-href-value-using-jquery
However, the code uses
var href = $('a:first').attr('href');
to get the first href on the page. I need it to get a specific href on the page (one titled "Previous").
Moving backward and forward through the user's history is done using the back(), forward(), and go() methods.
window.history.back();
window.history.forward();
Check out MozDev
<body id="body" data-page='2'>...
javascript
var num = document.getElementById('body').getAttribute('data-page');
document.onkeyup = function(e) {
if (e.keyCode == 37) {
window.location.href = "www.example.com/page/"+(num-1)+".html";
}
if (e.keyCode == 39){
window.location.href = "www.example.com/page/"+(num+1)+".html";
}
};
// similar behavior as an HTTP redirect
window.location.replace("http://stackoverflow.com");
// similar behavior as clicking on a link
window.location.href = "http://stackoverflow.com";
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
I have a page with two tabs that I want to be able to switch with Javascript, but also set the anchor (e.g. page.html#tab1) in the URL for bookmarking/linking.
By default the tab contents are in two divs, one below the other, and the anchor tag will scroll to the correct one, with JS disabled.
With JS enabled, CSS classes are applied to make them act as tabs. Each tab links to each anchor, but when you click to switch tabs, the page scrolls to the tab. If I return false from the onclick function then the URL doesn't change to include the anchor.
How do I make the browser URL change to page.html#tab1 but not scroll to #tab1 ??
I've played with this for a while, because I initially didn't believe you (I use the jQuery history plugin to get similar behavior).
And I'm stumped. I don't think you can. What you could do, as a workaround, is use javascript to set the hash to something DIFFERENT from what is actually on the page. And then use javascript upon load to read the hash and populate the correct content. I do this on my site. So in that scenario, users without javascript would be scrolled, users with javascript would keep the history chain, and it only gets wacky when people without send links to people with (or vice-versa).
A quick hack:
var thehash = e.target.hash;
$(thehash).prop('id',thehash.substr(1)+'-noscroll');
window.location.hash = e.target.hash;
$(thehash+'-noscroll').prop('id',thehash.substr(1));
This changes the id of the html element before and after changing the hash of the url. Works for me, but might as well break something. This prevents the browser from scrolling on a hash change, since there is not html element with that id in between.
Could you have some Javascript that changed the anchor names, set window.location.hash, and then changed the anchor names back?
(I've confirmed that andynormancx is right, and setting window.location.hash scrolls the view, but I'm too lazy to test if creating an anchor in the DOM to window.location.hash also scrolls.)
var Namespace = {
var timer, scroll;
}
// Onclick
Namespace.scroll = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
Namespace.timer = setInterval(function() { scrollTo(0, Namespace.scroll) }, 100);
location.hash = this.href;
clearInterval(Namespace.timer);
I found a nice solution here: http://lea.verou.me/2011/05/change-url-hash-without-page-jump/
Use a preventDefault on for example a click event
$('a').click((event) => {
event.preventDefault();
let hash = $(event.target).attr('href');
history.pushState(null, null, hash);
// The url now has a hash but the page won't jump to the given anchor
// .. handle the rest (an easing scroll for example)
});
window.location.hash = 'tab1';
might work.
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");
}
}