
folder-tree is a zero-dependency TypeScript tree view library for rendering and managing hierarchical data on a web page.
It accepts nested JSON, flat parent-based data, AJAX responses, lazy-loading callbacks, or existing HTML.
Optional plugins handle search, checkboxes, drag and drop, context menus, sorting, state persistence, node types, and other tree interactions.
Features
- Nested and flat JSON tree data.
- AJAX and callback-based lazy loading.
- Search with filtering and fuzzy matching.
- Checkbox selection with three-state cascading.
- Drag and drop with move and copy operations.
- Context menus with custom items and submenus.
- Node types with icons and structural rules.
- Child-node sorting with custom comparators.
- Tree state persistence through
localStorage. - Keyboard navigation and configurable shortcuts.
- ESM, CommonJS, and UMD builds.
- TypeScript declarations included.
- Custom plugin registration.
- Native DOM events.
How To Use It
Installation
Install the package with npm:
npm install @mdaemon/folder-tree
Import the tree class and stylesheet:
import { MDFolderTree } from '@mdaemon/folder-tree';
import '@mdaemon/folder-tree/styles.css';
Basic Usage
Create a container for the tree view:
<div id="folder-tree"></div>
Initialize the tree with hierarchical data:
const element = document.getElementById('folder-tree');
const tree = new MDFolderTree(element, {
core: {
data: [
{
id: 'documents',
text: 'Documents',
children: [
{
id: 'reports',
text: 'Reports'
},
{
id: 'invoices',
text: 'Invoices'
}
]
},
{
id: 'downloads',
text: 'Downloads'
}
]
}
});
Browser Build
The UMD build exposes MDFolderTree and mdTree() globally.
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@mdaemon/folder-tree/dist/styles.css"
>
<div id="folder-tree"></div>
<script src="https://cdn.jsdelivr.net/npm/@mdaemon/folder-tree/dist/MDFolderTree.umd.js"></script>
<script>
const tree = new MDFolderTree(
document.getElementById('folder-tree'),
{
core: {
data: [
{
id: 'projects',
text: 'Projects',
children: [
{ id: 'frontend', text: 'Frontend' },
{ id: 'backend', text: 'Backend' }
]
}
]
}
}
);
</script>
Loading Tree Data
Nested JSON
const tree = new MDFolderTree(element, {
core: {
data: [
{
id: 'projects',
text: 'Projects',
children: [
{
id: 'frontend',
text: 'Frontend',
children: [
{
id: 'components',
text: 'Components'
}
]
}
]
}
]
}
});
Flat JSON
Flat arrays can use parent references:
const tree = new MDFolderTree(element, {
core: {
data: [
{ id: '1', text: 'Projects', parent: '#' },
{ id: '2', text: 'Frontend', parent: '1' },
{ id: '3', text: 'Components', parent: '2' }
]
}
});
Lazy Loading
Use a core.data callback to load child nodes when a branch opens:
const tree = new MDFolderTree(element, {
core: {
data(node, callback) {
fetch(`/api/tree/${encodeURIComponent(node.id)}`)
.then(response => response.json())
.then(callback);
}
}
});
AJAX Data
core.data also accepts an AJAX configuration object:
const tree = new MDFolderTree(element, {
core: {
data: {
url(node) {
return `/api/tree/${encodeURIComponent(node.id)}`;
},
type: 'GET',
dataType: 'json',
headers: {
Accept: 'application/json'
}
}
}
});
Existing HTML
The tree can read nested <ul> and <li> markup:
<div id="folder-tree">
<ul>
<li id="projects">
<a>Projects</a>
<ul>
<li id="frontend">
<a>Frontend</a>
</li>
</ul>
</li>
</ul>
</div>
Initialize the existing markup:
const tree = new MDFolderTree(
document.getElementById('folder-tree')
);
Built-in Plugins
| Plugin | Purpose |
|---|---|
types | Node types, icons, attributes, and structural restrictions. |
checkbox | Checkbox state and three-state cascading. |
search | Text search, filtering, fuzzy matching, and remote search loading. |
changed | Selection difference data for the changed event. |
conditional_select | Conditional node activation. |
contextmenu | Node context menus. |
dnd | Drag and drop. |
massload | Batched lazy loading. |
sort | Child-node sorting. |
state | Tree state persistence. |
unique | Duplicate sibling-name validation. |
wholerow | Full-row node interaction. |
Plugins are enabled through the plugins array.
const tree = new MDFolderTree(element, {
core: {
data
},
plugins: [
'types',
'checkbox',
'search',
'contextmenu',
'dnd'
]
});
Checkboxes
Enable the checkbox plugin:
const tree = new MDFolderTree(element, {
core: {
data
},
checkbox: {
three_state: true,
tie_selection: false
},
plugins: ['checkbox']
});
Search
Enable the search plugin:
const tree = new MDFolderTree(element, {
core: {
data
},
search: {
show_only_matches: true,
fuzzy: true
},
plugins: ['search']
});
tree.search('invoice');
Clear the search:
tree.clear_search();
Drag And Drop
Enable drag and drop and permit structural changes through core.check_callback:
const tree = new MDFolderTree(element, {
core: {
data,
check_callback: true
},
dnd: {
copy: true,
drag_selection: true
},
plugins: ['dnd']
});
Context Menus
Enable the default context menu:
const tree = new MDFolderTree(element, {
core: {
data,
check_callback: true
},
plugins: ['contextmenu']
});
Custom menu items can replace the defaults:
const tree = new MDFolderTree(element, {
core: {
data
},
contextmenu: {
items(node) {
return {
open: {
label: 'Open',
action() {
console.log(node.id);
}
}
};
}
},
plugins: ['contextmenu']
});
Node Types
The types plugin can assign icons and structural restrictions:
const tree = new MDFolderTree(element, {
core: {
data
},
types: {
default: {
icon: 'md-tree-folder'
},
file: {
icon: 'md-tree-file',
max_children: 0
}
},
plugins: ['types']
});
Sorting
The sort callback receives two node IDs and uses the tree instance as this:
const tree = new MDFolderTree(element, {
core: {
data
},
sort(a, b) {
return this.get_text(a).localeCompare(
this.get_text(b)
);
},
plugins: ['sort']
});
State Persistence
Enable the state plugin to store open, selected, and related tree state in localStorage:
const tree = new MDFolderTree(element, {
core: {
data
},
state: {
key: 'project-tree',
ttl: 86400000
},
plugins: ['state']
});
Node Data Reference
Each JSON node can use these public fields:
id(string): Node ID.text(string): Node label.icon(string | boolean | null): Icon class list, image URL, default theme icon, or hidden icon.type(string): Node type used by thetypesplugin.children(TreeNodeData[] | boolean): Nested children or lazy-load state.state(object): Initial node state.li_attr(Record<string, string>): Attributes applied to the node<li>.a_attr(Record<string, string>): Attributes applied to the node anchor.data(Record<string, unknown> | false | null): Application data attached to the node.parent(stringin flat arrays): Parent node ID. Use#for a root node.
Node State
The public node state accepts:
opened(boolean): Starts the node open.selected(boolean): Starts the node selected.disabled(boolean): Starts the node disabled.checked(boolean): Starts the node checked when checkbox state is independent from selection.loaded(boolean): Marks a node as loaded.
All Configuration Options
Top-Level Configuration
core(CoreConfig): Core data, loading, selection, themes, keyboard behavior, and structural validation.types(Record<string, TypeConfig>): Node types and type rules.checkbox(CheckboxConfig): Checkbox behavior.search(SearchConfig): Search behavior.contextmenu(ContextMenuConfig): Context menu settings.dnd(DndConfig): Drag-and-drop settings.massload(MassloadCallback | AjaxConfig | null): Batched node loading.sort(SortComparator): Child-node sorting callback.state(StateConfig): State persistence settings.unique(UniqueConfig): Duplicate sibling-name rules.conditionalselect(ConditionalSelectCallback): Node activation callback.plugins(string[], default[]): Enabled plugin names.
Core Options
data(TreeNodeData[] | DataCallback | AjaxConfig | string | false, defaultfalse): Tree data source.multiple(boolean, defaulttrue): Permits multi-selection through user interaction.animation(number, default200): Open and close animation duration in milliseconds.themes(ThemeConfig): Theme settings.check_callback(boolean | function | object, defaultfalse): Controls create, rename, delete, move, copy, and edit operations.expand_selected_onload(boolean, defaulttrue): Opens ancestors of selected nodes before the initialreadyevent.force_text(boolean, defaultfalse): Forces node labels to render as text.dblclick_toggle(boolean, defaulttrue): Toggles branches on double click.compute_elements_positions(boolean, defaultfalse): Writesaria-setsizeandaria-posinsetvalues on rendered nodes.worker(boolean, defaulttrue): Uses a Web Worker for transferable JSON data.strings(Record<string, string> | function): Replaces built-in UI strings.error(function): Receives tree error objects.loaded_state(boolean, defaultfalse): Includes loaded node IDs in tree state.restore_focus(boolean, defaulttrue): Restores focus to the previously focused node.allow_reselect(boolean, defaultfalse): Re-runs selection behavior for an already selected node.keyboard(Record<string, KeyboardHandler | null> | boolean): Customizes keyboard shortcuts.falsedisables all shortcuts.sanitize_attrs(boolean, defaulttrue): Removes inlineon*attributes fromli_attranda_attr.
Keyboard Defaults
The default keyboard controls include:
ctrl+spaceenter- Arrow keys
*homeendf2
Theme Options
name(string | false, defaultdefault): Theme name.url(string | boolean, defaultfalse): Theme stylesheet URL.dir(string | false): Base directory used whenurlistrue.dots(boolean, defaulttrue): Shows connector dots.icons(boolean, defaulttrue): Shows node icons.ellipsis(boolean, defaultfalse): Enables ellipsis styling for long labels.stripes(boolean, defaultfalse): Enables striped rows.variant(string | false, defaultfalse): Theme variant.responsive(boolean, defaultfalse): Applies the responsive theme class.
Type Options
icon(string | boolean): Node icon.max_children(number, default-1): Maximum direct children.max_depth(number, default-1): Maximum descendant depth.valid_children(number | string[], default-1): Accepted child types.li_attr(Record<string, string>): Attributes merged into the<li>.a_attr(Record<string, string>): Attributes merged into the anchor.
Checkbox Options
keep_selected_style(boolean, defaulttrue): Keeps selected-node styling.visible(boolean, defaulttrue): Controls checkbox visibility.three_state(boolean, defaulttrue): Enables upward, downward, and undetermined cascading.cascade(string, default""whenthree_stateisfalse): Sets explicit cascade directions.tie_selection(boolean, defaulttrue): Uses selection state as checkbox state.whole_node(boolean, defaulttrue): Lets the node label toggle the checkbox.cascade_to_disabled(boolean, defaulttrue): Includes disabled nodes in cascading.cascade_to_hidden(boolean, defaulttrue): Includes hidden nodes in cascading.
Search Options
show_only_matches(boolean, defaultfalse): Hides nonmatching branches outside the required ancestry.show_only_matches_children(boolean, defaultfalse): Keeps descendants of matching nodes visible.close_opened_onclear(boolean, defaulttrue): Closes branches opened by a search after clearing it.case_sensitive(boolean, defaultfalse): Enables case-sensitive matching.fuzzy(boolean, defaultfalse): Enables approximate matching for patterns up to 32 characters.search_leaves_only(boolean, defaultfalse): Restricts matches to loaded leaf nodes.search_callback(function): Replaces the built-in matcher.ajax(false | AjaxConfig | function): Loads nodes required before a search.
AJAX Options
The AJAX object used by core.data, search.ajax, and massload accepts:
url(string | function, required): Request URL.data: Request data.type(string): HTTP method.method(string): HTTP method.dataType(string): Expected response type.contentType(string | false): Request content type.headers(Record<string, string>): Request headers.cache(boolean): Request cache setting.xhrFields.withCredentials(boolean): Sends credentials with the request.
Context Menu Options
select_node(boolean, defaulttrue): Activates an unselected node before opening the menu.show_at_node(boolean, defaulttrue): Positions the menu at the node.items(object | function): Menu item definitions or generator callback.
Context Menu Item Options
label(string | function): Item label.title(string): Title text.icon(string | false): Icon class list or image URL.action(false | function): Item handler.separator_before(boolean): Separator before the item.separator_after(boolean): Separator after the item._disabled(boolean | function): Disabled state._class(string): Item classes.shortcut(number): Keyboard shortcut code.shortcut_label(string): Shortcut label.submenu(Record<string, ContextMenuItem>): Nested items.
Drag And Drop Options
copy(boolean, defaulttrue): Lets Ctrl or Meta switch a drag from move to copy.open_timeout(number, default500): Delay before opening a hovered closed node.is_draggable(boolean | function, defaulttrue): Controls which nodes can start a drag.check_while_dragging(boolean): Runs structural checks during dragging.always_copy(boolean, defaultfalse): Copies every accepted drop.inside_pos(number | "first" | "last", default0): Child position for inside drops.drag_selection(boolean, defaulttrue): Drags the top selected nodes when the grabbed node belongs to the selection.touch(boolean | "selected"): Controls touch dragging.large_drop_target(boolean): Uses the full node as the drop area.large_drag_target(boolean | string): Expands the draggable area.use_html5(boolean, defaultfalse): Uses native HTML5 drag and drop.blank_space_drop(boolean, defaultfalse): Accepts root-level drops on empty tree space.
Massload
massload accepts a callback or AJAX configuration.
const tree = new MDFolderTree(element, {
core: {
data(node, callback) {
fetch(`/api/tree/${node.id}`)
.then(response => response.json())
.then(callback);
}
},
massload(ids, callback) {
fetch(
`/api/tree/batch?ids=${encodeURIComponent(ids.join(','))}`
)
.then(response => response.json())
.then(callback);
},
plugins: ['massload']
});
State Options
key(string, defaultjstree):localStoragekey.events(string): Events that schedule a state save.ttl(number | false, defaultfalse): Saved-state lifetime in milliseconds.filter(function): Adjusts state before restoration.preserve_loaded(boolean, defaultfalse): Keepscore.loadedin stored state.
Default event string:
changed.MDFolderTree open_node.MDFolderTree close_node.MDFolderTree check_node.MDFolderTree uncheck_node.MDFolderTree
Unique Options
case_sensitive(boolean, defaultfalse): Uses case-sensitive sibling-name comparison.trim_whitespace(boolean, defaultfalse): Trims surrounding whitespace before comparison.duplicate(function): Generates a replacement name for automatically created duplicates.
The default duplicate pattern uses:
Name (2)
Name (3)
Name (4)
Conditional Selection
conditionalselect receives the node and activation event:
const tree = new MDFolderTree(element, {
core: {
data
},
conditionalselect(node) {
return node.type !== 'readonly';
},
plugins: ['conditional_select']
});
Public API
Constructor
const tree = new MDFolderTree(element, config);
element(HTMLElement): Tree container.config(TreeConfig, optional): Tree configuration.
Instance Helpers
MDFolderTree.getInstance(element): Returns the tree instance attached to an element ornull.MDFolderTree.registerPlugin(name, factory): Registers a plugin factory.tree.getPlugin(name): Returns an active plugin instance ornull.
Node Lookup And Selection
| Method | Description |
|---|---|
get_node(obj, asDom?) | Resolves a node reference or its rendered element. |
get_parent(obj) | Returns the parent ID. |
get_path(obj, glue?, ids?) | Returns ancestor labels or IDs. |
get_text(obj) | Returns node text. |
set_text(obj, text) | Changes node text. |
get_json(obj?, options?) | Serializes a node, subtree, or root children. |
set_id(obj, newId) | Changes a node ID. |
is_selected(obj) | Checks selection state. |
get_selected() | Returns selected IDs. |
get_top_selected() | Returns selected nodes with no selected ancestor. |
get_bottom_selected() | Returns selected nodes with no selected descendants. |
select_node(obj, suppressEvent?, preventOpen?, event?) | Selects nodes. |
deselect_node(obj, suppressEvent?, event?) | Deselects nodes. |
select_all(suppress?) | Selects all nodes. |
deselect_all(suppress?) | Clears the selection. |
activate_node(obj, event?) | Runs user-style node activation. |
get_json() Options
flat: Returns a flat list withparentfields.no_state: Omits state.no_id: Omits node IDs and ID attributes.no_children: Omits children.no_data: Returnsdata: false.no_li_attr: Omits<li>attributes.no_a_attr: Omits anchor attributes.
Opening And Closing
| Method | Description |
|---|---|
open_node(obj, callback?, animation?) | Opens nodes and loads lazy children when required. |
close_node(obj, animation?) | Closes nodes. |
toggle_node(obj) | Toggles node state. |
open_all(obj?, animation?) | Opens descendants. |
close_all(obj?, animation?) | Closes descendants. |
is_open(obj) | Checks open state. |
is_closed(obj) | Checks closed state. |
is_parent(obj) | Checks whether a node has or can load children. |
is_leaf(obj) | Checks leaf state. |
Loading And Rendering
| Method | Description |
|---|---|
load_node(obj, callback?) | Loads or reloads node data. |
load_all(obj?, callback?) | Loads every unloaded descendant. |
refresh_node(obj) | Reloads a node and its open descendants. |
refresh() | Reloads the tree. |
redraw_node(obj) | Re-renders one node. |
redraw() | Re-renders the tree. |
get_children_dom(obj) | Returns rendered child elements. |
get_next_dom(obj, strict?) | Returns the next visible node element. |
get_prev_dom(obj, strict?) | Returns the previous visible node element. |
is_loaded(obj) | Checks loaded state. |
is_loading(obj) | Checks loading state. |
Enable, Disable, Show, And Hide
| Method | Description |
|---|---|
enable_node(obj) | Enables nodes. |
disable_node(obj) | Disables nodes. |
is_disabled(obj) | Checks disabled state. |
hide_node(obj) | Hides nodes. |
show_node(obj) | Shows nodes. |
hide_all() | Hides all nodes. |
show_all() | Shows all hidden nodes. |
is_hidden(obj) | Checks hidden state. |
Creating And Editing Nodes
Structural changes require an accepting core.check_callback.
| Method | Description |
|---|---|
create_node(parent, node?, pos?, callback?, isLoaded?) | Creates a node or subtree. |
rename_node(obj, text) | Renames nodes. |
delete_node(obj) | Deletes nodes. |
move_node(obj, parent, pos?, callback?, isLoaded?) | Moves nodes. |
copy_node(obj, parent, pos?, callback?, isLoaded?) | Copies nodes. |
edit(obj, defaultText?, callback?) | Starts inline editing. |
check(operation, obj, parent, pos?, more?) | Runs structural validation. |
last_error() | Returns the latest tree error. |
Accepted position values include numeric indexes plus:
firstinsidelastbeforeafter
Checkbox Methods
| Method | Description |
|---|---|
check_node(obj) | Checks nodes. |
uncheck_node(obj) | Unchecks nodes. |
check_all() | Checks all nodes. |
uncheck_all() | Clears all checks. |
is_checked(obj) | Checks checkbox state. |
get_checked() | Returns checked IDs. |
get_top_checked() | Returns checked nodes with no checked ancestor. |
get_bottom_checked() | Returns checked nodes with no checked descendants. |
get_undetermined() | Returns indeterminate IDs. |
is_undetermined(obj) | Checks indeterminate state. |
show_checkboxes() | Shows checkboxes. |
hide_checkboxes() | Hides checkboxes. |
toggle_checkboxes() | Toggles checkbox visibility. |
disable_checkbox(obj) | Disables node checkboxes. |
enable_checkbox(obj) | Enables node checkboxes. |
get_checked_descendants(obj) | Returns checked descendants. |
Search Methods
search() uses this signature:
tree.search( query, skipAsync, showOnlyMatches, inside, append, showOnlyMatchesChildren );
search(...): Runs a tree search and returns matching IDs.clear_search(): Clears the current search.
Theme Methods
| Method | Description |
|---|---|
set_theme(name, url?) | Changes the theme and can load its stylesheet. |
get_theme() | Returns the current theme. |
set_theme_variant(variant) | Changes the theme variant. |
get_theme_variant() | Returns the current variant. |
show_stripes() | Enables striped rows. |
hide_stripes() | Disables striped rows. |
toggle_stripes() | Toggles striped rows. |
show_dots() | Shows connector dots. |
hide_dots() | Hides connector dots. |
toggle_dots() | Toggles connector dots. |
show_icons() | Shows icons. |
hide_icons() | Hides icons. |
toggle_icons() | Toggles icons. |
show_ellipsis() | Enables ellipsis styling. |
hide_ellipsis() | Disables ellipsis styling. |
toggle_ellipsis() | Toggles ellipsis styling. |
Icon Methods
| Method | Description |
|---|---|
set_icon(obj, icon) | Changes node icons. |
get_icon(obj) | Returns the icon value. |
hide_icon(obj) | Hides icons on nodes. |
show_icon(obj) | Restores node icons. |
Type And Sort Methods
| Method | Description |
|---|---|
get_type(obj, rules?) | Returns the node type or effective type rules. |
set_type(obj, type) | Changes node types. |
get_rules(obj) | Returns effective type restrictions. |
sort(obj, deep?) | Sorts child nodes and optional descendants. |
State Methods
| Method | Description |
|---|---|
get_state() | Returns current tree and plugin state. |
set_state(state, callback?) | Applies tree state. |
The state plugin also exposes:
save_state()restore_state()clear_state()
Access them through:
const statePlugin = tree.getPlugin('state');
Clipboard Methods
| Method | Description |
|---|---|
cut(obj?) | Stores nodes in the shared move buffer. |
copy(obj?) | Stores nodes in the shared copy buffer. |
paste(obj, pos?) | Pastes buffered nodes. |
get_buffer() | Returns clipboard data. |
can_paste() | Checks whether clipboard data exists. |
clear_buffer() | Clears the clipboard. |
Container And Event Methods
| Method | Description |
|---|---|
get_container() | Returns the tree container. |
get_container_ul() | Returns the root <ul>. |
get_string(key) | Returns a configured UI string. |
hover_node(obj) | Applies hover state. |
dehover_node(obj) | Removes hover state. |
on(event, handler) | Registers an event handler. |
off(event, handler) | Removes an event handler. |
destroy() | Destroys the tree instance. |
Events
Tree events use the .MDFolderTree namespace.
Lifecycle And Data Events
| Event | Detail |
|---|---|
init.MDFolderTree | Initialization started. |
loading.MDFolderTree | Data loading started. |
loaded.MDFolderTree | Initial data loaded. |
ready.MDFolderTree | { instance } |
model.MDFolderTree | { nodes, parent } |
load_node.MDFolderTree | { node, status } |
load_all.MDFolderTree | { node } |
refresh_node.MDFolderTree | { node, nodes } |
refresh.MDFolderTree | Tree refresh finished. |
redraw.MDFolderTree | { nodes } |
destroy.MDFolderTree | Fires before teardown. |
Selection Events
| Event | Detail |
|---|---|
select_node.MDFolderTree | { node, selected, event } |
deselect_node.MDFolderTree | { node, selected, event } |
select_all.MDFolderTree | { selected } |
deselect_all.MDFolderTree | { selected, node } |
activate_node.MDFolderTree | Activated node and activation event. |
changed.MDFolderTree | Selection state and selection differences. |
dblclick.MDFolderTree | { node, event } |
Open And Close Events
| Event | Detail |
|---|---|
before_open.MDFolderTree | { node } |
open_node.MDFolderTree | { node } |
after_open.MDFolderTree | { node } |
close_node.MDFolderTree | { node } |
after_close.MDFolderTree | { node } |
open_all.MDFolderTree | { node } |
close_all.MDFolderTree | { node } |
Node Mutation Events
| Event | Detail |
|---|---|
create_node.MDFolderTree | Created node, parent, and position. |
rename_node.MDFolderTree | { node, text, old } |
delete_node.MDFolderTree | { node, parent } |
move_node.MDFolderTree | Moved node and old/new position data. |
copy_node.MDFolderTree | Copied node and destination data. |
set_text.MDFolderTree | Node, new text, and previous text. |
set_id.MDFolderTree | { node, old } |
edit.MDFolderTree | { node } |
Visibility Events
| Event | Detail |
|---|---|
enable_node.MDFolderTree | { node } |
disable_node.MDFolderTree | { node } |
hide_node.MDFolderTree | { node } |
show_node.MDFolderTree | { node } |
hide_all.MDFolderTree | { nodes } |
show_all.MDFolderTree | { nodes } |
hover_node.MDFolderTree | { node } |
dehover_node.MDFolderTree | { node } |
Checkbox Events
When checkbox.tie_selection is true, check operations use selection events.
| Event | Detail |
|---|---|
check_node.MDFolderTree | { node, selected, event } |
uncheck_node.MDFolderTree | { node, selected, event } |
check_all.MDFolderTree | { selected } |
uncheck_all.MDFolderTree | { selected, node } |
disable_checkbox.MDFolderTree | { node } |
enable_checkbox.MDFolderTree | { node } |
Search Events
| Event | Detail |
|---|---|
search.MDFolderTree | Result elements, query text, result IDs, and filtering state. |
clear_search.MDFolderTree | Result elements, query text, and result IDs. |
Drag And Drop Events
| Event | Detail |
|---|---|
dnd_start.MDFolderTree | Drag session data. |
dnd_move.MDFolderTree | Drag session data and current drop position. |
dnd_scroll.MDFolderTree | Drag session data during auto-scroll. |
dnd_stop.MDFolderTree | Drag session data and drop result. |
State Events
| Event | Detail |
|---|---|
restore_state.MDFolderTree | { state } |
state_ready.MDFolderTree | State restoration finished and automatic saving started. |
set_state.MDFolderTree | Programmatic state application finished. |
Clipboard Events
| Event | Detail |
|---|---|
cut.MDFolderTree | Buffered nodes and IDs. |
copy.MDFolderTree | Buffered nodes and IDs. |
paste.MDFolderTree | Parent, pasted nodes, mode, and IDs. |
clear_buffer.MDFolderTree | Clipboard cleared. |
Theme Events
| Event | Detail |
|---|---|
set_theme.MDFolderTree | { theme } |
show_stripes.MDFolderTree | Stripes enabled. |
hide_stripes.MDFolderTree | Stripes disabled. |
show_dots.MDFolderTree | Dots enabled. |
hide_dots.MDFolderTree | Dots disabled. |
show_icons.MDFolderTree | Icons enabled. |
hide_icons.MDFolderTree | Icons disabled. |
show_ellipsis.MDFolderTree | Ellipsis enabled. |
hide_ellipsis.MDFolderTree | Ellipsis disabled. |
Context Menu Events
show_contextmenu.MDFolderTree: Fires when a node context menu opens.context_show.vakata: Fires ondocumentwhen the menu opens.context_hide.vakata: Fires ondocumentwhen the menu closes.
Custom Plugins
Register a plugin factory before creating a tree that uses it:
MDFolderTree.registerPlugin('audit', () => ({
name: 'audit',
init(tree) {
tree.on(
'select_node.MDFolderTree',
function (event) {
console.log(
'Selected:',
event.detail.node.id
);
}
);
},
destroy() {}
}));
const tree = new MDFolderTree(element, {
core: {
data
},
plugins: ['audit']
});
Plugin Hooks
A custom TreePlugin can implement:
init(tree)destroy()onNodeRender(node, element)onBeforeRender(nodes)onBeforeActivate(node, event)onCheck(chk, node, parent, pos, more)
TreePluginHost API
The plugin host exposes:
configgetNode(id)getAllNodes()getNodeChildren(id)getSelectedIds()getOpenedIds()selectNode(id, suppress?, preventOpen?, event?)deselectNode(id, suppress?, event?)applySelection(ids, selected)selectAll(suppress?)deselectAll(suppress?)openNode(id, suppress?, animation?)closeNode(id, suppress?, animation?)getContainer()on(event, handler)off(event, handler)emit(event, detail)redrawNode(id)redraw()moveNode(id, parentId, position)copyNode(id, parentId, position)renameNode(id, text)deleteNode(id)createNode(parentId, data, position?)reorderChildren(parentId, childIds)setChildOrder(parentId, childIds)getRootNodeIds()
Migrating From jstree
folder-tree keeps familiar jstree configuration groups, node formats, plugin names, and many method signatures. Migration mainly affects initialization, events, CSS prefixes, and the tree data attribute.
Replace $.jstree() Calls
Import mdTree:
import { mdTree } from '@mdaemon/folder-tree';
Create a tree:
// jstree
$('#tree').jstree({
core: {
data
}
});
// folder-tree
mdTree('#tree', {
core: {
data
}
});
Retrieve the current instance:
const tree = mdTree('#tree', true);
Call an instance method:
mdTree('#tree', 'select_node', 'node-1');
mdTree() Signatures
mdTree(element): Creates a default tree or returns the existing instance.mdTree(element, config): Creates a configured tree or returns the existing instance.mdTree(element, true): Returns the existing instance.mdTree(element, 'method', ...args): Calls an instance method.
CSS Class Migration
| jstree | folder-tree |
|---|---|
.jstree | .md-tree |
.jstree-node | .md-tree-node |
.jstree-anchor | .md-tree-anchor |
.jstree-open | .md-tree-open |
.jstree-closed | .md-tree-closed |
.jstree-leaf | .md-tree-leaf |
.jstree-icon | .md-tree-icon |
.jstree-clicked | .md-tree-clicked |
.jstree-checkbox | .md-tree-checkbox |
.jstree-search | .md-tree-search |
Data Attribute Migration
Change data-jstree to data-md-tree:
<li
id="folder-1"
class="md-tree-open"
data-md-tree='{"type":"folder","opened":true}'
>
<a>Folder 1</a>
</li>
Event Migration
Replace jQuery event handlers with native DOM listeners:
document
.getElementById('tree')
.addEventListener(
'changed.MDFolderTree',
function (event) {
console.log(event.detail.selected);
}
);
Automated Migration Script
The package includes a script for scanning and applying common migration changes:
node node_modules/@mdaemon/folder-tree/scripts/migrate-from-jstree.mjs ./src
Styling
The main structural CSS uses the md-tree prefix. Project-specific node classes can be attached through:
li_attr.classa_attr.classtypes[type].li_attrtypes[type].a_attr
Alternatives And Related Resources
- 10 Best Tree View JavaScript Libraries in 2026 (Lightweight & Free)
- JavaScript Tree/TreeGrid with Drag, Edit & Filter – Wunderbaum
- Dynamic Interactive Tree View With Checkboxes – Treejs
- JavaScript Treeview Library for Hierarchical Data – Quercus.js
- Visualize Your Project Structure With The file-tree Component







