3

I'm creating a jstree in my program. Now I'm able to get the checked node id. But how can I get the id of the parent node id and also the parent's parent node id.

enter image description here

Below is my javascript to get the children node id.

 $('#tree-container').on('changed.jstree', function (e, data) {
                var i, j, r = [];
                for (i = 0, j = data.selected.length; i < j; i++) {
                    r.push(data.instance.get_node(data.selected[i]).id.trim());
                }
                //alert('Selected: ' + r.join(', '));
                console.log('Selected: ' + r.join(', '));
   

            });

Here is my jsfddle. Please take a look. http://jsfiddle.net/jjfcnho8/2/ When i select Child 9, I can get child 9 id. Then how can I get Child 2 and folder 1 id.

Anyone know please help me. Thank you very much!

eric
  • 163
  • 2
  • 10

3 Answers3

3

You could use the parents property of the node object you get from data.instance.get_node(). As several nodes could have the same ancestor, you'd maybe want to avoid gathering duplicates. For this you can use a Set. This is just one way you could do it:

var nodesOnSelectedPath = [...data.selected.reduce(function (acc, nodeId) {
    var node = data.instance.get_node(nodeId);
    return new Set([...acc, ...node.parents, node.id]);
}, new Set)];

console.log('Selected: ' + nodesOnSelectedPath.join(', '));

Note that this will include the root node as well, which has id '#'.

Here is the updated fiddle.

Without the root node

To get the list without the #, it is the easiest to apply a filter on the result:

console.log('Selected: ' + nodesOnSelectedPath.filter(id => id !== '#').join(', '));

EcmaScript2015

The above scripts use features from EcmaScript2015 (ES6). Some editors may highlight syntax errors when they are not configured to recognise ES6 syntax. Here you can find how to configure VSCode, Sublime Text, and WebStorm for ES6.

ES5 Alternative

In ES5 you would use an object (acc) to collect unique id references as property names. Although Object.keys is really ES6, it is often supported in otherwise ES5 browsers:

var nodesOnSelectedPath = Object.keys(data.selected.reduce(function (acc, nodeId) {
    var node = data.instance.get_node(nodeId);
    node.parents.forEach(function (id) {
        acc[id] = 1;
    });
    acc[node.id] = 1;
    return acc;
}, {}));

Here is the corresponding fiddle.

Circular references in data

You wrote in comments that you tried to do this:

JSON.stringify(data)

But that data structure has parent and child references in it, so it is possible to go from a child to its parent object, and from there back to its child object, ... which is endless. Such structures cannot be converted to JSON. See this Q&A for solutions.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • Thanks For your answer and I have some question to ask. 1) nodesOnSelectedPath = [...data.selected.reduce(function (acc, nodeId) { var node = data.instance.get_node(nodeId); return new Set([...acc, ...node.parents, node.id]); }, new Set)]; << This line show syntax error at my coding. But when I running, it still can run successfully. Why this will happen? – eric Dec 29 '16 at 01:24
  • 2)console.log(JSON.stringify(data, null, 2)); << This line make me got this error. Uncaught TypeError: Converting circular structure to JSON.. Only when I deleted this line, program only can run – eric Dec 29 '16 at 01:26
  • 3)How can i deleted the root node id ? Thank you – eric Dec 29 '16 at 01:26
  • I'm using this way to remove #. var itemtoRemove = "#"; nodesOnSelectedPath.splice($.inArray(itemtoRemove,nodesOnSelectedPath),1); – eric Dec 29 '16 at 02:41
  • Question 2 really is another question, and there are a lot of answers about that on SO. Anyway, I added an answer for all three follow-up questions in my answer ;-) – trincot Dec 29 '16 at 08:25
  • Thank you for answering my question. Really Learnt a lot of thing. Anyway, thanks again – eric Dec 29 '16 at 08:44
  • Thanks, this is (almost) working for me too, except that I get a `TypeError: data.selected.reduce(...).delete(...) is not iterable` if I put the `.delete('#')` part... please, any help? – Ivan Feb 22 '17 at 15:48
  • Indeed, it does not work with `.delete()` (this was a too-quick addition I made). Use `.filter` on the result instead. See update in answer. – trincot Feb 22 '17 at 16:08
  • Sorry to come again on this :-( please can you post a non-EC6 version of this script? – Ivan May 25 '17 at 18:24
  • I added an "ES5 Alternative" section to my answer. – trincot May 25 '17 at 19:55
0

Using jQuery, you can find parent element by this method

obj.parent();

or

obj.parent(expr); //expr is a filter express
Cai Yongji
  • 349
  • 1
  • 8
  • Can u pls explain more? I have try obj also. but it show "cannot read property 'obj' of undefined....". – eric Dec 28 '16 at 09:45
  • 3
    It is _very_ unlikely that the DOM parent is the same as the parent node within the tree itself – Alnitak Dec 28 '16 at 10:03
0

This can be achieved by getting this.parentNode.parentNode.parentNode.id in the onclick even of the jstree object.

example:

$('#myjstree').jstree({<your jstree parameters>}).on('click', '.jstree-anchor', function (e) {
if (this.parentNode.parentNode.parentNode.id == 'id_im_looking_for')
        alert('Yup GOT IT!') 
});

Tested this with jstree v3.2 using an html data source. A bit wonky? yes. Definitely test after upgrades to the jstree library because if the library developers change this structure of the nodes the example provided will no longer work.

T3.0
  • 446
  • 1
  • 6
  • 21