4

I'm trying to implement some navigation resistance when a user tries to navigate away from a certain view in our single page app. Basically I want to call something along the lines of a confirm(msg) before the hash changes. I want it to behave similarly to onbeforeunload.

I found this question and tried out the suggested answer: How can i execute code before hashchange

The problem with the one (unaccepted) answer to the above question is that it's using $(window).on('hashchange',...), then when the hash changes it does a confirm when you're already on the new view and tries to navigate you back to the previous page. This is not good UX, and on top of that if you have forms or a save in progress on that page, you lose all the state info from before you navigated away.

I tried changing his answer to use $(window).before('hashchange',...) but all that did was blow up in my face with a bizarre, seemingly unrelated error (see error text below). I haven't seen anything anywhere on how to intercept a hashchange event before the hash actually changes. Anybody have any suggestions?


Error message text: Uncaught TypeError: Cannot read property 'createDocumentFragment' of undefined

Edit Ok so apparently I'm attempting to misuse .before so disregard that part. I still need to intercept the hashchange event before it acts on the page

Community
  • 1
  • 1
StormeHawke
  • 5,987
  • 5
  • 45
  • 73
  • 3
    `.before()` is for inserting a new HTML element before another HTML element, it has nothing to do with event handling. – Barmar Aug 19 '15 at 20:32
  • That would explain the explosion. Do you know how to solve problem presented? – StormeHawke Aug 19 '15 at 20:33
  • How are they navigating away? – Barmar Aug 19 '15 at 20:33
  • Is this helpful: http://stackoverflow.com/questions/8208627/how-to-capture-browsers-back-forward-button-click-event-or-hash-change-event-in?lq=1 – Barmar Aug 19 '15 at 20:33
  • By navigating to other parts of the app, whether by using back/forward or clicking a link to go to another view – StormeHawke Aug 19 '15 at 20:37
  • As mentioned in the question I linked to, you can use the History API to catch uses of the back/forward button. – Barmar Aug 19 '15 at 20:41
  • If they click on links, you can use a click event listener to capture the click and do whatever you want. – Barmar Aug 19 '15 at 20:41
  • But then don't I need to bind said click event listener to every link visible on the page? That doesn't seem like a viable option – StormeHawke Aug 19 '15 at 20:42
  • It's easy in jQuery: `$("a").click(function() { ... })`. – Barmar Aug 19 '15 at 20:43
  • And if you only want to do it on certain links, give them a class and use `$("a.className").click(...)`. – Barmar Aug 19 '15 at 20:44
  • I would recommend using a decent SPA library like AngularJS. I'm not familiar with any others, but I know that Angular provides ways to handle that sort of thing with an "on view change"-like event. If you want to get serious about building SPAs, you'll definitely want to check it (or another popular one) out. It will make your life much easier in the long run if you take the time to learn it. – Andy Aug 19 '15 at 20:46
  • We're using knockout and a variety of other libraries to accomplish the same thing as angular. Don't ask me why – StormeHawke Aug 19 '15 at 20:47
  • Hey, that's fair. Whatever works for you. I'm surprised that the feature you're after isn't built into knockoutjs, however. – Andy Aug 19 '15 at 20:53
  • If it is I haven't found it – StormeHawke Aug 19 '15 at 20:54
  • Didn't go crazy reading it myself, but maybe this will help? http://stackoverflow.com/questions/10081671/how-do-you-observe-javascript-hashtables-in-knockout -- sorry, just realized that was for hash**tables**, not just `window.location.hash`. But in concept it might be similar to what you're trying to do... just make `window.location.hash` observable? – Andy Aug 19 '15 at 20:54
  • An observable is an object which contains a value, and which notifies subscribers whenever that value changes. It doesn't watch another variable for changes. – StormeHawke Aug 19 '15 at 21:03
  • What library are you using for your routing? (I'm not familiar with knockout, but doesn't look like it has a router?) Most routers should be able to provide a way to hook in to the routing flow. – Lee Aug 19 '15 at 22:49
  • You might be able to put together a hacky solution, by binding a listener to the hashchange event *before* your router's listener. Then you can optionally stop the event propagating. – Lee Aug 19 '15 at 23:10

0 Answers0