d3.js:使用selection.on创建一个扩展列表

Mik*_*war 3 d3.js

我有一个类似的数据结构

[
    {"name":"foo", "links":["a", "b", "c"]}, 
    {"name":"bar", "links":["d", "e", "f"]}
]
Run Code Online (Sandbox Code Playgroud)

我想列一个清单

<ul>
    <li> foo </li>
    <li> bar </li>
</ul>
Run Code Online (Sandbox Code Playgroud)

当我点击foo时,扩展为

<ul>
    <li> foo 
        <ul>
            <li> a </li>
            <li> b </li>
            <li> c </li>
        </ul>
    </li>
    <li> bar </li>
</ul>
Run Code Online (Sandbox Code Playgroud)

我想用d3.js这样做.制作热门列表非常简单有趣:

toplist = d3.select("body").append("ul");
toplist.selectAll("li")
    .data(data)
    .enter()
    .append("li")
        .text(function(d){return d.name;})
Run Code Online (Sandbox Code Playgroud)

添加子列表甚至很容易:

items = toplist.append("ul")
    .selectAll("li")
    .data(function(d){return d.links})
    .enter()
    .append("li")
         .text(function(d){return d})
Run Code Online (Sandbox Code Playgroud)

我可以on("click"..在每个li中添加一个toplist,比如

toplist.selectAll("li")
    .data(data)
    .enter()
    .append("li")
        .text(function(d){return d.name;})
        .on("click", expand)
Run Code Online (Sandbox Code Playgroud)

并将子列表代码移动到名为expand的函数中.看起来像

function expand(d,i){
Run Code Online (Sandbox Code Playgroud)

然后在其中包含上述items = ...代码.

麻烦的是,这则两侧展开的foo,并bar在同一时间.

如何为foolist元素提供单独的click事件,bar仅扩展该元素?本质上,我需要传递expand数据元素的索引,并让它只对DOM的特定部分进行操作.

任何帮助,将不胜感激!

mbo*_*ock 9

expand调用时,您拥有所需的一切.所述this上下文是被点击的li元素,并且d是相关联的数据.如果您只想展开(而不是在展开和折叠之间切换),那么您可以通过选择以下内容来创建子列表:

function expand(d) {
  d3.select(this)
      .on("click", null)
    .append("ul")
    .selectAll("li")
      .data(d.links)
    .enter().append("li")
      .text(function(d) { return d; });
}
Run Code Online (Sandbox Code Playgroud)

请注意,expand还会从单击的项目中删除单击处理程序; 单击两次时,您不想再次添加列表.

如果要在展开和删除之间切换,则需要跟踪某个状态:子菜单是打开还是关闭.您可以通过在d(d.open例如)上存储布尔值来执行此操作,或者您可以通过查询DOM以查看子菜单是否已存在来执行此操作:d3.select(this).select("ul").empty().

另一种可以做到这一点的方法是提前创建所有子菜单,然后通过displaystyle属性切换可见性.如果您拥有所有可用数据,这是最简单的选择; 如果您异步加载链接数据,我可能只会动态创建子菜单.

实例:http://bl.ocks.org/1541816