d3选择器为直系孩子

时间:2013-12-13 15:08:57

标签: d3.js

我显然可以这样做:

d3.selectAll('div#some-div>ul')

但是,如果我使用的是DOM节点或现有的D3选择:

d3.select(this).selectAll('ul')

将获得所有后代UL。所以,如果

var div = d3.select('div') 

给了我这个节点:

<div>
  <ul>
    <li>foo
      <ul><li>bar</li></ul>
    </li>
  <ul>
</div>

然后

var uls = div.selectAll('ul') 

将获得两个UL。我想我可以区分出顶级的一个,如:

uls.filter(function() { return this.parentNode === div.node() }

所以,我已回答了我自己的问题。也许对某人有用。或者也许有人可以推荐一个不那么难看的解决方案。

nrabinowitz的答案下面的答案更好,并返回与上面相同的结果。这是revised fiddle that compares them(但不使用console.log,在jsfiddle中对我来说很奇怪)

7 个答案:

答案 0 :(得分:21)

我不希望这个工作,但看起来D3将子选择任何元素作为选择的子项匹配选择器 - 所以这工作:

d3.select(this).selectAll('div > ul');

请参阅http://jsfiddle.net/g3aay/2/

答案 1 :(得分:18)

如果有人仍然感兴趣,d3.select(this.childNodes)正帮助我解决我挑选所有直系孩子的问题。或者,您可以使用

selection.select(function(){
  return this.childNodes;
})

答案 2 :(得分:4)

@ nrabinowitz的解决方案并不是一直有效。

就我而言,我试图做d3.select(this).selectAll(".childNode > *")

所以我试图让.childNode的所有直接孩子。问题是这是一个嵌套的堆栈,所以.childNode也可能出现在子节点中,这导致了问题。

我发现的最好方法是:

var child = d3.select(this).select(".childNode");
var sel = d3.select(this).selectAll(".childNode > *").filter(function() { 
    return this.parentNode == child.node();
});

答案 3 :(得分:1)

selectAll方法依赖于querySelectorAll本机方法(至少在v4中)。

这意味着您可以使用:scope伪选择器:

var uls = div.selectAll(':scope > ul') 

:scope伪选择器目前是draft specification,并且尚未在所有浏览器中受支持。有关MDN

:scope伪选择器的更多信息

答案 4 :(得分:0)

对于四年后的价值,可以使用​d3.selectAll('#id > *'),例如在​d3.selectAll('#id > *').remove()中删除ID = id

的元素的所有子元素

答案 5 :(得分:0)

基于Sigfrid的解决方案,这是我在一个正在进行的项目中添加到原型中的内容。

  /**
   * Helper that allows to select direct children.
   * See https://stackoverflow.com/questions/20569670/d3-selector-for-immediate-children
   *
   * @param {string} selector
   * @returns {Selection}
   */
  d3.selectAll('__nonexisting__').__proto__.MYPREFIX_selectChildren = function (selector) {
    var expectedParent = this.node();
    return this.selectAll(selector).filter(
      function() {
        return this.parentNode === expectedParent;
      }
    );
  };

我抓取原型对象的方式看起来有些笨拙。也许有更好的方法。

“ MYPREFIX_”用于防止名称冲突。

jsdoc @returns {Selection}模棱两可,不幸的是,此类型在闭包中声明,并且没有jsdoc可引用的全局名称(afaik)。

一旦包含此文件,您就可以执行以下操作:

d3.select('#some_id').MYPREFIX_selectChildren('ul')

答案 6 :(得分:0)

d3选择v2.0现在应该使用新的selection.selectChildren() / selection.selectChild()方法内置此功能-请参见https://github.com/d3/d3-selection/issues/243