Current File : /home/obaba/public_html/admin/assets/plugins/dynatree/doc/dynatree-doc.html |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>jquery.dynatree.js documentation</title>
<meta name="keywords" content="dynatree JavaScript JS dynamic html tree view treeview checkbox widget plugin for jQuery data structure library ajax open source free">
<meta name="description" content="dynatree is a JavaScript treeview plugin for jQuery with support for checkboxes and lazy loading of branches.">
<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>
<script src="../jquery/jquery.js" type="text/javascript"></script>
<script src="../jquery/jquery-ui.custom.js" type="text/javascript"></script>
<script src="../jquery/jquery.cookie.js" type="text/javascript"></script>
<link href="../src/skin/ui.dynatree.css" rel="stylesheet" type="text/css">
<script src="../src/jquery.dynatree.js" type="text/javascript"></script>
<!-- Convert tabs to spaces and doc CSS -->
<link rel="stylesheet" type="text/css" href="howto.css">
<script src="howto.js" type="text/javascript"></script>
<!-- Automatic TOC generator -->
<script src="./jquery.planize.js" type="text/javascript"></script>
<!-- PrettyPrint (triggered in onload event) -->
<link href="prettify.css" rel="stylesheet">
<script src="prettify.js" type="text/javascript"></script>
<script type="text/javascript">
$(function(){
// Log to Google Analytics, when not running locally
if ( document.URL.toLowerCase().indexOf('wwwendt.de/')>=0 ) {
var pageTracker = _gat._getTracker("UA-316028-1");
pageTracker._trackPageview();
}
// Create TOC
$("html *").planize({
title: "Table of contents",
min_level: 2,
generate_toc: true,
toc_elem: $("#toc")
});
// Format code samples
prettyPrint();
});
</script>
</head>
<body>
<h1>Dynatree documentation</h1>
<div class="hint">
This document describes dynatree version: <strong>$Version: 1.2.4$</strong>.<br>
Document revision: $Revision: 636, 2013-01-26 08:26:52$.<br>
A current version may be found at the project site
<a href="http://wwwendt.de/tech/dynatree/index.html">http://wwwendt.de/tech/dynatree/index.html</a>.
</div>
<p>
Dynatree is a dynamic JavaScript tree view control with support for checkboxes,
drag'n'drop, and lazy loading.
</p>
<p>
Main features:
</p>
<ul>
<li>Open source (<a href="http://code.google.com/p/dynatree/wiki/LicenseInfo">MIT and GPL License</a>)
<li>Optimized for large dynamic trees (DOM elements are only created when really needed).
<li>Programmable through a rich object oriented interface.
<li>Support for lazy loading and Ajax.
<li>Checkboxes and hierarchical selection.
<li>Supports drag and drop.
<li>Support for persistence.
<li>Keyboard aware.
<li>Initializes from HTML code, JSON, or JavaScript objects.
<li>Implemented as a <a href="http://jquery.com">jQuery</a> plugin.<br>
(Note: this doesn't mean that you have to use jQuery for your whole site.)
</ul>
<p class="info">
Dynatree runs best, when the HTML document is rendered in a strict mode like<br>
<code><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"></code>.
<br>
Avoid the <a href="http://en.wikipedia.org/wiki/Quirks_mode">quirks mode</a>.
</p>
<!-- jquery.planize will generate a TOC here: -->
<div id="toc">
</div>
<h2>Download</h2>
<p>
You can download the current dynatree package at
<a href="http://code.google.com/p/dynatree/downloads">http://code.google.com/p/dynatree/downloads</a>.
It contains everything needed including the source, some documentation and examples.<br>
jQuery is already included, but you can check the <a href="http://www.jquery.com">jQuery site</a>
for the latest versions of jquery.js and ui.core.js.
</p>
<h2>Examples</h2>
<p>
This documentation contains script examples and links.<br>
See also the <a href="samples.html">Example Browser</a> for some more advanced live demos.
</p>
<p class="info">
Using the <code>[View source code]</code> link in the
Example Browser is probably the best way to learn about Dynatree.
</p>
<h2 id="quickExample">Quick start</h2>
<p>
Let's start with a simple example:
</p>
<div class="codesample">
<a href="sample-quick.html">Try this example...</a>
<pre class="prettyprint">
<html>
<head>
<!-- Include the required JavaScript libraries: -->
<script src='jquery/jquery.js' type="text/javascript"></script>
<script src='jquery/jquery-ui.custom.js' type="text/javascript"></script>
<script src='jquery/jquery.cookie.js' type="text/javascript"></script>
<link rel='stylesheet' type='text/css' href='skin/ui.dynatree.css'>
<script src='jquery.dynatree.js' type="text/javascript"></script>
<!-- Add code to initialize the tree when the document is loaded: -->
<script type="text/javascript">
$(function(){
// Attach the dynatree widget to an existing <div id="tree"> element
// and pass the tree options as an argument to the dynatree() function:
$("#tree").dynatree({
onActivate: function(node) {
// A DynaTreeNode object is passed to the activation handler
// Note: we also get this event, if persistence is on, and the page is reloaded.
alert("You activated " + node.data.title);
},
persist: true,
children: [ // Pass an array of nodes.
{title: "Item 1"},
{title: "Folder 2", isFolder: true,
children: [
{title: "Sub-item 2.1"},
{title: "Sub-item 2.2"}
]
},
{title: "Item 3"}
]
});
});
</script>
</head>
<body>
<!-- Add a <div> element where the tree should appear: -->
<div id="tree"> </div>
</body>
</html>
</pre>
</div>
<p>
As an alternative, it is possible to leave away the <code>children</code> option and
add a <ul> inside the <div id="tree"> tag instead.<br>
See <a href="#initFromUl">Initializing the tree structure from a <ul> element</a> for an example.
</p>
<p>
I am going into more details in the following sections.
</p>
<h2>Initializing the tree</h2>
<p>
Dynatree is based on and made for jQuery. If you are not familiar with this, you might also want to check the <a href="http://docs.jquery.com">jQuery documentation</a>.
</p>
<p>
The tree is initialized in the onload event of the html document. In jQuery this is usually done by passing a function to $(..) :
</p>
<pre class="prettyprint">
<head>
<script type="text/javascript">
$(function(){
[…]
});
</script>
</head>
</pre>
<p>
The dynatree widget is then attached to an empty <div > element with a given ID of 'tree'.
This id can have any value, it only has to match the jQuery selector, in our case '#tree'.<br>
Options are passed to the dynatree() function as a dictionary in curly braces:
</p>
<pre class="prettyprint">
$("#tree").dynatree({
[…]
});
</pre>
<h3>Tree options</h3>
<p>
Tree options are passed as plain JavaScript objects in curly braces, e.g.<br>
<code>{ … }</code>.<br>
</p>
<p>
The following script shows the available options.<br>
All options have a reasonable default, so we may only have to pass the <code>onActivate</code> handler.
</p>
<pre class="prettyprint">
$("#tree").dynatree({
title: "Dynatree", // Tree's name (only used for debug outpu)
minExpandLevel: 1, // 1: root node is not collapsible
imagePath: null, // Path to a folder containing icons. Defaults to 'skin/' subdirectory.
children: null, // Init tree structure from this object array.
initId: null, // Init tree structure from a <ul> element with this ID.
initAjax: null, // Ajax options used to initialize the tree strucuture.
autoFocus: true, // Set focus to first child, when expanding or lazy-loading.
keyboard: true, // Support keyboard navigation.
persist: false, // Persist expand-status to a cookie
autoCollapse: false, // Automatically collapse all siblings, when a node is expanded.
clickFolderMode: 3, // 1:activate, 2:expand, 3:activate and expand
activeVisible: true, // Make sure, active nodes are visible (expanded).
checkbox: false, // Show checkboxes.
selectMode: 2, // 1:single, 2:multi, 3:multi-hier
fx: null, // Animations, e.g. null or { height: "toggle", duration: 200 }
noLink: false, // Use <span> instead of <a> tags for all nodes
// Low level event handlers: onEvent(dtnode, event): return false, to stop default processing
onClick: null, // null: generate focus, expand, activate, select events.
onDblClick: null, // (No default actions.)
onKeydown: null, // null: generate keyboard navigation (focus, expand, activate).
onKeypress: null, // (No default actions.)
onFocus: null, // null: set focus to node.
onBlur: null, // null: remove focus from node.
// Pre-event handlers onQueryEvent(flag, dtnode): return false, to stop processing
onQueryActivate: null, // Callback(flag, dtnode) before a node is (de)activated.
onQuerySelect: null, // Callback(flag, dtnode) before a node is (de)selected.
onQueryExpand: null, // Callback(flag, dtnode) before a node is expanded/collpsed.
// High level event handlers
onPostInit: null, // Callback(isReloading, isError) when tree was (re)loaded.
onActivate: null, // Callback(dtnode) when a node is activated.
onDeactivate: null, // Callback(dtnode) when a node is deactivated.
onSelect: null, // Callback(flag, dtnode) when a node is (de)selected.
onExpand: null, // Callback(flag, dtnode) when a node is expanded/collapsed.
onLazyRead: null, // Callback(dtnode) when a lazy node is expanded for the first time.
onCustomRender: null, // Callback(dtnode) before a node is rendered. Return a HTML string to override.
onCreate: null, // Callback(dtnode, nodeSpan) after a node was rendered for the first time.
onRender: null, // Callback(dtnode, nodeSpan) after a node was rendered.
postProcess: null, // Callback(data, dataType) before an Ajax result is passed to dynatree.
// Drag'n'drop support
dnd: {
// Make tree nodes draggable:
onDragStart: null, // Callback(sourceNode), return true, to enable dnd
onDragStop: null, // Callback(sourceNode)
// Make tree nodes accept draggables
autoExpandMS: 1000, // Expand nodes after n milliseconds of hovering.
preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
onDragEnter: null, // Callback(targetNode, sourceNode)
onDragOver: null, // Callback(targetNode, sourceNode, hitMode)
onDrop: null, // Callback(targetNode, sourceNode, hitMode)
onDragLeave: null // Callback(targetNode, sourceNode)
},
ajaxDefaults: { // Used by initAjax option
cache: false, // false: Append random '_' argument to the request url to prevent caching.
timeout: 0, // >0: Make sure we get an ajax error for invalid URLs
dataType: "json" // Expect json format and pass json object to callbacks.
},
strings: {
loading: "Loading…",
loadError: "Load error!"
},
generateIds: false, // Generate id attributes like <span id='dynatree-id-KEY'>
idPrefix: "dynatree-id-", // Used to generate node id's like <span id="dynatree-id-<key>">.
keyPathSeparator: "/", // Used by node.getKeyPath() and tree.loadKeyPath().
cookieId: "dynatree", // Choose a more unique name, to allow multiple trees.
cookie: {
expires: null // Days or Date; null: session cookie
},
// Class names used, when rendering the HTML markup.
// Note: if only single entries are passed for options.classNames, all other
// values are still set to default.
classNames: {
container: "dynatree-container",
node: "dynatree-node",
folder: "dynatree-folder",
empty: "dynatree-empty",
vline: "dynatree-vline",
expander: "dynatree-expander",
connector: "dynatree-connector",
checkbox: "dynatree-checkbox",
nodeIcon: "dynatree-icon",
title: "dynatree-title",
noConnector: "dynatree-no-connector",
nodeError: "dynatree-statusnode-error",
nodeWait: "dynatree-statusnode-wait",
hidden: "dynatree-hidden",
combinedExpanderPrefix: "dynatree-exp-",
combinedIconPrefix: "dynatree-ico-",
hasChildren: "dynatree-has-children",
active: "dynatree-active",
selected: "dynatree-selected",
expanded: "dynatree-expanded",
lazy: "dynatree-lazy",
focused: "dynatree-focused",
partsel: "dynatree-partsel",
lastsib: "dynatree-lastsib"
},
debugLevel: 1 // 0:quiet, 1:normal, 2:debug
});
</pre>
<p>
<strong>Details:</strong>
</p>
<dl class="optionList">
<dt>opts.classNames
<dd>
Type: <code>dictionary</code>, default: <code>$.ui.dynatree.defaults.classNames</code>.<br>
Override class names, that are used, when rendering the HTML markup.<br>
Typically this will require some customization of the CSS file too.
<br>
Example:
<pre class="prettyprint">
$("#tree1").dynatree({
checkbox: true,
// Override class name for checkbox icon:
classNames: {checkbox: "dynatree-radio"},
[...]
</pre>
</dd>
<dt>opts.clickFolderMode
<dd>
Type: <code>integer</code>, default: <code>3</code>.<br>
Define, how a mouse click will change a folder status.
<ol>
<li>Single-clicking a folder title (or pressing the [enter] or [space]
key) will activate it.<br>
In this mode documents and folders behave the same.
<li>Single-clicking a folder title expands the node. The folder cannot
be activated.
<li>Single-clicking a folder title will activate and expand it.
</ol>
</dd>
<dt>opts.persist
<dd>
Type: <code>boolean</code>, default: <code>false</code>.<br>
True: the tree's expansion, activation, focus and selection state is saved
to a session cookie, so reloading the page will restore the status.<br>
Notes: this may not work with lazy nodes.<br>
See <code>cookie</code> option.
</dd>
</dl>
<h3>Initializing the tree structure</h3>
<p>
A tree structure is made of <i>nodes</i>. Every node may in turn contain
a list child nodes.<br>
A dynatree always has exactly one <i>root node</i>, and all top level nodes
of our tree are created as direct descendants.<br>
The root node is usually hidden, so we only see the nodes that we have added.
</p>
<p>
Dynatree can read it's structure from different sources:
</p>
<ol>
<li>If the <code>children</code> option is passed, it will be used.
<li>Otherwise, if the <code>initAjax</code> option is passed, it will be used.
<li>Otherwise, if the <code>initId</code> option is passed, it will be used.
<li>Otherwise, if the the container <div> element contains a <ul> element,
it will be used.
<li>Otherwise, the tree is left empty.<br>
But we may choose to do so, if we want to modify the tree programmatically.
</ol>
<p>
Methods 1-3 expect a list of node options, as described in the following
sections.
</p>
<h4 id="nodeOptions">Node options</h4>
<p>
Node options are defined as plain JavaScript objects in curly braces, e.g.<br>
<code>{ … }</code>.<br>
Most of the time we pass a list of node options like this<br>
<code>children: [ { … }, { … }, … ]</code>.
</p>
<p>
The follwing snippet shows the attributes that can be used to define a tree node.<br>
There are reasonable default values for all options, so we may only have to pass a <code>title</code>.
</p>
<pre class="prettyprint">
children: [
{
title: null, // (required) Displayed name of the node (html is allowed here)
key: null, // May be used with activate(), select(), find(), ...
isFolder: false, // Use a folder icon. Also the node is expandable but not selectable.
isLazy: false, // Call onLazyRead(), when the node is expanded for the first time to allow for delayed creation of children.
tooltip: null, // Show this popup text.
href: null, // Added to the generated <a> tag.
icon: null, // Use a custom image (filename relative to tree.options.imagePath). 'null' for default icon, 'false' for no icon.
addClass: null, // Class name added to the node's span tag.
noLink: false, // Use <span> instead of <a> tag for this node
activate: false, // Initial active status.
focus: false, // Initial focused status.
expand: false, // Initial expanded status.
select: false, // Initial selected status.
hideCheckbox: false, // Suppress checkbox display for this node.
unselectable: false, // Prevent selection.
// The following attributes are only valid if passed to some functions:
children: null // Array of child nodes.
// NOTE: we can also add custom attributes here.
// This may then also be used in the onActivate(), onSelect() or onLazyTree() callbacks.
},
[…]
]
</pre>
<p>
The node options are also passed to the event handlers and can be accessed like this:
</p>
<pre class="prettyprint">
onActivate: function(node) {
alert("You activated " + node.data.title);
},
</pre>
<p>
<strong>Details:</strong>
</p>
<dl class="optionList">
<dt>data.activate
<dd>
If set to true, the node will be initially activated.
</dd>
<dt>data.addClass
<dd>
Class name that is added to the node's <span> element.<br>
Example:
<pre class="prettyprint">{ title: "Pretty node", addClass: "customClass1" }</pre>
or
<pre class="prettyprint"><li data="addClass: 'customClass1'">Pretty node</pre>
can be styled using css as
<pre class="prettyprint">span.customClass1 a { background-color: maroon; color: yellow; }</pre>
</dd>
<dt>data.children
<dd>
Array of node options, that are used to generate child nodes.<br>
This option is only valid when passed to certain functions, like <code>DynTreeNode.addChild()</code>.
</dd>
<dt>data.expand
<dd>
If set to true, the node will be initially expanded.
</dd>
<dt>data.focus
<dd>
If set to true, the node will be initially focused.
</dd>
<dt>data.hideCheckbox
<dd>
Suppress display of checkbox icon.<br>
It is still possible to (de)select the node using the API, keyboard or
initialization data. (The selection state may be visualized by a CSS
style.)<br>
See also <code>unselectable</code>.
</dd>
<dt>data.href
<dd>
Contains the link URL, if the tree was initialized from a <ul> tag:
<pre class="prettyprint"><div id="tree"><ul>
<li class="expanded folder">Search engines
<ul>
<li><a href="http://www.google.com" target="_self">Google</a>
<li><a href="http://www.bing.com">Bing</a>
</pre>
</dd>
<dt>data.icon
<dd>
Optional name of an image file relative to the image directory. <br>
If <i>null</i> specified, a default image is used depending on the node type (folder
or document). This is the default.<br>
If <i>false</i> specified, no image is displayed.
</dd>
<dt>data.isFolder
<dd>
Marks node as folder (treated as a document otherwise).<br>
See <a href="#foldersAndDocs">Folders and Documents</a>
</dd>
<dt>data.isLazy
<dd>
Enables delayed loading of the node contents. When a lazy node is expanded
for the first time, the onLazyRead() callback is called.
</dd>
<dt>data.key
<dd>
Uniquely identifies this node. It is optional, but we need it for some
functions like <code>tree.activateKey()</code>.<br>
If specified, the node's element id is generated by prepending a prefix
like this: <code>dynatree-id-<i>1234</i></code>.<br>
If <i>not</i> specified, a random key id is generated.
</dd>
<dt>data.select
<dd>
If set to true, the node will be initially selected.
</dd>
<dt>data.target
<dd>
See data.href.
</dd>
<dt>data.title
<dd>
Type: string, default: "".<br>
Displayed name of the node (html markup is allowed here).
</dd>
<dt>data.tooltip
<dd>
Optional string to display in a popup window when the cursor hovers over
the node.
</dd>
<dt>data.unselectable
<dd>
Prevent (de)selection of this node using API, mouse, and keyboard.<br>
It is still possible, to (de)select this node in the initialization data
or indirectly (in multi-hier mode).<br>
See also <code>hideCheckbox</code>.
</dd>
</dl>
<p>
To override the node attribute <i>defaults</i>, modify the structure before initializing
dynatree:
</p>
<pre class="prettyprint">
<script type="text/javascript">
$.ui.dynatree.nodedatadefaults["icon"] = false; // Turn off icons by default
$(function(){
$("#tree").dynatree({
rootVisible: false,
[...]
</pre>
<h4 id="foldersAndDocs">Folders and documents</h4>
<p>
When a node is of type <i>folder</i>, it get's a special folder icon and class name.<br>
We usually use them to hold child nodes.<br>
Also, folders can be expanded by clicking the title text (this behavior
can be controlled using the <code>clickFolderMode</code> option).
</p><p>
Non-folders ('documents') may also contain child nodes.<br>
Clicking on a child node activates it, so we have to click the small [+] icon in front to expand such a document node.
</p>
<h4>Initializing the tree structure from an object array</h4>
<p>
In the <a href="#quickExample">quick example above</a> we have already seen how a tree is initialized by passing a
node array with the <code>children</code> option.
</p>
<pre class="prettyprint">
$("#tree").dynatree({
children: [ … ],
[…]
});
</pre>
<p>
See also <a href="#nodeOptions">Node options</a>.
</p>
<h4 id="ajaxResponse">Initializing the tree structure from an Ajax response</h4>
<p>
Instead of passing an array of data objects, we can pass a url in the <code>initAjax</code>
option that will be used to contact an Ajax web service.
</p>
<pre class="prettyprint">
$("#tree").dynatree({
initAjax: {url: "/ajaxTree",
data: {key: "root", // Optional arguments to append to the url
mode: "all"
}
},
[…]
});
</pre>
<p>
The web service is expected to return a <a href="http://json.org/">valid JSON</a>
node list, formatted like this:<br>
<code>[ { ... }, { ... }, ... ]</code>.
</p>
<p>
Because the data request is performed asynchronously, the document will load faster.
Dynatree will display a spinning wheel, while waiting for the request to complete.
</p>
<p>
See <a href="#lazyLoading">Loading child nodes on demand</a> for details.<br>
See <a href="#lazyPersist">Persistence for lazy trees</a> for a sample on
how to combine this with persistence.
</p>
<h4 id="initFromUl">Initializing the tree structure from a <ul> element</h4>
<p>
If the container <code><div></code> contains a <code><ul></code> element,
the node titles are read from the <code><li></code> tags.<br>
If the title contains html markup, it may be better to wrap it inside a span element.
</p>
<p>
All other node options are specified in the <code>data</code> attribute of a <li> element.
For example
</p>
<pre class="prettyprint">
<li data="url: 'http://jquery.com'">jQuery home
<li data="url: 'http://example.com', addClass: 'customClass1'">Example page
</pre>
<p class="info">
Note that the <code>data</code> attribute is not valid in <code><li></code> elements in
some doctypes (HTML 4.01 transitional and Strict and XHTML 1.0 Strict).
Validators will complain about this.<br>
Also, if the <code>id</code> attribute is used to pass a key, it should be
alphanumeric and start with a letter to be compliant.<br>
(This doesn't seem to affect the functionality however.)
</p>
<p>
Nested <ul> elements are used to build a hierarchical tree structure.<br>
After the <ul> element was parsed, it is removed from the DOM tree.
</p>
<p>
Note that <a> elements are recognized:<br>
<code><li><a href='URL' target='TARGET'>TITLE</a></code> will result in<br>
node.data.title = TITLE<br>
node.data.href = URL<br>
node.data.target = TARGET
</p>
<div class="codesample">
<a href="sample-ul.html">Try this example...</a>
<pre class="prettyprint">
<head>
<!-- Include the required JavaScript libraries: -->
<script src='jquery/jquery.js' type="text/javascript"></script>
<script src='jquery/jquery-ui.custom.js' type="text/javascript"></script>
<link rel='stylesheet' type='text/css' href='skin/ui.dynatree.css' >
<script src='jquery.dynatree.js' type="text/javascript"></script>
<!-- Add code to initialize the tree when the document is loaded: -->
<script type="text/javascript">
$(function(){
$("#tree").dynatree({
onActivate: function(node) {
alert("You activated " + node);
}
});
});
</script>
</head>
<body>
<!-- Add a <div> element where the tree should appear: -->
<div id="tree">
<ul>
<li id="key1" title="Look, a tool tip!">item1 with key and tooltip
<li id="key2" class="selected">item2: selected on init
<li id="key3" class="folder">Folder with some children
<ul>
<li id="key3.1">Sub-item 3.1
<li id="key3.2">Sub-item 3.2
</ul>
<li id="key4" class="expanded">Document with some children (expanded on init)
<ul>
<li id="key4.1">Sub-item 4.1
<li id="key4.2">Sub-item 4.2
</ul>
<li id="key5" class="lazy folder">Lazy folder
</ul>
</div>
</body>
</pre>
</div>
<h4>Initializing the tree structure programmatically</h4>
<p>
Finally, it is always possible to program the DynaTree and DynaTreeNode objects directly.
</p>
<p>
See also <a href="#programming">Programming dynatree</a>.
</p>
<div class="codesample">
<a href="sample-api.html">Try this example...</a>
<pre class="prettyprint">
$(function(){
// Initialize the tree in the onload event
$("#tree").dynatree({
onActivate: function(node) {
alert("You activated " + node);
}
});
// Now get the root node object
var rootNode = $("#tree").dynatree("getRoot");
// Call the DynaTreeNode.addChild() member function and pass options for the new node
var childNode = rootNode.addChild({
title: "Child node 1",
tooltip: "This child node was added programmatically.",
isFolder: true
});
//
childNode.addChild({
title: "Document using a custom icon",
icon: "customdoc1.gif"
});
});
</pre>
</div>
<h2>Handling events</h2>
<p>
When a user clicks a node, we want to react in some way.
So at least we want to implement an <code>onActivate</code>
handler.
</p>
<p>
All event handlers are passed an instance of DynaTreeNode as argument.<br>
<code>this</code> refers to the Dynatree object.<br>
The node options can be accessed like this:
</p>
<pre class="prettyprint">
onActivate: function(node) {
alert("You activated " + node.data.title);
},
</pre>
<p>
See also <a href="#programming">Programming dynatree</a>.
</p>
<h3><code>DynaTree</code> callbacks</h3>
The <code>this</code> context is set to the tree object.<br>
Use <code>tree.isUserEvent()</code>, <code>tree.isInitializing()</code>,
and <code>tree.isReloading()</code> to determine who generated this event.
<dl class="optionList">
<dt>opts.onActivate(node)
<dd>
Called when a node was activated.
<pre class="prettyprint">onActivate: function(node) {
if(node.tree.isUserEvent()){
[...] // Do something after user activated the node (using mouse or keyboard)
}
}</pre>
</dd>
<dt>opts.onBlur(node)
<dd>
Called when a node lost the focus.
</dd>
<dt>opts.onClick(node, event)
<dd>
Called when a node was clicked.<br>
Use <code>node.getEventTargetType(event)</code> to check which area was clicked.<br>
Return <code>false</code> to prevent default processing
(setting focus, activate the node, expand folders, etc.).
<pre class="prettyprint">onClick: function(node, event) {
if(node.getEventTargetType(event) == "title"){
[...] // Handle the click event
return false;// Prevent default processing
}
}</pre>
</dd>
<dt>opts.onCreate(node, nodeSpan)
<dd>
Called after a node's HTML tag was created, i.e. when a node becomes
visible for the first time.<br>
This callback may be used to bind events or widgets for nodes that are
created lazily or programatically.<br>
<pre class="prettyprint">onCreate: function(node, nodeSpan) {
$(span).click(function(e){
alert('clicked ' + node);
});
}</pre>
(Note that the use of jQuery live events may often be a more efficient solution.)<br>
See also <code>opts.onRender</code>.
</dd>
<dt>opts.onCustomRender(node)
<dd>
Called before a node's title HTML tag will be created.
This happens when a node becomes visible for the first time.<br>
This callback may return a string that will be used instead of the
default HTML markup.
<pre class="prettyprint">onCustomRender: function(node) {
return "<span class='dynatree-title'>SPAM</span>"
}</pre>
</dd>
<dt>opts.onDblClick(node, event)
<dd>
Called when a node was double clicked.<br>
Use <code>node.getEventTargetType(event)</code> to check which area was clicked.<br>
Return <code>false</code> to prevent default processing (currently none).
</dd>
<dt>opts.onDeactivate(node)
<dd>
Called when a node was deactivated.
</dd>
<dt>opts.onExpand(flag, node)
<dd>
Called when a node was expanded/collapsed.
</dd>
<dt>opts.onFocus(node)
<dd>
Called when a node receives the focus.
</dd>
<dt>opts.onKeydown(node, event)
<dd>
Called on keydown events.<br>
Return <code>false</code> to prevent default processing
(generate keyboard navigation, focus, expand, activate, etc.).
</dd>
<dt>opts.onKeypress(node, event)
<dd>
Called on keypress events.<br>
Return <code>false</code> to prevent default processing (currently none).
</dd>
<dt>opts.onLazyRead(node)
<dd>
Called when a lazy node is expanded for the first time.
</dd>
<dt>opts.onPostInit(isReloading, isError [, XMLHttpRequest, textStatus, errorThrown])
<dd>
Called when the tree was (re)loaded.<br>
In case of an error, <code>isError</code> will be <code>true</code> and
addition info is passed: XMLHttpRequest, textStatus, errorThrown.
</dd>
<dt>opts.onQueryActivate(flag, node)
<dd>
Called before a node is (de)activated. Return <code>false</code> to prevent
this.
</dd>
<dt>opts.onQueryExpand(flag, node)
<dd>
Called before a node is expanded/collapsed. Return <code>false</code> to prevent
this.
</dd>
<dt>opts.onQuerySelect(flag, node)
<dd>
Called before a node is (de)selected. Return <code>false</code> to prevent
this.
</dd>
<dt>opts.onRender(node, nodeSpan)
<dd>
Called after every time a node's HTML tag was created or changed.<br>
This callback may be used to modify the HTML markup.
<pre class="prettyprint">onRender: function(node, nodeSpan) {
$(nodeSpan).find("a.dynatree-title").css("color", "red");
}</pre>
See also <code>opts.onCreate</code>.
</dd>
<dt>opts.onSelect(flag, node)
<dd>
Called when a node was (de)selected.
</dd>
<dt>opts.dnd.onDragStart(sourceNode)
<dd>
This function <i>must</i> be defined to enable dragging for the tree.
Return <code>false</code> to cancel dragging of node.
</dd>
<dt>opts.dnd.onDragEnter(targetNode, sourceNode)
<dd>
Return <code>true</code> to make tree nodes accept dropping of draggables.
</dd>
<dt>opts.dnd.onDragOver(targetNode, sourceNode, hitMode)
<dd>
</dd>
<dt>opts.dnd.onDragLeave(targetNode, sourceNode)
<dd>
</dd>
<dt>opts.dnd.onDrop(targetNode, sourceNode, hitMode)
<dd>
This function <i>must</i> be defined to enable dropping of items on the tree.
</dd>
<dt>opts.dnd.onDragStop(sourceNode)
<dd>
</dd>
<dt>ajaxOptions.success(node)
<dd>
(Passed as argument to <code>node.appendAjax(...)</code>.)<br>
Called after nodes have been created and the waiting icon was removed.
'this' is the options for this Ajax request
</dd>
<dt>ajaxOptions.error(node, XMLHttpRequest, textStatus, errorThrown)
<dd>
(Passed as argument to <code>node.appendAjax(...)</code>.)<br>
</dd>
</dl>
<h3>Handling activate/click</h3>
<p>
The following example handles an activation event by opening a url in a new window.<br>
This assumes, that we have defined an additional custom attribute named
'url' in the node options, like so:
</p>
<pre class="prettyprint">
<ul>
<li data="url: 'http://jquery.com'">jQuery home
<li data="url: 'http://docs.jquery.com'">jQuery docs
</pre>
<p>
or
</p>
<pre class="prettyprint">
children: [
{ title: "jQuery home", url: "http://jquery.com" },
{ title: "jQuery docs", url: "http://docs.jquery.com" },
</pre>
<p>
Also, the title of the currently active node is displayed in the <span id='echoActive'> tag.
</p>
<div class="codesample">
<a href="sample-events.html">Try this example...</a>
<pre class="prettyprint">
$("#tree").dynatree({
[…]
onActivate: function(node) {
if( node.data.url )
window.open(node.data.url);
$("#echoActive").text(node.data.title);
},
onDeactivate: function(node) {
$("#echoActive").text("-");
},
[…]
});
</pre>
</div>
<h3>Handling selection events</h3>
<p>
The following example writes the title of the currently focused node to the <span id='echoFocused'> element:
</p>
<div class="codesample">
<a href="sample-select.html">Try this example...</a>
<pre class="prettyprint">
$("#tree").dynatree({
[…]
onSelect: function(flag, node) {
if( ! flag )
alert("You deselected node with title " + node.data.title);
var selectedNodes = node.tree.getSelectedNodes();
var selectedKeys = $.map(selectedNodes, function(node){
return node.data.key;
});
alert("Selected keys: " + selectedKeys.join(", "));
},
[…]
});
</pre>
</div>
<h3>Handling focus changes</h3>
<p>
If we use the cursor keys to walk the tree nodes, the focus changes to the next node, but the active node remains the same unless we use [Space] or [Enter].<br>
Also, when we click on a folder node it is only focused, but not activated.
</p>
<p>
The following example writes the title of the currently focused node to the <span id='echoFocused'> element:
</p>
<div class="codesample">
<a href="sample-events.html">Try this example...</a>
<pre class="prettyprint">
$("#tree").dynatree({
[…]
onFocus: function(node) {
$("#echoFocused").text(node.data.title);
},
onBlur: function(node) {
$("#echoFocused").text("-");
},
[…]
});
</pre>
</div>
<h3 id="lazyLoading">Loading child nodes on demand ('lazy loading')</h3>
<p>
Dynatree supports delayed loading of tree nodes, which means we read the
child nodes only when their parent is expanded.
</p>
<p>
Because the data request is performed asynchronously, the browser will not
block and is still responsive. Dynatree will display a spinning wheel, while
waiting for the request to complete.
</p>
<p>
To make this happen, we have to
</p>
<ul>
<li>Mark some or all nodes as lazy, by setting the <code>isLazy</code> option to true.
<li>Implement a backend web service that delivers a <a href="http://json.org/">JSON</a>
formatted node list.
<li>Implement the <code>onLazyRead</code> callback to send an Ajax request,
create the child nodes, and set the 'ok' status.
</ul>
<div class="codesample">
<a href="sample-lazy.html">Try this example...</a>
<pre class="prettyprint">
$("#tree").dynatree({
[…]
onLazyRead: function(node){
node.appendAjax({url: "/sendData",
data: {"key": node.data.key, // Optional url arguments
"mode": "all"
}
});
},
[…]
});
</pre>
</div>
<p>
Typically we would implement <code>onLazyRead</code> by calling the
<code>node.appendAjax()</code> function.<br>
It expects one option object argument, as described in the documentation for
the <a href="http://docs.jquery.com/Ajax/jQuery.ajax">jQuery.ajax()</a> command.<br>
</p><p>
These options are set by default:<br>
<code>cache: false</code> and <code>dataType: "json"</code>.
</p><p>
Note that the <code>success</code> and <code>error</code> options
are implemented differently from the jQuery standard:<br>
They pass different arguments and are called <strong>after</strong> the
Dynatree default processing took place.<br>
This makes it easy to use the <code>success</code> callback to apply any
custom postprocessing, for example activating a node or binding events.
</p>
<pre class="prettyprint">
$("#tree").dynatree({
[…]
onLazyRead: function(node){
node.appendAjax({url: "/sendData",
data: {"key": node.data.key, // Optional url arguments
"mode": "all"
},
// (Optional) use JSONP to allow cross-site-requests
// (must be supported by the server):
// dataType: "jsonp",
success: function(node) {
// Called after nodes have been created and the waiting icon was removed.
// 'this' is the options for this Ajax request
},
error: function(node, XMLHttpRequest, textStatus, errorThrown) {
// Called on error, after error icon was created.
},
cache: false // Append random '_' argument to url to prevent caching.
});
},
[…]
});
</pre>
<p>
The web service is expected to return a <a href="http://json.org/">valid JSON</a>
node list, formatted like this:<br>
<code>[ { "title": "Node1", "isLazy": true, "key": "BC13B21636CD6D5C", … }, { … }, … ]</code><br>
See <a href="#nodeOptions">Node options</a> for a list of supported attributes.
</p><p>
When the response was received, <code>appendAjax()</code> appends the child
nodes and calls <code>node.setLazyNodeStatus(DTNodeStatus_Ok)</code> to
remove the wait icon.
</p><p>
Note that <code>initAjax</code> is simply a special case, where the tree's
root node is loaded on startup.<br>
See <a href="#ajaxResponse">Initializing the structure from an Ajax response</a>
for a sample to initialize the whole tree with an Ajax request.
</p><p>
This sample code (written in Python) shows how a server could create a
response:
</p>
<pre class="prettyprint">
# Build node list as JSON formatted string:
res = '['
res += '{ "title": "Node 1", "key": "k1", "isLazy": true },'
res += '{ "title": "Node 2", "key": "k2", "isLazy": true },'
res += '{ "title": "Node 3", "key": "k3", "isLazy": true }' # no trailing "," at the last line
res += ']'
# Add support for the JSONP protocol:
# This means, if the request URL contains an argument '?callback=xxx',
# wrap the result as 'xxx(result)'
if "callback" in argDict:
res = argDict["callback"] + "(" + res + ")"
# Make sure, content type is JSON:
start_response("200 OK", [("Content-Type", "application/json")])
# Return result (the square brackets are Python / WSGI specific):
return [ res ]
</pre>
<p>
See <a href="dynatree_server.py">dynatree_server.py</a> for a sample
implementation of a web server that handles this (~150 lines of Python code).<br>
When this server is running, you can try this <a href="sample-pyserver.html">live example</a>
of a lazy tree.
</p>
<h4 id="lazyCustom">Loading custom formats</h4>
<p>
If we need more control, or if the server cannot provide JSON in Dynatree's
native format, we could also use <a href="http://docs.jquery.com/Ajax/jQuery.ajax">jQuery.ajax()</a>
to fetch the data, then transform it and call <code>node.addChild()</code>:
</p>
<pre class="prettyprint">
$("#tree").dynatree({
[…]
onLazyRead: function(node){
$.ajax({
url: […],
success: function(data, textStatus){
// In this sample we assume that the server returns JSON like
// { "status": "...", "result": [ {...}, {...}, ...]}
if(data.status == "ok"){
// Convert the response to a native Dynatree JavaScipt object.
var list = data.result;
res = [];
for(var i=0, l=list.length; i<l; i++){
var e = list[i];
res.push({title: "" + i + ": " + e.fcurr + "-" + e.tcurr + ":" + e.ukurs,
icon: false});
}
// PWS status OK
node.setLazyNodeStatus(DTNodeStatus_Ok);
node.addChild(res);
}else{
// Server returned an error condition: set node status accordingly
node.setLazyNodeStatus(DTNodeStatus_Error, {
tooltip: data.faultDetails,
info: data.faultString
});
}
}
});
[…]
});
</pre>
<h2 id="dnd">Drag'n'drop</h2>
<p>
Drag and drop functionality is enabled by defining the appropriate callbacks:
</p>
<pre class="prettyprint">
$("#tree").dynatree({
[...]
dnd: {
onDragStart: function(node) {
/** This function MUST be defined to enable dragging for the tree.
* Return false to cancel dragging of node.
*/
logMsg("tree.onDragStart(%o)", node);
return true;
},
onDrop: function(node, sourceNode, hitMode, ui, draggable) {
/** This function MUST be defined to enable dropping of items on
* the tree.
*/
logMsg("tree.onDrop(%o, %o, %s)", node, sourceNode, hitMode);
sourceNode.move(node, hitMode);
}
}
});
</pre>
<p>
There are a lot more callbacks that can be used to fine tune the behaviour.
Check the source code in the samples in the <a href="samples.html">Example Browser</a>
to learn more.
</p>
<h2 id="persistence">Persistence</h2>
<p>
When initializing a tree in persist mode, we first check, if persistence
cookies already exist.<br>
If not, we assume first-time initializing, read the status from the tree source,
and store it into new cookies.
</p><p>
Otherwise we assume re-loading, ignore the source node attributes and override
them using the cookie info.
</p><p>
In either case, the 'active', 'expand' and 'select' status of a node is read from
the data or restored from the cookies.<br>
However, no onQueryActivate, onActivate, onExpand, onSelect, etc. events are fired.
(The only event that may be fired is onFocus.)<br>
In order to generate these events on reload, we may use the callback function onPostInit()
and tree.reactivate().
</p>
<pre class="prettyprint">
$("#tree").dynatree({
[…]
onPostInit: function(isReloading, isError) {
// 'this' is the current tree
// isReloading is true, if status was read from existing cookies
// isError is only used in Ajax mode
// Fire an onActivate() event for the currently active node
this.reactivate();
},
onActivate: function(node) {
// Use status functions to find out about the calling context
var isInitializing = node.tree.isInitializing(); // Tree loading phase
var isReloading = node.tree.isReloading(); // Loading phase, and reading status from cookies
var isUserEvent = node.tree.isUserEvent(); // Event was triggered by mouse or keyboard
$("#echoActive").text(node.data.title);
},
</pre>
<h3 id="lazyPersist">Persistence for lazy trees</h3>
<p>
The problem with restoring the status of a <b>lazy</b> tree is, that the currently active
or selected nodes may not be part of the tree, when it is freshly re-loaded.
</p><p>
The basic idea is to leave it up to the backend web service to deliver not only
the top-level nodes, but also all nodes that are required to display the current status.
</p><p>
For example, it may be neccessary to render 3 parent nodes, if the active node is at level # 4.<br>
The backend may also deliver all child nodes of expanded parents.<br>
Or in selectMode 3 (hierarchical) we may want to send all nodes, that are partly selected.
</p><p>
initAjax (and appendAjax) have 3 options, that make it easy to pass persistence
information to the web service.
</p><p>
See <a href="dynatree_server.py">dynatree_server.py</a> for a sample
implementation of a web server that handles this (~150 lines of Python code).<br>
When this server is running, you can try this <a href="sample-pyserver.html">live example</a>
of a lazy tree.
</p>
<pre class="prettyprint">
$("#tree").dynatree({
[…]
initAjax: {url: "/ajaxTree",
data: {key: key,
mode: mode,
filter: filter
},
addActiveKey: true, // add &activeKey= parameter to URL
addFocusedKey: true, // add &focusedKey= parameter to URL
addExpandedKeyList: true // add &expandedKeyList= parameter to URL
},
onPostInit: function(isReloading, isError) {
// In lazy mode, this will be called *after* the initAjax request returned.
// 'this' is the current tree
// isReloading is set, if status was read from existing cookies
// isError is set, if Ajax failed
// Fire an onActivate() event for the currently active node
this.reactivate();
},
onActivate: function(node) {
// Use status functions to find out about the calling context
var isUserEvent = node.tree.isUserEvent(); // Event was triggered by mouse or keyboard
$("#echoActive").text(node.data.title);
},
</pre>
<h2 id="programming">Programming dynatree</h2>
<p>
The dynatree widget provides a set of plugin methods, that can be called
directly.<br>
For example
</p>
<pre class="prettyprint">
$("#tree").dynatree("disable");
</pre>
<p>
However this plugin implementation is based on a class called <code>DynaTree</code>
that holds a set of <code>DynaTreeNode</code> objects.<br>
These classes expose methods that can be accessed for enhanced functionality.<br>
For example:
</p>
<pre class="prettyprint">
// Get the DynaTree object instance:
var tree = $("#tree").dynatree("getTree");
// Use it's class methods:
tree.activateKey("key1234");
// Get a DynaTreeNode object instance:
var node = tree.getNodeByKey("key7654");
var rootNode = $("#tree").dynatree("getRoot");
// and use it
node.toggleExpand();
</pre>
<h3>Dynatree Plugin methods</h3>
<p>
Besides the constructor, that is called like this:
</p>
<pre class="prettyprint">
$("#tree").dynatree({
[…]
});
</pre>
<p>
The following methods are globally available from the ui.dynatree namespace:
</p>
<dl class="optionList">
<dt>$.ui.dynatree.getNode(el)
<dd>
Return a DynaTreeNode object for a given DOM element.<br>
`el` may be a DOM element or a jQuery object.
Example: <pre class="prettyprint">$("#tree a").hover(function(){
var node = $.ui.dynatree.getNode(this);
logMsg("Hover in %s", node);
}, function(){
[...]
});</pre>
</dd>
<dt>$.ui.dynatree.getPersistData(cookieId, cookieOpts)
<dd>
Return cookie persistence info as dictionary.
</dd>
<dt>$.ui.dynatree.version
<dd>
Release version number.
</dd>
</dl>
<p>
The following methods are directly available from the plugin:
</p>
<dl class="optionList">
<dt>$("#tree").dynatree("disable")
<dd>
Disable event handling and add a class 'dynatree-disabled' to
the container element.
</dd>
<dt>$("#tree").dynatree("enable")
<dd>
Enable event handling and remove the 'dynatree-disabled' class from the
container element.
</dd>
<dt>$("#tree").dynatree("option", )
<dd>
Set a dynatree option at runtime.
Example: <pre class="prettyprint">$("#tree").dynatree("option", "autoCollapse", true);
$("#tree").dynatree("option", "fx", { height: "toggle", duration: 200 }); </pre>
</dd>
<dt>$("#tree").dynatree("getTree")
<dd>
Return the associated <code>DynaTree</code> object.
</dd>
<dt>$("#tree").dynatree("getRoot")
<dd>
Return the root <code>DynaTreeNode</code> object of the tree.
</dd>
<dt>$("#tree").dynatree("getActiveNode")
<dd>
Return the <code>DynaTreeNode</code> object that is currently active.<br>
(May be <code>null</code>.)
</dd>
<dt>$("#tree").dynatree("getSelectedNodes")
<dd>
Return an array of <code>DynaTreeNode</code> objects that are currently
selected.<br>
(May be empty: <code>[ ]</code>.)
</dd>
</dl>
<h3><code>DynaTree</code> class members</h3>
<dl class="optionList">
<dt>tree.activateKey(key)
<dd>
Activate and focus node with a given key and fire focus and activate events.<br>
If <code>activeVisible</code> option is set, all parents will be expanded as necessary.<br>
If key is null, the current activation is removed.<br>
Return the active DynaTreeNode.
</dd>
<dt>tree.count()
<dd>
Return the number of nodes.
</dd>
<dt>tree.disable()
<dd>
Disable input for the tree and display gray. This is a shortcut for
<code>$("#tree").dynatreee("disable")</code>.
</dd>
<dt>tree.enable()
<dd>
Complement to <code>tree.disable()</code>.
</dd>
<dt>tree.enableUpdate(enable)
<dd>
Turn rendering on or off and return the previous mode.
Disabling update may speedup processing, when adding lots of nodes.<br>
Don't forget to turn rendering back on, after applying the changes:
<pre class="prettyprint">var prevMode = tree.enableUpdate(false);
[...]
tree.enableUpdate(prevMode);</pre>
</dd>
<dt>tree.getActiveNode()
<dd>
Return the currently active DynaTreeNode or null.
</dd>
<dt>tree.getNodeByKey(key)
<dd>
Return DynaTreeNode with a given key or 'null' if not found.
</dd>
<dt>tree.getPersistData()
<dd>
Return cookie persistence info as dictionary.<br>
There is also a global function available:
<code>$.ui.dynatree.getPersistData(cookieId, cookieOpts)</code>.
</dd>
<dt>tree.getRoot()
<dd>
Return the <i>invisible</i> root DynaTreeNode object.
All visible toplevel nodes are children of this system node.
</dd>
<dt>tree.getSelectedNodes(stopOnParents)
<dd>
Return a list of currently selected DynaTreeNodes (may be an empty array).<br>
If stopOnParents is set to <code>true</code>, children of selected nodes
are skipped. This may be convenient in selectMode:3 (multi-hier).
</dd>
<dt>tree.initialize()
<dd>
Constructor (internal use).
</dd>
<dt>tree.isInitializing()
<dd>
Return <code>true</code>, if the tree is in the init phase.<br>
Use this function in an event handler, to check if the event was fired
during a page reload, when the cookie persistence is applied.
</dd>
<dt>tree.isReloading()
<dd>
Return <code>true</code>, if the tree is in the init phase and persistence is on,
and the current status was read from existing cookies.<br>
Use this function in an event handler, to check if the event was fired
during a page reload, when the cookie persistence is applied.
</dd>
<dt>tree.isUserEvent()
<dd>
Return <code>true</code>, if the tree is processing a user event.<br>
Use this function in an event handler, to check if the event was fired
in response to a mouse click or key stroke.<br>
Otherwise, the the event was generated by an API call or during
initialization.
</dd>
<dt>tree.loadKeyPath(keyPath, callback)
<dd>
Make sure that a node with a given ID is loaded, by traversing - and
loading - its parents. This method is ment for lazy hierarchies.<br>
A callback is executed for every node as we go.
<pre class="prettyprint">tree.loadKeyPath("/_3/_23/_26/_27", function(node, status){
if(status == "loaded") {
// 'node' is a parent that was just traversed.
// If we call expand() here, then all nodes will be expanded
// as we go
node.expand();
}else if(status == "ok") {
// 'node' is the end node of our path.
// If we call activate() or makeVisible() here, then the
// whole branch will be exoanded now
node.activate();
}else if(status == "notfound") {
var seg = arguments[2],
isEndNode = arguments[3];
}
});</pre>
</dd>
<dt>tree.logDebug(msg), logInfo(msg), logWarning(msg)
<dd>
(Internal use).
</dd>
<dt>tree.reactivate(setFocus)
<dd>
Fire onQueryActivate and onActivate events for the currently active node
(if there is one).<br>
This may be useful when processing an onPostInit callback.
</dd>
<dt>tree.redraw()
<dd>
Render all visible nodes.
See <code>node.render()</code> for details.
</dd>
<dt>tree.reload()
<dd>
Reload the the tree.<br>
For lazy trees this is done, by re-submitting the Ajax request that was
defined in the <code>initAjax</code> option.<br>
This will <strong>not</strong> work, if the tree was loaded from an embedded
<UL> element, because these elements are removed after they have been
rendered.
</dd>
<dt>tree.renderInvisibleNodes()
<dd>
Force immediate HTML creation for all nodes, even if inside collapsed
branches.
This may be useful, if we want to bind events or otherwise must access
these HTML elements.<br>
It will however degrade performance, especially on large trees!<br>
See <code>node.render()</code> for details.
</dd>
<dt>tree.selectKey(key, flag)
<dd>
Select or deselect node with a given key and fire focus and select events.<br>
Return the selected DynaTreeNode.
</dd>
<dt>tree.serializeArray(stopOnParents)
<dd>
Return selected nodes as array of <code>{name: 'TreeName', value: 'NodeKey'}</code>
objects, where name is the 'name' attribute of the tree's <div> element.<br>
This format is compatible with jQuery's serializeArray()
function and may be used in $.post() calls.<br>
See also the 'form' sample in the Example Browser.
</dd>
<dt>tree.toDict()
<dd>
Convert the tree into a JavaScript object.<br>
See <code>node.toDict()</code> for details.
</dd>
<dt>tree.visit(fn, includeRoot)
<dd>
Call <code>fn(node)</code> for all nodes.<br>
Stop iteration, if fn() returns false.
Stop iteration <i>of the current branch</i>, if fn() returns 'skip'.
</dd>
</dl>
<h3><code>DynaTreeNode</code> class members</h3>
<dl class="optionList">
<dt>Attribute 'data'</dt>
<dd>
Use this attribute to access all node options that were passed to create
this node.<br>
For example <code>node.data.title</code> or <code>node.data.tooltip</code>.
See also <a href="#nodeOptions">Node options</a>.
</dd>
<dt>node.activate()</dt>
<dd>
Activate this node - according to flag - and fire a onActivate event.<br>
If <code>activeVisible</code> option is set, all parents will be expanded as necessary.<br>
Focus is <em>not</em> set.
</dd>
<dt>node.activateSilently()</dt>
<dd>
Same as <code>activate()</code>, but does not fire events.
</dd>
<dt>node.addChild(nodeData[, beforeNode])</dt>
<dd>
Append a new child node.<br>
<i>nodeData</i> may be a node data object as defined in
<a href="#nodeOptions">Node options</a>, or an array thereof.
Also objects and arrays of type <code>DynaTreeNode</code> are allowed.<br>
Example:
<pre class="prettyprint">
var node = $("#tree").dynatree("getTree").getNodeByKey("1234");
node.addChild({title: "New Node", key: "3333"});
</pre>
Since the <i>nodeData</i> may be a nested data structure, it is possible
to create a deep hierarchy with one call.<br>
The optional argument <i>beforeNode</i> specifies a child <code>DynaTreeNode</code>
that the new node will be inserted before. (If this parameter is <i>null</i>
or omitted, the new node will be appended.)
</dd>
<dt>node.appendAjax(ajaxOptions)</dt>
<dd>
Accepts a standard jQuery Ajax option object.<br>
An asynchronous request is started, so this function returns immediately.
While loading, a spinning wheel is displayed. On error, a red icon is shown.<br>
The request handler must return a JSON object, formatted like the data's
<code>children</code> object.<br>
Use the <code>setLazyNodeStatus()</code> function to display the result.<br>
See <a href="#lazyLoading">Loading child nodes on demand ('lazy loading')</a> for details.
</dd>
<dt>node.countChildren()</dt>
<dd>
Return the number of descendant nodes, i.e. direct and indirect children.
</dd>
<dt>node.deactivate()</dt>
<dd>
Deactivate this node and fire an onDeactivate event.
</dd>
<dt>node.expand(flag)</dt>
<dd>
Expand or collapse this node - according to flag.
</dd>
<dt>node.focus()</dt>
<dd>
Set focus to this node. Parent nodes are expanded, if this is necessary
to make it visible.
</dd>
<dt>node.getChildren()
<dd>
Return list of child nodes or <code>null</code>.<br>
For lazy nodes that have not yet been loaded, <code>undefined</code> is
is returned.
</dd>
<dt>node.getEventTargetType(event)</dt>
<dd>
Return the part of a node, that a click event occurred on.<br>
Possible values: 'prefix' 'expander', 'checkbox', 'icon', 'title'.<br>
<code>null</code> is returned else.<br>
Note: there is no check, if the event was fired on <strong>this</strong> node.
</dd>
<dt>node.getLevel()
<dd>
Return the depth (i.e. number of parent nodes).<br>
0 is returned for the root node.
</dd>
<dt>node.getNextSibling()
<dd>
Return the successor node or <code>null</code>.
</dd>
<dt>node.getParent()
<dd>
Return the parent node or <code>null</code>.
</dd>
<dt>node.getPrevSibling()
<dd>
Return the predecessor node or <code>null</code>.
</dd>
<dt>node.hasChildren()
<dd>
Return <code>true</code> if node has child nodes.<br>
Return <code>false</code> if node is a leaf, i.e. has no child nodes.<br>
Return <code>undefined</code> if this is a lazy node, that was not yet
successfully loaded.<br>
A test for 'node is surely empty' would be coded like
<pre class="prettyprint">if(node.hasChildren() === false) ...</pre>
</dd>
<dt>node.isActive()
<dd>
Return true, if this node is activated. Only one tree node may be active
at any time.
</dd>
<dt>node.isChildOf(otherNode)
<dd>
Return true, if this node is a <i>direct</i> child of
<code>otherNode</code>.
</dd>
<dt>node.isDescendantOf(otherNode)
<dd>
Return true, if this node is a descendent (direct or indirect child) of
<code>otherNode</code>.
</dd>
<dt>node.isExpanded()
<dd>
Return true, if the node is expanded.
</dd>
<dt>node.isFirstSibling()
<dd>
Return true, if this node is the first of all children of the current parent.
</dd>
<dt>node.isFocused()
<dd>
Return true, if this node is has the focus.
</dd>
<dt>node.isLastSibling()
<dd>
Return true, if this node is the last of all children of the current parent.
</dd>
<dt>node.isLazy()
<dd>
Return true, if the node is lazy (loaded or not).
</dd>
<dt>node.isLoading()
<dd>
Return true, if the node is lazy and currently loading (i.e. an Ajax request is active).
</dd>
<dt>node.isSelected()
<dd>
Return true, if the node is selected.
</dd>
<dt>node.isStatusNode()
<dd>
Return true, if this is an temporary status node. Status nodes are
created while loading lazy data, to display a throbber or error
condition.
</dd>
<dt>node.isVisible()
<dd>
Return true, if the node is visible, i.e. all parents are expanded.
</dd>
<dt>node.makeVisible()
<dd>
Expand all parents as neccessary, to make this node visible.
</dd>
<dt>node.move(targetNode, mode)
<dd>
Move this node to <code>targetNode</code>.
Possible <code>mode</code>:
<ul>
<li><code>child</code>: append this node as last child of targetNode.
This is the default.
To be compatble with the D'n'd hitMode, we also accept 'over'.
<li><code>before</code>: add this node as sibling before targetNode.
<li><code>after</code>: add this node as sibling after targetNode.
</ul>
</dd>
<dt>node.reload(force)</dt>
<dd>
Deprecated. Use <code>reloadChildren()</code> instead.
</dd>
<dt>node.reloadChildren(callback)</dt>
<dd>
Discard and reload all children of a lazy node by triggering
the <code>onLazyRead</code> event.
if <code>callback</code> is passed, it is called after the Ajax request
was executed.
Example <pre class="prettyprint">node.reloadChildren(function(node, isOk){
if(!isOk) alert("Node " + node + " could not be reloaded.");
});</pre>
</dd>
<dt>node.remove()
<dd>
Remove this node and descendents from tree.
</dd>
<dt>node.removeChildren()
<dd>
Remove all child nodes and descendents.
</dd>
<dt>node.render(useEffects, includeInvisible)
<dd>
Redraw this node with current attributes. All HTML markup is updated
and class names are added according to current status.<br>
If this node is expanded, markup for children is recursively generated
as well.
<ul>
<li><code>useEffects</code>:<br>
(default: false) Set to false to prevent animated expand effects,
which would be applied asynchronously.
<li><code>includeInvisible</code>:<br>
(default: false) Force HTML creation for all descendants, even if
inside a collapsed branch.<br>
This may be useful, if we want to bind events or otherwise access
these HTML elements. It will however degrade performance, especially
on large trees.
</ul>
<br>
Most of the time, there is no need to call this explicitly, since it is
internally called on state changes.
</dd>
<dt>node.resetLazy()
<dd>
Remove all children from a lazy node and make sure it is collapsed.
The node will be re-loaded when expanded the next time.
</dd>
<dt>node.scheduleAction(mode, ms)
<dd>
Schedule a delayed action.
Possible <code>mode</code>:
<ul>
<li><code>expand</code>: Expand this node after <i>ms</i> microseconds.
<li><code>activate</code>: Activate this node after <i>ms</i> microseconds.
<li><code>cancel</code>: cancel pending action, if any was scheduled.
</ul>
</dd>
<dt>node.select(flag)
<dd>
Select or deselect this node - according to flag - and fire an onSelect event.
</dd>
<dt>node.setLazyNodeStatus(status)
<dd>
Display a dummy child node, to provide feedback, when loading a lazy node's content. <br>
Possible status:
<ul>
<li><code>DTNodeStatus_Loading</code>: show a spinning wheel, with 'loading...' message.
<li><code>DTNodeStatus_Error</code>: show an error icon and message.
<li><code>DTNodeStatus_Ok</code>: Remove the status node.
</ul>
Messages may be customized using the <code>strings.loading</code> and <code>strings.loadError</code> options.
</dd>
<dt>node.setTitle(title)
<dd>
Change current node title and redraw.
</dd>
<dt>node.sortChildren(cmp, deep)
<dd>
Sort child list by title.<br>
<code>cmd</code>: optional compare function. If ommitted sorting is done by node titles.<br>
<code>deep</code>: optional: pass true to sort all descendant nodes.<br>
Example<pre class="prettyprint">// Custom compare function (optional) that sorts case insensitive
var cmp = function(a, b) {
a = a.data.title.toLowerCase();
b = b.data.title.toLowerCase();
return a > b ? 1 : a < b ? -1 : 0;
};
node.sortChildren(cmp, false);</pre>
</dd>
<dt>node.toDict(recursive, callback)
<dd>
Convert the node into a JavaScript object.<br>
<code>recursive</code>: set to true, to include child nodes.<br>
<code>callback</code>: (optional) function to allow modifications.<br>
Example <pre class="prettyprint">var cb = node.toDict(true, function(dict){
dict.title = "Copy of " + dict.title;
delete dict.key; // prevent duplicate keys
});</pre>
</dd>
<dt>node.toggleExpand()
<dd>
Toggle expansion state.<br>
Expanding a lazy node, fires a onLazyRead event.
</dd>
<dt>node.toggleSelect()
<dd>
Toggle selection state.
</dd>
<dt>node.visit(fn, includeSelf)
<dd>
Call <code>fn(node)</code> for all child nodes.<br>
Stop iteration, if fn() returns false.
Stop iteration <i>of the current branch</i>, if fn() returns the string
'skip'.
</dd>
<dt>node.visitParents(fn, includeSelf)
<dd>
Call <code>fn(node)</code> for all parent nodes.<br>
Stop iteration, if fn(node) returns false.
</dd>
</dl>
<h3>Programming examples</h3>
<p>
The follwing code snippets should give an idea on how to use the API.
</p>
<h4>Example: Select a node with key '1234'</h4>
<pre class="prettyprint">
$("#tree").dynatree("getTree").selectKey("1234");
// or another way:
$("#tree").dynatree("getTree").getNodeByKey("1234").select();
// .. or yet another way (if 'generateIds' option was enabled):
$("#dynatree-id-1234").prop("dtnode").select();
</pre>
<h4>Example: Access the currently active node</h4>
<pre class="prettyprint">
var node = $("#tree").dynatree("getActiveNode");
if( node ){
alert("Currently active: " + node.data.title);
}
</pre>
<h4>Example: Retrieve a node using for a DOM element or jQuery object</h4>
<pre class="prettyprint">
$(".dynatree-partsel").each(function(){
var node = $.ui.dynatree.getNode(this);
[...]
});
</pre>
<h4>Example: Rename the active node</h4>
<pre class="prettyprint">
var node = $("#tree").dynatree("getActiveNode");
node.data.title = "My new title";
node.render();
</pre>
<h4>Example: Add a child to the active node</h4>
<pre class="prettyprint">
var node = $("#tree").dynatree("getActiveNode");
var childNode = node.addChild({
title: "My new node",
tooltip: "This folder and all child nodes were added programmatically."
});
</pre>
<p>
Note: instead of passing a single child object, we could also pass an array
of such objects.<br>
Also, the children may again contain <code>children</code> attributes, thus
defining a sub tree.
</p>
<h4>Example: Add a hover handler and find the hovered node from any sub element</h4>
<pre class="prettyprint">
// Bind hover events to the tree's <a> tags:
$("#tree a").hover(function(){
var node = $.ui.dynatree.getNode(this);
logMsg("Hover in %s", node);
}, function(){
var node = $.ui.dynatree.getNode(this);
logMsg("Hover out %s", node);
});
</pre>
<h4>Example: Expand all nodes</h4>
<pre class="prettyprint">
$("#tree").dynatree("getRoot").visit(function(node){
node.expand(true);
});
</pre>
<h4>Example: Save current tree status to the backend</h4>
<pre class="prettyprint">
// Get a JavaScript object copy of the tree
var dict = $("#tree").dynatree("getTree").toDict();
// ... then use Ajax to send this to your server...
</pre>
<h4>Example: activate a node depending on URL</h4>
This sample shows how to parse the page URL and activate a node accordingly:
<code>http://server/_test-194.html?activate=_11</code>
<pre class="prettyprint">
// Add a helper function to parse the URL
function getURLParameter(name) {
return unescape(
(RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]
);
}
// Evaluate the URL after the tree was loaded
$(function(){
$("#tree").dynatree({
[...]
onPostInit: function(isReloading, isError) {
var key = getURLParameter("activate");
if( key ) {
this.activateKey(key);
}
},
</pre>
<h2 id="theming">Theming and translation</h2>
<p>
The tree's fonts, colors, and icons are defined using CSS, so changing the
appearance is simply a matter of including a custom stylesheet or by
replacing <a href="../src/skin/icons.gif">icons.gif</a> with another
version.
</p>
<div class="codesample">
<a href="sample-theming.html">Try this example...</a>
<pre class="prettyprint">
<script src="../jquery/jquery.js" type="text/javascript"></script>
<script src="../jquery/jquery-ui.custom.js" type="text/javascript"></script>
<script src="../src/jquery.dynatree.js" type="text/javascript"></script>
<!-- Include the basic stylesheet: -->
<link href="../src/skin-vista/ui.dynatree.css" rel="stylesheet" type="text/css">
<!-- Override CSS with a custom stylesheet : -->
<link href="skin-custom/custom.css" rel="stylesheet" type="text/css" >
<script type="text/javascript">
$(function(){
$("#tree").dynatree({
[…]
});
});
</script>
</pre>
</div>
<p>
Custom.css would include lines like this:
</p>
<pre class="prettyprint">
.dynatree-has-children span.dynatree-icon
{
background-position: 0 0;
background-image: url("doc_with_children.gif");
}
</pre>
<p>
Changing the appearance and icons of <b>single nodes</b> is done by assigning a
custom class:
</p>
<pre class="prettyprint">
<ul>
<li data="addClass: 'custom1'">Document with custom class
</pre>
<p>
or
</p>
<pre class="prettyprint">
children: [
{ title: "Document with custom class", addClass: "custom1" },
</pre>
<p>
we would then add CSS definitions for the new node to our stylesheet:
</p>
<pre class="prettyprint">
span.custom1 a
{
background-color: #ffffbb;
color: maroon;
}
span.custom1 span.dynatree-icon
{
background-position: 0 0;
background-image: url("customDoc2.gif");
}
</pre>
<h3>Translation</h3>
<p>
Strings can be translated in the tree options:
</p>
<pre class="prettyprint">
$("#tree").dynatree({
[…]
strings: {
loading: "Daten werden geladen…",
loadError: "Fehler beim Laden!"
},
});
</pre>
<h2><a id="issues"></a>Feedback, version history, credits and known issues</h2>
<h3>Credits</h3>
<p>
I am using the <a href="http://prendreuncafe.com/work/jqplanize/">planize plugin</a>
by Nicolas Perriault for the table of contents.<br>
I am using <a href="http://code.google.com/p/google-code-prettify/">prettify.js</a>
by Mike Samuel for syntax highlighting in the of source code samples.
</p>
<h3>Feedback and support</h3>
<p>
First of all: this is work in progress.<br>
Any kind of feedback is very welcome :-)
</p>
<ul>
<li>A <a href="http://groups.google.com/group/dynatree">discussion forum</a> is in place to ask questions or discuss features.
<li>Check <a href="http://stackoverflow.com/tags/dynatree">Stack Overflow</a> for existing questions.
<li>Use the <a href="http://code.google.com/p/dynatree/issues/list">Issue Tracker</a> to get a list of known bugs, or vote for a feature.<br>
Please make sure you searched the group and issue tracker, before adding a new request.
<li>If you like:
<a href="http://wwwendt.de/freeware/donate.html">Make a donation</a>.
</ul>
</body>
</html>