logo

Notes Thread Navigation With DHTML

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:

image

Looking at the same view in the browser, by default, we see this:

image

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:

image

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.

JavaScript to the rescue:

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+
    • Mozilla
  • Generates XHTML 1.0 strict validated output
  • Alternative images for each node


Using dTree:

Before we look at using it with Domino, let's see how it works on a normal page. Here's the source JavaScript requried to generate a simple tree:

d = new dTree("d");
d.add(0,-1,"Codestore Navigation");
d.add(1,0,"Related Articles");
d.add(2,1,"Article 1","unid/DOMM-4Y9KZH?OpenDocument");
d.add(3,1,"Article 2","unid/DOMT-5UBUVW?OpenDocument");
d.add(4,0,"About Codestore","about?readform");
document.write(d);

Simple isn't it!?

The method for adding a new node to the tree is called "add()" and the parameters are as follows:

Name Type Description
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.


Example:

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:

@If(form="main";
"mytree.add('"+@Text(@DocumentUniqueID)+"', -1, '"+Title+"', '0/"+@Text(@DocumentUniqueID)+"?OpenDocument')"
;"")+@NewLine

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.

Now we need to place this view on both main and response forms, so that, whenever you open a document in a discussion, you get to see the whole thread as a navigation tree. First thing to do is add the required JavaScript file for the dTree code along with the dTree CSS file. You can download all the files needed here.

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:

image

Create a new JavaScript Library in Designer and paste in the text content of dtree.js. Save the library and call it "dtree.js". Import the dtree.css file in to the Style Sheets section of the database's shared resources. These are all the files you need in order to get started.

Now, in the HTML Head Content section of both forms, make sure the CSS and the JavaScript files are included. If you don't know how to do this, don't worry, the example database shows you how.

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:

image

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.

Summary:

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.

Feedback

    • avatar
    • Andrew Tetlaw
    • Fri 20 Feb 2004

    Way cool & a warning

    Thanks Jake! Just what I was looking for. dtree is exactly the kind of javascript API I like. It's simple, does only 1 thing very well, has an easy to understand API, very little config/setup and do on. Too many dhtml APIs are humungous and try to offer everything under the sun. The end result is often a confusin mess of an API and a huge config burden just to get started. Some more simple APIs can be found at http://youngpup.net .

    Anyways, I noticed that the dtree code uses the ids to write the current tree state to a cookie (if enabled). Cookies do have a maximum length for cookie values, last time I checked it was 4k. With your example thread and all nodes open the cookie looks like this:

    "409C234D9868F94586256E1D00814AB9.29E6FF4DA81977EE86256E1D00815498.9117CC01D83A7 17686256E3E003C0D08.E7829B0A4504AB6086256E3E00467693.74C22D0B707E662086256E3F002 DD052.E4DA017B1C3F684986256E3F00698333.AE7DF2A1AB4E95A086256E3F006B906B.3DEC0F9A F65152FA86256E3F006B98EA.7D143565619780FB86256E3E0052CD4B.5285FBB8F382329886256E 1D00817028.FF1C622AEFE6525186256E3E003B56D0.AE47DA647858A2FF86256E3E0053BDDC.944 208A3EB3CE8F286256E3F00540FE7.D95EC20C8C45C94680256E1E00572367.83D46D4AF7B40FFC8 6256E3E003AF24D.C4BBC3E4B803887886256E3E003B4B83.A15840E0423F970F86256E3E003B0E9 C.0EC57DB9241C718186256E3E0061C64D.628AEAFAECC9C39486256E3E0075DE5E"

    Which is only 626 bytes long. My point is a huge view with lots of tree nodes open may blow the limit. Small chance I know, but something to keep in mind.

    Anyway, off to implement! Thanks again.

  1. Great article Jake!

    Great article Jake - I'll be testing this out with a view to making navigation in a few of my webapps a tad more intuitive.

    Y'know I could never spell Feburary either ;) Justin

    • avatar
    • YoGi
    • Fri 20 Feb 2004

    Well, nice, but..

    I made a similar javascript library, for identical purposes, few months ago (not as advanced though :). What i realized is that acting this way was not a good idea, because i was losing some views benefits ; especially the facts that you always get a small chunk of the results ; you collapse a thread, you expand another, etc. Thus, users were not downloading a huge html page, but lots of small html pages. When you have thousands of entries, i'm sure that's much more convenient (would your users accept to download ~x00Kb pages and wait for the tree to compute ?). And browsing on several pages does not help us in that issue.

      • avatar
      • Jake Howlett
      • Fri 20 Feb 2004

      Re: Well, nice, but..

      Good point YoGi.

      Something I forgot to talk about was view document counts. By default this is 30. So, if a discussion goes beyond this number of document, you won't see them!

      There are ways round this. You can add count=-1 to the end of all the URLs or you can change the default count property of the embedded view to a higher number.

      I know it means more HTML to download, but so do all discussion templates where you see the thread of every page. The Notes.net forums, for example.

      Jake

    1. Re: Well, nice, but..

      So I am agree with YoGi. Same way I did before 4 years. I’ve created domino database based folders tree. It works fine in small databases and degrees download time in big databases. More documents in view - more time to download it. And in very big views tree generation take unacceptable time. The solution we found is to load only first level nodes while page downloading, and each node click downloads its sub-nodes. The advantage is it loads and renders very quick, - the disadvantage is it works only in MS Internet Explorer because of using Microsoft.XMLDOM ActiveX Control.

      Fabian Nirman

      SharePlace.info

      Show the rest of this thread

  2. A nice feature is the auto expand a defined node

    A nice feature of the script is the ability to expand automatically a defined node.

    Take for example a help application which uses the tree in the left side whilst displaying the help document in the right - you could link directly to the appropriate help document (from within another application) and once opened auto expand its place in the tree.

    Works very well and gives context sensitive navigation. I guess this would work just as well for site navigation.

    • avatar
    • Adam Gadsby
    • Fri 20 Feb 2004

    Slight Problem With Your Code

    Jake,

    I have experienced a minor issue with your code in your article.. I had to modify the "(threads)" view, column 2 formula to the following:

    "mytree.add('"+@Text(@DocumentUniqueID)+"','"+@Text($REF)+"','"+Title+"','0/"+@T ext(@DocumentUniqueID)+"?OpenDocument');"

    otherwise I received an error if there were any responses.

    Just thought I would share this incase anybody else experiences the same problem.

    Other than that, its a great article.

    Cheers Adam

      • avatar
      • Adam Gadsby
      • Fri 20 Feb 2004

      Re: Slight Problem With Your Code

      Forgot to say, the bit I changed is just before the +Title bit... you had: \"" (2 double quotes)

      I had to change it to: '" (single quote double quote)

      Ta

    • avatar
    • Paul
    • Fri 20 Feb 2004

    We sussed this about 18 monts ago

    • avatar
    • Tamer
    • Tue 24 Feb 2004

    More scalable with XML

    Making an XML-based view and using something like the XLoadTree script ( http://webfx.eae.net/dhtml/xloadtree/xloadtree.html ) let's you dynamically load just the part of the tree that the user is viewing/acting on. This is especially helpful in larger views -- plus the XML-tagged views can be used for various purposes with XSLT, rather than the very specific purpose of this JS implementation.

      • avatar
      • Jake
      • Tue 24 Feb 2004

      NICE! Re: More scalable with XML

      I can see another article on its way. Thanks Tamer!

    1. XloadTree view

      Hi

      I actually made some webviews based on XloadTree a couple of years ago. It is pretty cool but it is only useful with small amounts of documents in each category. Otherwise it is VERY slow. And IE goes bananas with RAM..it eats away ...plus the old cache bug in IE means it loads the graphics for every document from the server and not from the cache.

      regards Jesper Kiær http://www.jezzper.dk

  3. Holy Grail: the only way to go is...

    Typical really. You come up with a neat piece of code and some smart arse pokes faults in it:

    - Its slow to load - It won't cope with large amounts of data

    The environment we've chosen to work within is always prone to these problems. Indeed anything Domino view based is always going to perform 'badly'.

    I downloaded dTree and ruthlessly pulled it apart to serve my own meek needs, added xml functionality along the lines of xTree and came across all the same problems. But for me it didn't matter. My goal was to build a non-scalable tree of a known size but not a known content.

    In order to acheive the holy grail though what we need is a set of basic building blocks:

    - Virtually scrolling interface so that top level we can fetch data on demand and only download enough to fill the visible region. - Fetch data on demand using xml to populate all levels of the tree/view - Build all icons and images using best practice methods to avoid caching

    Of course doing all of the above cross browser, modular and configurable will indeed be challenging and perhaps costly.

    1. Re: Holy Grail: the only way to go is...

      If you have a code ex. with Fetch data on demand, will you then send it to me ?

      Please....

    • avatar
    • TomK
    • Tue 27 Apr 2004

    Great Stuff Jake

    Just wonder, how do you implement the openAll() and closeAll() method on Domino. I havetried but failed.

    Regards,

    1. Re: Great Stuff Jake

      This article is exactly what I have been looking for. However, some of my views are receiving a "Stack Overflow" or "Out of stack space" error. Any ideas why this is happening?

  4. Limitation of the number of nodes in the tree

    Hi, I'm using the dtree. and if the number of nodes goes beyond 1000, my internet explorer 6.0 shows an error saying that "the script might cause the browser to run slow".. any workarounds or solutions will be helpful..

    regards, Gaurav

    1. Re: Limitation of the number of nodes in the tree

      It is posible to use @DocNumber and @DocParentNumber instead of the 32 character long DocumentUniqueID. This will probably give you some more documents in the view before you start to get the Error msg. And it will be a lot less characters to load into the browser.

      Then the code would lokk something like this:

      ID := "'" + @DocNumber + "'"; PID := "'" + @DocParentNumber + "'";

      "myMenu.add(" + ID + "," + PID + ",'" + Name + "','" + link + "');"

    • avatar
    • Romano Soprano
    • Fri 1 Jul 2005

    Long line wrapping?

    Great article. I only have one question. Is there a way to make text wrapping look good - not cut at the right side ('white-space: nowrap;' in the dtree.css file) and indented at the left side? Something like this site http://javascript.cooldev.com/scripts/cooltree/demos/wrapping/ This site's example only works in IE but I would really like to see the Gecko solution. Maybe I should ask Geir Landrö, the creator of dTree.

  5. Limitation of dtree

    Hi, I am facing a problem while using dtree.js when the size of the data is increased it is unable to load all the data. So, i would like to know if there is any limitation in the dtree.js.

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:



Navigate other articles in the category "JavaScript"

« Previous Article Next Article »
Overcoming DBLookup Size Limits   Making Domino Behave Relationally, Part 2

About This Article

Author: Jake Howlett
Category: JavaScript
Hat Tip: Mark Barton
Keywords: response; hierarchy; discussion; thread; tree;

Attachments

fancy_threads-v1.0.zip (174 Kbytes)

Options

View Online Demo
Feedback
Print Friendly

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »