Drilldown - Ajax Patterns

Drilldown

From Ajax Patterns

(Difference between revisions)
Revision as of 03:47, 20 November 2005
Mahemoff (Talk | contribs)

← Previous diff
Revision as of 17:35, 7 July 2006
Mahemoff (Talk | contribs)
Drilldown Menu moved to Drilldown
Next diff →

Revision as of 17:35, 7 July 2006

Evidence: 2/3

Tags: Drilldown Menu Progressive


Contents

In A Blink

progressive menu (three frames)

Games > Retro > Galaga etc


Goal Story

Pam is booking a trip on the corporate travel planner. She sees a form with the usual fields, and clicks on location. Suddenly, a list of cities fades in beside the form, and Pam selects Paris. Beside the city list, a third list appears, this one showing approved hotels. Pam chooses the Hilton and both lists disappear. The location field now contains "Paris Hilton" as Pam had intended.


Problem

How can the user select an item in a hierarchical structure?


Forces

  • Applications and websites are often arranged in hierarchies. To navigate, users need to choose a page from within the hierarchy.
  • Hierarchy navigation should be fast.


Solution

To let the user locate an item within a hierarchy, provide a dynamic drilldown. The drilldown allows navigation through a hierarchy and ultimately an item being chosen. At each level, there are several types of element in the drilldown:

  • Category A read-only name for the present level.
  • Individual items which the user can choose to end the interaction.
  • Sub-Categories which the user can choose to drill down to a deeper level.
  • Upward Navigator which "drills up" one or more levels.

In some hierarchies, items and categories are mutually exclusive: items only exist at the edges - or leaves - of the hierarchy. Even when that's the case, items and categories should be distinguished for the sake of clarity. The upward navigator goes by different names, but a general guidelines is to tell the user which category they're going back to.

Typical applications include navigating through separate areas of the application, and filling out a field by navigating through a hierarchy of candidate items

As the user drills down the hierarchy, do you show each progressive level? There are three main options:

  • Keep the drilldown in a fixed area. Each time the user clicks on a category, the drilldown morphs to show only that category. This has the benefit of preventing page rearrangement.
  • Show all levels at once. Each time the user clicks on a category, expand out the drilldown region to add a new list for each category.
  • As a variant on the second approach, all levels are shown,but the sub-menus are rendered in front of the rest of the document, so the menu is effectively modal: nothing else can be done from the time the menu is opened to the time the selection is made. This approach is similar to choosing an application from the Windows Start menu.

The first two options are modeless, the third is modal. Modeless interaction works well with Ajax, where it's possible to dynamically update, without page refresh, the menu as well as any surrounding content related to the user's selection. Specifically:

  • Each navigation through the [Drilldown] can result in a server call, to fill the next level with the latest content, or even auto-generate new content.
  • The display throughout the application can change to reflect the state of the drilldown, giving the user a "tour" through the hierarchy. As a user drills down from the top level to a deep category, the application is always synchronised with the current level. So the display reflects the medium-depth categories along the way. Because the interaction is modeless, the user is then free to stay on those categories.
  • The user can iterate between drilling down and performing other tasks. Imagine the user is a humans resource clerk needs to use a drilldown to select an "employee of the month". She's already decided on the region, and drills down to show all the employees there. Now that she can see each candidate, she can go perform some research in another region of the page, or on another website. When she returns, the drilldown is still there, waiting to be completed.


Decisions

Will you call on the server each time the user navigates through the Drilldown?

Sometimes, the entire hierarchy is loaded as a one-off event. Other times, categories can be pulled down as required using an XMLHttpRequest Call. The choice is governed by two things:

  • How big is the hierarchy? The more items, and the more information per item, the less desirable it is to transfer and cache the data.
  • Is the hierarchy subject to change? In this case, you'll need to retrieve fresh data from the server at the time a category is opened up. In a more extreme case, the server might even generate the hierarchy data on demand. For instance, an RSS feed aggregator might present a drilldown with categories such as "sport feeds", "politics feeds". The contents of these will be generated at the time the user drills down to a particular feed.


Real-World Examples

Betfair

Betfair uses Drilldown to locate an event you wish to bet on. At the top level, the "All Markets" drilldown contains various categories in alphabetical order: from "American Football" to "Special Bets" to "Volleyball". Clicking on "Special Bets" yielded several countries, along with a "General" category, and you can continue to drill down to the list of bets. Clicking on one of those bets sets the main page content.

"All Markets" is one of two drilldowns. The other is "My Markets", a personalised drilldown available to registered users.


Backbase

The Backbase Portal Demo contains several independent Portlets. Of interest here is the "Local Directory" portlet, which is actually a Drilldown, with toplevel categories such as "Education" and "Health" drilling down to relevant links.

Refactoring Illustration

Overview

The basic Portal Demo illustrates Multi-Stage Download, showing how different content blocks can be downloaded in parallel.One of those is a block of links to Ajax resources. To keep the block small, only a few links are present. But is there any way we could keep the link block physically small, while offering a large number of links? Of course there is ... a Drilldown will occupy roughly the same space, but with a little interaction, the user will be able to navigate through a large collection of links.

The refactored version includes a drilldown. A Category can contain any combination of Categories and Links. For instance: The top-level category, "All Categories", contains only Categories, the "Websites" category contains just links, and the "Overviews" category contains some overviews as well as a sub-category, "Podcast Overviews". Categories and links are rendered similarly, but not identically. Each category menu includes a link to the previous category level.

The basic interaction sequence works like this:

  1. User clicks on a category.
  2. A callback function detects the click, and issues an XMLHttpRequest query on the desired category.
  3. Server responds with the new category name, its parent (null in the case of the top-level category), and each category and link in the drilldown. All of this is in XML format.
  4. Browser replaces existing drilldown with a drilldown based on the new category information.

On page load, the drilldown is blank and the browser requests information for the top-level category. The server response triggers the creation of a new drilldown.

Browser-Side Implementation

The initial HTML just shows a blank div. The width is constrained because the drilldown's parent container has a fixed width.

Loading ...

On page load, the top-level category is requested.

 retrieveCategory("All Categories");

Then begins the standard process of requesting a category with XMLHttpRequest, then rendering the menu accordingly. This not only occurs on page load, but every time the user clicks on a category within in the dropdown.

The server returns the category an XML file with category data. For example, you can see the data for the "Overviews" category at http://ajaxify.com/run/portal/drilldown/drilldown.phtml?categoryName=Overviews. The specification contains the name, the parent name, a list of items. Each item is either a category or a link. Note that only the information for this level of the drilldown is provided.

  <category name="Overviews" parent="All Categories">
    <items>
      <link>
        <url>http://en.wikipedia.org/wiki/AJAX</url>
        <name>Wikipedia Article</name>
      </link>
      <link>
        <url>http://www.adaptivepath.com/publications/essays/archives/000385.php</url>
        <name>First Ajax</name>
    </link>
    <category name="Podcast Overviews" parent="Overviews" />
  </items>
  </category>

The browser parses this XML to produce HTML for the drilldown. Links are shown as standard HTML anchor links, categories are Div elements. Event handlers ensure that when a category is clicked, including the "Back To (previous)" category, the browser will kick off another retrieve-and-render cycle.

  function onDrilldownResponse(xml) {
 
    var category = xml.getElementsByTagName("category")[0];
    var html="";
 
    var categoryName = category.getAttribute("name");
    html+="<div id='categoryName'>" + categoryName + "</div>";
 
    var parent = category.getAttribute("parent");
    if (parent && parent.length > 0) {
      var parentName = category.getAttribute("parent");
      html+="<div id='parent' onclick=\"retrieveCategory('" + parent + "')\""
           + "'>Back to <br/>'" + parent + "'</div>";
    }
 
    var items = category.getElementsByTagName("items")[0].childNodes;
    for (i=0; i<items.length; i++) {
      var item = items[i];
      if (item.nodeName=="link") {
        var name = item.getElementsByTagName("name")[0].firstChild.nodeValue;
        var url = item.getElementsByTagName("url")[0].firstChild.nodeValue;
        html+="<div class='link'><a href='" + url + "'>" + name + "</a></div>";
      } else if (item.nodeName=="category") {
        var name = item.getAttribute("name");
        html+="<div class='category' "
                 + "onclick='retrieveCategory(\""+name+"\")'>"+name+"</div>";
      }
    }
 
    $("drilldown").innerHTML = html;

  }

Server-Side Implementation

The server-side implementation relies on the Composite pattern (see Gamma et al., 1995). A Category consists of further Category objects, and also Link objects. We rely on Category and Link having two common operations:

  • asXMLTag() renders the item as an XML tag. For categories, there is a special optional parameter that determines whether or not the tag will include all items.
  • findItems($name) recursively finds an item - either a Category or a Link - having the specified name.

With these operations encapsulated in the Category and Link objects, the main script is quite small.

 require_once("Link.php");
 require_once("Category.php");
 require_once("categoryData.php");

 header("Content-type: text/xml");

 $categoryName = $_GET['categoryName'];
 $category = $topCategory->findItem($categoryName);
 if ($category) {
   echo $category->asXMLTag(true);
 } else {
   echo "No category called '$categoryName'";
 }

Further Refactoring: A Drilldown with Dynamic Content

In the refactoring above, the top-level category, and all of the data underneath it, are hard-coded in categoryData.php. In fact, the hierarchy data could easily be generated on demand, to create a drilldown with dynamic content.

TODO composite diagram Item -> Category, Link.

In a further refactoring, the Portal SyncLinks Demo does something like this. Every thirty seconds or so, a separate process parses the ajaxpatterns wiki links page, and saves the links as a hierarchy of Category and </tt>Link</tt> objects. The toplevel category is serialised to a file. In this new version, categoryData.php no longer hard-codes the categories, but unserialises the recently generated hierarchy.

Drilldown could easily be made truly dynamic, heading over to the links page every time category data is requested (an example of Cross-Domain Proxy). In fact, that's how it worked while the drilldown was developed, but performance constraints make it impractical. So a small change was made to periodically refresh the data instead.


Alternatives

Live Search

Drilldown lets the user locate an item by browsing through a hierarchy. Live Search instead lets locate an item by typing, and the data need not be hierarchical.


Related Patterns

Microlink

There may be an opportunity to associate microcontent with categories in the drilldown. Each time the user clicks on a Drilldown, Microcontent may be produced. For example, a navigation style drilldown would let the user navigate through a hierarchy, and see page content update accordingly. In an Ajax application, the page content would be replaced without page reload, hence the drilldown items are a form of Microlink.

Browser-Side Cache

If each navigation event leads to a query of the server, consider retaining results in a Browser-Side Cache.

Portlet

A drilldown is usually a form of Portlet. It has its own state and the user can usually conduct a conversation with the drilldown in isolation.


Visual Metaphor

Drilldown involves classic hierarchical structure - think of offices containing filing cabinets, filing cabinets containing folders, folders containing documents.


Want to Know More?