XUL Tree Variables

XUL TreePictured here is part of what I’ve been working on for the last few days. I won’t go into much detail, but it’s a Firefox extension to improve the bookmark experience (does anybody actually use bookmarks? I save them but seldom have the heart to go back to the horrible user interface to retrieve them). Essentially, the project lets you label the bookmarks and have them closer at hand (in a sidebar) while browsing. It’s similar to del.icio.us but provides a nice integrated user interface and should eventually have a lot of bells and whistles that make it just an absolute singing joy to use. But it wasn’t easy.

The picture shows a tree, which is a XUL element useful for maintaining lots of information efficiently. You’ll recognize the tree from email programs, the Windows explorer, (conceptually) Web site navigation in many cases, and other places. Trees can be a pain to work with in XUL in particular because they’re populated by data in the RDF format. And there are all sorts of weird things about using RDF with trees. For example, you use a template to do so, and this makes it so that you can’t actually directly manipulate individual tree cells as elements in the document object model. They don’t exist. If you try to iterate down the XML defining the tree, you have no access to the elements that the RDF populated the tree with, so you can’t really perform operations on the elements. Additionally, a treecell keeps only a label and a value applied to it, and there are no functions for grabbing other attributes you may wish to store for a tree cell. In my case, I need a title and a value (the link itself) for displaying and clicking on a bookmark. But I also need to know what label has been applied to a given bookmark so that I can manipulate it. And since there’s no way I can divine to store a third value associated with a given treecell, I’m kind of up the creek.

Or not. It occurred to me that I could just add another treecell to the row and not display it. So where, before, an excerpt of my template looked something like this:

            <action>
                 <treechildren>
                    <treeitem uri="?category">
                        <treerow>
                            <treecell label="?label" value="?url" src="chrome://bookmarks/skin/buttons/document.png"/>
                        </treerow>
                    </treeitem>
                </treechildren>
            </action>

Now it looks more like this:

            <action>
                 <treechildren>
                    <treeitem uri="?category">
                        <treerow>
                            <treecell label="?mycategory" value="?mycategory"/>
                            <treecell label="?label" value="?url" src="chrome://bookmarks/skin/buttons/document.png"/>
                        </treerow>
                    </treeitem>
                </treechildren>
            </action>

I’ve added a treecell that contains the category associated with the given link. I then tweak my column headers to look like this:

        <treecols>
            <treecol id="category" hidden="true" label="Tag" flex="1" ignoreincolumnpicker="true"/>
            <treecol id="url" label="Bookmarks" primary="true" flex="1"/>
        </treecols>

The “ignoreincolumnpicker” attribute prevents the header from being displayed in a little button that lets you pick which columns to display in the tree. That’s just an extra precaution, though, as there’s an attribute on the tree tag itself named “hidecolumnpicker” that defaults to false and that I’ve set to true.

While this method actually does exactly what I need it to do, I’m not altogether satisfied with it because it feels a little jury-rigged. Trees should be for display of data rather than for manipulation of it. It seems as if there should be some way to store other values within a tree cell or tree row that can be extracted, but in most of a day’s wheel spinning, I could find none because the elements of an RDF-generated tree are moving targets that you can’t directly manipulate. In any case, this method seems to work for now, and I’m sticking with it barring feedback from any gurus who can point out something obvious that I’m missing.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s