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&ParentUnid="+inheritunid+"\">New folder</a>";
b:="<a href=\""+DbPath+"page?OpenForm&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.
Comments
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.