C - A class to manage displaying a hash tree of data, for use in CGI scripts


CGI::Explorer - A class to manage displaying a hash tree of data, for use in CGI scripts

The format of the hash is discussed in the FAQ section.


Install /css/xtree.css, /js/xtree.js, and /images/*, as per the installation instructions, below.

Then run the demos example/bootstrap-hobbit.pl, which creates a database table using DBIx::Hash2Table, and then example/hobbit.cgi, which reads a database table using DBIx::Table2Hash.

Or, run example/hobbit-hash.cgi which has the same hash directly in the source code.


CGI::Explorer is a pure Perl module.

It is a support module for CGI scripts. It manages a hash, a tree of data, so that the script can display the tree, and the user can single-click on the [+] or [-] of a node, or double-click on the icon of a node, to open or close that node's sub-tree.

Opening a node reveals all children of that node, and restores their open/closed state.

Closing a node hides all children of that node.

When you click on the text of a node, the node's id is submitted to the CGI script via the path info of the URL attached to that node. This path info mechanism can be overridden.

The id is assigned to the node when you call the method hash2tree(), which is where the module converts your hash into JavaScript.

Neither the module CGI.pm, nor any of that kidney, are used by this module.


The makefile will install /perl/site/lib/CGI/Explorer.pm.

You must manually install <Document Root>/css/xtree.css, <Document Root>/js/xtree.js, and <Document Root>/images/explorer/*.

If you choose to put the CSS elsewhere, you'll need to call new(css => '/new/path/xtree.css').

If you choose to put the JavaScript elsewhere, you'll need to call new(js => '/new/path/xtree.js').

These last 2 options can be used together, and can be passed into hash2tree() or set() rather than new().

If you choose to put the images elsewhere, you'll need to edit lines 69 .. 81 of xtree.js V 1.17.

Warning: V 1 'v' V 2

The API for CGI::Explorer version 2 is not compatible with the API for version 1.

This is because version 2 includes CSS and JavaScript to handle expanding and contracting sub-trees purely within the client. No longer do client mouse clicks cause a round trip to the server/CGI script and back.

Constructor and initialization

new(...) returns a CGI::Explorer object.

This is the class's contructor.

Almost every option is demonstrated by the program example/hobbit.cgi.

Note: All methods (except get()) use named parameters.



Q: What is the format of this thing you call a 'hash tree'?

A: It is simply a hash, with these characteristics:

Q: Why use em rather than px in left_style and right_style?

A: The designers of CSS2, Hakon Lie and Bert Bos, recommend using relative sizes, and specifically em.

Q: Why does my tree display 'funny'?

A: Because browsers vary in how well they render CSS.

Under Win2K, IE 6.00.2600, the style 'overflow: auto' in left_style renders as it should.

Under Win2K, IE 5.00.3502, 'overflow: auto' renders as though you had specified 'overflow: visible'.

Q: How do I configure Apache V 2 to use /perl/ the way you recommend in the next Q?

A: Add these options to httpd.conf and restart the server:

        Alias /perl/ "/apache2/perl/"
        <Location /perl>
                SetHandler perl-script
                PerlResponseHandler ModPerl::Registry
                Options +ExecCGI
                PerlOptions +ParseHeaders
                Order deny,allow
                Deny from all
                Allow from

Q: How do I run the demo?

A: Install example/hobbit.cgi as /apache2/perl/hobbit.cgi and run it via your browser, by typing

into your browser. Study the screen.

Now, click on the [+] signs to open the tree until you can see 'Evil Grey Gnome', noting the spelling of Grey.

Now click on the text 'Evil Grey Gnome'.

Lastly, click on 'Prettiest grand gnome' in the breadcrumb trail. Neat, huh?

Note: The update button in example/hobbit.cgi does not actually do anything.

Q: How are node ids generated?

A: Well, by rolling your mouse over the nodes' texts, you can see in the browser's status line URLs like:

(for Evil Grey Gnome)

These ids are generated sequentially, starting with 'rm00000'. So, the second id will be 'rm00001', and so on.

The initial value is the default value for the node_id parameter to new() or hash2tree().

Hence you can control the values of the ids by initializing the node_id parameter, subject to the warnings which follow.

Values for node_id are generated for all nodes in the hash tree for which you have not supplied a node-specific value for node_id.


Q: How is the breadcrumb trail in example/hobbit.cgi generated?

A: See the source.

Q: How do I know when to pass a given parameter in to a method? Eg: Do I call new() or hash2tree() to set a value for node_id or current_icon?

A: You can pass in any parameter to any method (except get()) at any time before that parameter is actually needed.

All methods (except get()) take a list of named parameters, and store the values of the parameters internally within the object.

So, when you see this code in example/hobbit.cgi:

        my($tree)       =$explorer->hash2tree(current_id=>$current_id,hashref=>$hash);

you know the call to id2key() must be using the value of current_id passed in in the call to hash2tree().

You could have used this code:

        my($tree)       =$explorer->hash2tree(hashref=>$hash);

but that would mean the value of current_id was not available during the call to hash2tree(), so the current node in the tree could not have had the special icon designated by the value of the parameter current_icon (if you passed in a value for current_icon in the call to new() or hash2tree() of course.), because at the time of calling hash2tree(), the code in that module would not know the value of current_id.

Even worse, if current_id somehow had a value from a previous call to a method, the wrong node would be flagged as the current node.

Q: I'm running on a Pentium II at 266MHz. I'm finding that as I get up to many hundreds of nodes, it takes a long time to update the screen.

A: Yes.

Emil has kindly offered to work on speeding things up. I have one idea, but have not tried implementing it yet.

Method: hash2tree(current_id => $current_id, hashref => $hash)

Returns the JavaScript which populates the tree.

You can also retrieve this JavaScript by calling:

        $explorer -> hash2tree(hashref => $hashref);
        my($tree) = $explorer -> get('jscript') . $explorer -> get('tree');

Note: $explorer -> get('js') returns the name of the file of JavaScript written by Emil, ie '/js/xtree.js', by default. Try not to get the 2 options 'js' and 'jscript' confused. It'll make you look silly :-).

The 2 parameters listed here are those you would normally pass into hash2tree(), but you are not limited to these parameters.

Method: get('Name of object attribute')

Returns the value of the named attribute. These attributes are discussed above, in the section called 'Constructor and initialization'.

The demo example/hobbit.cgi calls this method a number of times.

Method: get_node([current_id => $id])

Returns a hash ref.

The [] refer to an optional parameter, not to an array ref.

This method uses the value of current_id to find and return the node corresponding to current_id.

If current_id is '', the get_node returns the value you previously passed in for the hashref option.

Method: id2key([current_id => $id])

Returns a string.

The [] refer to an optional parameter, not to an array ref.

This method converts a node id, eg retrieved from the path info, into a string which contains, in order, all hash keys required to find the node within the tree.

The hash keys are separated by $;, aka $SUBSCRIPT_SEPARATOR.

The demo example/hobbit.cgi has an example which uses this method.

Method: key2id([current_key => $key])

Returns a string.

The [] refer to an optional parameter, not to an array ref.

This method converts a string of hash keys, concatenated with $;, into the corresponding node id.

By default, this method uses the value of current_key generated by a previous call to id2key().

Method: key2url([current_key => $key])

Returns a string.

The [] refer to an optional parameter, not to an array ref.

This method converts a string of hash keys, concatenated with $;, into the corresponding node URL.

By default, this method uses the value of current_key generated by a previous call to id2key().

Method: new(...)

Returns a object of type CGI::Explorer.

See above, in the section called 'Constructor and initialization'.

Method: set(%arg)

Returns nothing.

This allows you to set any option after calling the constructor.

Eg: $explorer -> set(css => '/css/even_better.css');

Icons for Nodes

CGI::Explorer ships with an images/ directory containing 1 or 2 (open/closed) PNGs for each icon.

Most of these icons are those shipped by Emil A Eklund in his xtree package.

I have added 3 icons to the set, all from this web site:


The make file does not install this images/ directory automatically. You must install it manually under the web server's document root.

Required Modules

None, not even CGI.pm. Well OK, one - Exporter.

In particular, the fine module Tree::Nary, used in V 1 of CGI::Explorer, is no longer needed.


See Changes.txt.


CGI::Explorer V 2 depends heavily on the superb package xtree, written by Emil A Eklund, and in fact my module is no more than a Perl wrapper around xtree.

Please visit the web site http://www.eae.net (from his initials) where more goodies by Emil and his colleague Erik Arvidsson are on display.

Unused Namespace - DBIx::CSS::TreeMenu

In the POD for 2 recent modules, I intimated I was going to release a module called DBIx::CSS::TreeMenu, which of course was to be based on xtree.

However, I've since decided to incorporate these ideas into CGI::Explorer V 2.

There is clearly no need for the current module to be linked into the DBIx:: namespace. Further, CSS is a mechanism used, and while it could be in the namespace, I no longer think that is appropriate. Otherwise, any module using CSS would have CSS:: in it's name, and taken to the illogical extreme, all modules would be in the Perl:: namespace!

So, I'm abandoning all plans to issue a module called DBIx::CSS::TreeMenu.

However, I still have my eye on another package, by Erik Arvidsson, called tabpane. I am intending to put a Perl wrapper around tabpane, but have not yet decided on a Perl module name.


CGI::Explorer was written by Ron Savage <ron@savage.net.au> in 2001.

Home page: http://savage.net.au/index.html


Australian copyright (c) 2001, Ron Savage. All rights reserved.

        All Programs of mine are 'OSI Certified Open Source Software';
        you can redistribute them and/or modify them under the terms of
        The Artistic License, a copy of which is available at:

 C - A class to manage displaying a hash tree of data, for use in CGI scripts