The situation is this: I’m using jQuery for loading of all sub-pages of my main web page, and I want to maintain the browser history so that a user can simply click the “Back” button to navigate to the previous link. I found a jQuery history plug-in that implements all of the history caching with a few lines of JavaScript, and an included .js file. It seems to work really well, but I had one issue: The browser’s scroll position would auto-scroll to the link’s position. It turns out this was developer error, but it took me a couple hours to finally figure out where the problem was, so I decided I should blog about it in case anyone was having the same problem and found this in the Google search results.
In order to make the jQuery history plug-in work, one needs to format one’s links like so:
<pre><a href="#1" rel="history">load 1</a></pre>
And add the following bit of javascript to the top of the page for processing:
<script type="text/javascript"> var timeoutValue; // PageLoad function // This function is called when: // 1. after calling $.historyInit(); // 2. after calling $.historyLoad(); // 3. after pushing "Go Back" button of a browser function pageload(hash) { // hash doesn't contain the first # character. if (hash) { // restore ajax loaded state if ($.browser.msie) { // jquery's $.load() function does't work when hash include special characters like aao. hash = encodeURIComponent(hash); } //timeoutValue = setTimeout("IsLoading(true);", 200); $("#pagecontent").load(hash + ".html"); } else { // start page $("#pagecontent").load("menuItem1.html"); hash = "menuItem1"; } ColorActiveMenu(hash); } function ColorActiveMenu(menuName) { var items = $("#mainMenu > *"); items.attr("class", ""); menuName = "#" + menuName; $(menuName).attr("class", "current"); } $(document).ready(function() { //alert("Document ready"); // Initialize history plugin. // The callback is called at once by present location.hash. $.historyInit(pageload, "menuItem1.html"); // set onlick event for buttons $("a[rel='history']").click(function() { // var hash = this.href; hash = hash.replace(/^.*#/, ''); // moves to a new page. // pageload is called at once. // hash don't contain "#", "?" $.historyLoad(hash); return false; }); if (location.hash == "") { pageload("menuItem1"); } }); </script>
In the $(document).ready event, the last line we add to the onClick event of each of our links we're adding to the history cache, we use 'return false;' which I thought would counteract any effect of auto-scrolling that would occur due to using the pound (#) mark in the href of the link. It turns out this was incorrect. (at least in the context of IE and Firefox) Consider the following piece of code from a "menu" that I created for a page I developed recently:
<ul id="mainMenu" class="menu"> <li id="menuItem1" class="current"><a href="#menuItem1" rel="history"> Menu Item 1</a> <li id="menuItem2"><a href="#menuItem2" rel="history"> Menu Item 2</a> <li id="menuItem3"><a href="#menuItem3" rel="history"> Menu Item 3</a> </li> </ul>
Note, I also changed the javascript a little to automatically load the first item. My goal was to have a menu that would make certain CSS changes based upon which page was currently loaded. To do this, I added the ID attribute to each of the <li> tags, in order to identify them when I was ready to mark each item as active. Here is a live demo of what I was trying to accomplish as well as the bug I encountered / created by using these specific ID names.
The issue seems to be that since I set the ID value to the exact same value as the hash value (e.g. id=”menuItem1” and href=”#menuItem1”) that the browser detected the <li> tag menuItem1 in this case as the position in the page that I wanted to scroll to when this link was clicked.
To work around this behavior, I merely changed the names of the ID attributes I assigned to each <li> tag, like so:
<ul id="mainMenu" class="menu"> <li id="limenuItem1" class="current"><a rel="history" href="#menuItem1" > Menu Item 1</a></li> <li id="limenuItem2"><a rel="history" href="#menuItem2" > Menu Item 2</a></li> <li id="limenuItem3"><a rel="history" href="#menuItem3" > Menu Item 3</a></li> </ul>
Note, that I also had to make one minor change to the pageload javascript function to add the “li” prefix to each ID attribute:
ColorActiveMenu("li" + hash);
Here is the full working page.
Hope this helps.