How to use D3 selectAll with multiple class names
Asked Answered
B

2

39

I'm experimenting with using multiple class names for SVG elements so that (hopefully) I could select a subset of them using selectAll and "parts" of the class name. Unfortunately nothing I've tried works and I haven't found an example online. The code below demonstrates what I'm trying to do with a simple example of four circles. Two circles have class name "mYc 101" and two circles have class name "mYc 202". selectAll(".mYc") gives all four circles. What if I want only the circles with class name "mYc 101"? Can this be done? How? Thanks times infinity!!

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<div id="my_div"></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
    var m_div = d3.select("#my_div");
    var m_svg = m_div.append("svg");

    var g = m_svg.append("g");

    g.append("circle")
        .attr("class", "mYc 101")
        .attr("cx", 100)
        .attr("cy", 100)
        .attr("r", 50) 
        .attr("style", "stroke: green; stroke-width: 8; fill: #000000");

    g.append("circle")
        .attr("class", "mYc 101")
        .attr("cx", 300)
        .attr("cy", 100)
        .attr("r", 50) 
        .attr("style", "stroke: green; stroke-width: 8; fill: #000000");

    g.append("circle")
        .attr("class", "mYc 202")
        .attr("cx", 100)
        .attr("cy", 300)
        .attr("r", 50) 
        .attr("style", "stroke: blue; stroke-width: 8; fill: #000000");

    g.append("circle")
        .attr("class", "mYc 202")
        .attr("cx", 300)
        .attr("cy", 300)
        .attr("r", 50) 
        .attr("style", "stroke: blue; stroke-width: 8; fill: #000000");

    // This selects all four circles
    var list = d3.selectAll(".mYc");

    // But if I want to select only class "mYc 101", none of these work.
    // In fact they all give an error.
    // var list1 = d3.selectAll(".mYc 101");
    // var list1 = d3.selectAll(".mYc .101");
    // var list1 = d3.selectAll(".mYc.101");
    // var list1 = d3.selectAll(".mYc,.101");
    // var list1 = d3.selectAll(".101");

</script>
</body>
Bellflower answered 2/7, 2013 at 21:3 Comment(0)
L
57

The most D3 way to do this would be to chain the selectors using the filter method:

var list1 = d3.selectAll(".mYc").filter(".101");

This won't work though because class names cannot start with a number. So you have to rename to something like "a101" and then you can do

var list1 = d3.selectAll(".mYc").filter(".a101");

See this fiddle.

Lordan answered 2/7, 2013 at 21:26 Comment(1)
Thanks so much Lars!! The key was the fact that class names cannot start with a number. BillBellflower
S
39

Another way I have found to do this is to select both classes at the same time as a single string, for example:

var list1 = d3.selectAll(".mYc.a101")

It won't work if you add in a space in between, or add a comma in between (which selects things that have either class instead).

Stealer answered 4/5, 2014 at 0:24 Comment(2)
Lars' answer is fuller, but this is the one that helped me understand.Pechora
furthermore, you can use var list1 = d3.selectAll("circle.mYc.a101")Stieglitz

© 2022 - 2024 — McMap. All rights reserved.