Powerful Dynamic Tree Plugin With jQuery - jsTree

File Size: 442 KB
Views Total: 70760
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
Powerful Dynamic Tree Plugin With jQuery - jsTree

jsTree is a powerful jQuery plugin used to generate dynamic, interactive tree views (for example folder tree) with support for inline editing, drag'n'drop, checkboxes, keyboard navigation and more.

More features:

  • Supports HTML and JSON data.
  • AJAX enabled.
  • Custom node icons.
  • Lazy loading.
  • Callback function.
  • Searchable and filterable.

See Also:

Basic usage:

1. Install & download.

# NPM
$ npm install jstree --save

2. Import a theme CSS of your choice in the document.

<link rel="stylesheet" href="themes/default/style.min.css">
<link rel="stylesheet" href="themes/default-dark/style.min.css">

3. Import jQuery library and the jsTree plugin's script into the document.

<script src="https://code.jquery.com/jquery-1.12.4.min.js" 
        integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" 
        crossorigin="anonymous"></script>
<script src="jstree.min.js"></script>

4. Generate a tree structure from HTML data.

<div id="html" class="demo">
  <ul>
    <li data-jstree='{ "opened" : true }'>Root node
      <ul>
        <li data-jstree='{ "selected" : true }'>Child node 1</li>
        <li>Child node 2</li>
      </ul>
    </li>
  </ul>
</div>
$('#html').jstree();

5. Generate a tree structure from inline data.

<div id="data" class="demo"></div>
$('#data').jstree({
  'core' : {
    'data' : [
      { "text" : "Root node", "children" : [
          { "text" : "Child node 1" },
          { "text" : "Child node 2" }
      ]}
    ]
  }
});

6. Generate a tree structure from an external JSON file via AJAX.

<div id="ajax" class="demo"></div>
$('#ajax').jstree({
  'core' : {
    'data' : {
      "url" : "./root.json",
      "dataType" : "json" // needed only if you do not supply JSON headers
    }
  }
});

7. All default configuration options and callback functions.

/**
 * data configuration
 *
 * If left as `false` the HTML inside the jstree container element is used to populate the tree (that should be an unordered list with list items).
 *
 * You can also pass in a HTML string or a JSON array here.
 *
 * It is possible to pass in a standard jQuery-like AJAX config and jstree will automatically determine if the response is JSON or HTML and use that to populate the tree.
 * In addition to the standard jQuery ajax options here you can suppy functions for `data` and `url`, the functions will be run in the current instance's scope and a param will be passed indicating which node is being loaded, the return value of those functions will be used.
 *
 * The last option is to specify a function, that function will receive the node being loaded as argument and a second param which is a function which should be called with the result.
 *
 * __Examples__
 *
 *  // AJAX
 *  $('#tree').jstree({
 *    'core' : {
 *      'data' : {
 *        'url' : '/get/children/',
 *        'data' : function (node) {
 *          return { 'id' : node.id };
 *        }
 *      }
 *    });
 *
 *  // direct data
 *  $('#tree').jstree({
 *    'core' : {
 *      'data' : [
 *        'Simple root node',
 *        {
 *          'id' : 'node_2',
 *          'text' : 'Root node with options',
 *          'state' : { 'opened' : true, 'selected' : true },
 *          'children' : [ { 'text' : 'Child 1' }, 'Child 2']
 *        }
 *      ]
 *    }
 *  });
 *
 *  // function
 *  $('#tree').jstree({
 *    'core' : {
 *      'data' : function (obj, callback) {
 *        callback.call(this, ['Root 1', 'Root 2']);
 *      }
 *    });
 *
 * @name $.jstree.defaults.core.data
 */
data      : false,
/**
 * configure the various strings used throughout the tree
 *
 * You can use an object where the key is the string you need to replace and the value is your replacement.
 * Another option is to specify a function which will be called with an argument of the needed string and should return the replacement.
 * If left as `false` no replacement is made.
 *
 * __Examples__
 *
 *  $('#tree').jstree({
 *    'core' : {
 *      'strings' : {
 *        'Loading ...' : 'Please wait ...'
 *      }
 *    }
 *  });
 *
 * @name $.jstree.defaults.core.strings
 */
strings     : false,
/**
 * determines what happens when a user tries to modify the structure of the tree
 * If left as `false` all operations like create, rename, delete, move or copy are prevented.
 * You can set this to `true` to allow all interactions or use a function to have better control.
 *
 * __Examples__
 *
 *  $('#tree').jstree({
 *    'core' : {
 *      'check_callback' : function (operation, node, node_parent, node_position, more) {
 *        // operation can be 'create_node', 'rename_node', 'delete_node', 'move_node', 'copy_node' or 'edit'
 *        // in case of 'rename_node' node_position is filled with the new node name
 *        return operation === 'rename_node' ? true : false;
 *      }
 *    }
 *  });
 *
 * @name $.jstree.defaults.core.check_callback
 */
check_callback  : false,
/**
 * a callback called with a single object parameter in the instance's scope when something goes wrong (operation prevented, ajax failed, etc)
 * @name $.jstree.defaults.core.error
 */
error     : $.noop,
/**
 * the open / close animation duration in milliseconds - set this to `false` to disable the animation (default is `200`)
 * @name $.jstree.defaults.core.animation
 */
animation   : 200,
/**
 * a boolean indicating if multiple nodes can be selected
 * @name $.jstree.defaults.core.multiple
 */
multiple    : true,
/**
 * theme configuration object
 * @name $.jstree.defaults.core.themes
 */
themes      : {
  /**
   * the name of the theme to use (if left as `false` the default theme is used)
   * @name $.jstree.defaults.core.themes.name
   */
  name      : false,
  /**
   * the URL of the theme's CSS file, leave this as `false` if you have manually included the theme CSS (recommended). You can set this to `true` too which will try to autoload the theme.
   * @name $.jstree.defaults.core.themes.url
   */
  url       : false,
  /**
   * the location of all jstree themes - only used if `url` is set to `true`
   * @name $.jstree.defaults.core.themes.dir
   */
  dir       : false,
  /**
   * a boolean indicating if connecting dots are shown
   * @name $.jstree.defaults.core.themes.dots
   */
  dots      : true,
  /**
   * a boolean indicating if node icons are shown
   * @name $.jstree.defaults.core.themes.icons
   */
  icons     : true,
  /**
   * a boolean indicating if node ellipsis should be shown - this only works with a fixed with on the container
   * @name $.jstree.defaults.core.themes.ellipsis
   */
  ellipsis    : false,
  /**
   * a boolean indicating if the tree background is striped
   * @name $.jstree.defaults.core.themes.stripes
   */
  stripes     : false,
  /**
   * a string (or boolean `false`) specifying the theme variant to use (if the theme supports variants)
   * @name $.jstree.defaults.core.themes.variant
   */
  variant     : false,
  /**
   * a boolean specifying if a reponsive version of the theme should kick in on smaller screens (if the theme supports it). Defaults to `false`.
   * @name $.jstree.defaults.core.themes.responsive
   */
  responsive    : false
},
/**
 * if left as `true` all parents of all selected nodes will be opened once the tree loads (so that all selected nodes are visible to the user)
 * @name $.jstree.defaults.core.expand_selected_onload
 */
expand_selected_onload : true,
/**
 * if left as `true` web workers will be used to parse incoming JSON data where possible, so that the UI will not be blocked by large requests. Workers are however about 30% slower. Defaults to `true`
 * @name $.jstree.defaults.core.worker
 */
worker : true,
/**
 * Force node text to plain text (and escape HTML). Defaults to `false`
 * @name $.jstree.defaults.core.force_text
 */
force_text : false,
/**
 * Should the node be toggled if the text is double clicked. Defaults to `true`
 * @name $.jstree.defaults.core.dblclick_toggle
 */
dblclick_toggle : true,
/**
 * Should the loaded nodes be part of the state. Defaults to `false`
 * @name $.jstree.defaults.core.loaded_state
 */
loaded_state : false,
/**
 * Should the last active node be focused when the tree container is blurred and the focused again. This helps working with screen readers. Defaults to `true`
 * @name $.jstree.defaults.core.restore_focus
 */
restore_focus : true,
/**
 * Should reselecting an already selected node trigger the select and changed callbacks
 * @name $.jstree.defaults.core.allow_reselect
 */
allow_reselect : false
/**
 * Default keyboard shortcuts (an object where each key is the button name or combo - like 'enter', 'ctrl-space', 'p', etc and the value is the function to execute in the instance's scope)
 * @name $.jstree.defaults.core.keyboard
 */
keyboard : {
  'ctrl-space': function (e) {
    // aria defines space only with Ctrl
    e.type = "click";
    $(e.currentTarget).trigger(e);
  },
  'enter': function (e) {
    // enter
    e.type = "click";
    $(e.currentTarget).trigger(e);
  },
  'left': function (e) {
    // left
    e.preventDefault();
    if(this.is_open(e.currentTarget)) {
      this.close_node(e.currentTarget);
    }
    else {
      var o = this.get_parent(e.currentTarget);
      if(o && o.id !== $.jstree.root) { this.get_node(o, true).children('.jstree-anchor').focus(); }
    }
  },
  'up': function (e) {
    // up
    e.preventDefault();
    var o = this.get_prev_dom(e.currentTarget);
    if(o && o.length) { o.children('.jstree-anchor').focus(); }
  },
  'right': function (e) {
    // right
    e.preventDefault();
    if(this.is_closed(e.currentTarget)) {
      this.open_node(e.currentTarget, function (o) { this.get_node(o, true).children('.jstree-anchor').focus(); });
    }
    else if (this.is_open(e.currentTarget)) {
      var o = this.get_node(e.currentTarget, true).children('.jstree-children')[0];
      if(o) { $(this._firstChild(o)).children('.jstree-anchor').focus(); }
    }
  },
  'down': function (e) {
    // down
    e.preventDefault();
    var o = this.get_next_dom(e.currentTarget);
    if(o && o.length) { o.children('.jstree-anchor').focus(); }
  },
  '*': function (e) {
    // aria defines * on numpad as open_all - not very common
    this.open_all();
  },
  'home': function (e) {
    // home
    e.preventDefault();
    var o = this._firstChild(this.get_container_ul()[0]);
    if(o) { $(o).children('.jstree-anchor').filter(':visible').focus(); }
  },
  'end': function (e) {
    // end
    e.preventDefault();
    this.element.find('.jstree-anchor').filter(':visible').last().focus();
  },
  'f2': function (e) {
    // f2 - safe to include - if check_callback is false it will fail
    e.preventDefault();
    this.edit(e.currentTarget);
  }
}

8. Enable plugins to enhance the tree. All possible plugins:

  • checkbox: Shows checkboxes in the front of each node
  • contextmenu: Shows a context menu on right click.
  • dnd: Allows you to re-order nodes via drag and drop.
  • massload: Allows you to load multiple datasets.
  • search: Allows you to filter through nodes with a search box.
  • sort: Auto sorts nodes.
  • state: Saves all opened and selected nodes in the browser.
  • types: Adds a "type" for a node.
  • unique: Makes node name unique.
  • wholerow: Makes each node appear block level which makes selection easier. 
$('#container').jstree({

  // options here
  "core" : {  }, 

  // plugins here
  "plugins" : ["contextmenu", "dnd", "search", "state", "types", "wholerow"]
  
});

Changelog:

v3.3.16 (2023-09-19)

  • Added allow_reselect option, to be able to revert latest select_node changes.

v3.3.15 (2023-02-20)

  • Fixed: Delete event doesn't works

v3.3.14 (2023-01-16)

  • Fixed theme issue.

v3.3.12 (2021-09-04)

  • Updated context and drag'n'drop modules
  • fixed memory leak in context menu plugin

v3.3.11 (2020-12-19)

  • added raw value to edit callback

v3.3.10 (2020-06-16)

  • improved aria

2020-04-22

  • Compatible with jQuery 3.5+

2020-02-11

  • v3.3.9: Add a class to the jstree-marker indicating its position. By adding this class we can set custom icons for the different positions in our CSS.

2019-04-29

  • v3.3.8: Fixed an new error when moving a node to its current position

2019-01-03

  • v3.3.7: added proper error when using invalid JSON; replaced use of jQuery global with $ function parameter

2018-11-07

  • v3.3.7: bound redraw focus restore

2018-10-17

  • v3.3.6: namespaced events; fixed HTML eval vulnerability; fixed custom elements

2018-07-08

  • v3.3.5: improved html5 drags

2018-01-09

  • fixed edge case with contextmenu appearing in the wrong place

This awesome jQuery plugin is developed by vakata. For more Advanced Usages, please check the demo page or visit the official website.