Standards-Based Collapsible Table of Contents Widget (CTOCWidget)
Introduction
Recently, while developing the new table of content widget for the JavaScript references in the DevEdge MultiBar Sidebar Tab, I found the need for a tree-based collapsible list. This article chronicles my experience creating a tree-based table of contents widget using XML and the W3C DOM.
Design
I had a choice of either reusing an existing solution or starting from scratch. The old xbCollapsibleList which was ported from a script written for 4.x generation browsers or the newer xbTreeWidgetStatic were obvious candidates. xbCollapsibleList was not seriously considered due to its obsolete design. However, xbTreeWidgetStatic provided a good basis to start from; however its reliance upon a procedural means of defining the tree was undesirable.
Since the table of contents widget would be hosted inside a sidebar tab in either Netscape 7.x or Mozilla based browsers, cross-browser compatibility was not an issue and I decided to implement a pure standards-based widget for simplicity sake. This widget would use the same presentational markup used in xbTreeWidgetStatic but would generate its content from an external XML document which described the table of contents.
Markup
XML Description
I decided that the simplest approach would be to use an XML
document composed of two elements: toc and item.
The document element toc would contain the table of
contents definition while a set of nested item elements
would provide the hierarchical description of the items in the
table of contents.
toc and item would each have a
title attribute which would serve as a label for
each entry. item elements would have an additional
attribute url which would point to the location
of the document to be loaded when the item was
activated. item elements would be nested to represent
the hierarchal nature of a table of contents.
Example
<toc title="Table of Contents title">
<item title="Item1 Title" url="url1" />
<item title="Item2 Title" url="url2">
<item title="Subitem 1 Title" url="url3"/>
</item>
</toc>
HTML Representation
The tree would be contained in an overall DIV
which would allow the table of contents widget to be styled.
Each contained item would be contained in its own DIV
which contained a handle DIV and an
optional children DIV. The handle
would contain the descriptive text for each table of contents
entry along with an image depicting whether the item
is in an open or closed state. Event handlers attached to the
handle open (display child items)
or close (hide child items).
<DIV class = "CTOCWidget_view">
<DIV class = "CTOCWidget_item">
<DIV class = "CTOCWidget_itemhandle" style = "cursor: pointer;">
<IMG style = "height: 12px; width: 16px;" src = "closed.gif">
<A href = "url1" target = "_content">
Item1 Title
</A>
</DIV>
</DIV>
<DIV class = "CTOCWidget_item">
<DIV class = "CTOCWidget_itemhandle" style = "cursor: pointer;">
<IMG style = "height: 12px; width: 16px;" src = "closed.gif">
<A href = "url2" target = "_content">
Item2 Title
</A>
</DIV>
<DIV class = "CTOCWidget_itemchildren" style = "display: none; position: relative; left: 1em;">
<DIV class = "CTOCWidget_item">
<DIV class = "CTOCWidget_itemhandle" style = "cursor: pointer;">
<IMG style = "height: 12px; width: 16px;" src = "open.gif">
<A href = "url3" target = "_content">
Subitem 1 Title
</A>
</DIV>
</DIV>
</DIV>
</DIV>
</DIV>
Script
CTOCWidget.js implements
a JavaScript Object CTOCWidget which is used to
manage creating the table of contents from the corresponding
XML document.
- Constructor
-
- CTOCWidget(Node domTOCModel, String target)
-
Constructs an instance of the widget from the XML document
domTOCModelcontaining the table of contents which will activate its links in thewindowtarget namedtarget.
- Class Properties
-
- CTOCWidget._handleImages
-
_handleImagesis an object which specifies the images to be displayed in the open or closed state of a node in the table of contents tree. You can override the default values before constructing the table of contents. - CTOCWidget._classPrefix
-
_classPrefixis a string which is used to prefix the class names used in the HTML to represent the table of contents. The default is"CTOCWidget".
- Properties
-
- Node model
-
modelholds a reference to the XML Document which contains the table of contents. - String target
-
targetis the value of thetargetattribute on all generated hyperlinks and is used to activate links in specific windows or frames. - HTMLDivElement view
-
viewcontains a reference to the outer-mostDIVcontaining the table of contents widget.
- Methods
-
- _createItemView(Node modelItem, String target
-
_createItemViewis an internal method used to create a view corresponding to a specific item in the table of contents model. The DOM Level 2 Core and DOM Level 2 HTML APIs are used to create the HTML markup which represents the widget. - toggleHandle(Event e)
-
An event handler attached to the widget to handle clicks on the item's view handle. The DOM Level 2 Events API is used to attach
clickevent handlers to the handle while the DOM Level 2 CSS API is used to hide/show an item's children by setting its style.display property.
Examples
Creating the table of contents widget requires two steps:
-
Load the external XML document describing the table of contents. In the examples below I used the DOM Level 3 Load API to asynchronously load the XML document and the DOM Level 2 Events API to process the loaded document when the
loadevent fires. -
Create the HTML markup to represent the table of contents.
var domTOCModel;
function loadToc()
{
// get XML document file name from the query string
var tocFile = document.location.search.substring(1);
// create an XML document and load the file using
// W3C DOM 3 Load and W3C DOM 2 Events
domTOCModel = document.implementation.createDocument('', '', null);
domTOCModel.addEventListener('load', onLoadToc, false);
domTOCModel.load(tocFile);
}
function onLoadToc()
{
// when the XML document is loaded, create the
// table of contents view and insert into the HTML document
var title = domTOCModel.documentElement.getAttribute('title');
var h1 = document.createElement('h1');
h1.appendChild(document.createTextNode(title));
var tocWidget = new CTOCWidget(domTOCModel, '_content');
document.body.appendChild(h1);
document.body.appendChild(tocWidget.view);
}
You can see the CTOCWidget in action by clicking the following
links in Netscape 7.0x or Mozilla.
Notes
CTOCWidget is currently written to use the W3C Standards
for the DOM directly without work-arounds for other browsers which
do not support the appropriate standards.
As a result, CTOCWidget is not supported by Internet Explorer, Opera
or other browsers.
