You are not logged in Log in Join
You are here: Home » Members » cybertad » How-To Documents » How-To: Secrets of working with the tree tag

Log in
Name

Password

 

How-To: Secrets of working with the tree tag

Introduction

The DTML tree tag is a very cool feature of Zope. However, too many of it's coolest features are under-documented. Under-documented? Well, basically, as with most things in the Zope world (and that is rapidly changing!), the documentation is there, you just had to search all over to find it, and here are the places to go:

After trying to find information on some of the different usages of the tree tag, and just about going bald at my own hands, I have compiled my findings in this one document.

What you will not find here are the basics. These are pretty well documented in the FAQs or the Users Guide. What you will find are the things that are NOT very well documented. Displaying only certain objects or subobjects, using the tree tag in conjunction with Z SQLMethods, and other obscure, but useful, stuff. By the way, this document assumes Zope 2 and uses the <dtml->...</dtml> syntax.

Displaying only certain objects/subobjects.

As with any documentation efforts by mere mortals such as myself, I can't take responsibilty if what I write is wrong. That said, please, if you know of any changes that need to be made to this document, either with respect to it's accuracy or completeness, please let me know!

For those people not used to the Python way of doing things (which is something that you will pick up quickly, like it or not), the idea of trying to get the tree tag to display only specified objects can be somewhat maddening. Until now.

'<dtml-tree branches_expr="objectValues([Folder, 'DTML Document'])">'

The branches_expr attribute of the tree tag works just like the expr attribute of any other tag (i.e. if, elif, etc.). Looking at it like that, it makes sense that, since all you want to do is pass the objectValues method a valid Python list, you could do this

&lt;dtml-in &quot;currentFolderName.objectValues()&quot; sort=meta_type&gt; &lt;dtml-var meta_type&gt;&lt;BR&gt; &lt;/dtml-in&gt;

Keep folder names from being links

to get a tree of only Folder and DTML Document subobjects. What you are passing in the list is the metatype of the Product. Remember, each Product defines it's own metatype, or "information about the type of product it is". If you want to show more types, just add them to the list. Run the following code to see what metatypes you have access to in objectValues in the current folder.

This is a common problem. When creating a tree of objects, you will want most of them to be clickable. In other words, if you have a tree of documents, you will want to be able to click on the documents link and go directly to it. However, if you have a tree of documents AND folders, you will still want to be able to click on the document link, but NOT on the Folder itself. In the case of Folders, you will just want to click on the +/- sign to the left of it to collapse or expand it. If you were to click on the Folder name, it would take you to the index_html document in that folder and therefore would not display the next branch of the tree.

To remedy this situation, we will test to see if the object we are displaying is a Folder or not. If it is a Folder object, we will only display the name. If it is anything else, we will display it's name as a link. Pretty simple stuff.

'<dtml-tree currentFolderName branches_expr="objectValues()" sort=id> <dtml-if "meta_type==Folder"> <dtml-var title_or_id> <dtml-else> <A HREF="<dtml-var tree-item-url>"><dtml-var title_or_id></A> </dtml-if> </dtml-tree>'

Display object's icon in Tree

The following code will return a tree of all subobjects in the folder currentFolderName and display them sorted by id. It will display Folder objects with a +/- to the left of them, but not as links themselves. Anything that is not a Folder will be clickable.

'<dtml-tree currentFolderName branches_expr="objectValues()" sort=id> <dtml-if "meta_type==Folder"> <IMG SRC="<dtml-var icon>" BORDER=0> <dtml-var title_or_id> <dtml-else> <A HREF="<dtml-var tree-item-url>"> <IMG SRC="<dtml-var icon>" BORDER=0> <dtml-var title_or_id></A> </dtml-if> </dtml-tree>'

Selectively display objects

It is very easy to dispay the icon that is associated with the meta_type of the object. Simply add output, within an HTML Image tag the variable icon. Don't forget to add BORDER="0" to the HTML Image tag, otherwise the icon will display with a large border around it (if it is inside a link).

Ocassionally you might want certain objects to be displayed in your tree, such as the document listing the tree, but not want it to be a link. This is pretty simple.

'<dtml-call "REQUEST.set(thisDocument, id)">'

First of all, we create a variable called thisDocument and assign it the value of the id of the current DTML Document.

'<dtml-tree currentFolderName branchesexpr="objectValues()" sort=id> <dtml-if ".getitem(thisDocument,1) != _.getitem(id,1)"> <IMG SRC="<dtml-var icon>" BORDER="0"> <A HREF="<dtml-var tree-item-url>"><dtml-var title_or_id></A> </dtml-if> </dtml-tree>'

The next thing to do is test your new variable against each iteration of the tree tag. If the id of the current iteration matches the value of the variable you set, then this code will not display that object as a link.

This will not work with DTML Methods, as DTML Methods take on the id of the Folder they are in or the DTML Document that is calling them. Due to the coolness of Aquisition, this can work to your advantage. Something I have done is create a DTML Method that contains all of the above code and use it to do a site map. I include it in my standard_html_header method, and, due to Aquisition, the thisDocument variable that gets set is the id of the calling DTML Document.

more to come...