Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling hash with HTML5 History API

I am using the history.js plugin here: https://github.com/browserstate/history.js/ for handling HTML5 History in my application. And I want to handle both HTML5 and HTML4 versions (using the hash fallback).

You can see the demo here: http://dev.driz.co.uk/history45/


Question 1

How do I load the correct content based on the hash when a person visits a url with a hash in (hasn't clicked a link on the website) As the server won't understand what the code is and I don't want to have to double the request by checking if the hash exists and then calling the content via AJAX. So for example: http://dev.driz.co.uk/history45/#about.php doesn't load in the about.php content.

Update:

I've seen some examples here: https://gist.github.com/balupton/858093 which seem to cover loading the correct content (even optimised versions). But I'm struggling to get it to work in combination with my HTML5 version. View source: http://dev.driz.co.uk/history45/ AND it only runs when a person clicks a link instead of on page load which is the original issue.

Update 2:

Tried an example here: http://dev.driz.co.uk/history4/#/contact.php to get the content to load in contact.php content using the snippet in the source but doesn't work...? BUT according to the article here: https://github.com/browserstate/history.js/wiki/Intelligent-State-Handling#wiki-why-the-hashbang-is-unnecessary this code SHOULD be AJAX loading in the correct content if it has a hash on it. Any ideas why?


Question 2

How do I force the /#/ on the root and prefix all urls with `#/'

As currently if you try and visit a page via a link in a HTML4 browser, you end up with weird urls like:

http://dev.driz.co.uk/history45/#contact.php and http://dev.driz.co.uk/history45/#./

instead of:

http://dev.driz.co.uk/history45/#/contact.php and http://dev.driz.co.uk/history45/#/


And if I start on an inner page with:

http://dev.driz.co.uk/history45/contact.php and choose a link then I end up with: http://dev.driz.co.uk/history45/contact.php#about.php when what it should be is: http://dev.driz.co.uk/history45/#/about.php

like image 686
Cameron Avatar asked Feb 11 '14 23:02

Cameron


2 Answers

How do I load the correct content based on the hash when a person visits a url with a hash in (hasn't clicked a link on the website) As the server won't understand what the code is

The server won't see the # or anything after it

and I don't want to have to double the request by checking if the hash exists and then calling the content via AJAX.

Your only other option is to redirect (by setting location with JavaScript) to the URL that you would have used if the history API was available.

How do I force the /#/ on the root?

You'd have to redirect to the homepage (again by setting location) if the history API isn't supported.


I take the view that if they are using a browser which doesn't support the history API (which probably means Windows XP and IE 8 these days) then they can get the non-Ajax fallbacks and I never have to deal with the hash hack.

like image 57
Quentin Avatar answered Oct 21 '22 22:10

Quentin


If all you want to do is to force all browsers (both HTML4/5) to use hashes, you'd use change the History.js Options within your init

History.options.html4Mode = true 

However, you may also want to consider using the $.address functionality from jQuery which can append any new URL you want with a hash.

Also within the $.address method, you could also determine where to redirect the user based on their init URL if they were accessing the site for the first time: Say, have a user access a URL with say http://www.site.com/#/about.php

you could then have a function which listens to any changes to any changes based on the URL changes

$.address.change(fn)

REF: http://www.asual.com/jquery/address/docs/

UPDATE

One thing I've discovered that may apply here is that if you have a click event handler which behaves by pushing a new state, even if you are currently on that same page, History js will append the same url to the end of the existing URL with a hash

e.g. If on About Page (and your state is "about") and you click the about link - your URL will change from http://www.site.com/about
to
http://www.site.com/about#/about

To save yourself the hassle, have an if statement on that button that checks your History State for "about" and if not, pushState "About"

e.g.

$('.about.btn').on('click', function(e){
  if(History.getState().data.State != "About") {
    e.preventDefault();
    History.pushState({"State": "About"}, null, "/about"); 
  }
})
like image 38
Denis Tsoi Avatar answered Oct 21 '22 23:10

Denis Tsoi