You are here: Home >> How-Tos >> Building a Hierarchical Bookmarks Panel

How-To: Building a Hierarchical Bookmarks Panel

By Samuel Reynolds

Introduction

I wanted to create a sidebar panel for sharing bookmarks, arranged in categories. In addition, when I'm logged in, I want to see additional bookmarks that are not visible to visitors.

A primary goal in creating this bookmarks panel is to have a single repository for my bookmarks, rather than having them (incompletely and inconsistently) duplicated across multiple browsers on multiple computers running multiple operating systems.

One place where I can maintain my bookmarks and from which I can use them, regardless of what machine, browser, operating system, state, country, galaxy...sorry, got a little carried away there. But you know what I mean, I'm sure.

The bookmarks sidebar panel would look something like this:

Administrator sees this:   Anyone else sees this:
Knowledge Management
Google Search
WWW Virtual Library
KMWorld
The KMForum
Meta Knowledge Management Portal

Python
Google Search
Python.org
Zope.org
Twisted Matrix Laboratories

  Knowledge Management
Google Search
WWW Virtual Library
KMWorld

Python
Google Search
Python.org
Zope.org

I didn't want to maintain two separate lists of links.

What I Did

One Message For Each Category

First, I created a separate message for each bookmark category. The message subject will be used for the bookmark section title, and the message body will contain a series of HTML links. For example:

Subject: Knowledge Management
Content: <a href='#'>Google Search</a><br />
<a href='#'>WWW Virtual Library</a><br />
<a href='#'>KMWorld</a><br />
<!--#if condition="username == '<!--#msgOwner-->'"-->
<a href='#'>The KMForum</a><br />
<a href='#'>Meta Knowledge Management Portal</a><br />
<!--#endif-->

Note the conditional macro. It marks off a block of links that will only appear to the message owner when the message is displayed---or when the message is included in the sidebar. Nobody else will see the links in this section.

A Custom Message Field For Query

I went to my site admin pages, and created a new message Custom Field called IncludeInBookmarks, with type Popup Menu. I gave it just one value: Yes. (I'll show later how No appears as the default value when the custom field is displayed.)

Add Custom Field To Message Templates

I added the custom message field to the templates for Message View and Message Edit. To do this, I had to create new Message View and Message Edit templates. I used the Create panel in the Admin-->Templates page to clone the default (read-only) templates, and added one more row to the headers section. The change was identical in both templates:

Label: Bookmarks
Value: <!--#msgCustomField fieldName="IncludeInBookmarks" noValueText="No"-->

The <!--#msgCustomField> macro renders as a simple value text when the message is viewed, but renders as a popup menu input widget when the message is being edited.

Note the noValueText parameter on the <!--#msgCustomField> macro. This parameter specifies what to display as the value if no value has yet been set for the custom field. Since by default no value is set, the default display becomes No. The user can then select Yes (in edit mode, of course), or leave it as it is.

Administrators Only. I wrapped the inserted table row in a conditional, so it is only shown to administrators. That way, only administrators are allowed to edit the field, and it doesn't clutter up the display for non-administrators.

The result (in my template, which will probably not match yours exactly) looks like this:

<!--#if condition="userIsConvAdmin"-->
<tr valign='top'>
   <td class="msgLabelCell" align="right">Bookmarks</td>
   <td class="msgValueCell" align="left" colspan="3">
      <!--#msgCustomField fieldName="IncludeInBookmarks" noValueText="No"-->
   </td>
</tr>
<!--#endif-->

Create Advanced Query Page

In my site's Admin-->Structure page, I created a new Advanced Query Page named Links. I gave it the following settings:

Query Options
Allow search arg overrides?No
Run Query on Load?Yes
Show only bound URLs?No
Show only Top Level Topics?No
Show only first message in each thread?No
Cache default query?Yes
Max age of default query cache? (minutes)15
Query Defaults
Custom Fields: IncludeInBookmarks?Yes
Others ignored
Form Settings
Show Form?No
Others ignored
Result Settings
Items Per Page?10
Page Content Template:Ignored
Query Result Template: <!--#queryResultBody-->
Message Template:
   <div class='bookmarksSectionTitle'>
      <a href='<!--#msgUrl-->'><!--#msgSubject--></a>
   </div>
   <div class='bookmarksSection'>
      <!--#msgBody-->
   </div>

The sole purpose of this query is to bring together all the individual Bookmarks pages. So I indicated that the form should not be displayed and that the search parameters should not be overriden.

The Custom Fields:IncludeInBookmarks selection of Yes specifies what pages are to be included in the query result.

The Query Result Template specifies that only the query results should be included, with no additional markup or framing.

The Message Template specifies two styled div blocks. The first, with a class of bookmarksSectionTitle, includes the message subject, linked back to the original bookmark message for editing/viewing. The second, with a class of bookmarksSection, simply includes the message body; the actual link markup already appears in the original bookmark message body.

These two CSS classes must be defined in the default CSS.

Add CSS Classes

I created my own default style sheet in the Admin-->Stylesheets page. (You can either copy an existing sheet or create a new one from scratch.) I made my new sheet the default by going to the Admin-->Structure page, clicking on the Properties tab, and selecting it on the Stylesheet popup menu.

In my style sheet, I added the following style declarations:

.bookmarksSection{
  margin: 0em .25em 0em 2em;
  padding: 0px; }

.bookmarksSectionTitle{ font-family: Verdana, sans-serif; font-weight: bold; margin: 0px; padding: 0px; }

.bookmarksSectionTitle a{ text-decoration: none; }

I specified no margin or padding in .bookmarksSectionTitle. Since the bookmarks will be included in a side panel, they will be wrapped in another div anyway; the enclosing div will specify the inset (padding) around the bookmarks.

I specified a relatively large left margin in .bookmarksSection so the individual items will be indented under the titles. I left the padding at zero for the same reasons as for .bookmarksSectionTitle.

I also specified, via .bookmarksSectionTitle a, that links in the title should not be underlined. This was partly an esthetic and partly a practical choice. From an esthetic standpoint, it makes the appearance of the titles very consistent, and removes the distracting underline that would appear by default. From a practical standpoint, since the link back to the message is primarily for the administrators' benefit, this de-emphasises the link for everyone. The administrators (for the moment, me) presumably know the link is there if they need it.

Add Bookmarks Panel To Page Template

I created my own default page template in the Admin-->Templates page. (You can either copy an existing sheet or create a new one from scratch.) I made my new template the default by going to the Admin-->Structure page, clicking on the Properties tab, and selecting it on the Template popup menu.

In my page template, I added the following block to incorporate my new grouped bookmarks (or, if you prefer, Links) panel:

<div class='panelRight'>
   <div class='sidebarTitle'>Links</div>
   <div class='sidebarBlock'>
      <!--#insertQuery aqpPath="Links"-->
   </div>
</div>

Note that the page structure in my template are defined using CSS div blocks. In a site that is formatted using tables, rather than CSS, these divs would be table cells, instead.

The CSS classes are discussed below. The key element is the <!--#insertQuery aqpPath="Links"--> macro. This macro inserts the results of the advance query page named Links---the entire, categorized list of bookmarks.

In my style sheet, as part of my basic site formatting, I have the following style declarations:

.panelRight{ float: right;
  margin: 0px;
  margin-left: 18px;
  width: 22%; }

.sidebarBlock{ font-family: Verdana, sans-serif; font-size: 80%; background-color: #FFE6CC; color: #663300; padding: 6px; margin: 6px; margin-top: 0px; width: 144px; border: 1px solid #663300; border-top: 0px; }

.sidebarBlock a{ color: #663300; text-decoration: underline; }

.sidebarBlock a:active{ color: #994700; text-decoration: underline; }

.sidebarBlock a:visited{ color: #663300; text-decoration: underline; }

.sidebarTitle{ font-family: Verdana, sans-serif; font-weight: bold; font-size: 80%; color: #FFE6CC; background-color: #D55F00; text-transform: uppercase; margin: 6px; margin-bottom: 0px; padding: 0px 4px 0px 4px; width: 144px; border: 1px solid #663300; border-bottom: 0px; }

.sidebarTitle a{ color: #FFE6CC; text-decoration: none; }

.sidebarTitle a:visited{ color: #FFE6CC; text-decoration: none; }

.panelRight defines a block width, floats the block to the right side of the page, and forces a margin to its left. I also have a similar .panelLeft class, that floats to the left side of the page and forces a margin to its right.

.sidebarBlock and .sidebarTitle form a labelled sidebar with a 1-pixel dark brown border. .sidebarTitle uppercases the text and displays it as beige on dark orange and uppercases it.

The final result looks like this:

sidebar.gif

A Good Start

I've described my first attempt to create a panel of categorized links. I know this is not the only way to do this. And it doesn't do everything I want it to, and is not as easy to maintain as I would like.

But it works!

Not bad for having only started with Conversant a week ago, huh?

Wish List: Some Ideas for Further Investigation

A few things I would like it to do or support, which this approach doesn't:
  • As described, multiple users can maintain their own categorized bookmarks pages (though I have restricted it to administrators by hiding the edit control). But if more than one user creates a page for the same category, it will result in repeated categories in the Links panel. It would be nice to be able to merge the links by category, and eliminate duplicates. After all, screen space is limited.

  • Rather than simply presenting an indented list of links, generate a DHTML menu. Make each category a menu title, and the links under it menu items, hidden until the title is clicked. This would do even more for screen space than the previous item. Besides, it's cool!

  • Rather than having to edit a page of HTML links each time I want to add a link, provide a mechanism to add a link and label via a single HTTP request (e.g., a link with path args).

  • Rather than having to edit a page of HTML links each time I want to add a link, provide a columnar view of text widgets, with the labels in one column and the link URLs in another. This would require a plugin, I think.

  • Create a remote-control page for browsing the bookmarks. The page would include a link back to the home site, maybe a few other utility links, and the full menu of categorized links, in a small remote-control window. Clicking on a link in the remote-control window would load the page into the main browser window (most likely, the one from which the remote-control was opened).

QuickStart
Main Menu
Discussion

Guests
Welcome!
  • Sign Up
  • Logon

  • Search


    This site managed with Conversant, © Copyright 2008 Macrobyte Resources; Unless otherwise stated, content © 2000 - 2005 Mark Morgan
    Site design adapted from a free template at Free Site Templates.