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') {
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?