Onhashchange with browser buttons only

I have this problem (I use jQuery, but I'm not limited to this):

I use combo navigation tips (#id) and Ajax. To make pages move in place (using anchor navigation) or retrieve information (using Ajax), I use the onhashchange event.

EDIT: I had a little typo. I forgot to check if the mouseDown flag was true and the hashchange event was raised, so I added that the if statement.

with jQuery it looks like this: (of course, this code is wrapped in a function and initialized on loading the DOM, but it does not matter for the question)

$(window).bind('hashchange', function(e) { } 

To ensure that only browsers that support onhashchange read the code, I encapsulate it as follows:

 if ('onhashchange' in window) { $(window).bind('hashchange', function(e) { } } 

My web application is designed so that I want the onhashchange event to fire when I press the back / forward buttons in the browser. For this I like it:

 if ('onhashchange' in window) { $(window).bind('mousedown hashchange', function(e) { } } 

Now, if I click in the viewport, I will call the mousedown event. If the mousedown event fires, I know that I did not push the browser button back / forward, and I can stop the onhashchange event using a flag similar to this:

 var mouseDown = false; if ('onhashchange' in window) { $(window).bind('mousedown hashchange', function(e) { if (e.type === 'mousedown') { mouseDown = true; } if (mouseDown && e.type === 'hashchange') { // if the mousedown event was triggered and when the haschange event triggers, // we need to stop the hashchange event and restore the mouseDown flag mouseDown = false; e.stopPropagation(); } if (!mouseDown && e.type === 'hashchange') { // Do the onhashchange stuff here } } } 

This causes a problem for IE because it does not allow mouse events to be bound to a window object (?). IE will never see the mousedown event.

To solve this problem with IE , I can use the "clientY" property. This property is passed in all event calls in IE and reports the coordinates of the mouse. If e.clientY is less than 0, the mouse is outside the viewport and I find out that I called onhashchange by clicking the browser buttons back / forward. Now it looks like this:

 var mouseDown = false; if ('onhashchange' in window) { $(window).bind('mousedown hashchange', function(e) { // IE: Use e.clientY to check if the mouse position was within the viewport (ie not a nagative value for Y) // !IE: Use e.type if (e.type === 'mousedown' || e.clientY > 0 ) { mouseDown = true; } if (mouseDown && e.type === 'hashchange') { // if the mousedown event was triggered and when the haschange event triggers, // we need to stop the hashchange event and restore the mouseDown flag mouseDown = false; e.stopPropagation(); } if (!mouseDown && e.type === 'hashchange') { // Do the onhashchange stuff here } } } 

This solution worked like a charm until I had to add support for navigation with arrows on the keyboard. Now it doesn’t matter where the mouse is on the screen. While the IE window is "active", a keypress event when listening to keyboard input signals is triggered when a keyboard is pressed. This means that client validation does not work more than expected.

Problem:

As far as I know, onhashchange should be attached to the window object. All events must be handled within the same callback function if I want to be able to control one event while listening to another.

How can I make this work?

+6
javascript jquery ajax hashchange
source share
2 answers

So just put -

"how do I distinguish between pressing the back / forward button against navigation going from interacting with the DOM."

You might want to have a flag such that when you change the hash of the URL from the code, you set this flag, ignore the hashchange event, and then set the flag. In this case, the event will be ignored (as if the reverse decision regarding what you are trying to do). You obviously want to wrap this in a function.

In general, applications that use the hashchange event for navigation often use the hashchange event as a means to change the state of the application. Therefore, there is only one entry point, and you do not need to distinguish whether an event is generated when the browser interacts with the browser and the domain. I would recommend changing your approach.

I would also like to point out that the story can be supported in all browsers (even IE6 and IE7 using iFrame hack). Take a look at the jQuery history plugin

+3
source share

Reference library to achieve this: http://benalman.com/projects/jquery-bbq-plugin/

I used it and it works great

Think about putting a "!" after "#" in the url so that Google will find ajax pages http://code.google.com/web/ajaxcrawling/docs/getting-started.html

+1
source share

All Articles