Skip to content

Instantly share code, notes, and snippets.

@hobbes7878
Last active August 29, 2015 14:16
Show Gist options
  • Save hobbes7878/742d62b97c808594dc23 to your computer and use it in GitHub Desktop.
Save hobbes7878/742d62b97c808594dc23 to your computer and use it in GitHub Desktop.
#NICAR15: D3's General Update Pattern

A intro demonstration of the general update pattern on a simple HTML table.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>D3.js Simple Update Pattern</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<link href='styles.css' rel='stylesheet' type='text/css'>
</head>
<body>
<table id="myTable"></table>
<script src="script.js"></script>
</body>
</html>
// Some data
var myData = [
'Make interactive charts',
'that are totally legit.',
'Use "Join - Enter',
'Update - Exit."'
]
// Select our table.
var table = d3.select("#myTable");
/*
When we want to update a chart with new data, we need to put all the elements
we want to redraw inside a function we can call and pass that func the new data.
*/
function update(newData){
/*
Within our function, we create, update and remove data-bound HTML or SVG elements
in 4 steps: JOIN, ENTER, UPDATE and EXIT. In D3 lingo these steps are called the
"general update pattern" because this pattern of code is ubiquitous in d3.
We'll walk you through it below, but read more here, here and here:
http://bl.ocks.org/mbostock/3808218
http://bl.ocks.org/mbostock/3808221
http://bl.ocks.org/mbostock/3808234
*/
// JOIN
// First, we join our data to a set of HTML or SVG elements. In this case,
// our data will be bound to all the rows in our table, one row for each element
// in our data array.
var rows = table.selectAll("tr")
.data( newData );
// ENTER
// In this step, we add any new HTML or SVG elements we need based on our data array.
// So if our table already has 3 rows but our data array has 4 elements, the ENTER statement
// will add/append one new row, bound to the last data element in our array.
rows.enter()
.append("tr")
// In this step, we also set any default styles or attributes when the element
// is created. Because we want our text to fade in, we set opacity style to 0 when the
// table row is first created.
.style("opacity",0);
// UPDATE
// The update step defines how we'll change existing HTML/SVG elements based on new data.
// For example, if you have a bar chart, the height of the bars would be set here so that
// the bars update when we pass new data to the chart. In our case, we'll set the text we want inside
// our table rows.
// We also set our opacity style to 1, but only after a transition step lasting 1 sec (1000 millisecs).
// This gives our text a fade-in effect.
// The transition method tries to interpolate a smooth transition between the existing styles or
// attribute properties of an HTML/SVG element and the styles and properties set after it. In this case,
// transition makes the opacity on our tr's change evenly from 0 (set in ENTER step) to 1.
rows
.text(function(d){ return d; })
.transition().duration(1000)
.style("opacity",1);
// EXIT
// The exit step is the opposite of the enter step in that we remove any HTML/SVG elements that are
// no longer bound to data. So if our table has 4 tr's, but our new data array now only has 3 elements,
// the last tr would be removed.
//Here, we use a transition to fade out our text BEFORE we remove the unnecessary table rows.
rows.exit()
.transition().duration(1000)
.style("opacity",0)
.remove();
}
// Let's run our update function.
// We're going to iterate over myData so we add one data element at a time.
var i = 1;
setInterval(
function(){
// Call our update function with a slice of myData.
update( myData.slice(0,i) );
// Iterate our slice index, i.
if ( i < myData.length ){ i += 1 } else { i = 0 };
} , 1200
);
@import url(http://fonts.googleapis.com/css?family=Bangers);
table {
margin:20px 20px;
width:100%;
}
tr {
font-family: 'Bangers', sans-serif;
font-size: 50px;
padding:0px 10px;
line-height: 45px;
}
/*Quick color-ramp*/
tr:nth-child(1) {
color: #EA8481;
}tr:nth-child(2) {
color: #DC514C;
}tr:nth-child(3) {
color: #BB302C;
}tr:nth-child(4) {
color: #891B17;
}tr:nth-child(5) {
color: #580A07;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment