Keeping the Web in Web 2.0

Designing user interaction for web applications

CHI 2008, April 5-10, Florence, Italy

Copyright is held by the author/owner(s)
ACM 08/0004

The Plan

Part 1: Introduction, Examples, and Theory
  • Analysis of application state and its representation in browser history and bookmarks.
  • A conceptual framework for designing application state in Ajax applications.
Part 2: Practice
  • Illustration through examples.
  • Casual introduction to the Javascript programming language.
  • Equally casual introduction to DHTML: HTML Document Object Model (DOM) and event handling.

The Web Application Revolution, 1:
HTML, HTTP, URLs

Web pages replace the GUI of applications.
Advantages:
Disadvantages:

Emergent Advantages of Web Applications

Two more properties of Web Application UIs emerged as important:

The Web Application Revolution, 2:
Ajax

Ajax — Asynchronous Javascript And XML
...but not really:
Altogether, a powerful programming paradigm for web applications.

The Web Application Revolution, 2:
Ajax

Application maintains specific interaction state on the client side.
Advantages:
Disadvantages:

History versus Bookmarks, 1

Experiment:
  1. Load a page. »
  2. Scroll down.
  3. Go to another page. »
  4. Go back to the previous page.
Result:

History versus Bookmarks, 2

Experiment:
  1. Load a page. »
  2. Scroll down.
  3. Bookmark it.
  4. Load the bookmarked page.
Result:
Conclusion:

Clicking versus Scrolling, 1

Experiment:
  1. Load a page. »
  2. Scroll down.
  3. Go back.
Result:

Clicking versus Scrolling, 2

Experiment:
  1. Load a page with anchors. »
  2. Follow a link to an anchor on the same page. »
  3. Note that the URL has changed.
  4. Go back.
Result:
Conclusion:

Google Maps

Experiment:
  1. Load Google Maps. »
  2. Load a place, e.g. [Rome].
  3. Pan the map.
  4. Load another place, e.g. [Florence].
  5. Change the map type to [Terrain].
  6. Go back.
Result:
Conclusion:

Chatbox in Google Docs

Experiment:
  1. Go to Google Docs. »
  2. Open a spreadsheet.
  3. Open the [Discuss] pane.
  4. Leave the page. »
  5. Come back.
Result:

Inbox in Google Mail

Experiment:
  1. Load GMail. »
  2. View inbox, note last conversation on first page.
  3. Go to second page.
  4. From another window, send a message to yourself. »
  5. Go back to first page.
Result:

Summary of Observations

  1. Only some elements of interaction state are recorded in browser history.
  2. Only some elements are recorded in bookmarks.
  3. Only some state changes create history.
  4. When one element changes, it may reset other elements to their default values (it's said to dominate those).
  5. The default value of one element may depend on the value of another.
  6. External factors can change the application state.

Classes of Interaction State Elements, 1

Hard State
Soft State
Transient State
External state

Classes of Interaction State Elements, 2

History State versus Bookmarked State
Class Preserved in
History Navigation Bookmarks
Hard Yes Yes
Soft Yes Maybe
Transient Maybe No
External No No
Notes

Designing Application State

What we've learned — Part 1

Upcoming: A Toy Application

Simple »
Sophisticated »

The Plan

Part 1: Introduction, Examples, and Theory
  • Analysis of application state and its representation in browser history and bookmarks.
  • A conceptual framework for designing application state in Ajax applications.
Part 2: Practice
  • Illustration through examples.
  • Casual introduction to the Javascript programming language.
  • Equally casual introduction to DHTML: HTML Document Object Model (DOM) and event handling.

Recap: Classes of Interaction State Elements

Hard State
Soft State
Transient State
External state

About the Code Snippets

Notes:
What we will encounter in the snippets:

Code Abbreviations

state_base.js
// Fetch a pointer to a DOM element by id.
function $(id) {
  return document.getElementById(id);
}
state_iframe.js
// Fetch the query part of the page URL.
function urlQuery(window) {
  return window.location.search.substring(1);
}
state_base.js
function objectSetInterval(instance, method, interval) {
  window.setInterval(function() {
    method.apply(instance);
  }, interval);
}

About the DOM

Document Object Model (DOM): an object-oriented Application Programming Interface (API) for
User interaction is modeled by DOM Events:

A Toy Application

http://ajaxchi.googlepages.com/ »

A Toy Application: HTML

colortoy.html
<head>
  <script src="colortoy.js"></script>
  <script>
    var colorToy = new ColorToy;
  </script>
</head>
<body>
  <table><tr><td><div>
    <select onchange="colorToy.change(this)">
      <option value="white">white</option>
      ...
    </select>
  </div></td></tr></table>
</body>

A Toy Application: onchange handler

colortoy.js
ColorToy.prototype.change = function(select) {
  var color = select.options[select.selectedIndex].value;
  select.parentNode.style.backgroundColor = color;
  if (this.changeHandler_ && select.id) {
    this.changeHandler_(select.id, color);
  }
};

Statement of the Problem

Challenge:
Tasks:

Notes

Prerequisites
Implementation methods
Implementation considerations (not covered)

URL Fragment Identifier Method

What we abuse leverage:

URL Fragment Identifier Method

Principle
Consequences

Example

http://ajaxchi.googlepages.com/ »

Implementation Details

Record State Changes

state_hash.js
StateHash.prototype.record = function(name, value, hard) {
  var state = State.decode(location.hash.substring(1));
  state[name] = value;

  var stateUrl = State.encode(state);
  this.currentHash_ = "#" + stateUrl;

  if (hard) {
    location.href = this.currentHash_;
  } else {
    location.replace(this.currentHash_);
  }
}
This also creates a bookmark URL.

Record State Changes (IE6)

example_hash.js
StateHash.prototype.record = function(name, value, hard) {
  var state = State.decode(location.hash.substring(1));
  state[name] = value;

  var stateUrl = State.encode(state);
  this.currentHash_ = "#" + stateUrl;

  var a = document.createElement('A');
  a.style.position = 'absolute';
  a.style.top = getScrollTop(window) + 'px';
  a.name = stateUrl;

  document.body.appendChild(a);
  if (hard) {
    location.href = this.currentHash_;
  } else {
    location.replace(this.currentHash_);
  }
  document.body.removeChild(a);
}

Encode State in URL Parameters

state_base.js
State.encode = function(state) {
  var params = [];
  for (var i in state) {
    if (state.hasOwnProperty(i)) {
      var value = state[i];
      if (value != null) {
        params.push(encodeURIComponent(name) + "=" +
                    encodeURIComponent(value));
      }
    }
  }
  return params.join("&");
};

Decode State From URL Parameters

state_base.js
State.decode = function(encoded) {
  var params = encoded.split("&");
  var state = {};
  for (var i = 0; i < params.length; i++) {
    var nameValue = params[i].split("=");
    if (nameValue[0]) {
      state[decodeURIComponent(nameValue[0])] =
          decodeURIComponent(nameValue[1]);
    }
  }
  return state;
};

Restore State from Browser History

state_hash.js
StateHash.prototype.detectHistoryNavigation_ = function(load) {
  objectSetInterval(this, function() {
    if (location.hash != this.currentHash_) {
      this.currentHash_ = location.hash;
      var state = State.decode(this.currentHash_);
      load(state);
    }
  }, 50);
};
This also restores application state from URL.

Hidden Iframe Method

What we abuse leverage:

Hidden Iframe Method

Principle
Consequences

Example

http://ajaxchi.googlepages.com/ »

Implementation Details

For more, see the additional slides.

What we've learned — Part 2

Page Reload

Updating External State

In our demo, we just store the external state in the browser cookie, so that it will be available in all windows of the same browser. But it isn't really external.

More design problems