Building a tree component in Domino
A tree component is a nice thing to have. People are used to organize their documents and files in folders and subfolders. In my previous post, I've asked what would be on your wish list. Patrick Kwinten and Theo Heselmans stepped forward, Patrick with the tree component and Theo with a date picker. There are many good date pickers around, so I decided to have a go at the tree component.
The HTML
A tree is basically nothing more than a set of nested unordered lists. I've added a few tags to handle the presentation and the behaviour: b for the expand/collapse buttons, i for the folder icon and a div to put the child elements in with Ajax:
<div class="tree"><ul>
<li id="aaa"><b></b><i></i><a href="">Lorem ipsum dolor sit amet</a><div>...</div></li>
<li id="bbb"><b></b><i></i><a href="">Ut enim ad minim veniam</a><div>...</div></li>
<li id="ccc" class="last"><b></b><i></i><a href="">Excepteur sint occaecat</a><div>...</div></li>
</ul></div>
The CSS
.tree{border:inset 1px;background:#fff;padding:2px;height:300px;overflow:auto}
.tree ul{list-style:none;margin:0;padding:0;background:url(line1.gif) repeat-y}
.tree li{clear:both;line-height:18px}
.tree .last{background:#fff url(line2.gif) no-repeat}
.tree b,.tree i{display:block;float:left;width:18px;height:18px}
.tree b{background:url(plus5.gif);cursor:pointer}
.tree b.min{background:url(min.gif)}
.tree b.none{background:url(none.gif);cursor:default}
.tree a{text-decoration:none;color:#000;padding:0 4px}
.tree a.on{background:#66f;color:#fff}
.tree i{background:url(folder.gif)}
.tree div{margin-left:18px;clear:both;display:none}
This gives the following result:

The Ajax
The JavaScript G.tree singleton is used to add the expand/collapse behaviour to the tree. When it finds three dots, it knows that it has to retrieve the child nodes with an Ajax call. The response format is JSON, e.g.:
[{id:'',href:'pub/BEDE-7A69QL',label:'Binaries',type:'folder'},{id:'',href:'pub/BEDE-7A5GKY',label:'Templates',type:'folder'}]
This is my Ajax singleton. It's probably the smallest code you can get away with:G.ajax={
_:function(){var w=window;return w.XMLHttpRequest?new w.XMLHttpRequest():w.ActiveXObject?new ActiveXObject('Microsoft.XMLHTTP'):null},
get:function(a){var o=this._();o.open('GET',a,false);o.send(null);return o}
}
The JavaScript tree
G.tree={
init:function(){
var m=this,o=$$('div'),i
for(i=0;i<o.length;i++){if(o[i].className=='tree')m.prepare(o[i])}
},
prepare:function(a){
var m=this,o=$$('ul',a)[0],i,p,q
if(G.gecko)G.clean(o)
q=o.childNodes;for(i=0;i<q.length;i++)$$('b',q[i])[0].onclick=m.click
q=$$('a',o);for(i=0;i<q.length;i++)q[i].onclick=m.set
},
set:function(){
var m=G.tree,o=this,q=m.active
if(q)q.className='';o.className='on';m.active=o
},
click:function(){
var m=G.tree,o=this,s=$$('div',o.parentNode)[0],cn=o.className,n=cn==''
if(cn=='none')return
o.className=n?'min':'';s.style.display=n?'block':''
if(s.innerHTML=='...')m.load(o.parentNode.id,s)
},
load:function(a,b){
var v=G.ajax.get(G.session.path+'ajax-tree?open&id='+a).responseText
G.tree.add(v,b)
},
add:function(a,b){
var m=G.tree,o=eval(a),i,q,p,n=o.length
b.innerHTML=''
if(n==0){b.style.display='';$$('b',b.parentNode)[0].className='none';return}
q=G.create('ul')
for(i=0;i<n;i++)m.add2(q,o[i])
q.childNodes[i-1].className='last'
b.appendChild(q)
},
add2:function(a,b){
var m=this,o=G.create('li',{id:b.id}),f=G.append,p=G.session.path
f(o,'b',{onclick:m.click})
f(o,'i',{className:b.type})
f(o,'a',{href:p+b.href,innerHTML:b.label,onclick:m.set})
f(o,'div',{innerHTML:'...'})
a.appendChild(o)
}
}
Next
In my next post, I'll explain what happens on the Domino side and I'll add a sample database to download.
Comments
To add a comment, log in or register as new user. It's free and safe.