As Domino developers we are all used to the idea of response documents arranged in a threaded hierarchy. We see them all the time in Notes views. They're fairly easy to create. All you need is a view, containing parent and child documents, that has a response-only column. You get a simple but effective way of navigating the resulting document structure.
What's never been easy is duplicating this functionality on the web. The de-facto solution was to use a custom view, a lot of fields and a dblookup. I talked about this approach in this article, some time ago. Since then we've seen the View Applet grow in popularity but we are still without a satisfactory way of mimicking the client's features. Hopefully, I can offer a nice alternative for you.
Let's take a simple example of a discussion thread. In the Notes client, here's what we would expect to see:
Looking at the same view in the browser, by default, we see this:
It's the Java View Applet and it does a fairly good job of replicating the functionality of the client. We don't like the applet though, do we? Oh no sir, we hate the applets!
Turning off the applet and using plain HTML we might see something like this:
Again, the functionality is there but it's ugly and requires a lot of server traffic. What we want is something light-weight and easy to use. That's what this article is about to describe.
Have you ever thought to yourself that you could create some really fancy views, all by yourself, using some DHTML? I know I have. The only thing that ever stopped me was knowing it would take a hell of a long time to do it. What would be better is if somebody had written it already, in a form that could easily be plugged in to Domino, and that they were giving away for free. Well, somebody has!
The code I am talking about is called dTree. It's a really nice script that works well across most browsers and is fairly easy to configure to meet your needs. Have a look at this example to see how you can alter the configuration in different ways.
What's particularly nice about dTree is the ease with which it can be used in Domino. That's what the rest of this article will be devoted to. First a simple example:
Just to show that it is configurable, here's the same tree but without the folders, icons or lines:
And, finally, a sample implemented in a Domino database. This is what we are working toward in this article and the template is available for download at the bottom of this article.
Out of interest, here's how the script is promoted on the author's site:
- Unlimited number of levels
- Can be used with or without frames
- Remembers the state of the tree between pages
- Possible to have as many trees as you like on a page
- All major browsers suported
- Internet Explorer 5+
- Netscape 6+
- Opera 7+
- Generates XHTML 1.0 strict validated output
- Alternative images for each node
d = new dTree("d");
Simple isn't it!?
The method for adding a new node to the tree is called "add()" and the parameters are as follows:
|id||Number||Unique identity number.|
|pid||Number||Number refering to the parent node. The value for the root node has to be -1.|
|name||String||Text label for the node.|
|url||String||Url for the node.|
|title||String||Title for the node.|
|target||String||Target for the node.|
|icon||String||Image file to use as the icon. Uses default if not specified.|
|iconOpen||String||Image file to use as the open icon. Uses default if not specified.|
|open||Boolean||Is the node open.|
mytree.add(1, 0, 'My node', 'node.html', 'node title', 'mainframe', 'img/musicfolder.gif');
The fact that we can apply this so easily to Notes hinges on the first two parameters. The first is the unique ID of the node and the second is the unique ID of its parent. Think of this in Notes terms and we soon see that we can make both parameters the @DocumentUniqueID of the documents and its parent, respectively.
Note: Although the API of the script says that the first two parameters are Numbers, it's not strictly true. We can use the 32 character hex id of a Notes document!
By now, you should start seeing how this would take shape in a Notes view that shows response documents in a hierarchy. The two systems seem made for each other.
Using dTree in Domino:
Hopefully this won't turn in to a lesson in creating response views. We should all be comfortable with this and I'll try and skip the gory details. There's a sample database you can download at the end of the article, so anything you don't understand will be demonstrated in there.
Obviously we need a view. Before I create this I will assume a few things. Firstly, that we are using a simple response document hierarchy consisting of a standard form called "main" and a response-type form called "response". Secondly, that both of these forms contain a field called "MainID" that contains the document unid of the top-most document in the thread.
Create a view and call it "(Threads)". The selection criteria should be something like Select Form="main":"response". By default the view will have the property "Show response documents in a hierarchy" enabled. Leave this so. The only other property to change on the View is to make sure that "Treat view contents as HTML" is selected.
The view needs three columns. The first is categorised column and displays the MainID field I mentioned. Because it's a categorised view we can add it to a form and restrict it to only show documents in one category. In our case we restrict it to the thread we are interested in by using the MainID field of a document. This way we only ever see documents relating to the thread we are interested in.
The second and third columns show the response documents and main documents, respectively. The formula for both columns is very similar. The main difference is that the second column has the property "Show responses only" enabled. You don't have to have the columns in this order but it makes sense in Designer when you view the data, this way. First lets look at the third column's formula:
"mytree.add('"+@Text(@DocumentUniqueID)+"', -1, '"+Title+"', '0/"+@Text(@DocumentUniqueID)+"?OpenDocument')"
First we test to see if the form is the main document. If, and only if, it is we create the "root" node for the tree. This is special because it has the parent id of -1. All trees have to have a root node with this id! If it's not the main document we simply have an empty entry in the column. Note that this "root" node has the ID of the document id of the main document. By definition this is the value of MainID and the same in all documents in the thread.
The second column has the following formula:
"mytree.add('"+@Text(@DocumentUniqueID)+"', '" + @Text($REF) + "', \""+ Title + "\', '0/" + @Text(@DocumentUniqueID)+"?OpenDocument');"
The trick here is that we've used the reserved field called "$Ref" to access the ID of the document's parent. This way we can ensure that every node refers to its rightful parent.The resulting code from both columns would look something like:
mytree.add('246A0A59E91E277486256E1D00812489', -1, "The first main topic", 'all/246A0A59E91E277486256E1D00812489?OpenDocument')
mytree.add('409C234D9868F94586256E1D00814AB9', '246A0A59E91E277486256E1D00812489', "First response (Jake, 16/01/2004 11:32)", 'all/409C234D9868F94586256E1D00814AB9?OpenDocument');
Note how the first response we add has the parent id parameter which is the same as the root node, its parent. Also, that the second node has the parent ID that's the same as the main ID - because it's on the first level of responses.
Extract the zip contents to your hard-drive and get ready to add the ones we need to your database. I'm assuming we're all working with Domino 6, although this script will work with any version.
Import all the images from the "img" folder as Image Resource elements in Designer. Rename them if you like so that they are easily recognised:
Note: Depending on where you placed all the images and how you named them you may need to edit the configuration from within the dtree.js library.
On both the forms we need to embed the (Threads) view. We do this inside <script> tags, like so:
The important step is to make sure that the view is restricted to "Show single category", using the simple formula - @Text(MainID).
Can you see how it all works now? Because the view is treated as HTML and it lives inside a <script> tag, it simply makes a series of calls to the tree's .add() method and build us our navigation. As simple as that. Here's the sample database. Download it and play around.
Taking it further:
Had any ideas about how you can use it yet? Maybe you just want to use it like I've demonstrated, for discussion threads. This isn't the place you can use it though. Obviously, it can be used for displaying documents in any kind of parent/child relationship. Also, it can be used for site navigation at a higher level. Even if you have to hardcode the IDs and links, it's versatile enough to be used all over a site.
If you look at the API documentation for dTree you should get some idea for further enhancements. Notice how you can specify the icon for each node on a document-by-document basis. You could use this to highlight documents or for whatever purpose you see fit.
Whether or not you read this whole article you should all be able to get at least something from the content. I would imagine most of you will simply want to download the demo database and take it from there. It's would be too hard to cover how to create the whole thing from scratch. All this article is meant to do is accompany the download for those who might not be comfortable with working out how it all sits together inside an NSF.