Publishers of technology books, eBooks, and videos for creative people

Home > Articles > Web Design & Development > Usability

Web Design Reference Guide

Hosted by

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

Designing With Code: Tumblelogging

Last updated Oct 17, 2003.

As Robert Hoekman mentioned in his previous Designing the Obvious Clinic on Tumblr, tumblelogs are more stream-of-conscious than traditional blogs. With this concept in mind, the interactive process for adding items to your tumblelog should be extremely fast, eliminating any distractions and letting your thoughts flow. I love the simplicity of Tumblr, but I think it could be improved to allow posts to be more spur of the moment.

Have you ever had a brilliant idea, only to forget what it was when the time came around to finally implement it? Well, I don't know about you, but I have these moments all too often, so when I create web applications, I try to spare my users a similar fate.

In Tumblr, when choosing an action—such as adding a quote, a post, etc.—the buttons for the rest of the actions disappear. If you decide to change actions, you're forced to hit the back button, which interrupts the experience and causes you to lose focus. Simply keeping the actions consistent across all of the pages would certainly prevent this issue from ever occurring. We could even add a visual marker to identify what action is currently active.

Figure 01

Figure 1. Disappearing navigation

Figure 02

Figure 2. Consistent navigation

I know the navigation adds some height and additional elements to the page, but it's well worth the improved experience. I always try to create a simple visual design in my web apps, but simple interactions are just as important.

Now that our experience is not interrupted by the disappearing navigation, let's take it a step further and eliminate the page reloads. To do this, we'll implement an Ajax engine to allow the application to run in one page with dynamic page states. This will eliminate almost all of the user effort and allow thoughts to flow freely.

Before getting started, you can download the source code for the example that we will create here. Let's start with the HTML from Tumblr's publisher page. We'll add absolute paths to all of the URLs and strip the content and navigation so that we're left with the shell of the web page.

Tumblr, stripped of content and navigation (shell.html)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

    <title>Tumblr</title>
    <link href="http://www.tumblr.net/stylesheets/publisher.css" media="screen" rel="Stylesheet" type="text/css"/>

    <script type="text/javascript" language="javascript" src="http://www.tumblr.net/javascript/prototype.js"></script>
    <script type="text/javascript" language="javascript" src="http://www.tumblr.net/javascript/effects.js"></script>

  </head>
  <body id="publisher_index">
    <div id="header">
      <a href="./"><img src="http://www.tumblr.net/images/publisher_logo.gif" id="logo" alt="Tumblr"/></a>

              <p><a href="http://krishadlock.tumblr.com">Take me to krishadlock.tumblr.com</a> «</p>
        <p><a href="/settings">Change settings</a> «</p>

        <p><a href="/publisher/logout">Log out</a> «</p>
        <p>
          <span style="background-color:#6aa72d; color:#e9f7b8;">New:</span> 

          <b><a href="http://blog.davidville.com/2007/03/01/import-feeds/"
          target="_blank">Introducing “Import Feeds”</a></b> »
        </p>

                  </div>
      <div id="container">
        <img id="top" src="http://www.tumblr.net/images/publisher_top.gif" alt=""/>

        <div id="inner_container">
          <h1>Add a new...</h1>
      <div id="create_buttons">
      </div>
      <div id="page"></div>

    </div>
    <img id="bottom" src="http://www.tumblr.net/images/publisher_bottom.gif" alt="" /></div>
  </body>

</html>

We will then create an Ajax engine that takes requests and delegates responses to a specified callback method.

Ajax engine (js/Ajax.js)

var Ajax = new Object();
Ajax.isUpdating = true;
Ajax.Request = function(method, url, callback)
{
  this.isUpdating = true;
  this.callbackMethod = callback;
  this.request = (window.XMLHttpRequest)? new XMLHttpRequest(): new ActiveXObject("MSXML2.XMLHTTP"); 
  this.request.onreadystatechange = function() { Ajax.checkReadyState(); };
  this.request.open(method, url, true);
  this.request.send(url);
}
  
Ajax.checkReadyState = function(_id)
{
  switch(this.request.readyState)
  {
    case 1: break;
    case 2: break;
    case 3: break;
    case 4:
      this.isUpdating = false;
      this.callbackMethod(this.request.responseXML.documentElement);
  }
}

With the Ajax engine included in the index page we can start making requests. We will create two methods: AddNavigation and AddPage. AddNavigation will parse an XML file that contains the navigation and add it to the page where it used to belong. AddPage will parse XML files that contain the different page content and add it to a div with an id named page.

Tying it all together (index.html)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

    <title>Tumblr</title>
    <link href="http://www.tumblr.net/stylesheets/publisher.css" media="screen" rel="Stylesheet" type="text/css"/>

    <script type="text/javascript" language="javascript" src="http://www.tumblr.net/javascript/prototype.js"></script>
    <script type="text/javascript" language="javascript" src="http://www.tumblr.net/javascript/effects.js"></script>

    <script type="text/javascript" src="js/Ajax.js"></script>
    <script type="text/javascript">
      function AddNavigation(xml)
      {
        var navigation = xml.getElementsByTagName('navigation')[0];
        document.getElementById('create_buttons').innerHTML = navigation.firstChild.data;
        Ajax.Request('GET', 'pages/posts.xml', AddPage);
      }
      
      function AddPage(xml)
      {
        var page = xml.getElementsByTagName('page')[0];
        document.getElementById('page').innerHTML = page.firstChild.data;
      }
    </script>

  </head>
  <body id="publisher_index" onload="javascript:Ajax.Request('GET', 'navigation.xml', AddNavigation);">
    <div id="header">

      <a href="javascript:Ajax.Request('GET', 'pages/posts.xml', AddPage);"><img src="http://www.tumblr.net/images/publisher_logo.gif" id="logo" alt="Tumblr"/></a>

              <p><a href="http://krishadlock.tumblr.com">Take me to krishadlock.tumblr.com</a> «</p>
        <p><a href="/settings">Change settings</a> «</p>

        <p><a href="/publisher/logout">Log out</a> «</p>
        <p>
          <span style="background-color:#6aa72d; color:#e9f7b8;">New:</span> 

          <b><a href="http://blog.davidville.com/2007/03/01/import-feeds/"
          target="_blank">Introducing “Import Feeds”</a></b> »
        </p>

                  </div>
      <div id="container">
        <img id="top" src="http://www.tumblr.net/images/publisher_top.gif" alt=""/>

        <div id="inner_container">
          <h1>Add a new...</h1>
      <div id="create_buttons">
      </div>
      <div id="page"></div>

    </div>
    <img id="bottom" src="http://www.tumblr.net/images/publisher_bottom.gif" alt="" /></div>
  </body>

</html>

Now that all of our requests are being made and the engine is in place, we simply need to take the page content from Tumblr and add it to XML files that can be loaded dynamically. Rather than showing the entire page content from Tumblr, here is an example of the XML structure that each page will use, plus the navigation that we will load when the page is first entered.

XML structure of pages (pages/*.xml)

<?xml version="1.0" encoding="ISO-8859-1" ?>
<tumblr>
  <page><![CDATA[]]></page>

</tumblr>
XML structure of navigation (navigation.xml)
<?xml version="1.0" encoding="ISO-8859-1" ?>
<tumblr>
  <navigation><![CDATA[

    <a href="javascript:Ajax.Request('GET', 'pages/regular.xml', AddPage)"><img src="http://www.tumblr.net/images/add_regular_post.gif" alt="Regular Post"/></a>
    <a href="javascript:Ajax.Request('GET', 'pages/photo.xml', AddPage)"><img src="http://www.tumblr.net/images/add_photo.gif" alt="Photo"/></a>

    <a href="javascript:Ajax.Request('GET', 'pages/quote.xml', AddPage)"><img src="http://www.tumblr.net/images/add_quote.gif" alt="Quote"/></a>
    <a href="javascript:Ajax.Request('GET', 'pages/link.xml', AddPage)"><img src="http://www.tumblr.net/images/add_link.gif" alt="Link"/></a>

    <a href="javascript:Ajax.Request('GET', 'pages/conversation.xml', AddPage)"><img src="http://www.tumblr.net/images/add_conversation.gif" alt="Conversation"/></a>
    <a href="javascript:Ajax.Request('GET', 'pages/video.xml', AddPage)"><img src="http://www.tumblr.net/images/add_video.gif" alt="Video" style="margin-right:0px;"/></a>

    <div style="clear:both; height:1px;"></div>
  ]]></navigation>
</tumblr>

With this code in place the entire application becomes a single screen and allows for much quicker decisions. Overall, this example is essentially a web site component that can easily be reused for other single-screen applications. A live running sample can be viewed here.