# jqTree

JqTree is a jQuery widget for displaying a tree structure in html
It supports json data, loading via ajax and drag-and-drop.

Download jqTree

#### Introduction

JqTree is a jQuery widget for displaying a tree structure in html. It supports json data, loading via ajax and drag-and-drop.

#### Features

- Create a tree from JSON data
- Load data using ajax
- Drag and drop
- Saves the state
- Keyboard support
- Lazy loading
- Works on ie8+, firefox 3.6+, chrome and safari
- Written in Coffeescript

The project is hosted on github, has a test suite.

#### Demo

    var data = [
        {
            label: 'node1',
            children: [
                { label: 'child1' },
                { label: 'child2' }
            ]
        },
        {
            label: 'node2',
            children: [
                { label: 'child3' }
            ]
        }
    ];
    $('#tree1').tree({
        data: data,
        autoOpen: true,
        dragAndDrop: true
    });

#### Requirements

- jQuery 1.5+ or 2.0

#### Downloads

- All (version 0.21): jqTree.tar.gz
- Javascript: tree.jquery.js
- Css: jqtree.css
- Image: jqtree-circle.png

#### Tutorial

Include jQuery.

    <script src="jquery.min.js"></script>

Include tree.jquery.js:

    <script src="tree.jquery.js"></script>

Include jqtree.css:

    <link rel="stylesheet" href="jqtree.css">

Optionally, for saveState include jquery-cookie:

    <script src="jquery.cookie.js"></script>

Create a div.

    <div id="tree1"></div>

Create tree data.

    var data = [
        {
            label: 'node1',
            children: [
                { label: 'child1' },
                { label: 'child2' }
            ]
        },
        {
            label: 'node2',
            children: [
                { label: 'child3' }
            ]
        }
    ];

Create tree widget.

    $(function() {
        $('#tree1').tree({
            data: data
        });
    });

Alternatively, get the data from the server.

    $.getJSON(
        '/some_url/',
        function(data) {
            $('#tree1').tree({
                data: data
            });
        }
    );

#### Examples

- Example 1 - load json data
- Example 2 - load json data from the server
- Example 3 - drag and drop
- Example 4 - save the state
- Example 5 - load nodes on demand from the server
- Example 6 - autoEscape
- Example 7 - autoscroll
- Example 8 - multiple select
- Example 9 - custom html
- Example 10 - use icon toggle buttons

#### Changelog

#### 0.21 (june 7 2014) version

- Issue 263: Improve styling of toggle button
- Issue 266: Make it possible to use html for toggle buttons
- Issue 262: updateNode on first level makes node disappear (thanks to Miloš Đekić)
- Issue 260: Exempt 'select' elements from keyboard navigation (thanks to Eli Flanagan)
- Issue 270: Fixed error 'selected_single_node is not defined' (thanks to Bryan Smith)
- Issue 279: .jqtree-moving removed when loading subtree (thanks to Marc-Stefan Cassola)
- Issue 280: CSS3 Circle and style optimization (thanks to Marc-Stefan Cassola)
- Issue 283: Added function getNodesByProperty (thanks to Cedrik Vanderhaegen)
- Issue 292: Save state if multiple nodes are selected (thanks to MykhailoP)
- Issue 294: Handle click on input element in tree (thanks to Naeco33)

#### 0.20 (march 9 2014)

- Issue 235: Added setOption function
- Issue 241: Prevent duplicate event call after re-initalization
- Issue 246: Check if folder must be opened while moving node (thanks to Dave Gardner)
- Issue 247: Improve performance of updateNode (thanks to Gordon Woodhull)
- Issue 250: Improve performance of creating dom elements (thanks to Carlos Scheidegger)
- Issue 252: BorderDropHint has wrong height for border-box box-sizing (thanks to simshaun)
- Issue 253: Added reload function
- Issue 256: Toggler button is underlined
- Issue 257: Make it possible to open a lazily loaded folder using the keyboard
- Issue 258: Correctly unselect children if a node is reloaded

#### 0.19 (december 8 2013)

- Issue 225: Fixes TypeError when removing nodes without ids that aren't selected (thanks to Marcus McCurdy)
- Issue 222: scrollToNode does not consider direct parent
- Issue 228: add property click_event to tree.click and tree.dblclick events (thanks to Gordon Woodhull)
- Added option openFolderDelay: the delay for opening a folder during drag-and-drop (thanks to Jason Diamond)

#### 0.18 (september 17 2013)

- Issue 132: Skip keyboard handling if focus is on input element (thanks to Bingeling)
- Issue 179 and 180: Added dataFilter option to filter the returned data from jQuery.ajax (thanks to Cheton Wu and Tony Dilger)
- Issue 184: If the node id is 0, the id mapping is incorrect (thanks to Ika Wu)
- Issue 190: The function selectNode should not toggle (thanks to Gordon Woodhull)
- Issue 192: Added keyboardSupport option (thanks to Ika Wu)
- Issue 181: Added tree.dblclick event (thanks to eskaigualker)
- Issue 196: localStorage doesn't work in Safari private browsing (thanks to thebagg)
- Issue 203: Adding deselected_node attribute to event object of tree.select event (thanks to tedtoer)

#### 0.17 (july 14 2013)

- Issue 132: Added keyboard support
- Issue 154: Calling loadDataFromUrl should not trigger tree.init event (thanks to Davide Bellini)
- Issue 158: Index not updated on updateNode (thanks to Sam Mousa)
- Issue 159: Cannot reselect node after unselecting it (thanks to Comanche)
- Issue 162: Added getPreviousSibling and getNextSibling functions (thanks to Dimaninc)
- Issue 169: Added touch support (thanks to Comanche)
- Issue 171: Added functions getState and setState
- Issue 175: Make it possible to install jqTree using bower (thanks to Adam Miskiewicz)

#### 0.16 (may 17 2013)

- Issue 62: Added functions for multiple select
- Issue 125: Add option for overriding TRIANGLE_RIGHT and TRIANGLE_DOWN (thanks to Sam D)
- Issue 126: Event tree.open event fires after first tree.select on top level node
- Issue 129: Allow native context menu to be display (thanks to Charles Bourasseau)
- Issue 130: Selectable not implemented (thanks to Sam D)
- Issue 133: loadDataFromUrl doesn't work when only parent_node and callback are passed in (thanks to Simone Deponti)
- Issue 134: selectNode from inside tree.init breaks on loadData (thanks to Sam D)
- Issue 145: Auto-open nodes with drag n drop when drag not enabled for that node (thanks to Daniel Powell)
- Issue 146: Added function scrollToNode (thanks to Davide Bellini)

#### 0.15 (march 16 2013)

- Issue 100: Clicking on the jqtree-element element will trigger click event
- Issue 102: Add original event to tree.move event
- Issue 103: Added getLevel function to Node class
- Issue 104: The addNodeBefore method must return the new node
- Issue 105: Added nodeClass option
- Issue 112: Fix call to iterate in removeNode (thanks to Ingemar Ådahl)
- Issue 113: Added onLoadFailed option (thanks to Shuhei Kondo)
- Issue 118: Deselect a node when click and already selected
- Issue 119: Make it easier to reload a subtree
- Issue 121: Unselect node if it's reloaded by loadDataFromUrl

#### 0.14 (december 2 2012)

###### Api changes

- Removed parameter must_open_parents from function selectNode.
- Changed slide parameter in functions openNode and closeNode.

###### Issues

- Issue 80: Support more options for loading data from the server. E.g. the 'post' method (thanks to Rodrigo Rosenfeld Rosas)
- Issue 81: getSelectedNode must return false if node is removed
- Issue 82: Autoscroll for drag-and-drop
- Issue 84: Fix correct type param in $.ajax() (thanks to Rodrigo Rosenfeld Rosas)
- Issue 85: Option to turn slide animation on or off
- Issue 86: The openNode function must automatically open parents
- Issue 87: Remove the must_open_parents parameter from the selectNode function
- Issue 88: selectNode must also work if selectable option is false
- Issue 89: Clicking in title with img or em does not work
- Issue 96: Added jqtree_common class to avoid css clashes (thanks to Yaniv Iny)

#### 0.13 (october 10 2012)

- Issue 54: Added tree.select event
- Issue 63: Fixed contextmenu event
- Issue 67: Use unicode characters for triangle buttons (thanks to Younès)
- Issue 70: Load data from the server using the loadData function
- Issue 78: Drag and drop is trigger happy

#### 0.12 (august 14 2012)

- Issue 46: Added tree.refresh event
- Issue 47: Function 'selectNode' must properly open the parent nodes
- Issue 49: Make sure that widget functions can be called in the 'tree.init' event
- Issue 50: Add namespace to css classes
- Issue 51: closeNode to collapse tree doesn't work
- Issue 55: Load-on-demand from the server
- Issue 58: Added updateNode function
- Issue 59: Added moveNode function
- Issue 60: Use native JSON.stringify function

#### 0.11 (july 8 2012)

- Autoescape text
- Added autoEscape option
- Issue 33: appendNode does not correctly refresh the tree
- Issue 34: unset internal pointer to previously selected node on DOM deselect
- Issue 38: Correctly check if browser has support for localstorage
- Issue 41: Open nodes are not displayed correctly in ie7

#### 0.10 (june 10 2012)

- Optimized getNodeById
- Issue #18 and #26: Made comparison in getNodeById less strict
- Added function prependNode
- Added 'data-url' option
- Added removeNode function
- Issue #24: Tree with jquery ui Dialog: expand causes resize and move problem
- Added Travis ci support
- Added addNodeAfter, addNodeBefore and addParentNode
- Renamed icons.png to jqtree-icons.png
- selectNode with empty node deselects the current node

#### 0.9 (may 9 2012)

- Issue 15: 'tree.open' event is not triggered when dragging nodes
- Issue 18: Allow moveNode to be canceled through ev.preventDefault()
- Use sprite for images
- Added function closeNode
- Added support for localstorage
- Implemented alternative data format

#### 0.8 (april 18 2012)

- Replace jquery.ui widget with SimpleWidget
- Added 'previous_parent' to 'tree.move' event
- Add posibility to load subtree
- Added 'tree.open' and 'tree.close' events

### Tree options

#### autoEscape

Determine if text is autoescaped. The default is true.

#### autoOpen

Open nodes initially.

- true: open all nodes.
- false (default): do nothing
- n: open n levels

Open all nodes initially:

    $('#tree1').tree({
        data: data,
        autoOpen: true
    });

Open first level nodes:

    $('#tree1').tree({
        data: data,
        autoOpen: 0
    });

#### closedIcon

A character or symbol to display on closed nodes. The default is '&#x25ba;' (►)

    $('#tree1').tree({
        closedIcon: '+'
    });

#### data

Define the contents of the tree. The data is a nested array of objects. This option is required.
It looks like this:

    var data = [
        {
            label: 'node1',
            children: [
                { label: 'child1' },
                { label: 'child2' }
            ]
        },
        {
            label: 'node2',
            children: [
                { label: 'child3' }
            ]
        }
    ];
    $('#tree1').tree({data: data});

- label: label of a node (required)
- children: array of child nodes (optional)

You can also include other data in the objects. You can later access this data.
For example, to add an id:

    {
        label: 'node1',
        id: 1
    }

#### dataFilter

Process the tree data from the server.

    $('#tree1').tree({
        url: '/my/data/',
        dataFilter: function(data) {
            // Example:
            // the server puts the tree data in 'my_tree_data'
            return data['my_tree_data'];
        }
    });

#### dataUrl

Load the node data from this url.

    $('#tree1').tree({
       dataUrl: '/example_data.json'
    });

You can also set the data-url attribute on the dom element:

    <div id="tree1" data-url="/example_data.json"></div>
    <script>
        $('#tree1').tree();
    </script>

#### dragAndDrop

Turn on dragging and dropping of nodes.

- true: turn on drag and drop
- false (default): do not allow drag and drop

Example: turn on drag and drop.

    $('#tree1').tree({
        data: data,
        dragAndDrop: true
    });

#### keyboardSupport

Enable or disable keyboard support. Default is enabled.

Example: disable keyboard support.

    $('#tree1').tree({
        keyboardSupport: false
    });

#### onCanMove

You can override this function to determine if a node can be moved.

    $('#tree1').tree({
        data: data,
        dragAndDrop: true,
        onCanMove: function(node) {
            if (! node.parent.parent) {
                // Example: Cannot move root node
                return false;
            }
            else {
                return true;
            }
        }
    });

#### onCanMoveTo

You can override this function to determine if a node can be moved to a certain position.

    $('#tree1').tree({
        data: data,
        dragAndDrop: true,
        onCanMoveTo: function(moved_node, target_node, position) {
            if (target_node.is_menu) {
                // Example: can move inside menu, not before or after
                return (position == 'inside');
            }
            else {
                return true;
            }
        }
    });

#### onCanSelectNode

You can set a function to override if a node can be selected. The function gets a node as parameter, and must return true or false.
For this to work, the option 'selectable' must be 'true'.

    // Example: nodes with children cannot be selected
    $('#tree1').tree({
        data: data,
        selectable: true
        onCanSelectNode: function(node) {
            if (node.children.length == 0) {
                // Nodes without children can be selected
                return true;
            }
            else {
                // Nodes with children cannot be selected
                return false;
            }
        }
    });

#### onCreateLi

The function is called for each created node. You can use this to define extra html.

    $('#tree1).tree({
        data: data,
        onCreateLi: function(node, $li) {
            // Add 'icon' span before title
            $li.find('.jqtree-title').before('<span class="icon"></span>');
        }
    });

#### onIsMoveHandle

You can override this function to determine if a dom element can be used to move a node.

    $('#tree1').tree({
        data: data,
        onIsMoveHandle: function($element) {
            // Only dom elements with 'jqtree-title' class can be used
            // as move handle.
            return ($element.is('.jqtree-title'));
        }
    });

#### onLoadFailed

When loading the data by ajax fails, then the option onLoadFailed is called.

    $('#tree1').tree({
        url: '/my/data/',
        onLoadFailed: function(response) {
            //
        }
    });

#### openedIcon

A character or symbol to display on opened nodes. The default is '&#x25bc;' (▼)

    $('#tree1').tree({
        openedIcon: '-'
    });

#### openFolderDelay

Set the delay for opening a folder during drag-and-drop. The delay is in milliseconds. The default is 500 ms.

    $('#tree1').tree({
        url: '/my/data/',
        openFolderDelay: 1000
    });

#### saveState

Save and restore the state of the tree automatically. Saves in a cookie which nodes are opened and selected.
The state is saved in localstorage. In browsers that do not support localstorage, the state is saved in a cookie. For this to work, please include jquery-cookie.

For this to work, you should give each node in the tree data an id field:

    {
        label: 'node1',
        id: 123,
        childen: [
            label: 'child1',
            id: 124
        ]
    }

- true: save and restore state in a cookie
- false (default): do nothing
- string: save state and use this name to store in a cookie

    $('#tree1').tree({
        data: data,
        saveState: true
    });

Example: save state in key 'tree1':

    $('#tree1').tree({
        data: data,
        saveState: 'tree1'
    });

#### selectable

Turn on selection of nodes.

- true (default): turn on selection of nodes
- false: turn off selection of nodes

Example: turn off selection of nodes.

    $('#tree1').tree({
        data: data,
        selectable: false
    });

#### slide

Turn slide animation on or off. Default is true.

    $('#tree1').tree({
        slide: false
    });

#### useContextMenu

Bind the context menu event (true/false).

true (default)
A right mouse-click will trigger a tree.contextmenu event. This overrides the native contextmenu of the browser.

false
A right mouse-click will trigger the native contextmenu of the browser.

### Functions

#### addNodeAfter

function addNodeAfter(new_node_info, existing_node);

Add a new node after this existing node.

    var node1 = $('#tree1', 'getNodeByName', 'node1');
    $('#tree1').tree(
        'addNodeAfter',
        {
            label: 'new_node',
            id: 456
        },
        node1
    );

#### addNodeBefore

function addNodeBefore(new_node_info, existing_node);

Add a new node before this existing node.

#### appendNode

function appendNode(new_node_info, parent_node);

Add a node to this parent node. If parent_node is empty, then the new node becomes a root node.

    var parent_node = $tree.tree('getNodeById', 123);

    $tree.tree(
        'appendNode',
        {
            label: 'new_node',
            id: 456
        },
        parent_node
    );

To add a root node, leave *parent_node* empty:

    $tree.tree(
        'appendNode',
        {
            label: 'new_node',
            id: 456
        }
    );

#### closeNode

function closeNode(node);
function closeNode(node, slide);

Close this node. The node must have child nodes.
Parameter slide: close the node using a slide animation (default is true).

    var node = $tree.tree('getNodeById', 123);
    $tree.tree('closeNode', node);

To close the node without the slide animation, call with slide parameter is false.

    $tree.tree('closeNode', node, false);

#### getNodeById

function getNodeById(id);
Get a tree node by node-id. This assumes that you have given the nodes in the data a unique id.

    var $tree = $('#tree1');
    var data = [
        { id: 10, name: 'n1' },
        { id: 11, name: 'n2' }
    ];

    $tree.tree({
        data: data
    });
    var node = $tree.tree('getNodeById', 10);

#### getSelectedNode

Get the selected node. Returns the row data or false.

    var node = $tree.tree('getSelectedNode');

#### getState

function getState();

Get the state of tree: which nodes are open and which one is selected?

#### getTree

function getTree();

Get the root node of the tree.

#### loadData

function loadData(data);
function loadData(data, parent_node);

Load data in the tree. The data is array of nodes.
You can replace the whole tree or you can load a subtree.

    // Assuming the tree exists
    var new_data = [
        {
            label: 'node1',
            children: [
                { label: 'child1' },
                { label: 'child2' }
            ]
        },
        {
            label: 'node2',
            children: [
                { label: 'child3' }
            ]
        }
    ];
    $('#tree1').tree('loadData', new_data);

Load a subtree:

    // Get node by id (this assumes that the nodes have an id)
    var node = $('#tree1').tree('getNodeById', 100);

    // Add new nodes
    var data = [
        { label: 'new node' },
        { label: 'another new node' }
    ];
    $('#tree1').tree('loadData', data, node);

#### loadDataFromUrl

function loadDataFromUrl(url);
function loadDataFromUrl(url, parent_node);
function loadDataFromUrl(parent_node);

Load data in the tree from an url using ajax. You can replace the whole tree or you can load a subtree.

    $('#tree1').tree('loadDataFromUrl', '/category/tree/');

Load a subtree:

    var node = $('#tree1').tree('getNodeById', 123);
    $('#tree1').tree('loadDataFromUrl', '/category/tree/123', node);

You can also omit the url. In this case jqTree will generate a url for you. This is very useful if you use the load-on-demand feature:

    var $tree = $('#tree1');

    $tree.tree({
        dataUrl: '/my_data/'
    });

    var node = $tree.tree('getNodeById', 456);

    // jqTree will load data from /my_data/?node=456
    $tree.tree('loadDataFromUrl', node);

You can also add an on_finished callback parameter that will be called when the data is loaded:

function loadDataFromUrl(url, parent_node, on_finished);
function loadDataFromUrl(parent_node, on_finished);

    $('#tree1').tree(
        'loadDataFromUrl',
        '/category/tree/123',
        null,
        function() {
            alert('data is loaded');
        }
    );

#### moveNode

function moveNode(node, target_node, position);

Move a node. Position can be 'before', 'after' or 'inside'.

    var node = $tree.tree('getNodeById', 1);
    var target_node = $tree.tree('getNodeById', 2);

    $tree.tree('moveNode', node, target_node, 'after');

#### openNode

function openNode(node);
function openNode(node, slide);

Open this node. The node must have child nodes.
Parameter slide: open the node using a slide animation (default is true).

    // create tree
    var $tree = $('#tree1');
    $tree.tree({
        data: data
    });

    var node = $tree.tree('getNodeById', 123);
    $tree.tree('openNode', node);

To open the node without the slide animation, call with slide parameter is false.

    $tree.tree('openNode', node, false);

#### addParentNode

function addParentNode(new_node_info, existing_node);

Add a new node as parent of this existing node.

    var node1 = $('#tree1', 'getNodeByName', 'node1');
    $('#tree1').tree(
        'addParentNode',
        {
            label: 'new_parent',
            id: 456
        },
        node1
    );

#### reload

function reload();

Reload data.

    $('#tree1').tree('reload');

#### removeNode

function removeNode(node);

Remove node from the tree.

    $('#tree1').tree('removeNode', node);

#### selectNode

function selectNode(node);
function selectNode(null);

Select this node.
You can deselect the current node by calling selectNode(null).

    // create tree
    var $tree = $('#tree1');
    $tree.tree({
        data: data,
        selectable: true
    });

    var node = $tree.tree('getNodeById', 123);
    $tree.tree('selectNode', node);

#### scrollToNode

function scrollToNode(node);

Scroll to this node. This is useful if the tree is in a container div and is scrollable.

    var node = $tree.tree('getNodeById', 1);
    $tree.tree('scrollToNode', node);

#### setOption

function setOption(option, value);

Set a tree option. These are the same options that you can set when creating the tree.

    $('#tree1').tree('setOption', 'keyboardSupport', false);

#### setState

function setState(state);

Set the state of the tree: which nodes are open and which one is selected?

#### toggle

function toggle(node);

Open or close the tree node.

#### toJson

function toJson();
Get the tree data as json.

    // Assuming the tree exists
    $('#tree1').tree('toJson');

#### updateNode

function updateNode(node, label);
function updateNode(node, data);

Update the title of a node. You can also update the data.

Update the label:

    var node = $tree.tree('getNodeById', 123);

    $tree.tree('updateNode', node, 'new label');

Update the data (including the label)

    var node = $tree.tree('getNodeById', 123);

    $tree.tree(
        'updateNode',
        node,
        {
            label: 'new label',
            other_property: 'abc'
        }
    );

### Events

#### tree.click

Triggered when a tree node is clicked. The event contains the following properties:

- node: the node that is clicked on
- click_event: the original click event

    // create tree
    $('#tree1').tree({
        data: data
    });

    // bind 'tree.click' event
    $('#tree1').bind(
        'tree.click',
        function(event) {
            // The clicked node is 'event.node'
            var node = event.node;
            alert(node.name);
        }
    );

The default action is to select the node. You can prevent the selection by calling preventDefault:

    $('#tree1').bind(
        'tree.click',
        function(event) {
            event.preventDefault();
        }
    );

#### tree.close

Called when a node is closed.

    $('#tree1').bind(
        'tree.close',
        function(e) {
            console.log(e.node);
        }
    );

#### tree.contextmenu

Triggered when the user right-clicks a tree node. The event contains the following properties:

- node: the node that is clicked on
- click_event: the original click event

    // bind 'tree.contextmenu' event
    $('#tree1').bind(
        'tree.contextmenu',
        function(event) {
            // The clicked node is 'event.node'
            var node = event.node;
            alert(node.name);
        }
    );

#### tree.dblclick

The tree.dblclick is fired when a tree node is double-clicked. The event contains the following properties:

- node: the node that is clicked on
- click_event: the original click event

    $('#tree1').bind(
        'tree.dblclick',
        function(event) {
            // event.node is the clicked node
            console.log(event.node);
        }
    );

#### tree.init

Called when the tree is initialized. This is particularly useful when the data is loaded from the server.

    $('#tree1').bind(
        'tree.init',
        function() {
            // initializing code
        }
    );

#### tree.move

Triggered when the user moves a node.

Event.move_info contains:

- moved_node
- target_node
- position: (before, after or inside)
- previous_parent

    $('#tree1').tree({
        data: data,
        dragAndDrop: true
    });

    $('#tree1').bind(
        'tree.move',
        function(event) {
            console.log('moved_node', event.move_info.moved_node);
            console.log('target_node', event.move_info.target_node);
            console.log('position', event.move_info.position);
            console.log('previous_parent', event.move_info.previous_parent);
        }
    );

You can prevent the move by calling event.preventDefault()

    $('#tree1').bind(
        'tree.move',
        function(event) {
            event.preventDefault();
        }
    );

You can later call event.move_info.move_info.do_move() to move the node. This way you can ask the user before moving the node:

    $('#tree1').bind(
        'tree.move',
        function(event) {
            event.preventDefault();

            if (confirm('Really move?')) {
                event.move_info.do_move();
            }
        }
    );

Note that if you want to serialise the tree, for example to POST back to a server, you need to let tree complete the move first:

    $('#tree1').bind(
        'tree.move',
        function(event)
        {
            event.preventDefault();
            // do the move first, and _then_ POST back.
            event.move_info.do_move();
            $.post('your_url', {tree: $(this).tree('toJson')});
        }
    );

#### tree.open

Called when a node is opened.

    $('#tree1').bind(
        'tree.open',
        function(e) {
            console.log(e.node);
        }
    );

#### tree.select

Triggered when a tree node is selected or deselected.
If a node is selected, then event.node contains the selected node.
If a node is deselected, then the event.node property is null.

    $('#tree1').bind(
        'tree.select',
        function(event) {
            if (event.node) {
                // node was selected
                var node = event.node;
                alert(node.name);
            }
            else {
                // event.node is null
                // a node was deselected
                // e.previous_node contains the deselected node
            }
        }
    );

### Multiple selection

Jqtree has some functions that can help you to implement multiple selection. See Example 8 - multiple select.

In order for multiple selection to work, you must give the nodes an id.

#### addToSelection

Add this node to the selection

    var node = $('#tree1').tree('getNodeById', 123);
    $('#tree1').tree('addToSelection', node);

#### getSelectedNodes

Return a list of selected nodes.

    var nodes = $('#tree1').tree('getSelectedNodes');

#### isNodeSelected

Return if this node is selected.

    var node = $('#tree1').tree('getNodeById', 123);
    var is_selected = $('#tree1').tree('isNodeSelected', node);

#### removeFromSelection

Remove this node from the selection.

    var node = $('#tree1').tree('getNodeById', 123);
    $('#tree1').tree('removeFromSelection', node);

### Node functions

You can access a node using for example getNodeById function:

    var node = $('#tree1').tree('getNodeById', 123);

The Node object has the following properties and functions:

#### children

You can access the children of a node using the children property.

    for (var i=0; i < node.children.length; i++) {
        var child = node.children[i];
    }

#### getData

Get the subtree of this node.

    var data = node.getData();

#### getLevel

Get the level of a node. The level is distance of a node to the root node.

    var node = $('#tree1').tree('getNodeById', 123);

    // result is e.g. 2
    var level = node.getLevel();

#### getNextSibling

Get the next sibling of this node. Returns a node or null.

    var level = node.getNextSibling();

#### getPreviousSibling

Get the previous sibling of this node. Returns a node or null.

    var level = node.getPreviousSibling();

#### parent

You can access the parent of a node using the parent property.

    var parent_node = node.parent;