3

So I'd like my page to load content if a window's hash has changed.

Using Mootools, this is pretty easy:

$extend(Element.NativeEvents, {
    hashchange: 1
});

and then:

window.addEvent('hashchange', function() {});

However, the hashchange event is firing when the page is being loaded, even though the specification require it not to fire until the page load is complete!

Unless I am loading the page for the first time, with no hash, then all works as expected.

I think the problem here is the fact that the browser considers the page load "complete", and then runs the rest of the JavaScript, which includes hash detection to load the requisite page.

For example, if I typed in http://foo.bar/, all would work fine. However, http://foo.bar/#test would, ideally, load the initial page, detect the hash, and load the "test" content.

Unfortunately, the browser loads the initial page, considers it "domready", and THEN loads the "test" content, which would then fire onHashChange. Oops?

This causes an infinite loop, unless I specifically ask the browser NOT to update the hash if an onHashChange event is firing. That's easy:

var noHashChange;
noHashChange = true;
var hashes = window.location.hash.substr(1).split("/"); // Deciphers the hash, in this case, hashes[0] is "test"
selectContent(hashes[0]); // Here, selectContent would read noHashChange, and wouldn't update the hash
noHashChange = false;

So now, updating the hash AFTER the page has loaded will work properly. Except it still goes nuts on an initial page load and fetches the content about 3 or 4 times, because it keeps detecting the hash has changed. Messy.

I think it may have something to do with how I am setting the hash, but I can't think of a better way to do so except:

window.location.hash = foobar;

... inside of a function that is run whenever new content is selected.

Therein lies the problem, yes? The page is loaded, THEN the content is loaded (if there is content)...

I hope I've been coherent...

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Julian H. Lam
  • 25,501
  • 13
  • 46
  • 73

3 Answers3

0

Perhaps you could check the hash first to eliminate the recursion:

 if(window.location.hash != foobar){ window.location.hash = foobar;}

Why is the onHashChange handler changing the hash anyways? If there's some default that it's selecting first before loading the content, then perhaps that could go in a seperate function.

(I say this because it looks like you've some sort of directory structure-esque convention to your location.hash'es, perhaps you're selecting a specific leaf of a tree when the root is selected or something?)

Tim Snowhite
  • 3,736
  • 2
  • 23
  • 27
  • 1
    As it turns out, I haven't been coherent much, since, reading over my question, I have no idea what I was trying to say. Cheers on the answer, it is indeed a directory structure. I'll check out your solution. – Julian H. Lam Aug 02 '10 at 06:10
  • Can you post your correct solution or select an answer as the correct one for this question? – Tim Snowhite Sep 20 '10 at 19:35
  • Hi Tim - we decided not to implement onHashChange "yet". But rest assured, this is on the back of my mind, and once we do get around to it, I'll let you know how we did it. Between then and now, we may have discovered a mootools function that handles this properly, so this may be moot. – Julian H. Lam Dec 29 '10 at 05:45
0

you could implement an observer for the hash object that will trigger a function when the has object has changed.it does nothing to do with the actual loading of the page. the best way to do this is via Object.prototype.watch
see other pages on same topic : On - window.location.hash - Change?

Community
  • 1
  • 1
gion_13
  • 41,171
  • 10
  • 96
  • 108
0

have a look at MooTools History it implements the onhashchange if the new html5 history api isn't available, no need to reinvent the wheel :)

Leon Radley
  • 7,596
  • 5
  • 35
  • 54