cheton / infinite-tree Goto Github PK
View Code? Open in Web Editor NEWA browser-ready tree library that can efficiently display a large amount of data using infinite scrolling.
Home Page: https://infinite-tree.js.org
License: MIT License
A browser-ready tree library that can efficiently display a large amount of data using infinite scrolling.
Home Page: https://infinite-tree.js.org
License: MIT License
This library is very wonderful.
it seems that flattening of 100,000 nodes takes time. Correct me if I'm wrong.
One approach can be taken where flattening should be done in chunks and that operation should return promise.
Calling tree.checkNode(node)
/ tree.uncheckNode(node)
will update the node's check and indeterminate state and also its parent / child nodes.
Reproduce with the following code:
var i = new InfiniteTree()
i.addChildNodes({id: 'test'})
console.log(i.nodes)
i.removeNode(i.nodes[0])
console.log(i.nodes)
i.addChildNodes({id: 'test'})
console.log(i.nodes)
Results in:
[Node]
[]
[]
Should result in:
[Node]
[]
[Node]
It is not possible to drag things in from the outside, for example, dragging folders from the explorer onto nodes. After setting the hoverclass, after placing the data outside the browser on the node, the hoverclass node is not removed
I noticed the license for clusterize.js has changed from MIT to GPLv3.
While this would not cause any issues for people with personal projects, this would cause problems with folks using your tree library for commercial usage.
https://github.com/NeXTs/Clusterize.js/blob/master/LICENSE
Not sure if you are aware of this.
I have tried to get the supplied example code to work, but it only produces a plain list of names, there is no indentation or option to open/close nodes. Whats going wrong?
The output is this:
Fruit
Apple
Banana
Cherry
But it should be this:
>Fruit
>Apple
>Banana
>Cherry
The code is this:
(Note, i found the js at unpkg, but I could not find the css, so I downloaded the css from the "dist" dir)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Infinite Tree Example</title>
<link rel="stylesheet" href="tree.css">
<script src="https://unpkg.com/[email protected]/dist/infinite-tree.min.js"></script>
</head>
<body>
<div id="tree"></div>
<script>
// Define the JSON data to display
const data = {
id: 'fruit',
name: 'Fruit',
children: [{
id: 'apple',
name: 'Apple'
}, {
id: 'banana',
name: 'Banana',
children: [{
id: 'cherry',
name: 'Cherry',
loadOnDemand: true
}]
}]
};
// Create the Infinite Tree instance
const tree = new InfiniteTree({
el: document.querySelector('#tree'),
data: data,
autoOpen: true, // Defaults to false
droppable: { // Defaults to false
hoverClass: 'infinite-tree-droppable-hover',
accept: function(event, options) {
return true;
},
drop: function(event, options) {
}
},
shouldLoadNodes: function(parentNode) {
if (!parentNode.hasChildren() && parentNode.loadOnDemand) {
return true;
}
return false;
},
loadNodes: function(parentNode, next) {
// Loading...
const nodes = [];
nodes.length = 1000;
for (let i = 0; i < nodes.length; ++i) {
nodes[i] = {
id: `${parentNode.id}.${i}`,
name: `${parentNode.name}.${i}`,
loadOnDemand: true
};
}
next(null, nodes, function() {
// Completed
});
},
nodeIdAttr: 'data-id', // the node id attribute
rowRenderer: function(node, treeOptions) { // Customizable renderer
return '<div data-id="<node-id>" class="infinite-tree-item">' + node.name + '</div>';
},
shouldSelectNode: function(node) { // Determine if the node is selectable
if (!node || (node === tree.getSelectedNode())) {
return false; // Prevent from deselecting the current node
}
return true;
}
});
</script>
</body>
</html>
tree.css
.infinite-tree-scroll {
overflow: auto;
max-height: 400px; /* Change the height to suit your needs. */
}
.infinite-tree-table {
width: 100%;
}
.infinite-tree-content {
outline: 0;
position: relative;
}
.infinite-tree-content .infinite-tree-selected.infinite-tree-item,
.infinite-tree-content .infinite-tree-selected.infinite-tree-item:hover {
background: #deecfd;
border: 1px solid #06c;
}
.infinite-tree-content .infinite-tree-item {
border: 1px solid transparent;
cursor: default;
}
.infinite-tree-content .infinite-tree-item:hover {
background: #f2fdff;
}
.infinite-tree-content .infinite-tree-item:disabled,
.infinite-tree-content .infinite-tree-item[disabled] {
cursor: not-allowed;
opacity: 0.5;
}
.infinite-tree-content .infinite-tree-node {
position: relative;
}
.infinite-tree-content .infinite-tree-toggler {
color: #666;
user-select: none;
}
.infinite-tree-content .infinite-tree-toggler:hover {
color: #333;
text-decoration: none;
}
.infinite-tree-content .infinite-tree-title {
cursor: pointer;
user-select: none;
}
.infinite-tree-no-data {
text-align: center;
}
As I understood, infinite-tree is based on clusterize.js. Clusterize is available either under commercial license or under GNU GPL v3. If I understand correctly it is not possible to release derived work (infinite-tree) under MIT if you use GPL's version of clusterize.
The root is almost always superfluous, and we always want to start only showing the roots children, with autoOpen as false (to hid the grandchildren until opened).
I've a scenario where L2(Child) level tree structure is opened. Clicking on L2 context menu icon, which do something and switching context menu icon to some other icon. To do this, managing a flag variable at each node to show the corresponding icon at particular node level and after updating this flag data with each node, need to re-render the tree so that as per corresponding flag variable, context icon appear at DOM.
Getting below issues after updating tree data:
My full code is as per below:
// load updated tree data
that.tree.loadData(that.props.treeconfig.listOfContanier);
// getting parent node L1 level
let parentNode = that.props.selectedNode;
const { tree } = that.treeRef.current;
// Below code should open referred node and child nodes should appear as it has child data. But seems not working so
tree.openNode(parentNode);
Does anyone run into the such kind of issues? Any help would be appreciated.
Are there any examples of how to implement lazy loading into this project?
Thanks
Hey there,
I have a tree view displaysing a couple of hundred items.
When scrolling down to a certain position it begins to flicker like crazy.
Going up and down from empty space to some elements above.
When I manipulate the rowsInBlock or blockInCluster to where no scrolling would be needed, it just works fine. But that is not what I would like to do to fix it.
Can you help me out?
Thanks in advance!
能出一个中文文档吗?
还有你现在这个API看起来好费劲啊,同时好奇你的demo代码,在哪?
https://infinite-tree.js.org/examples.html#/filebrowser
Hi,
i would like to sort my nodes after i moved some around.
Is there any sort function alrdy available?
Can someone give a hint on how i could implement sorting?
Hi, I thought of another useful feature. Can we select multiple nodes? so for example, when I press ctrl I will be able to select more than one, and shift from index to index, etc..
Thanks
demo.zip
The minimum demo cannot run in IE8
I am trying to make the tree drag/droppable but no matter what, it doesnt start working.. I have a custom rowRenderer which sets the treeNodeAttributes to true, the tree has droppable: true (I also tried setting it up as an object (I cant even get a console.log). I am using my own custom click handler (tree.on('click), but even if I dont, and comment it out, I still cant make it drag.. the example https://infinite-tree.js.org/examples.html#/classic works, but its still hard to start a drag process.. any idea how should I fix this issue ? dragging will be the main feature in the app..
thanks
Edit: this tree has a nice drag/drop functionalities, but the other features are not as good as this infinite tree (https://angular2-tree.readme.io/docs)
What would be the best, cleanest way to swap the position of two nodes?
Move the selected one above the other and vice versa
Thanks
When you have a large data set, you have to start with all nodes except children of root closed.
i.e. use autoOpen(false)
However, searching when autoOpen is false is bad - it doesnt show the filtered nodes, only their parents, and you still have to open each parent in turn to find what you are looking for.
Also, in the UI, it would be great to give the user a button to "Open All" and "Close All".
This would work really well with the ability to toggle "autoOpen" This can only be set when you create the tree, you cant seem to change it after.
Hi!
It will be great to have a minimum working example to start with. Right now, I've tried example from README, but it outputs just
Page with examples is also of little help since it contains several examples and all the code is organized to accommodate these examples.
HTML page that I used.
Thanks!
Hi,
i try to achive that at first display all nodes are close (autoOpen=false) (no problem here yet),
than if the user searches something and i apply the filter i want to open all rendered nodes.
When unfilter is called i want all nodes be close again.
Is this somehow possible? I couldnt find a solution for this yet.
I would be glad for help or a hint.
When I click on a node, the row renderer is called twice, with two different NodeIds. It is called with the previous selected node, and the one that should be selected.
And sometimes, when I updateNode, I change the id of the current node, and in my app its trying to call the function with the new id (which is good), and than with the old id (which doesnt exist anymore, and the app is throwing error).
As you can see from the gif, the click event is fired only once (thats how it should be), and the console.log inside of the rowRenderer is called twice.
So if I call "update" on a node, is it also trying to update all of its children ?
On click of node, I want to add/load dynamic data in child node, how can I achieve this. I tried many solution but noting work. Could you please help me.
After opening many hierarchy of tree closing of tree is taking larger time. some time after increasing the node browser is getting unresposive
it seems to be fixed at something like 200px. i would like to have it expand with the size of the page, or at least, double the fixed height.
the demo drag & drop works on chrome and edge but not on internet explorer, any suggestions?
When I reload the tree data I would like to keep the same nodes expanded/collapsed if they still exist.
Currently I can't find any option to do so. Am I missing something?
Regard,
Aleš
请问如何做异步加载节点??
现在有个需求,需要把树中的某个节点拖动其他区域,想问下该怎么配置呢
Browsing to the demo site - https://infinite-tree.js.org/examples.html#/default - with IE11 yields a frozen progress indicator spinner, but nothing else. Looking at the developer tools, I see nothing in the Console and no Network errors - just a lack of any signs of progress on initializing. I can select across the different demo links, with the corresponding URL update being reflected in the browser, but no change in the appearance.
We're seeing similar issues with attempting to use the component in our code, but the fact that it isn't working on the demo site seemed like the best reproduce scenario we could find :)
I have a node which is loaded from the server, it loads 170k+ other nodes under it. An exception is raised in all Array.splice.apply calls in the code :
parentNode.children.splice.apply(parentNode.children, [index, 0].concat(newNodes));
...
this.nodes.splice.apply(this.nodes, [parentOffset + 1, deleteCount].concat(nodes));
this.rows.splice.apply(this.rows, [parentOffset + 1, deleteCount].concat(rows));
...
this.nodes.splice.apply(this.nodes, [nodeIndex + 1, 0].concat(nodes));
this.rows.splice.apply(this.rows, [nodeIndex + 1, 0].concat(rows));
The exception is “Maximum call stack size exceeded” and it's discussed here : https://stackoverflow.com/questions/21679300/array-unshift-invoked-using-apply-causes-maximum-call-stack-size-exceeded
I have soved it by creating a new method to do the splice in chunks :
function spliceApply(t,a,b,c)
{
for (var i = Math.floor(c.length / 10000); i>=0; --i)
t.splice.apply(t,[a,b].concat(c.slice(i*10000,(i+1)*10000)));
}
and transformed for example : parentNode.children.splice.apply(parentNode.children, [index, 0].concat(newNodes)) to spliceApply(parentNode.children,index,0,newNodes);
I haven't tested the code intensively but it works, hope you can fix it.
Thank you
The current plugin is not compatible with any ie version since it utilizes the Object.assign function.
Using the existing _extends function instead solves the problem.
Hi,
I'm unable to view all the data when I scroll down. I know I'm missing something, but don't know what, please help.
Thanks!
add to line 83 in infinite-tree.js @cheton
state = {
openNodes: [],
rootNode: createRootNode(),
selectedNode: null
}
I am having trouble building this project. If I just download and do npm install, the eslint and stylint tests fail. It looks like it references older webpack?
Hi, I tried to flex the tree's container to fit the screen, but the tree gets hidden after some scrolling.. What would be the best way to change the height of the tree dynamically based on the screen size? Manually increase the height or ?
Ty
Regards
Hi, I was just wondering if there was a preferred way to listen for events in the HTML string returned by a custom rowRenderer.
If it was an option, I'd just return a premade Element, but it looks like only strings are accepted, and as such, I would need to use some kind of event delegation to be able to listen for something like a click on the element.
One example of a use case for this would be to have a "+" or "-" depending on node.state.open, and to call tree.openNode or tree.closeNode when it is clicked.
If there is an existing feature that allows this, I'd be happy to use it.
Thanks.
Even when using the function below to explicitly turn the search field into a string, I sometimes encounter an error "uncaught typeerror. filterText.toLowercase() is not a function", at infinite-tree.js, line 770.
If I add a ".toString() call on that line so it looks like this:
filterText = filterText.toString().toLowerCase();
I no longer encounter the error.
onUpdateSearchField(e)
{
if(this.tree)
{
//console.log("filtering tree2 with");
this.tree.filterString = e.target.value.toString();
this.tree.filter(this.tree.filterString, filterOptions);
}
}
Hi,
I am looking to add indentation lines to different levels of the tree when the parent node is expanded.
Is this something that can be achieved / would you be able to point me in the right direction as to do so?
I have attached an image which will show more clearly what im looking to do.
Any help is greatly appreciated, thank you
Great library! Forgive me if I'm missing something obvious, but even when using the rowRenderer below, the tree still shows blank lines for the nodes filtered out. This results in a tree with only the filtered nodes (correct), but spaced by large amounts of blank rows. It seems that even returning an empty string produces a row in the tree.
rowRenderer={({ node, tree}) => {
if (node.state.filtered === false) {
return('');
}
...
Is there any way how to wire keyboard shortcuts to navigate through the nodes? Arrow UP, Down, left (minimize), right (expand) etc..?
Thanks
I am planning to wrap the tree in an angular component and expose some APIs, so it will be usable in angular, but since I dont have a lot of knowledge about how the renderer works on this tree yet, could you maybe in short elaborate what would be the best way to do it and if it is doable at all?
Another thing that I was concerned about was the following scenario:
Regards
Any recommendations on filterings?
API data structure may have different field name, need a way to customize it. So we don't need to change API field name to 'loadOnDemand'
Hi,
I have a node with around 60k children, and this is causing long running script message to appear on page load, and also when i click on the node to open it.
Im wondering how do i go about speeding this process up?
Many Thanks
I'm using whatever the default row render is. Its ugly, but it works - I get indentation and the arrow to drop down children.
But filtering doesn't work. when I set a filter, it shows no rows. It would seem the default row renderer is not handinging filtering for some reason.
I don't know how to write a custom row renderer wich indents, opens closes, shows arrow etc.
The one in the example code doesn't work at all:
rowRenderer: function(node, treeOptions) { // Customizable renderer
return '<div data-id="<node-id>" class="infinite-tree-item">' + node.name + '</div>';
},
I.e. it doesn't indent, allow nodes to open/close or show the arrow.
Any ideas?
Hi,
I tried using scrollToNode and notice that sometimes it just fails. It returns true, but does not actually scroll.
After some testing it seems like the problem occurs when I try to scroll to a node that is outside of the currently rendered nodes.
Can you please have a look since this is vital when implementing search on the tree.
Thank you and br,
Aleš
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.