Radix Tree jQuery Plugin
Perfect for dashboards, data explorers, and any UI that needs a dynamic, hierarchical structure.
Installation
CDN (jsDelivr, GitHub)
<!-- jQuery (required) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
<!-- Radix Tree Plugin (latest) -->
<script src="https://cdn.jsdelivr.net/gh/dxmari/jquery-radix-tree@latest/tree.js"></script>
<!-- No CSS needed! -->
<div class="radix-tree"></div>
<script>
$('.radix-tree').radixTree({ data: [ /* ... */ ] });
</script>
CDN (jsDelivr, specific version)
<script src="https://cdn.jsdelivr.net/gh/dxmari/jquery-radix-tree@v1.0.0/tree.js"></script>
CDN (unpkg, npm)
<script src="https://unpkg.com/jquery-radix-tree@latest/dist/tree.js"></script>
NPM
npm install jquery-radix-tree
import 'jquery-radix-tree/dist/tree.js';
import $ from 'jquery';
$('.radix-tree').radixTree({ data: [ /* ... */ ] });
const data = [
{
label: 'Universe',
open: true,
children: [
{ label: 'Galaxies', children: [ { label: 'Milky Way' }, { label: 'Andromeda' } ] },
{ label: 'Black Holes' }
]
}
];
$('.radix-tree').radixTree({ data });
lazyLoad
callback to fetch children only when a node is expanded. Ideal for large datasets or
when loading data from a server.
function myLazyLoad(node, done, delay) {
setTimeout(() => {
if (node.label === 'Galaxies') {
done([{ label: 'Milky Way' }, { label: 'Andromeda' }]);
} else {
done([{ label: 'No data' }]);
}
}, delay); // Use the dynamic delay
}
$('.radix-tree').radixTree({
data: [{ label: 'Galaxies', lazy: true }],
lazyLoad: myLazyLoad,
lazyLoadDelay: 1200 // Set delay dynamically (ms)
});
const demoData = [
{
label: 'Big Folder',
open: true,
infinite: true,
lazy: true,
badge: 100,
tags: ['infinite', 'files']
}
];
function infiniteLazyLoad(node, done, opts, delay) {
const total = 100;
const page = opts && opts.page ? opts.page : 1;
const pageSize = opts && opts.pageSize ? opts.pageSize : 20;
const start = (page - 1) * pageSize;
const end = Math.min(start + pageSize, total);
const children = [];
for (let i = start; i < end; i++) {
children.push({
label: 'File ' + (i + 1),
badge: (i % 2 === 0) ? 'even' : 'odd',
tags: (i % 10 === 0) ? ['milestone'] : []
});
}
setTimeout(() => {
done(children, end < total);
}, delay); // Use the dynamic delay
}
// Example 1: Small pageSize, default threshold (pagination enabled for 5)
$('.radix-tree-small').radixTree({
data: demoData,
lazyLoad: infiniteLazyLoad,
pageSize: 5, // Pagination enabled for 5 (default threshold is 5)
lazyLoadDelay: 800
});
// Example 2: Custom threshold (pagination only for pageSize >= 10)
$('.radix-tree-large').radixTree({
data: demoData,
lazyLoad: infiniteLazyLoad,
pageSize: 5, // Pagination NOT enabled for 5 (threshold is 10)
paginateThreshold: 10,
lazyLoadDelay: 800
});
disabled
property to prevent interaction with specific nodes or entire subtrees, useful for
permissions or workflow restrictions.
const data = [
{
label: 'Root',
open: true,
children: [
{ label: 'Enabled Node' },
{
label: 'Disabled Subtree',
disabled: true,
children: [
{ label: 'Child 1' },
{ label: 'Child 2', children: [{ label: 'Grandchild 1' }] }
]
}
]
}
];
$('.radix-tree').radixTree({ data });
// In event callbacks
onCheck: function(node, checkbox, siblings) {
console.log('Node changed:', node.label);
console.log('Siblings:', siblings.map(s => s.label));
console.log('Complete sibling objects:', siblings);
}
// Programmatically
const siblings = $('.radix-tree').radixTree('getSiblings', nodeId);
console.log('Siblings:', siblings);
$('.radix-tree').radixTree({
data: [
{
label: 'Projects',
badge: 3,
tags: ['active'],
children: [
{ label: 'Frontend', badge: 'New', tags: ['UI', 'urgent'], id: 'frontend' },
{ label: 'Backend', badge: 5, tags: ['API'], id: 'backend' },
{ label: 'Mobile', badge: 2, tags: ['React Native'], id: 'mobile' }
]
}
],
onCheck: function(node, checkbox, siblings) {
console.log('Checked:', node.label, checkbox.checked);
console.log('Siblings:', siblings.map(s => s.label));
}
});
$('.radix-tree').radixTree({
data: [
{
label: 'Organization',
open: true,
children: [
{ label: 'Engineering', badge: 15, tags: ['tech'], id: 'eng' },
{ label: 'Marketing', badge: 8, tags: ['creative'], id: 'marketing' },
{ label: 'Sales', badge: 12, tags: ['revenue'], id: 'sales' }
]
}
],
onExpand: function(node, details, siblings) {
console.log('Node expanded:', {
node: node.label,
id: node.id,
_radixId: node._radixId,
checked: node.checked,
open: node.open,
siblings: siblings.map(s => s.label)
});
},
onCollapse: function(node, details, siblings) {
console.log('Node collapsed:', {
node: node.label,
siblings: siblings.map(s => s.label)
});
},
onCheck: function(node, checkbox, siblings) {
console.log('Node checked:', {
node: node.label,
checked: checkbox.checked,
siblings: siblings.map(s => s.label)
});
}
});
const $tree = $('.radix-tree');
// Get all checked nodes
const checked = $tree.radixTree('getChecked');
// Get only checked parent nodes that are currently open
const openChecked = $tree.radixTree('getOpenChecked');
// Get only checked parent nodes that are currently closed
const closedChecked = $tree.radixTree('getClosedChecked');
// Set checked state
$tree.radixTree('setChecked', 'node-id', true); // Check
$tree.radixTree('setChecked', 'node-id', false); // Uncheck
// Get sibling nodes
const siblings = $tree.radixTree('getSiblings', 'node-id');
// Expand/collapse nodes
$tree.radixTree('expand', 'node-id');
$tree.radixTree('collapse', 'node-id');
// Get/set data
const data = $tree.radixTree('getData');
$tree.radixTree('setData', newData);
$('.radix-tree').radixTree({
data: [
{
label: 'π Documents',
open: true,
children: [
{
label: 'π Work',
children: [
{ label: 'π Reports' },
{ label: 'π Projects' },
{ label: 'π§ Emails' }
]
},
{
label: 'π Personal',
children: [
{ label: 'πΈ Photos' },
{ label: 'π Books' },
{ label: 'π΅ Music' }
]
}
]
}
],
focusMode: {
enabled: true,
type: ['highlight', 'accordion'], // Single mode: 'highlight' or multiple modes: ['highlight', 'accordion']
autoScroll: true,
highlightColor: '#4caf50',
animationDuration: 300,
preserveRoot: true,
maxOpenLevels: 2
},
onExpand: function(node, details, siblings) {
console.log('Focused on:', node.label);
},
onCollapse: function(node, details, siblings) {
console.log('Collapsed:', node.label);
}
});
$('.radix-tree').radixTree('setData', newData);
const checked = $('.radix-tree').radixTree('getChecked');
lazy: true
on nodes and provide a lazyLoad
callback.
For infinite scroll, set infinite: true
and adjust pageSize
and
lazyLoadDelay
as needed.
disabled: true
on any node or subtree in your data.const openChecked = $('.radix-tree').radixTree('getOpenChecked');
const closedChecked = $('.radix-tree').radixTree('getClosedChecked');
Troubleshooting
Tree not rendering?
Make sure you included jQuery and the plugin script before your initialization code. Check the browser console for JavaScript errors.
Checkboxes not working?
Check for JavaScript errors in the console and ensure your data structure is correct. Verify that nodes
have the proper checked
and indeterminate
properties.
Custom classes not appearing?
Verify you are using the className
and rootClassName
options as shown in the
examples. Check that your CSS is properly targeting the generated class names.
Lazy loading not working?
Ensure you've set lazy: true
on nodes and provided a lazyLoad
callback
function. Check that the callback calls the done
function with the children array.
Infinite scroll issues?
Verify that infinite: true
is set and check your pageSize
and
lazyLoadDelay
settings. Ensure your lazy load callback handles pagination correctly.
Contributing
How to Contribute
- Fork the repo - Create your own copy of the repository
- Create a feature branch - Work on your changes in a separate branch
- Add tests if possible - Ensure your changes work correctly
- Open a PR - Submit a pull request with a clear description of your changes
Development Setup
- Clone the repository:
git clone https://github.com/dxmari/jquery-radix-tree.git
- Install dependencies:
npm install
(if you want to run tests) - Test your changes by opening
index.html
in a browser
Testing
Optional Mocha/Chai tests are available for plugin logic. Run tests with:
npm test
Questions & Support
For questions, open an issue or start a discussion on GitHub. We're here to help!
Note: The plugin is designed to be lightweight and dependency-free (except jQuery). When contributing, please maintain this philosophy and ensure any new features don't add unnecessary complexity.
What Users Are Saying
