posted on Monday, May 22, 2006 1:13 PM
by
jritmeijer
Workaround for bookmarking problem in Ajax based web sites
Anyone who has ever used rich
web 2.0, Ajax, internet applications such as
Google Maps or
Windows Live Local has probably noticed that there is no way to easily bookmark the page with the current location while maintaining the page's state. Sure you can click on the 'permalink' or 'link to this page' links and then bookmark it, but how intuitive is that?
The reason for this is quite technical, the URL on the top of the page only displays the state of the page when it was loaded from the server, not the changes you have made (scrolling, zooming, navigating) since it was loaded. The result is that when you bookmark the original address you are usually presented with a map of North America, which is usually quite a few miles away from the address of the cinema you are really after.
What most developers don't realise is that there is a perfectly viable workaround for this bookmarking problem as you are allowed by the most common browsers' security model to dynamically rewrite the hash (#) part of a URL without performing a postback to the server. You simply serialize your state in this hash using JavaScript and deserialize it when the page is loaded again from a bookmark.

I would love to take credit for this simple, yet elegant, workaround, but I am afraid the credit goes to
Mike Stenhouse, who has borrowed it from yet someone else.
I have placed a
very simple example online that illustrates the concept. The Ajax / DHTML state is very simple, but anyone with an ounce of imagination can see that the same thing could apply to longitude, latitude and zoom factor on a mapping site.
The relevant part of the code is:
4 <script language="javascript" type="text/javascript">
5 function serialize()
6 {
7 var hashState = escape(currentState);
8
9 location.hash = hashState;
10 }
11
12 function deSerialize()
13 {
14 var hashState = unescape(location.hash);
15
16
17 if(hashState == "")
18 {
19 currentState = "1";
20 }
21 else
22 {
23 // ** Get rid of the leading #
24 currentState = hashState.substr(1);
25 }
26 }
27
28 function renderState()
29 {
30 switch(currentState)
31 {
32 case "1":
33 document.all.ajaxState.innerHTML = "State 1";
34 break;
35 case "2":
36 document.all.ajaxState.innerHTML = "State 2";
37 break;
38 default:
39 document.all.ajaxState.innerHTML = "Unknown";
40 }
41 document.title = "Ajax bookmarking fix / workaround. State: " + currentState;
42 }
43
44 function changeState()
45 {
46 if(currentState == "1")
47 currentState = "2";
48 else
49 currentState = "1";
50
51 serialize();
52 renderState();
53 }
54
55 var currentState = "1";
56 script>
57 head>
58 <body onload="deSerialize();renderState();">
Naturally in the real world the serialization function would be a bit more complex depending on the amount of data that needs to be serialised in order to maintain state.