1

I have created a Javascript widget that allows user to embed a calendar on external websites. Right now i'm not handling browser back/forward button in any way, that means that if they click on an event, it is loaded through ajax, but then if they click "back" they are taken to the previous website.

I see two solutions for this
1) keep track of history in a javascript object and then try to detect "back" and "forward" clicks
2) keep track of current state in a url hash. ( like www.xxx.com/events#timely=my-fantastic-event )

Solution number 2 would allow also bookmarking of events, although i think it would be a still slow as it first would need to load the page and then load the event ( i mean first it load www.xxx.com/events and then it detects the hash and loads the event )

So real case scenario. I have my events on the website www.fantastic-events.com. I use the javcascript widgets to embed the calendar on www.event-listings.com/events. When the user clicks on the detail of an event, i could probably push the state i want ( www.event-listings.com/event/my-fantastic-event ) and use History.js to to catch the steate change and load the correct event but that would create an url which is not usable afterwards. I mean that if a user bookmarks www.event-listings.com/event/my-fantastic-event and visdits it later it won't work because my javascript widget would not be loaded.

Any suggestion/consideration?

Nicola Peluchetti
  • 76,206
  • 31
  • 145
  • 192
  • Page will NOT reload if you change only part of url after # sign. So my vote is for second option. You need to change hash part of url on every user click and implement onHashChange event handler to do action based on current hash. and back and forward button will work as usual. – Nebojsa Susic Oct 20 '14 at 22:13
  • look into hashchange events and browser history API. Can even get rid of hash by using base tag and history API to mimic virtual directories – charlietfl Oct 20 '14 at 22:19
  • 1
    Why are you talking about hash when there is the [History api](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history#Adding_and_modifying_history_entries)? – epascarello Oct 20 '14 at 22:20
  • @epascarello because i'm embedding content from www.aaaa.com on www.bbb.com. So if i use History pushState i would force a page reload that i can't handle – Nicola Peluchetti Oct 20 '14 at 22:22
  • To be clear i could probably push the state www.xxx.com/event/my-fantastic-event and make it work, but then it would make an url that would be invalid later on – Nicola Peluchetti Oct 20 '14 at 22:26
  • use example.com as a "dummy" url – epascarello Oct 20 '14 at 22:30
  • @epascarello i've written a more concrete test scenario – Nicola Peluchetti Oct 20 '14 at 22:35

1 Answers1

2

There are two main methods for achieving what you are after.
One of them, is the hash method you've mentioned. If you need to support older browsers (IE <= 9), that's the way to go. If you decide to use this method, your friend is the hashchange event. The hash pattern relies on this event in order to trigger functionality. In its most naive way it will look something like:

window.addEventListener('hashchange', function (e) {
    var hash = window.location.hash;
    if (hash === 'event-1') {
        // ...
    }
    else if (...) {
        // ...
    }
});

Your other option, is to use the History API, specifically - the pushState method, alongside the popstate event. It should be noted that the pushState method does not create an HTTP request. Also, if the user changes the current history entry (with the back/forward buttons), the browser will not reload, but instead, will trigger a popstate event, that you can listen to. If the user if navigating to a history entry that was not created using pushState or replaceState, the browser will load the resource as expected (you won't harm the user's experience - if she wants to get out of the website, she'll succeed).

Note that using the hashchange method might conflict with other libraries that use that method, and since most popular frameworks (ember, angular, etc..) use that method for browser compatibility reasons, it is kinda risky.

For your concern regarding the 'non existing page' problem - A possible solution is to use query params for your state, and not non-existing URLs:

window.history.pushState({ event: 'event-id' }, "Event Title", "?event=event-id");

You can then parse the query-parameters on page-load, and use their values in order to initialize your component in the desired state.

You can take a look at this nice MDN article for better reference.

Tudmotu
  • 845
  • 8
  • 11