javascript - Onhashchange with browser buttons only - Stack Overflow

I've got this issue (I'm using jQuery but I'm not restricted to it):I'm using a bo

I've got this issue (I'm using jQuery but I'm not restricted to it):

I'm using a bo of Anchor navigation (#id) and Ajax requests. To get the pages to move into place (using anchor navigation) or to fetch 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 triggered so I added that if statement.

with jQuery it looks like this: (of course this code is wrapped in a function and initialized on DOM load but it doesn't matter for the question)


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

To ensure only browsers supporting the onhashchange reads the code I encapsulate it like this:


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

My web app is made in such way that I only want the onhashchange event to trigger when I hit the back/forward buttons in the browser. To do that I do like this:


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

Now if I click within the viewport I will trigger the mousedown event. If the mousedown event is triggered I know that I didn't click the browser back/forward buttons and I can stop the onhashchange event using a flag like 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 since it seams you cannot bind mouse events to the window object (?). IE will never "see" the mousedown event.

To solve this IE issue I can take the "clientY" property. This property is passed in all event calls in IE and tells you the coordinates of the mouse. If e.clientY is less then 0, the mouse is outside the viewport and I will know that I triggered the onhashchange by clicking the browser back/forward buttons. It now 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 (i.e. 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 was working like a charm until I had to add support for navigating with the arrows on the keyboard. Now it doesn't matter where on the screen the mouse is. As long as the IE window is "active", the keydown event listening for keyboard input triggers when hitting the keyboard. This means that the clientY check does not work anymore as intended.

The Problem:

As far as I know, the onhashchange must be bound to the window object. All events must be processed within the same callback function if I want to be able to control one event by listening for another.

How can I get this to work?

I've got this issue (I'm using jQuery but I'm not restricted to it):

I'm using a bo of Anchor navigation (#id) and Ajax requests. To get the pages to move into place (using anchor navigation) or to fetch 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 triggered so I added that if statement.

with jQuery it looks like this: (of course this code is wrapped in a function and initialized on DOM load but it doesn't matter for the question)


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

To ensure only browsers supporting the onhashchange reads the code I encapsulate it like this:


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

My web app is made in such way that I only want the onhashchange event to trigger when I hit the back/forward buttons in the browser. To do that I do like this:


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

Now if I click within the viewport I will trigger the mousedown event. If the mousedown event is triggered I know that I didn't click the browser back/forward buttons and I can stop the onhashchange event using a flag like 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 since it seams you cannot bind mouse events to the window object (?). IE will never "see" the mousedown event.

To solve this IE issue I can take the "clientY" property. This property is passed in all event calls in IE and tells you the coordinates of the mouse. If e.clientY is less then 0, the mouse is outside the viewport and I will know that I triggered the onhashchange by clicking the browser back/forward buttons. It now 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 (i.e. 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 was working like a charm until I had to add support for navigating with the arrows on the keyboard. Now it doesn't matter where on the screen the mouse is. As long as the IE window is "active", the keydown event listening for keyboard input triggers when hitting the keyboard. This means that the clientY check does not work anymore as intended.

The Problem:

As far as I know, the onhashchange must be bound to the window object. All events must be processed within the same callback function if I want to be able to control one event by listening for another.

How can I get this to work?

Share Improve this question edited Jan 4, 2011 at 11:25 Patrik asked Jan 3, 2011 at 17:40 PatrikPatrik 1321 gold badge2 silver badges8 bronze badges 2
  • ('onhashchange' in window) will always return false if it isn't yet defined and true it is already defined. It doesn't mean the browser will actually execute the code on a hashchange This is similar to window.onload which is undefined unless a function has actually been assigned to it, even though practically all browswers support it. – qwertymk Commented Jan 3, 2011 at 18:39
  • Yes, I intentionally left out the function declaration since I didn't see it as relevant for the question. The function that binds the hashchange event is called when the DOM loads. – Patrik Commented Jan 3, 2011 at 21:49
Add a ment  | 

2 Answers 2

Reset to default 3

So, simply put-

"how do I distinguish between a back/forward button press vs. navigation ing from interacting with the DOM".

You may want to have a flag such that when you are changing the hash part of the URL from code, you set this flag, ignore the hashchange event, then unset the flag. In which case the event will be ignored ( a kind of reverse solution as to what you're trying to do). You'd obviously want to wrap this in a function.

In general however, applications that use the hashchange event for navigation will often use the hashchange event as a means for changing the state of the application. Therefore, there is only one entry point and you do not need to distinguish between whether the event is generated by browser navigation vs. dom interaction. I'd probably remend changing your approach.

I'd also point you to the fact that history can be supported across all browsers (even IE6 and IE7 using an iFrame hack). Take a look at the jQuery history plugin

The reference library to achieve this: http://benalman./projects/jquery-bbq-plugin/

I used it and it works great

Think about putting "!" after "#" in the url, so that google can discover the ajax pages http://code.google./web/ajaxcrawling/docs/getting-started.html

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745618625a4636386.html

相关推荐

  • javascript - Onhashchange with browser buttons only - Stack Overflow

    I've got this issue (I'm using jQuery but I'm not restricted to it):I'm using a bo

    11小时前
    40

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信