Handling the back button click action using JavaScript (in pages with fragment identifiers) to route the request to another page

So there is this new issue at work where the browser back button is not behaving as desired. The idea is that when the user clicks the browser back button on any page, the user should be routed to the default login page. As much as that sounds like a symptom of an inherently fundamental fault, I feel it is much better than what most other sites do – disable the back button altogether (which can be circumvented of course).

The product in question is a standard JSP-based web application with the normal JS+CSS++HTML client-side stack. The layout is pretty simple – there is a main Login Page, and then the user is presented with a navigation pane on the left-hand side, and with a main page displaying the results of the various options presented in the navigation pane. The idea is that whenever a user clicks on the back button from any page, he or she should be presented with the Login Page. Easier said than done! First of all, there is no real event associated with the browser back button click (or a lot of other browser actions for that matter) in JavaScript. There are plenty of hacks that can be done to achieve most use cases. In this specific case though, the problem was a specific option on the navigation pane – the ‘Inventory’ option, which simply displays various objects as hyperlinks in the main pane. Upon clicking any of these objects, the URL uses fragment identifiers (of the format: http://<host>:<port>/<main-url>#detailedInfo. This practically messes up the aforementioned hacks (using iframes, polling of hash changes, onbeforeunload, onunload, etc). Since the history object of the browser still contains the same base URL for both the main pane as well as the fragment identifier, options such as using iframes and onbeforeunload/onunload events fail completely. Also, using hash changes (either polling or using the basic window.onhashchange event) also do not solve the problem since the URL hash does change even on clicking the anchor for the fragment identifer (which is not desirable) as well as on clicking the back button (or the alt-leftarrow combination). However, unlike the many trolls that abound the various forums online, I present to you an actual solution to the problem at hand, which may be customized to suit any specific situation as the case may be.

For my demo, I have created a base page – Page1.html which simulates the main page. Page2.html contains the logic for detecting back-button clicks (note that since the forward button is not enabled, that case does not pose a problem. Also, the advantage with this method is that refreshing the page does not cause any unexpected or anomalous behavior either). I have also created another page, Login.html which simply simulates the default Login Page.

1. Page1.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8"/>
		<title>Page 1</title>
	</head>
	<body>
		<h1>Welcome to the Main page</h1>
		<a href="Page2.html">Page 2</a>
	</body>
</html>

2. Page2.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8"/>
		<title>Page 2</title>
		<script type="text/javascript">
			var origURL = window.document.location.href;
			var origFileName = origURL.substring(origURL.lastIndexOf("/") + 1, origURL.length);
	        </script>
	</head>
	<body>
		<h1>Welcome to the Details  page</h1>
		<a href="#detailedInfo">Details</a>
		<p id="details">Details here!</a></p>
		<script type="text/javascript">
			window.onhashchange= function() {
				var url = window.document.location.href;
				var fileName = url.substring(url.lastIndexOf("/") + 1, url.length);
			
                        	if(fileName.search(origFileName) != -1) 
                                    && fileName.search("#detailedInfo") != -1) {
                                           // Do nothing.
					} else {
                                                //This would be a proper URL when deployed on a Web Server.
						window.location.replace("Login.html");
					}
			}
		</script>
	</body>
</html>

3. Login.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8"/>
		<title>Login Page</title>
	</head>
	<body>
		<h1>Welcome to the login page</h1>
	</body>
</html>

Explanation: The logic here hinges upon the fact that most modern browsers (this code has been tested on Firefox 18.0.1, Chrome 24.0.1312.57, Opera 12.00, and Internet Explorer 9) support the window.onhashchange event. This event is basically generated when the location hash (in simple terms, the hash of the URL of the current window) changes. Thankfully, this also includes the case where the fragment id of the anchor target is appended to the main URL.

Thus, in Page2.html, I simply get a handle to the original page name when I enter the page, and the check if the new page name (that includes the fragment identifier) contains the original page name as well as the fragment identifier. If so, it means that we are still on the same page, and so we do nothing. Otherwise, it means that the back button has been clicked (or invoked through history.back(), or through the keyboard action – alt+ left arrow). In this case, we simply change the location of the current window to the Login Page. And that’s it!

P.S: The fragment identifier, #detailedInfo has been hardcoded in this snippet, but it need not be so. We can simply check for the main page, and any fragment identifier, to ascertain if we are still on the same page or not. Note that this is a very specific case – any other situations beyond this case have to be handled in their own right.

P.P.S: While Firefox supports the “contains” method (in the style of Java) for searching substring matches in string objects, all the other browsers support the “search” method, including Firefox itself! So this snippet works uniformly across all browsers.

Handling the back button click action using JavaScript (in pages with fragment identifiers) to route the request to another page