将具有多个 parents 的图形数据转换为 jstree Javascript 的数据

Turning graph data with multiple parents into data for jstree Javascript

我有以下要求:

  1. 使用 SPARQL 查询维基百科
  2. 使用该数据使用 jstree 构建树。

我从查询中获得的数据可以拼凑在一起以显示从一个节点到另一个节点的路径。基本上是一个图表。然后在第二步,我必须将它转换成一棵树(省略一些细微差别)

经过一些处理,我到达了以下数据的阶段

//Object contain all nodes
{Id:[Array of parents]}

例如,如果我有

{A:[B,C],
B:[],
C:[]}

表示我的树中有4个节点。 A 有 2 parents BCBC 属于根。 (事实是,这个数据不适合做树,但我还是要做)

问题是 jstree 数据模型不允许呈现相同的 ID,所以我需要创建一个额外的假 A。上面的数据将变成同样的东西供 jstree 使用

[
{id:0_A,parent:B},
{id:1_A,parent:C},
{id:B,parent:#},
{id:C,parent:#},
]

我不知道如何做到这一点。我有一种微弱的感觉,我需要递归地遍历 parent 数组中的每个元素,直到它们的 parent 数组中只有 1 个元素,并相应地创建额外的假节点。但是我想不出一个完整的方法。

示例:

{A:[B,C,D],
 B:[],
 C:[],
 D:[B,C]
}
//Recursively following B,C,D in A will give us the result that 4 fake A are needed
//The same in D. Following B and C will lead to 2 node that only have 1 or less result in their parent array--> 2 fake D

会上交

[
{id:0_A,parent:B},
{id:1_A,parent:C},
{id:2_A,parent:0_D},
{id:3_A,parent:1_D},
{id:B,parent:#},
{id:C,parent:#},
{id:0_D,parent:B},
{id:1_D,parent:C},
]

上面树的jsfiddle http://jsfiddle.net/2wrcdvjq/1/

The problem being that jstree data model does not allow same ID to be presented

这并不完全正确,实际上它根本不在乎。更重要的是 HTMLTree 有这样的方式 每个节点只能有一个父节点

A node A is inserted into a node B when the insertion steps are invoked with A as the argument and A's new parent is B.

JSTree uses appendChild to append the node with id to the parent - thus removing it from other subtrees/leafes.

但是如果你使用这个

[
  {id:'B',text: '#', parent: '#'},
  {id:'A',text: Math.random(), parent: 'B'},
  {id:'A',text: Math.random(), parent: 'B'}, 
  {id:'A',text: Math.random(), parent: 'B'}, 
  {id:'A',text: Math.random(), parent: 'B'}, 
  {id:'A',text: Math.random(), parent: 'B'}
]

他们都会出现在B

我能想到你能做的最好的事情就是将回调传递给 core.data 并填充子项,或者假设会有子项并在打开时填充。

变体 1 - 在结构上填充

变体 2 - lazy daisy - on after_open(我做了这个循环以强调它的优势)

  1. 构建中

$(function () {

  let dat = {
      A:['B','C','D'],
      B:['#'],
      C:['#'],
      D:['B','C']
  }
    function populate(objId){

 
 let rtn = []
 for(let key in dat){
  
   if(dat[key].includes(objId)){
    
    
     rtn.push({
       text:key,
        children: populate(key)
      })
    }
    }
    return rtn
  }
    $('#jstree').jstree({
        "core" : {
            "data" : function (obj, cb) {
                        cb.call(this,populate(obj.id))
            }
        }
    });
    
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/jstree.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" rel="stylesheet"/>

<div id="jstree">
</div>

  1. 懒惰的雏菊:

$(function () {

  let dat = {
      A:['B','C','D'],
      B:['#'],
      C:['#'],
      D:['B','C','A']
  }
  function populate(objId){

  
  let rtn = []
  for(let key in dat){
  
      if(dat[key].includes(objId)){


          rtn.push({
            text:key,
            children: ['...']
          })
      }
    }
    return rtn
  }
    $('#jstree2').jstree({
        "core" : {
          check_callback : true,
            "data" : function (obj, cb) {
            
            cb.call(this,populate(obj.id))
            }
        }
    }).on('after_open.jstree', (e, openNode) => {
        
            let children = populate(openNode.node.text)
            
            $(e.currentTarget).jstree("delete_node", openNode.node.children)
            if(children.length)
            for(let newNode of children)
            $(e.currentTarget).jstree("create_node", openNode.node, newNode)
    });
    
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/jstree.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" rel="stylesheet"/>

<div id="jstree">
</div>

<div id="jstree2">
</div>