1

I'm using the jQuery Address library to re-write my URL depending on what the user is doing in the page. The intention is to allow users to bookmark pages and come back later. The page never refreshes as all server interaction is done via ajax.

jQuery Address is writing URLs like this:

http://localhost:9000/#/u/scott_tiger

I need a to set up a route in Play to be able to route that request through to the appropriate controller. So I set this up:

GET     /#/u/{username}                Controller.showUser

This doesn't work though, the route definition gets ignored. I've tried loads of things such as trying to escape the "#" and replacing it with a variable that I've populated with Character.toString(35). None of this works.

Does anyone know how I can either define the route properly or get jQuery Address not to write the "#".

EDIT: The "#" doesn't get sent to the server does it. Doh! OK, question is revised.

Matt Biggin
  • 85
  • 1
  • 10

2 Answers2

9

No. The # and the part of the URL after that is not sent to the server. So your play app on the server will never see such URLs.

HTML5 solution

You need to handle these URLs on the client side using JavaScript. In modern browsers with good HTML5 support, you can modify the address without reloading the page. See Manipulating the browser history on how to do it for these browsers. And see When can I use... for browser support.

#-URLs

On Internet Explorer and older versions of other browsers you need to use # URLs and use JavaScript to load the state (e.g. get the user page /u/scott_tiger in your example). See How to run a JavaScript function when the user is visiting an hash link (#something) using JQuery? for how to do this in JavaScript. Also if a user bookmarks a page with a #-URL you need to reload the state.

See also: What's the shebang/hashbang (#!) in Facebook and new Twitter URLs for?

JavaScript libraries

You may use JavaScript libraries to handle this for you history.js is an example. Also bigger frameworks like Backbone.js handle this.


Does anyone know how I can get jQuery Address not to write the "#".

If you don't write the #-part of the URL, the state can not be linked. So you can not get back to e.g. Scott Tigers profile page if you bookmark the page, because the URL is only http://localhost:9000/ and you will arrive on the front page, while the user though he would arrive on the profile page.

Community
  • 1
  • 1
Jonas
  • 121,568
  • 97
  • 310
  • 388
  • You're perfectly correct. Thanks. Any idea how do I dynamically re-write the URL without refreshing the page? – Matt Biggin Dec 09 '11 at 15:46
  • Just remove the #/ from jQuery Address' rewriting logic and you should be able to use the routes just fine. – Shawn Steward Dec 09 '11 at 15:48
  • Not sure how to stop the jQuery Address plugin from including the "#". I'll investigate. Thanks. – Matt Biggin Dec 09 '11 at 15:49
  • @Jonas: I think I'm being dim today (it's been a long week and I need coffee), I don't see the relevance. The basic requirement here is that when the user clicks a link on the page I want to change the URL. Then if they bookmark that link I want Play to route the request to a controller that will reload that page. The jQuery Address plugin looked like a good fit to re-write the URL but from what I can tell it can only write URLs with "#" in. – Matt Biggin Dec 09 '11 at 15:59
  • 1
    @MattBiggin: It's only in HTML5-ready browsers you can **change** the URL without reloading the page or using `#` (see the Mozilla article I linked to.) Browsers like Internet Explorer and older version of other browsers, you can use a `#` link, but when they visit such a link, you need to use javascript to reload that state (see my question I linked to). – Jonas Dec 09 '11 at 16:07
2

Armed with my new understanding of URLs (thanks @Jonas) I realised that I'd missed half of the story.

I'm using JQuery Address to change the URL depending on what you click in the application. This works great and on lots of browsers. What I was missing was using JQuery Address to watch for external address changes (bookmarks, history, back/forward) and respond accordingly. i.e. set the page up correctly by firing the appropriate Ajax calls and rendering that data appropriately.

Changing the address

$.address.title("new title describing application state");
$.address.parameter("q", "val1");
$.address.parameter("g", "val2");
$.address.update();

Restoring the state

$.address.externalChange(function(event) {
    var val1 = event.parameters["q"];
    var val2 = event.parameters["g"];
    // do something with those values
});
Matt Biggin
  • 85
  • 1
  • 10