
Performing subselection
It is quite common that you will need to perform scoped selection when working on visualization. For example, selecting all div
elements within a particular section
element is one use case of such scoped selection. In this recipe, we will demonstrate how this can be achieved with different approaches and their advantages and disadvantages.
Getting ready
Open your local copy of the following file in your web browser:
https://github.com/NickQiZhu/d3-cookbook/blob/master/src/chapter2/sub-selection.html
How to do it...
The following code example selects two different div
elements using two different styles of subselection supported by D3.
<section id="section1"> <div> <p>blue box</p> </div> </section> <section id="section2"> <div> <p>red box</p> </div> </section> <script type="text/javascript"> d3.select("#section1 > div") // <-- A .attr("class", "blue box"); d3.select("#section2") // <-- B .select("div") // <-- C .attr("class", "red box"); </script>
This code generates the following visual output:

Subselection
How it works...
Though producing the same visual effect, this example demonstrates two very different subselection techniques. We will discuss them separately here so you can understand their pros and cons as well as when to use one versus the other.
Selector level-3 combinators: On line A, d3.select
is used with a special looking string which consists of one tag name connected with another one using a greater-than sign (U+003E, >). This syntax is called combinators (the greater-than sign here indicates it is a child combinator). Level-3 selector supports a few different kinds of structural combinators. Here we are going to give a quick introduction to the most common ones.
The descendant combinator: This combinator has the syntax like selector selector
.
The descendant combinator, as suggested by its name, is used to describe a loose parent-child relationship between two selections. The reason why it is called loose parent-child relationship is that the descendant combinatory does not care if the second selection is a child or a grandchild or a great-grandchild of the parent selection. Let's look at some examples to illustrate this loose relationship concept.
<div> <span> The quick <em>red</em> fox jumps over the lazy brown dog </span> </div>
Using the following selector:
div em
It will select the em
element since div
is the ancestor of the em
element and em
is a descendent of the div
element.
Child combinator: This combinator has the syntax like selector > selector
.
The child combinator offers a more restrictive way to describe a parent-child relationship between two elements. A child combinator is defined using a greater-than sign (U+003E, >) character separating two selectors.
The following selector:
span > em
It will select the em
element since em
is a direct child of the span
element in our example. While the selector div > em
will not produce any valid selection since em
is not a direct child of the div
element.
Note
The level-3 selector also supports sibling combinators however since it is less common we are not going to cover it here; interested readers can refer to W3C level-3 selector documentation http://www.w3.org/TR/css3-selectors/#sibling-combinators
The W3C level-4 selector offers some interesting additional combinators, that is, following-sibling and reference combinators that can yield some very powerful target selection capability; see http://dev.w3.org/csswg/selectors4/#combinators for more details.
The D3 subselection: On line B and C, a different kind of subselection technique was used. In this case a simple D3 selection was made first on line B selecting section #section2
element. Immediately afterwards another select
was chained to select a div
element on line C. This kind of chained selection defines a scoped selection. In plain English, this basically means to select a div
element that is nested under #section2
. In semantics, this is essentially similar to using a descendant combinator #section2 div
. However, the advantage of this form of subselection is that since the parent element is separately selected therefore it allows you to handle the parent element before selecting the child element. To demonstrate this, let's take a look at the following code snippet:
d3.select("#section2") // <-- B .style("font-size", "2em") // <-- B-1 .select("div") // <-- C .attr("class", "red box");
As shown in the preceding code snippet, now you can see before we select the div
element, we can apply a modifier function to #section2
on line B-1. This flexibility will be further explored in the next section.