Giter Site home page Giter Site logo

cheton / infinite-tree Goto Github PK

View Code? Open in Web Editor NEW
165.0 11.0 39.0 8.52 MB

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

JavaScript 99.09% Stylus 0.91%
infinite-scroll tree event-delegation

infinite-tree's Issues

Flattening of very large data is slow

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.

Drag and drop data onto nodes from outside the browser

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

example code not working

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;
  }

License

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.

tree.openNode function is not working for a node while updating tree data via tree.loadData function

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:

  • On Re-render Tree data, L2 or other child level nodes is closed and only L1 level nodes appear
  • To open the child nodes after loading Tree data, using Tree function as tree.openNode(parentNode); but seems it doesn't work.

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.

Lazy loading query

Are there any examples of how to implement lazy loading into this project?

Thanks

Flickering when scrolling down

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!

Any possibility to sort Nodes

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?

Select multiple nodes

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

drag & drop

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)

Swap nodes

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

Feature request: openAll() and closeAll()

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.

Minimum working example

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 a list.

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!

Open or close alls Nodes

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.

rowRenderer onclick

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.
gif

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 ?

Semi selective state problem

image
In the semi selected state, it does not take effect. At the same time, can your demo provide uncompiled code?

Demo site not loading with IE11

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.

image

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 :)

Splice.Apply causes “Maximum call stack size exceeded” when there is 170k+ nodes under one node

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

IE compatibility

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.

How do you build this thing?

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?

Resizing the tree

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

Adding event handlers to rowRenderer elements.

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.

filtering can sometimes cause an uncaught type error

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);            
    }
}

Adding Indentation lines

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.

indentation lines

Any help is greatly appreciated, thank you

filtering a react-infinite-tree still renders blank lines for filtered nodes

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('');
}
...

Keyboard events

Is there any way how to wire keyboard shortcuts to navigate through the nodes? Arrow UP, Down, left (minimize), right (expand) etc..?

Thanks

Angular2 support

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:

  • Lets assume that I have 5 nodes, and when I expand the 2nd node, it is so long that even the hidden nodes which are in the DOM are part of it, and the 3rd (its sibling) node is not on the dom yet. What would happen if I collapse the 2nd node? Will the 3rd node become visible instantly? Here is a screenshot of what I mean: http://prntscr.com/e5q5cg
  • Is it possible to add Branch lines and how complicated it will be? (Since the tree is linear in the DOM, and not nested). Here is what I mean by Branch Lines: http://prntscr.com/e5q5td

Regards

Filtering

Any recommendations on filterings?

Customize loadOnDemand field name

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'

Loading/opening node with around 60k children

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

How do you write a row renderer? Example one in docs doesn't work.

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?

ScrollToNode fails if target node outside of buffer window

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š

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.