Building News Applications
COMM 177T/277T (2019)

D3 for D3 and Coding Workshop

Day 17 ~ May 28, 2019

Overview

Browser developer tools such as those provided by Chrome and Firefox provide numerous ways to explore and experiment with front-end code. The debugger feature of the developer toolbar is an especially powerful tool. It not only allows you to freeze a program to work through bugs, but allows you to explore the inner workings of a library or framework.

Today, we'll go deeper into D3 by using debugger-driven discovery...yes, D3 for D3. We'll focus on grasping one of the most important but initially confusing aspects of the D3 library -- data joins.

We'll devote any time remaining in class to hands-on work for the final project.

Pre-flight setup

Before we dive into the guts of D3, let's do some preliminary setup.

Both Chrome and Firefox provide similar debugging functionality, but
the interfaces vary for certain features (e.g. viewing DOM
properties). It can be helpful to use both when using a debugger to
explore code..

Data Joins

We know that D3 can create, style and animate page elements based on data points. But how does it work its magic? What are the mechanics that enable D3 to do what it does?

Exploring this question will take us into the DOM and D3's internals, and hopefully illuminate the critical concept of a data join.

Data binding basics

First, we'll use the debugger to explore the mechanics of data binding in the simplest scenario - when the number of data points corresponds exactly to the number of DOM nodes.

Some key questions you should be able to answer after the debugger demonstration in class:

Exercise - Display the points

Try updating the code so that the three circles will display in positions based on their respective coordinates. This will require you to set several attributes on each circle:

When data exceeds nodes

A common idiom in D3 involves declaratively selecting page elements that don't yet exist, and using D3 to create those elements after binding them to data.

For example, in the below body element, there's an svg with one circle
element but three data points:

<body>
<svg>
<circle></circle>
</svg>
<script src="d3.v5.js"></script>
<script type="text/javascript">
var coordinates = [[0,0], [10,10], [20, 20]];
// circle selection
var cs = d3.select('svg')
.selectAll('circle')
.data(coordinates)
.enter()
.append('circle');
</script>
</body>

Use a debugger to step through the source code and answer the following questions:

When nodes exceed data

When performing a data join, nodes that have no corresponding data are "sequestered" in the _exit property of the D3 selection.

Dynamic visualizations that rely on data updates after page load are a common use case for exit node manipulation.

For example, the below code contains 5 circles and only 3 data
coordinates:

<body>
<h1>D3 - Under the Hood</h1>
<svg>
<circle></circle>
<circle></circle>
<circle></circle>
<circle></circle>
<circle></circle>
</svg>
<script src="d3.v5.js"></script>
<script type="text/javascript">
var coordinates = [[0,0], [10,10], [20, 20]];
// circle selection
var cs = d3.select('svg')
.selectAll('circle')
.data(coordinates);
//console.log(cs);
</script>
</body>

Above, the two "excess" circle nodes are placed in the D3 selection's _exit attribute, where they can be manipulated (e.g. removed from the page).

Try updating the code to add .exit().remove() as below. Then reload the
page to see the effect.

  var cs = d3.select('svg')
.selectAll('circle')
.data(coordinates)
.exit().remove();

Summary

By working with a debugger, hopefully we've shed light on some of the
core concepts of data binding in D3.

Some key takeaways:

Further reading

For a deeper dive into data joins, check out these two resources: