Bookmark with del.icio.us submit HTML5%20History%20is%20the%20Future digg.com reddit

HTML5 History is the Future

interface History {
  ...
  void pushState(in any data, in DOMString title, in optional DOMString url);
  void replaceState(in any data, in DOMString title, in optional DOMString url);
};
interface HTMLBodyElement : HTMLElement {
  ...
  attribute Function onpopstate;
};

The new interface provides push/pop semantics that, until now, we've emulated using JavaScript libraries like Really Simple History.

Web Apps and History

Web applications need to interact with the browser history to support bookmarkable and "back-buttonable" states. This is a pretty common feature of Ajaxy applications. For example, visit http://www.viewru.com/#Bonobo and browse or search for your favorite musician. The application uses an Ajaxy, single-window-context model to keep the music playing while you browse, but supports bookmarks and the back-button because users expect these features to work in their browser.

Prior to the HTML5 History additions, a solution to this problem involved these two parts:

// Store a representation of the state in the location hash
function setState(state) {
  window.location.hash = state;
}
// Detect a change to location.hash
var lastState;
window.setTimeout(function() {
  var state = window.location.hash;
  if (lastState != state) {
    lastState = state;
    handleState(state);
  }
}, 100);

The solution is less than ideal for several reasons:

Sluggishness
  • Executing a timeout function every 100ms won't make your app any faster.
  • 100ms delay in responding to back button actions.

Browser compatibility
  • The solution above doesn't work, for example, in IE 6-7, which won't add a history event on a hash change. Really Simple History gets around this by adding an iframe and issuing a call to your server for every state change. Webkit browsers present different challenges.

Not a stack
  • Suppose your application transitions from A->B->C. Can it transition directly back to A?

The HTML5 version looks like this:

// Push the state onto the history stack
function setState(state) {
  window.history.pushState(state, '');
}
// Respond to a popstate event.
window.onpopstate = function(e) {
  handleState(e.state);
};

Here, state may be a string representation of the current application state, but it can also be an object. Note that it will be deep-copied on each pushState() operation.

Storing application state in the hash is a hack

You may point out that the new hashchange event in HTML5 addresses concerns about sluggishness, but why use location.hash at all? Storing application state in the location hash presents some real problems and limitations. Here's a short list:

  • Content isn't crawlable: Most crawlers do not execute JavaScript or traverse dynamic fragment ids. If you want users to find your site and content via Search Engines, this just won't do.
  • Audible "click" in IE: For some reason, IE makes a sound every time you update the location. Imagine if your application updated the location on every mousemove event!
  • HTTP-Referer is inaccurate or missing data: The fragment ID isn't exposed in the referrer.
  • Handling bookmarks requires extra round trip:
    • Fetch myApp.html
    • Parse myApp.html#myState (server can't see myState)
    • Fetch myState
  • Legacy (and non-JS) browsers effectively have different URI schemes and can't share bookmarks and links.

HTML5 History and URLs

Perhaps the most interesting feature of the new pushState() and replaceState() interfaces is the optional url argument. For the first time, web developers are able to change the effective URL to represent a change in application state without navigating away from a window context. It's very powerful. The location bar, bookmark service, and HTTP-Referer all reflect the new URL. This feature addresses many of the issues I mentioned above:

  • Content is crawlable: A developer may express all crawlable states of their application as valid URLs.
  • HTTP-Referer is meaningful: The referrer can reflect the latest state of the application and show or hide any information to/from 3rd parties, at the developer's discretion.
  • Bookmarks can be handled in a single fetch: Since application state can be expressed in a URL, it's possible to service a request for the application and state in one request/response.
  • Can use a single URI scheme to cover new and old browsers: Since information is encoded in URLs instead of the location hash, modern and legacy users can share bookmarks and links.
  • Audible "click" in IE? Okay, I don't know about this one, but it makes sense that programmatic operations on window.history would not have an audible side effect, right?

Availability and further reading

You can take these new features for a spin in Firefox nightlies. For more info, see:

Bookmark with del.icio.us submit A%20Quick%20svg2vml%20Example%3A%20Gradients digg.com reddit

A Quick svg2vml Example: Gradients

A couple weeks ago I mentioned the first release of svg2vml, a lightweight library that enables cross platform, JavaScript-driven vector graphics. Here's a quick example where I use svg2vml to create Digg style gradient buttons:

If you're reading from a feed reader that doesn't embed iframes, you'll need to click through to see the example.

Check out the frame source for full details. Notice that the button itself is an HTML DIV and that we use CSS and HTML elements to define and position our text. So it's possible to mix HTML and vector graphics as you see fit.

We're just scratching the surface. svg2vml can do all kinds of cool stuff. Have fun!

Bookmark with del.icio.us submit Tutorial%3A%20Building%20a%20Snowflake%20Graph%20from%20XML digg.com reddit

Tutorial: Building a Snowflake Graph from XML

I just posted this new tutorial on jsviz.org...

JSViz 0.3.3 includes a few examples to help you get started. In this tutorial, I'm going to go over one of them. We'll create a Snowflake Graph from the contents of an XML file. You can find the example source, with comments based on this tutorial in the 0.3.3 Distribution.

Here's the final product

1) Start with a new HTML file

Add appropriate JSViz imports and an empty "init()" function body:

Continue reading this post at jsviz.org...

Bookmark with del.icio.us submit JSViz%200.3.3%20Released digg.com reddit

JSViz 0.3.3 Released

The jsviz.org website is now available but I'll be cross-posting big news here to keep subscribers and search traffic informed:

JSViz 0.3.3 is now available. This release includes two major features:

Snowflake Model is an updated implementation of the "Tree Model" offered in JSViz 0.2. This is a geometric model, offering superior speed to Force Directed layouts, but only capable of representing hierarchical data (sorry, no circuits).

An Example Snowflake Graph

Layouts offer a simplified interface to the core JSViz libraries. New projects can now be created with minimal code and simple configuration. Additional examples, using Layouts:

An Example Force Directed Graph with Data Loader
An Example Force Directed Graph with Randomly Generated Data

You can download the full source as a single ZIP archive or browse individual files on the Download page

I'll follow up with tutorials shortly.

Bookmark with del.icio.us submit More%20Music%20Mashing digg.com reddit

More Music Mashing

I've received a lots of great comments and e-mails about the music recommendations demo I posted a week or so ago. But a number of you mentioned that the recommendations were a little funny. Questions and observations so far:

  • Theivery Corporation is the center of the universe! Every album ever released is 3 or fewer hops away from a Theivery Corporation album.
  • Why is every album I search for related to Beck? or Moby? or Neil Young? Though I'll point out, the man has been in almost every band that's ever released an album. Seriously, that album by the Back Street Boys and Young is one of my favorites!
  • How is this tool useful if the only related albums to my search are by the same artist?

Right. So ... There's a lesson here:

There's always a little bit of "magic" in a mashup.

The music recommendations demo gets album relationships from Amazon.com's E-commerce API. Similarity is based on buying patterns, which apparently lead to some unexpected or disappointing results. So I decided to try out an alternative.

I worked up a quick mashup using the Audioscrobbler (Last.fm) API for Artist-to-Artist recommendations. Audioscrobbler uses the listening patterns of it's users to determine relationships. Unfortunately, the images served up with this API aren't especially useful in identifying artists, especially when scaled down. So this demo is currently text-only. If you're interested, the demo could be extended to grab an album image from Amazon.com. I tried this and bailed out quickly because it added a lot of latency to the addition of new nodes, but you may be able to cut this down using an image cache.

So give it a try.

Oh, one more thing! These demos don't work so well in ie7. This isn't an issue with the JSViz 0.3.1 API. I'll fix the demos when I have some spare time. Thanks for all the feedback. It's useful in driving this project.