ColumNav

Overview

ColumNav is a hierarchical menu implementation utilizing Bill Scott's Yahoo UI Carousel component. Content is loaded from an unordered list and displayed in a scrollable viewport, similar to Column View in the Mac OS X Finder. Features include:

Examples

The following examples demonstrate the various ways content can be loaded when initializing a ColumNav object:

Additional examples, demonstrating some customizations:

Download

Usage

Setting up ColumNav is a straightforward process of providing the proper HTML, JavaScript, and CSS configuration, along with creating the data source. Understanding how a data source is formed and processed is key to using ColumNav, so it is presented first below.

Data sources

You have two types of objects to choose from when building a data source: DOM or JSON. In either case, the object represents a normal HTML unordered list. Each list item contains a link and possibly a nested sub-list (or some arbitrary HTML). For example, a DOM representation of basketball teams might look like this:

<ul id="basketball-list" title="Basketball Teams">
  <li>
    <a href="http://sports.yahoo.com/nba/">NBA</a>
    <ul>
      <li>
        <a href="">Atlantic</a>
        <ul>
          <li><a href="http://sports.yahoo.com/nba/teams/bos">Boston Celtics</a></li>
          <li><a href="http://sports.yahoo.com/nba/teams/njn">New Jersey Nets</a></li>
          <li><a href="http://sports.yahoo.com/nba/teams/nyk">New York Knicks</a></li>
          <li><a href="http://sports.yahoo.com/nba/teams/phi">Philadelphia 76ers</a></li>
          <li><a href="http://sports.yahoo.com/nba/teams/tor">Toronto Raptors</a></li>
        </ul>
      </li>
    </ul>
  </li>
  <li><a href="examples/ajax/ncaa/index.xml" rel="ajax">NCAA</a></li>
</ul>

The equivalent JSON object would look like this:

{ "ul": {
    "@id": "basketball-list",
    "@title": "Basketball Teams",
    "li": [
      { "a": { "@href": "http://sports.yahoo.com/nba/", "#text": "NBA" },
        "ul": {
          "li": [
            { "a": { "@href": "", "#text": "Atlantic" },
              "ul": {
                "li": [
                  { "a": { "@href": "http://sports.yahoo.com/nba/teams/bos", "#text": "Boston Celtics" } },
                  { "a": { "@href": "http://sports.yahoo.com/nba/teams/njn", "#text": "New Jersey Nets" } },
                  { "a": { "@href": "http://sports.yahoo.com/nba/teams/nyk", "#text": "New York Knicks" } },
                  { "a": { "@href": "http://sports.yahoo.com/nba/teams/phi", "#text": "Philadelphia 76ers" } },
                  { "a": { "@href": "http://sports.yahoo.com/nba/teams/tor", "#text": "Toronto Raptors" } }
                ]
            } },
          ]
      } },
      { "a": { "@href": "ajax/json/ncaa/index.json", "@rel": "ajax", "#text": "NCAA" } }
    ]
} }

When imported into the ColumNav component, the data source is divided into "panes" based on each item's position in the list. Top-level items are viewable at first ("NBA" and "NCAA" above), while nested items occupy subsequent panes. Bottom-level items act as normal links unless their rel attribute contains the flag ajax. In this case, the URL specified in the href attribute is used to retrieve the next pane in the series via Ajax.

ColumNav instances can be initialized using a pre-built object (DOM or JSON) or from an object acquired via Ajax. See the datasource configuration property below.

IMPORTANT: Data sources loaded though Ajax should be served with a proper mime type. XML sources should have an appropriate mime type like text/xml or application/xml, while JSON sources must be sent as application/json.

All link attributes in the data source are propagated to the ColumNav. You can, for example, specify a class attribute for a particular link, and use that value for fine-grained CSS control. See the CSS section below. Additionally, each list node (<ul>) can specify a title attribute.

HTML

The HTML structure of each ColumNav should conform to that expected by the Carousel component script:

<div id="mycolumnav" class="carousel-component">
  <div class="carousel-clip-region">
    <ul class="carousel-list"></ul>
  </div>
</div>

The specific class names are required by the Carousel. See the Carousel documentation for more information. The id value is arbitrary, and will be passed as the first argument to the ColumNav constructor (see below).

Additionally, you can provide a "back" button for retracing your steps:

<div class="prevButton">
  <a href="javascript:void(0)" id="mycolumnav-prev">&lt; back</a>
</div>

The HTML can be anything, provided the clickable element has an id attribute. The id will be passed to the ColumNav constructor to enable the button. A ColumNav instance can have multiple back buttons. See the configuration properties below.

JavaScript

ColumNav relies on Carousel, which in turn relies on the Yahoo UI Library (version 0.12 or above). Include the required files in the <head> of your document. Note that you can include YUI files hosted on Yahoo servers. If you are going to be processing JSON objects, include the JSON parsing script as well.

<script type="text/javascript" src="http://yui.yahooapis.com/2.2.2/build/utilities/utilities.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.2.2/build/container/container_core-min.js"></script>
<script type="text/javascript" src="carousel.js"></script>
<script type="text/javascript" src="columnav.js"></script>
<!-- if JSON data sources: -->
<script type="text/javascript" src="json.js"></script>

Note that the distribution contains minimized versions of both Carousel and ColumNav JavaScript files.

Since a ColumNav instance depends on the existence of a specific HTML element, it is best to instantiate it after page load. For instance:

<script type="text/javascript">
  function init() {
      // ... do other stuff first, perhaps ...
      var cn_cfg = { prevElement: 'mycolumnav-prev'', datasource: some_url_or_object };
      var cn = new YAHOO.extension.ColumNav('mycolumnav', cn_cfg);
  }
  YAHOO.util.Event.addListener(window, 'load', init);
</script>

The ColumNav constructor accepts two arguments: the id of the outermost <div> (the one with class="carousel-component"), and an object containing configuration properties. These properties are name/value pairs governing the ColumNav look and behavior:

Event handlers

A ColumNav instance exports two public methods: reset() which can be called at any time to revert the component back to its original state, and toString() which returns a string representation of the ColumNav instance.

CSS

Two stylesheets are required:

<link href="carousel.css" rel="stylesheet" type="text/css"/>
<link href="columnav.css" rel="stylesheet" type="text/css"/>

The carousel.css file governs the layout and behavior of the underlying Carousel component, and should not be edited. The columnav.css file can be edited to customize the look and feel of the ColumNav component. Apart from altering fonts, colors, margins, etc., rules can be added to display different icons for each list item type. When the script runs, it introduces up to six additional CSS class names which you can use to refine the display:

In addition to these class names, others can be added to an item by including them in the data source, providing fine-grained CSS control. For example:

<ul title="Basketball Teams">
    <li><a href="examples/ajax/ncaa/index.xml" class="ncaa" rel="ajax">NCAA</a><li>
</ul>

When loaded into the ColumNav, the link above will contain two class names: "ncaa" (propagated from the data source), and "columnav-has-next" (due to the presence of rel="ajax"). This allows you to display a different icon based on the given class name. For example:

.carousel-component ul.carousel-list li a.ncaa span {
    background-image: url(ncaa-logo.png);
}

Note the background image belongs to the nested span.

It is important to remember that the data source markup is not copied verbatim into the ColumNav (except for non-menu content). Instead, it is transformed into a format more suitable for containment within the Carousel component. For instance, when the markup above is translated into the Carousel (e.g. #mycolumnav ul.carousel-list) it looks like this:

<li id="columnav-item-1" class="columnav-menu">
  <div title="Basketball Teams">
    <a href="examples/ajax/ncaa/index.xml" class="ncaa columnav-has-next" rel="ajax">
      <span>NCAA</span>
    </a>
  <div>
</li>

Keep this in mind when styling the ColumNav.

Tips

Credits

My name is David Lindquist, and I wrote the ColumNav JavaScript, CSS, examples, and this documentation. Many thanks to Bill Scott for his wonderful Carousel component upon which ColumNav is based, and to the Yahoo UI developers for my favorite JavaScript framework. Special thanks go to Nate Steiner for suggesting the ColumNav name, and for convincing me to allow for non-Ajax content loading.

Questions? Comments? Send me email at david.lindquist@gmail.com.