Does d3 have api which similar with jQuery.closest(selector)?
Asked Answered
W

4

15

DOM like this:

<g.module>
  <g.control>
    <rect>

I didn't find the closest API: https://github.com/mbostock/d3/wiki/API-Reference

How can I get the nearest matched elements from it's parent? Just like this:

var module = d3.select(".control").closest(".module");
Wooden answered 22/8, 2013 at 8:55 Comment(1)
D3 doesn't provide any functionality to move up the DOM tree.Theca
W
4

Browsers now have closest method on DOM node:

d3.select(rect.node().closest('svg'));

and similar code to @JayB with this method:

d3.selection.prototype.closest = function(selector) {
  var arr = [];
  this.each(function() {
    arr.push(this.closest(selector));
  });
  return d3.selectAll(arr);
};

that allow to use just: rect.closest('svg');

the only problem is that it's not supported by IE

Wes answered 3/7, 2018 at 14:51 Comment(2)
It doesn’t work with any versions of IE or only legacy browsers of IE.Aachen
@JavascriptCoder MDN link provide the chart, it seems that closest is not supported by IE but you can create polyfill for that method. Or you can use JayB solution, this one is for modern browsers. Also if you have to add closest polyfill it will be shorter to just add closest to d3.Wes
A
1

If your DOM is really that specific example, you can select parent nodes with D3 as noted in their docs here:

You can see the parent node of each group by inspecting the parentNode property of each group array, such as selection[0].parentNode.

So in your case, var module = d3.select(".control").parentNode; should work.

Apotropaic answered 17/4, 2015 at 1:40 Comment(0)
U
1

You could add "closest" to the d3 selection prototype like this:

d3.selection.prototype.closest = function (selector) {
    var closestMatch = undefined;
    var matchArr = [];
    this.each(function () {
        var elm = this;
        while (typeof elm.parentNode.matches === "function" && !closestMatch) {
            elm = elm.parentNode;
            if (elm.matches(selector)) {
                closestMatch = elm;
                matchArr.push(closestMatch);
            }
        }
        closestMatch = undefined;
    });
    return d3.selectAll(matchArr);
}
Unveiling answered 9/11, 2015 at 19:24 Comment(0)
J
0

You can make the selection with jquery and pass that to d3.

var selection = $('.control').closest('.module');
var module = d3.select(selection);

This may or may not work depending on what you need it for, but might be a simple workaround.

Johnnyjohnnycake answered 28/1, 2014 at 18:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.