31

I have a Ajax heavy application that may have a URL such as

http://example.com/myApp/#page=1

When a user manipulates the site, the address bar can change to something like

http://example.com/myApp/#page=5

without reloading the page.

My problem is the following sequence:

  1. A user bookmarks the first URL.
  2. The user manipulates the application such that the second URL is the current state.
  3. The user clicks on the bookmark created in step 1.
  4. The URL in the address bar changes from http://example.com/myApp/#page=5 to http://example.com/myApp/#page=1, but I don't know of a way to detect the change happened.

If I detect a change some JavaScript would act on it.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
JoshNaro
  • 2,047
  • 2
  • 20
  • 40
  • I'm curious, why was the app designed like this? I can't see any actual need for the URL change. – Vinko Vrsalovic Dec 18 '09 at 22:07
  • It works just like a query string, but doesn't cause the browser to reload the page. This is was done, so that the payload of the client doesn't have to be retrieved and loaded every time a page is changed. The payload is not easily cached, demands a substantial JavaScript initialization time, and would not provide the client with a seemless experience. – JoshNaro Dec 21 '09 at 15:06

4 Answers4

42

HTML5 introduces a hashchange event which allows you to register for notifications of url hash changes without polling for them with a timer.

It it supported by all major browsers (Firefox 3.6, IE8, Chrome, other Webkit-based browsers), but I'd still highly suggest to use a library which handles the event for you - i.e. by using a timer in browsers not supporting the HTML5 event and using the event otherwise.

window.onhashchange = function() {
    alert("hashtag changed");
};

For further information on the event, see https://developer.mozilla.org/en/dom/window.onhashchange and http://msdn.microsoft.com/en-us/library/cc288209%28VS.85%29.aspx.

a55
  • 376
  • 3
  • 13
ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
19

check the current address periodically using setTimeout/interval:

 var oldLocation = location.href;
 setInterval(function() {
      if(location.href != oldLocation) {
           // do your action
           oldLocation = location.href
      }
  }, 1000); // check every second
Mottie
  • 84,355
  • 30
  • 126
  • 241
user187291
  • 53,363
  • 19
  • 95
  • 127
  • 1
    This answer is correct. You should also consider using something like the YUI History manager componentry, which does it for you, in a cross-browser way. – Jonathan Feinberg Dec 18 '09 at 22:12
  • If I type in a new address and press Enter there is no way the current page will be able to stop that. – ZippyV Dec 18 '09 at 22:20
  • 2
    Yeah, I was hoping there was a hidden event or something. Using an interval just doesn't seem "right" to me somehow. Thanks. – JoshNaro Dec 21 '09 at 15:02
  • Is such short time interval good for the app? That is, doesn't it keep the browser too busy in executing the function? – Hasib Mahmud Aug 11 '14 at 15:07
  • 1
    This is ugly, but apparently the only way: http://stackoverflow.com/questions/3522090/event-when-window-location-href-changes – user2398029 Nov 29 '14 at 00:48
  • your code is syntax wrong. Please update it. (do your action). – albanx Feb 29 '16 at 11:00
  • Can someone please explain to me how could this possibly ever work? When I change the address in the address bar, the browser fetches a new page, and the old page is destroyed, so this function never gets a chance to run. – Mike Nakis May 16 '17 at 16:09
  • 1
    @MikeNakis The premise of the question is that your scenario isn't occurring. The page is being changed in some dynamic way with the URL changing but without ever being torn down. – ojchase Mar 02 '21 at 08:59
6

You should extend the location object to expose an event that you can bind to.

ie:

window.location.prototype.changed = function(e){};

(function() //create a scope so 'location' is not global
{
    var location = window.location.href;
    setInterval(function()
    {
        if(location != window.location.href)
        {
            location = window.location.href;
            window.location.changed(location);
        }
    }, 1000);
})();

window.location.changed = function(e)
{
    console.log(e);//outputs http://newhref.com
    //this is fired when the window changes location
}
Skawful
  • 9,087
  • 4
  • 20
  • 19
  • 1
    Actually, as it uses a timer, it does not really bring any enhancement wrt what the selected solution does – jmd Feb 15 '13 at 12:01
  • 1
    It's not the best idea to extend a global object that already exposes a value you can watch. – Trendy Sep 22 '16 at 14:38
0

SWFaddress is an excellent library for these types of things.

moritzstefaner
  • 210
  • 1
  • 8