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:

How to do it...

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset