<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The True Tribe &#187; Search Results  &#187;  saving state</title>
	<atom:link href="http://www.thetruetribe.com/?s=saving+state&#038;feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.thetruetribe.com</link>
	<description>Vroom! That&#039;s us leaving IE in the dust.</description>
	<lastBuildDate>Fri, 22 Jan 2010 23:34:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Saving State: What To Do When Users Leave</title>
		<link>http://www.thetruetribe.com/2008/06/saving-state-what-to-do-when-users-leave/</link>
		<comments>http://www.thetruetribe.com/2008/06/saving-state-what-to-do-when-users-leave/#comments</comments>
		<pubDate>Fri, 13 Jun 2008 06:10:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[JSON]]></category>

		<guid isPermaLink="false">http://wordpress.thetruetribe.com/?p=41</guid>
		<description><![CDATA[In this era of rich JavaScript applications, so much
focus is given to the features of the application that one
crucial element is often overlooked: What happens when the
user leaves the page? We take it for granted that pages
will look the same when we leave and return, but a new
question merges for sites using rich JavaScript
interaction: If [...]]]></description>
			<content:encoded><![CDATA[<p>In this era of rich JavaScript applications, so much<br />
focus is given to the features of the application that one<br />
crucial element is often overlooked: What happens when the<br />
user leaves the page? We take it for granted that pages<br />
will look the same when we leave and return, but a new<br />
question merges for sites using rich JavaScript<br />
interaction: If the user leaves and returns to the page,<br />
will the application state be preserved?<span id="more-41"></span></p>
<p>The effects of losing application state can range from<br />
minor annoyances like losing what page you&#8217;re on, to<br />
all-out frustration after losing a carefully-typed message<br />
because you accidentally triggered the browser&#8217;s back<br />
button. (It&#8217;s easier than you think&#8211; hitting backspace<br />
when the document is in focus triggers the back button in<br />
most browsers). Couple this with the fact that some users<br />
may expect pages to save form data, because of their prior<br />
experience to that effect, and it becomes apparent that a<br />
robust strategy for preserving application state must be<br />
devised.</p>
<p>Browsers automatically save data entered into form<br />
fields, but all JavaScript variables are lost when the user<br />
leaves the page. Furthermore, any form fields that were<br />
created by JavaScript will also be lost. So, for all but<br />
the most simple applications, JavaScript must have a<br />
strategy for saving state that deals with these<br />
limitations.</p>
<p>Some sites like <a href="&lt;br"></a> &#8220;http://www.thesixtyone.com&#8221;&gt;<em>thesixtyone.com</em><br />
reside entirely on a single page and capture users&#8217; back<br />
button clicks with named anchors. But, try writing a wall<br />
post on Facebook and you&#8217;ll find that it does not save the<br />
post if you leave the page. Accidentally pressing backspace<br />
is all too easy in cases like this where typing is<br />
involved, which is why sites like Gmail and Blogger warn<br />
users that they will lose data before leaving the page.</p>
<h3>How To Warn Users Before Leaving the Page</h3>
<p>One way you can do this is by assigning a confirmation<br />
message to the return value of the<br />
<em>window.onbeforeunload</em> event handler. The user will<br />
be presented with two choices, <em>OK</em> and<br />
<em>Cancel</em>, along with a custom message of your<br />
choosing.</p>
<p>In the following example, we regsiter an anonymous<br />
function as the event handler for<br />
<em>window.onbeforeunload</em>, and add our own custom<br />
message:</p>
<h5>Using <em>window.onbeforeunload</em> to confirm if a<br />
user wants to leave the page (<a href="&lt;br"></a> &#8220;/examples/saving-state/example-1.html&#8221;&gt;example 1)</h5>
<pre class="js:nocontrols">window.onbeforeunload = function() {
  return "You will lose any unsaved information.";
};</pre>
<p>The browser displays your custom message, given in the<br />
return statement of the <em>onbeforeunload</em> event<br />
handler, along with the browser default message. In<br />
Firefox, the result is:</p>
<blockquote><p>Are you sure you want to navigate away from this<br />
page?<br />
You will lose any unsaved information.<br />
Press OK to continue, or Cancel to stay on the current<br />
page.</p></blockquote>
<h3>Retaining Data When Users Do Leave the Page</h3>
<p>You may opt to silently save the user&#8217;s data when they<br />
leave the page. This may give a better user experience<br />
since they are not confronted with a choice, and their data<br />
is saved automatically.</p>
<p>This is one of the times where Ajax comes in handy.<br />
However, there are also other ways to do this without using<br />
Ajax, such as cleverly storing information in named anchors<br />
or hidden form fields. We&#8217;ll examine each of these<br />
practices in more depth, but suffice it to say that the<br />
hidden form fields approach works better for conventional<br />
websites that are spread across many pages, whereas storing<br />
data in named anchors is better for single-page, pure<br />
JavaScript applications.</p>
<p>It turns out that while you could (and should) save<br />
state to the server using Ajax, for some cases you will<br />
want to avoid Ajax altogether and use a simpler,<br />
clientside-only model.</p>
<h3>Using Hidden Form Fields to Save State</h3>
<p>As mentioned, all JavaScript objects are lost when the<br />
user leaves or refreshes the page. But, browsers will<br />
retain data in form fields, provided that the form elements<br />
were not generated using JavaScript. Given this limitation,<br />
it is necessary to save JavaScript variables (or the<br />
serialized JSON strings of such objects) to hidden form<br />
fields if they need to be retained.</p>
<p>Here is a basic example showing how variables can be<br />
stored to hidden form fields and restored on page load:</p>
<pre class="html:nocontrols">
<input id="saved-data" type="hidden" /></pre>
<h5>Saving data in hidden form fields (<a href="&lt;br"></a> &#8220;/examples/saving-state/example-2.html&#8221;&gt;example 2)</h5>
<pre class="js:nocontrols">// The variable userData is some necessary information we need from the user.
// The first time the user visits the page, they must enter this data manually.
// But, when leaving and returning to the page (or refreshing the page), we'll check
// if they already entered the data, and if so, restore it from a hidden form field.

var userData;

// Register event handlers
window.onload = function() {
 restoreState();
 if (!userData) {
    userData = prompt('Please enter the data to save', 'test');
 }
 document.write("userData: " + userData);
}

window.onbeforeunload = saveState;

// This function is called onbeforeunload and writes the userData to the hidden form field
function saveState() {
   document.getElementById('saved-data').value = userData;
}

// This function is called onload and checks if any data is present in the hidden form field
// If so, it defines userData to be the saved data
function restoreState() {
   var savedData = document.getElementById('saved-data').value;
   if (savedData != "") {
        userData = savedData;
   }
}</pre>
<p>In the above example, all we&#8217;re saving is one string<br />
from the user. But what about cases where we need to save<br />
many different values? For instance, what if we&#8217;re using<br />
object-oriented code and have numerous nested objects<br />
within objects we need to store? At times like this,<br />
<strong>serializing objects with JSON</strong> is the<br />
easiest way to store the data. Without using JSON, you&#8217;d<br />
have to create a hidden form field for each value you want<br />
to save, whereas JSON can create string representations of<br />
complex data structures that you can easily <em>eval</em><br />
back into JavaScript objects once they&#8217;re fetched from the<br />
DOM.</p>
<h3>So What is JSON, Anyway?</h3>
<p>JSON (pronounced &#8220;Jason&#8221;), short for <em>JavaScript<br />
Object Notation</em> is a lightweight, human- and<br />
machine-readable way to represent the string serializations<br />
of objects. These strings can be evaluated back into<br />
JavaScript objects as needed. For instance, say I create a<br />
JavaScript object to represent a person (in this case,<br />
me):</p>
<pre class="js:nocontrols">var person = new Object();
person.name = "Jonah";
person.age = 24;
person.gender = "male";
person.location = "Seattle, WA";</pre>
<p>The JSON representation of this object is as<br />
follows:</p>
<pre class="js:nocontrols">{
    'person': {
        'name': 'Jonah',
        'age': 24,
        'gender': 'male',
        'location': 'Seattle, WA'
    }
}</pre>
<p>Then, if you need to reconstruct the object at a later<br />
point, you can simply eval the JSON string:</p>
<pre class="js:nocontrols">var jsonString = "{'person': {'name': 'Jonah', 'age': 24, 'gender': 'male', 'location': 'Seattle, WA'}}";
var person = eval( '(' + jsonString + ')' );    

console.assert(person.name == 'Jonah');
console.assert(person.age == 24);
console.assert(person.gender == 'male');
console.assert(person.location == 'Seattle, WA');</pre>
<p>If you&#8217;ve written JavaScript using object literal syntax<br />
before, this should be familiar to you. The only minor<br />
difference between JSON and the standard JavaScript object<br />
literal syntax is that JSON requires quotes around key in a<br />
key/value pair. So, <em>name</em> is a valid JavaScript key<br />
but in JSON it would have to be <em>&#8216;name&#8217;</em>. (Note: It<br />
doesn&#8217;t matter if you use single- or double-quotes, as long<br />
as they are matched).</p>
<h3>Stringifying Objects in JSON</h3>
<p>To use JSON, it&#8217;s necessary to include a library of JSON<br />
methods. Don&#8217;t worry, the library is quite small. The<br />
entire thing shouldn&#8217;t be more than 2k and can be obtained<br />
from <a href="http://www.json.org/js.html">json.org</a>.<br />
Eventually, the JSON methods will be included as part of<br />
the core JavaScript language, but for the time being, we&#8217;re<br />
left to use the methods provided by json.org or those found<br />
in libraries such as MooTools, Prototype and jQuery.</p>
<p>Depending on the library used, the method names for<br />
serializing an object into a JSON string are different.<br />
But, they are all used in rather similar fashion. For now,<br />
we&#8217;ll assume you&#8217;re using the library from <a href="&lt;br"></a> &#8220;http://www.json.org/js.html&#8221;&gt;json.org and use the<br />
method names provided in its API.</p>
<h5>Saving complex JavaScript data structures as JSON<br />
strings (<a href="/examples/saving-state/example-3.html">example 3</a>)</h5>
<pre class="js">// The variable userData is some necessary information we need from the user.
// The first time the user visits the page, they must enter this data manually.
// But, when leaving and returning to the page (or refreshing the page), we'll check
// if they already entered the data, and if so, restore it from a hidden form field.

var userData;

// Register event handlers
window.onload = function() {
 restoreState();
 if (!userData) {
    userData = new Object();
    userData.name = prompt('Please enter a name', 'Jonah');
    userData.age = parseInt(prompt('Please enter an age', '24'));
    userData.gender = prompt('Please enter a gender', 'male');
    userData.location = prompt('Please enter a location', 'Seattle, WA');
 }
 displayData(userData);
}

window.onbeforeunload = saveState;

// This function is called onbeforeunload and writes the userData to the hidden form field
function saveState() {
   document.getElementById('saved-data').value = JSON.stringify(userData);
}

// This function is called onload and checks if any data is present in the hidden form field
// If so, it defines userData to be the saved data
function restoreState() {
   var savedData = document.getElementById('saved-data').value;
   if (savedData != "") {
        userData = eval( '(' + savedData + ')' );
   }
}

// This is a helper function that iterates through each property in an object and renders it in HTML.
function displayData(obj) {
 var list = document.createElement('ul');
 for (var property in obj) {
    var text = document.createTextNode(property + ': ' + obj[property])
     var line = document.createElement('li');
     line.appendChild(text);
     list.appendChild(line);
 }
 document.getElementsByTagName('body')[0].appendChild(list);
}</pre>
<p>This example is pretty similar to the previous one where<br />
we saved a string. The only difference is that in this<br />
case, the string is a representation of a complex<br />
JavaScript object. In fact, you can save the entire state<br />
of your application in one JSON string, as long as the<br />
application state is completely stored as properties of a<br />
single object. There are a few minor gotchas, such as<br />
having to add parentheses around the JSON string when<br />
evaluating it. But, overall this is a clean and<br />
straightforward approach that is very useful when complex<br />
data structures must be retained.</p>
<h3>Using Named Anchors to Save State</h3>
<p>An alternate option for retaining state is to not<br />
actually let the user leave the page at all. Rather, when<br />
following links on the site, update the named anchor<br />
(everything after the number sign in a URL), instead of<br />
changing the actual document being displayed.</p>
<p>The problem that this is trying to solve is the fact<br />
that Ajax applications will normally break the back button.<br />
A user loads the application on the homepage and clicks to<br />
visit a different page, but since the new page is loaded in<br />
via Ajax, the browser URL doesn&#8217;t change. Then the user<br />
clicks the back button and leaves the application<br />
altogether&#8211; not the intention of the user, who just wanted<br />
to get back to the homepage.</p>
<p>Storing data in named anchors offers a solution to this<br />
problem. Each time the application state changes,<br />
JavaScript updates the named anchor with a token<br />
representing the application state. When the page is<br />
loaded, data is read from the named anchors and the state<br />
can be restored.</p>
<p>Say you&#8217;re on the homepage of an ecommerce Ajax<br />
application and click on a product you&#8217;d like to view.<br />
Instead of changing URLs to the detail page, the<br />
application loads in new data with Ajax. So, when a user<br />
clicks on the new Brad Mehldau CD for instance, instead of<br />
going to a different URL (yoursite.com/brad-mehldau/) the<br />
document URL remains the same, but JavaScript updates the<br />
named anchor: yoursite.com/#brad-mehldau.</p>
<p>One site which does this unbelievably well is <a href="&lt;br"></a> &#8220;http://www.thesixtyone.com&#8221;&gt;<em>thesixtyone.com</em><br />
(Thanks, Derek!). The entire site resides in one document,<br />
truly a rich JavaScript application if I&#8217;ve ever seen one.<br />
But, despite the fact that the entire application is<br />
contained in a single document URL, due to clever use of<br />
named anchors, the site has full back button support and<br />
you can even email working links to friends.</p>
<p>Implementing code to save state in named anchors is out<br />
of scope for this article, but you can see how it is<br />
somewhat similar to saving data in hidden form fields. In<br />
this case, there are a few more issues to mitigate and it&#8217;s<br />
somewhat tricky, but the reward is an Ajax site with fully<br />
functional back button support and the ability to share<br />
links &#8212; worth all the effort, in my book.</p>
<h3>So What Use is Ajax, Then?</h3>
<p>Since we&#8217;ve made it this far, you might think that there<br />
is no use for Ajax in all this. Actually, Ajax is great for<br />
saving state to the server, especially for saving data<br />
beyond the lifespan of the browser session. Ajax can be<br />
used to save messages periodically (like how Gmail and<br />
Google Docs automatically save on a timer every few<br />
minutes). It can also be used to send data when the user<br />
leaves the page by capturing the <em>onbeforeunload</em><br />
event, but this is unreliable and I would not depend on<br />
this Ajax request to complete. Instead, try to save the<br />
data before the user attempts to leave the page, by either<br />
firing the Ajax request on a timer or another event on the<br />
page (leaving focus on a form element, for example).</p>
<p>Some frameworks like Prototype have serialize() methods<br />
that return URL query string representations of objects.<br />
This is perfect for saving data through GET requests. Yes,<br />
GET requests have a 2000-character limit and other<br />
limitations, but in most cases this won&#8217;t be an issue. Even<br />
without helper methods to serialize objects, it&#8217;s a fairly<br />
simple matter to construct an Ajax request that will save<br />
the necessary data to the server.</p>
<h3>Wrapping Up</h3>
<p>To re-cap, it is a good practice to check if users are<br />
sure they want to leave a page when they are entering<br />
information, but it&#8217;s even better to silently save that<br />
information for them. (Arguably you would want to do both,<br />
like how Gmail and Blogger save state <em>and</em> ask<br />
users if they are sure they want to leave the page). There<br />
are many different ways to save state, some purely<br />
client-side and others relying on saving data to the server<br />
with Ajax. The solutions which save data to the server are<br />
suitable for times when the data needs to be saved beyond<br />
the browsing session.</p>
<p>Of the two client-side solutions explored, hidden form<br />
fields and named anchors, the former is more suitable for<br />
conventional websites spanning many pages while the latter<br />
better suits single-page Ajax applications. Using named<br />
anchors also has the added benefit of allowing users to<br />
bookmark and send links to the JavaScript application in<br />
various states, and the state is preserved beyond the<br />
browsing session.</p>
<p>Whatever strategy you follow, your users will thank you<br />
for the time saved and frustration avoided of having to<br />
re-enter lost information.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.thetruetribe.com%2F2008%2F06%2Fsaving-state-what-to-do-when-users-leave%2F&amp;linkname=Saving%20State%3A%20What%20To%20Do%20When%20Users%20Leave"><img src="http://www.thetruetribe.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>]]></content:encoded>
			<wfw:commentRss>http://www.thetruetribe.com/2008/06/saving-state-what-to-do-when-users-leave/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
