NAME
TreeNavigator - Navigation in a tree structure
SYNOPSIS
<head>
<script src="prototype.js"></script>
<script src="Keymap.js"></script>
<script src="Navigator.js"></script>
<link href="Navigator.css" rel="stylesheet" type="text/css">
</head>
<body onload="new GvaScript.TreeNavigator('TN_tree')">
<div id="TN_tree">
<div class="TN_node">
<span class="TN_label">Label 1</span>
<div class="TN_content">
<div class="TN_node">
<span class="TN_label">Label 1.1</span>
<div class="TN_content">
...Content of node 1.1
</div>
</div>
<div class="TN_leaf">
<span class="TN_label">Label 1.2 for leaf</span>
</div>
</div>
</div>
</div>
</body>
DESCRIPTION
Handles navigation in a data tree. The tree description is usual HTML, with some special classes to identify nodes. Nodes can be browsed, closed or opened. All operations take place directly within the tree, not in a separate panel.
To read further chapters of this documentation, use the arrow keys or the TAB
key. To see the whole page at once (for example for printing), press the Ctrl-keypad *
key.
DESTRUCTOR
mytreenavigator.destroy();
This method will remove all handlers assigned to tree navigator. Call this method when the tree navigator element is removed from the DOM.
Tree structure
A tree is a collection of nodes. Each node must have a label element and can have a content element. A node may be either open (its content is visible) or closed (its content is invisible). The label of the node is always visible, if the node itself is visible. Some nodes can be declared as leaves : in that case they have no content and have no open/close operations.
The content of a node may include other nodes, so a whole subtree may become invisible if the parent node is closed. Opening or closing nodes may be controlled by the mouse, by the keyboard, or through the programming interface.
A node's content may also by dynamic, by specifying TN:contentURL
with the URL as value:
<div class="TN_node TN_closed" TN:contentURL="/my/url.html">
<div class="TN_label">Label for dynamic node</div>
</div>
If the user opens that node, the content of the URL will by dynamically fetched and inserted into the tree. The content then stays there, but can be forcibly reloaded by hitting the Ctrl-R
key.
HTML tree declaration
The tree can be any HTML block element. It should contain one or several block elements declared with class TN_node
or class TN_leaf
-- usually these are DIV elements. Other HTML elements may be freely interspersed with nodes, although this usually does not make much sense for navigability.
Every node must in turn contain an inline element declared with class TN_label
-- usually this is a SPAN element. If the node is not a leaf, it may then contain a block element declared with class TN_content
-- usually this is another DIV element. Both the label and the content should be direct children of the node element.
At initialisation time, a new SPAN element is automatically inserted before each label, in order to add the +/- navigation buttons.
Icons customization
By default, the navigation buttons inserted on the left of labels are small icons representing +/- signs. To show other icons, change the CSS rules about the TN_button
class:
.TN_button {
background-image: url(myIconForOpenNodes.gif);
}
.TN_closed .TN_button {
background-image: url(myIconForClosedNodes.gif);
}
In addition, if you want another icon for illustrating the node's content (like for example an open or closed folder), you can proceed as follows:
add an empty
span
element within the labels that should have the icon<span class="TN_label"><span class="specialNode"></span>some label</span>
define CSS background images for selectors
.specialNode
and.TN_closed .specialNode
, as in the example above
Usage : navigation
Navigation in the tree is either with the mouse or with the keyboard. At any point in time, at most one node is selected : this is the one that receives keyboard events. Hence if the tree has no selected node, no keyboard events are interpreted.
Mouse events
Mousing over a node label adds the class TN_mouse
to that node; the default style for that class is just to underline the label.
Clicking on a node label selects that node and fires the Ping
event. Clicking on the square +/- icon on the left of the label toggles the open/closed status of the node.
Keyboard events
keypad +
-
open the node
keypad -
-
close the node
keypad *
-
open the node and all its subnodes
keypad /
-
close the node and all its subnodes
Ctrl-keypad *
-
activate "show all" mode (the content of closed nodes is nevertheless visible, which may be useful for printing)
Ctrl-keypad /
-
deactivate the "show all" mode
TAB
-
if closed, open the node; if already opened, pass focus to the next item (maybe the next node, or another tabindex-enabled HTML element, such as a form control).
ARROW_UP
-
move to previous displayed node
ARROW_DOWN
-
move to next displayed node
ARROW_LEFT
-
if open, close the node; if already closed, move to parent node
ARROW_RIGHT
-
if closed, open the node; if already open, move to next subnode
HOME
-
select the first node of the tree
END
-
select the last visible subnode of the tree
Ctrl-PAGE_UP
-
select the enclosing node (useful if not positioned on a node, but within a long node content)
Ctrl-PAGE_DOWN
-
select the displayed node after the current enclosing node (useful if not positioned on a node, but within a long node content)
Ctrl-R
-
refresh the node's content (if that node has an URL for dynamic content).
RETURN
-
fire the
Ping
event Ctrl-1
..Ctrl-9
-
close all nodes at level of the specified digit, and open all nodes above
char(s)
-
Tree navigator supports the 'Find As You Type' feature that allows quick node navigation when you type a series of characters. This feature is enabled by default whenever any node is active. The series of characters are cleared after an 800ms timeout of no character input. After that, a new search will be effective.
Programming interface
Methods
new GvaScript.TreeNavigator
var treeNavigator = new GvaScript.TreeNavigator(
elem,
{opt1:"val1", opt2:"val2", ...}
);
Creates the object that controls navigation in the tree. Arguments are
elem
-
the HTML element containing the tree, or the id of that element.
options
-
an optional inline object specifying options.
The tree navigation object is returned, which may be useful if you later want to act on the tree programmatically (opening or closing nodes).
Unless otherwise specified, the method adds a tab index to each label (so that the user can jump to the next label through the TAB
key). The method also registers onfocus
, onblur
, onmouseover
, onmouseout
and onclick
handlers for label elements. Finally, as already mentioned, a new SPAN element is automatically inserted before each label.
Available options are:
tabIndex
Which tabIndex will be assigned to node labels. If labels should not participate in tabbing, specify a value of -1 (this is the default).
Setting tabIndex >= 0
is especially useful for structuring forms in treeNavigator sections : then the user will be able to smoothly tab from section headers (i.e. treeNavigator labels) to form fields within these sections.
treeTabIndex
Which tabIndex will be assigned to the tree element (if not already specified in markup). The default is 0; specifying a higher value would give a higher priority to the tree navigator within the tabbing order.
Setting tabIndex
to a negative value means that the tree navigator receives no focus. In that case, the keymap created for capturing keyboard events will be bound globally to the document
element (and therefore might interact in unpredictable ways with other elements capturing keys; so this is not a recommended setting).
flashDuration
Duration (in milliseconds) of "flashing", i.e. visual feedback when a key is pressed in a wrong context, like for example trying to open a node which is already open; default is 200 ms.
flashColor
Color for "flashing", expressed as standard CSS color; default is red.
selectOnButtonClick
If true, clicking on a "+/-" button next to a label will not only open or close the node, but will also select that node; default is true.
noPingOnFirstClick
If true, clicking on an unselected node will just select that node, without firing the Ping
event. Since the node will then be selected, a second clic (or a double-clic) will fire the event.
This option is false
by default.
selectFirstNode
If true (the default), the first node is selected and gets focus just after constructing the tree navigator.
createButtons
If true, creates the "+/-" buttons next to labels; default is true.
autoScrollPercentage
Makes sure that the selected node is visible in the central area of its offset parent; if not, the parent is scrolled. The percentage is the ratio between the parent height and the margin at which scrolling must occur (default is 20%);
keymap
A keymap object (see Keymap.js
). If that option is given, keyboard handlers are pushed into that keymap; otherwise a new keymap is created.
If you supply your own keymap, make sure that:
the keymap is attached to an element that properly receives keyboard events. The document element does, but the tree DIV element does not, unless it contains items with activated focus (with
tabIndex
defined and positive).the keymap is created with options
preventDefault:false
andstopPropagation:false
(because when the tree has no selected node, the tree navigation handlers do not consume events and try to propagate them further).
classes
Class names for various parts of the tree structure. This should be an inline object, with keys corresponding to the names below, and with values specified either as a single class name or as an array of class names.
- node
-
Class(es) for node elements (default is
TN_node
). A node should contain a label element and a content element, and should have styledisplay:block
. - leaf
-
Class(es) for leaf elements (default is
TN_leaf
). A leaf should contain just a label element. - label
-
Class(es) for label elements (default is
TN_label
). A label should have styledisplay:inline
. - content
-
Class(es) for content elements (default is
TN_content
). - closed
-
Class(es) for marking closed nodes (default is
TN_closed
). - selected
-
Class(es) for marking the selected node (default is
TN_selected
). - mouse
-
Class(es) added when the mouse hovers over a node (default is
TN_mouse
). -
Class(es) for buttons added automatically by the tree navigator (default is
TN_button
). - showall
-
Class(es) for the special mode in which closed nodes are nevertheless displayed (default is
TN_showall
).
Node manipulation
All methods below take a node element as argument, i.e. are called according to pattern:
treeNavigator.method(node);
open(node)
-
opens the node
close(node)
-
closes the node
openAtLevel(elem, level)
-
walks down the tree and opens all subnodes of
elem
until levellevel
; closes nodes underneath openEnclosingNodes(elem)
-
walks up the DOM, starting at
elem
(which might by any element on the page), and opens all nodes found on the way select(node, prevent_autoscroll)
-
If there was a selected node, unselect it; then select the argument node. The argument can be
null
, in which case the tree no longer has any selected node.The second argument
prevent_autoscroll
is optional; if true, no autoscroll will be performed. scrollTo(node)
-
Positions the node in the middle of the screen
flash(node, duration, color)
-
Changes the background color of node to color for duration milliseconds. Duration and color are optional and default to 200 ms and 'red' (unless otherwise specified in the options to the
treeNavigator
constructor). isClosed(node)
-
Returns true if the node is closed
isVisible(node)
-
Returns true if the node is visible (i.e. does not have
display:none
).
Walking the tree
nextSibling(node)
-
Returns the next sibling tree node (i.e. next HTML sibling element having class
TN_node
; this is not equivalent tonode.nextSibling
). previousSibling(node)
-
Returns the previous sibling tree node.
parentNode(node)
-
Returns the parent tree node.
firstSubNode(node)
-
Returns the first subnode within that node's content. If no argument is given, returns the first node of the tree.
lastSubNode(node)
-
Returns the last subnode within that node's content. If no argument is given, returns the last node of the tree.
lastVisibleSubNode(node)
-
Returns the last visible subnode (recursively) of the argument node. If no argument is given, returns the last visible subnode of the tree.
label(node)
-
Returns the label of that node, i.e. the first HTML child element having class
TN_label
. content(node)
-
Returns the content of that node, i.e. the last HTML child element having class
TN_content
. nextDisplayedNode(node)
-
Returns the next tree node in page display order (i.e. next visible node down the page).
previousDisplayedNode(node)
-
Returns the previous tree node in page display order (i.e. previous visible node up the page).
enclosingNode(elem)
-
Returns the first tree node that contains the given element (which might be for example a form input).
Event handling
Manipulations to the tree generate events for which clients can register some handlers, exactly like ordinary HTML events.
Event list
Select
/ Deselect
triggered when a node is marked / unmarked as the currently selected node. Both events are not triggered immediately, but only after selectDelay
milliseconds have elapsed : this is an optimization to avoid too many calls while the user is navigating quickly through the nodes; in other words, intermediate nodes crossed while navigating the tree will not receive any trigger.
If label selection is associated with focus (i.e. if tabIndex
was not set to -1), then selection/deselection events are also triggered when the user switches to another desktop window.
Open
/ Close
triggered when a node is opened or closed
BeforeLoadContent
/ AfterLoadContent
triggered before/after a node's content is loaded from an URL (throug opening the node, or hitting the Ctrl-R
key) -- see the section below about dynamic tree updates).
inspect
triggered when a user calls the inspector for a node (either by hitting the RETURN key or by double-clicking the node's label)
Event structure passed to handlers
Handlers can access an event
structure, similar to what is passed to ordinary HTML events; the entries are:
type
-
the name of the triggered event (i.e.
Select
,Deselect
,Open
, etc.) target
-
the node element on which the event was triggered
srcElement
-
synonym for
target
-
the tree navigator object controlling the target node
Registering event handlers
Event handlers can be registered in several ways:
additional attributes on node elements
<div class="TN_node" TN:onOpen="handleOpen(this, treeNavigator)">
The additional attribute is the event name, prefixed by the constant TN:on
; so in the example above, a hander is registered for event Open
.
The string containing handler code is evaluated in a context where some special variables are predefined:
targetNode
-
the node element
this
-
the node element (synonym for
targetNode
) -
the tree navigator object
event
-
an event structure as described above
If the string just contains the name of a handler function (i.e. without the parentheses), then that function will be called with a single argument, namely the event structure described above. Therefore
<div class="TN_node" TN:onOpen="handleOpen">
is equivalent to
<div class="TN_node" TN:onOpen="handleOpen(event)">
additional attributes on the tree element
<div id="theTree" TN:onOpen="handleOpen(targetNode, this)">
Handlers can be registered on the tree element, exactly like for node elements. The only difference is that this
is then bound to the tree element instead of the target node.
additional properties on the tree navigator object
var treeNavigator = new Tree.Navigator('myTree', {onOpen: myOpenHandler});
treeNavigator.onClose = function(event){doSomethingWith(event.target)};
Handlers can be inserted as properties on the tree navigator object, either through options to the constructor, or later on through ordinary property assignments. These properties start with the constant on
followed by the event name, but without the TN:
prefix. Handlers are called with a single argument, namely the event structure described above.
Dynamic tree expansion
treeNavigator.initSubTree(subtree);
Whenever a subtree was added programmatically into the tree, this method should be called in order to install the navigation buttons, mouse event handlers and tabbing behaviour. The initSubTree
method expects to find at least one TN_label
element within the subtree.
This method is called automatically when a subtree is dynamically fetched through the TN:contentURL
property.