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.