Anonymous
Domino 2.0 Rich Internet Applications with IBM Lotus Notes/Domino
You are here: Today » Tree component: the Domino side
« @Formula to generate a valid RFC822 date-time
Building a tree component in Domino »

Tree component: the Domino side

This is part 2 of the Domino/Ajax tree component. I will explain the different design elements and code I use.

The 'Folder' and 'Page' forms

Both inherit the ParentUnid field value from their parent when composed. To do this, the 'New page' and 'New folder' actions are computed in a field called 'LocalActions':

a:="<a href=\""+DbPath+"folder?OpenForm&amp;ParentUnid="+inheritunid+"\">New folder</a>";
b:="<a href=\""+DbPath+"page?OpenForm&amp;ParentUnid="+inheritunid+"\">New page</a>";
c:="<a href=\""+DbPath+"pub/"+DocKey+"?editdocument\">Edit</a>";
a:b:c

The HTML fragment used in the detail right pane in folders is computed in a field 'treeValue':

"<li><a href=\""+DbPath+"pub/"+DocKey+"\"><span class=\"folder\"></span>"+Subject+"</a></li>"

The JSON and HTML fragments used in the HTML tree are also computed on the page, in 'aValue' and 'aValue2':

"{id:'"+InheritUnid+"',href:'pub/"+DocKey+"',label:'"+Subject+"',
type:'folder'}"

"<li id=\""+InheritUnid+"\"><b></b><i></i><a href=\"/domino/pub/"+DocKey+"\">"+Subject+"</a><div>...</div></li>"

The 'tree' and 'tree2' views

The 'tree' view is used to render the folder content, both subfolders and pages. This is the formula that gets the contents of a folder:

a:=@DbLookup(""; ""; "tree"; InheritUnid; 3);
@If(@IsError(a); ""; @If(a=""); ""; "<ul>"+@Implode(a; @NewLine)+"</ul>")

The 'tree2' view contains both the JSON and the HTML fragments to build the tree.

The navigator for the Ajax calls

I used a navigator 'ajax-tree' with a '$$NavigatorTemplate for ajax-tree' form. The doctype on the form is 'text/javascript', and there is only one computed field to build the JSON. The formula uses 'LookupId', retrieved from the Query_String:

a:=@DbLookup(""; ""; "tree-2"; LookupId; 3);
b:=@If(@IsError(a); ""; a);
"["+@Implode(b; ",")+"]"

The LotusScript

To render the tree component with the active path expanded and the active folder highlighted, I use a QueryOpen agent 'TreeBuilder'. This includes my StringBuilder Class, and a new Tree Class to render the tree:

Class Tree
    Private s As notessession
    Private db As notesdatabase
    Private     view As NotesView
    Private doc As NotesDocument
    Private active As String
    Private path As String
    Private debug As stringbuffer
    
    Sub New
        Set s=New notessession
        Set db=s.CurrentDatabase
        Set view=db.GetView("tree-2")
        Set doc=s.DocumentContext
        Set debug=New stringbuffer(100)
        path=doc.DbPath(0)
        debug.add "test"
        Call setActive
    End Sub
    
    Sub setActive
        Dim tmp As New StringBuffer(10)
        Dim tmpDoc As notesdocument
        
        Select Case doc.form(0)
        Case "Folder", "Page"
            Set tmpDoc=doc
            tmp.add tmpDoc.UniversalID                    
            While Not tmpDoc.ParentUnid(0)="root"
                debug.add "setActive: " & tmpDoc.subject(0)
                Set tmpDoc=db.GetDocumentByUNID(tmpDoc.ParentUnid(0))
                tmp.add tmpDoc.UniversalID        
            Wend
        End Select
        active=tmp.collapse(",")
    End Sub
    
    Function getTree(Byval sNode As String) As String
        Dim vc As NotesViewEntryCollection
        Dim entry As notesviewentry
        Dim tmp As New StringBuffer(50)
        Dim i As Integer, max As Integer
        Dim sTmp As String, sUnid As String
        Dim sTmpTree As String
        
        Set vc=view.GetAllEntriesByKey(sNode)
        max=vc.Count
        If max>0 Then
            tmp.add "<ul>"
            For i=1 To max
                Set entry=vc.GetNthEntry(i)
                sTmp=Replace(entry.ColumnValues(3), "/domino/", path)
                sUnid=Strleft(Strright(sTmp, |id="|), |"|)
                If i=max Then sTmp=Replace(sTmp, "<li", |<li class="last"|)
                If Instr(active, sUnid)>0 Then
                    sTmpTree=getTree(sUnid)
                    If sTmpTree="" Then
                        sTmp=Replace(sTmp, |<b|, |<b class="none"|)
                    Else
                        sTmp=Replace(sTmp, |<b|, |<b class="min"|)
                        sTmp=Replace(sTmp, |<div>...|, |<div style="display:block">| & sTmpTree)                        
                    End If
                End If
                tmp.add sTmp
            Next
            tmp.add "</ul>"            
        End If
        getTree=tmp.collapse(NEWLINE)
    End Function
End Class

In the main routine, the tree is built and the active folder is highlighted:

Sub Initialize
    Dim s As New notessession
    Dim doc As NotesDocument
    Set doc=s.DocumentContext
    On Error Goto catch
    
    Dim theTree As New Tree
    Dim sTmp As String,sTmp2 As String
    
    sTmp=theTree.getTree("root")
'mark the active folder
    Select Case doc.form(0)
    Case "Folder"
        sTmp2=doc.docKey(0) & |"|
        sTmp=Replace(sTmp, sTmp2, sTmp2 & | class="on"|)    
    Case "Page"
        sTmp2=s.CurrentDatabase.GetDocumentByUNID(doc.parentUnid(0)).docKey(0) & |"
|
        sTmp=Replace(sTmp, sTmp2, sTmp2 & | class="on"|)    
    End Select
    doc.ReplaceItemValue "TreeComponent", sTmp

    Goto finally
catch:
    sTmp="Error " & Err & " in line " & Erl & ": " & Error$
    doc.ReplaceItemValue "TreeComponent", sTmp
    Resume finally
finally:
End Sub

Finally

This is just a proof of concept. A lot of enhancements can be made: better error trapping, adding a breadcrumb trail from the tree, adding display options as in Windows Explorer, etc. I've included the sample database so that you can study it. Have fun.

Download

tree.nsf (384 kB)

Star rating

100%

Comments

  1. 2008-01-03 13:57:37, Patrick Kwinten

    wow! this looks quiet impressive! thanks for the worked out example! now I will digg in the code and see if I understand it :o)

To add a comment, log in or register as new user. It's free and safe.