Skip to content

Instantly share code, notes, and snippets.

@eenblam
Forked from gka/index.html
Last active October 28, 2016 15:13
Show Gist options
  • Save eenblam/ca680ca54541a6670e209556685a1a73 to your computer and use it in GitHub Desktop.
Save eenblam/ca680ca54541a6670e209556685a1a73 to your computer and use it in GitHub Desktop.
(TODO: Update to D3v4) simple tables in D3

Below, I build on Gregor Aisch's article by incorporating dynamic columns.

Known issues:

  • I haven't fixed resizing yet
  • divs will overlap on small browser windows
  • d3-jetpack is great, but not necessary as a dependency. Most of the d3.f() calls could just be d => d.
<!DOCTYPE html>
<!-- Source: http://bl.ocks.org/gka/17ee676dc59aa752b4e6 -->
<html>
<head>
<meta charset="utf-8">
<style>
.dash { width: 100%; }
table, #toggles { display: inline-block; }
table {
width: 40%;
padding-left: 5%;
padding-right: 5%;
}
#toggles {
width: 30%;
padding-left: 5%;
padding-right: 5%;
}
body { font-family: 'Helvetica Neue', Helvetica; font-weight: 300; padding: 20px;}
th { text-align: left; }
th, td { padding: 0 1em 0.5ex 0;}
th.center, td.center { text-align: center; }
th.num, td.num { text-align: right; }
</style>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="https://rawgit.com/gka/d3-jetpack/master/d3-jetpack.js"></script>
</head>
<body>
<div id="dash">
<div id="toggles"></div>
<table></table>
</div>
<script src="table.js"></script>
</body>
</html>
// table.js
// Same format we'd get from d3.csv
var data = [
{ title: "The Godfather", year: 1972, length: 175, budget: 6000000, rating: 9.1 },
{ title: "The Shawshank Redemption", year: 1994, length: 142, budget: 25000000, rating: 9.1 },
{ title: "The Lord of the Rings: The Return of the King", year: 2003, length: 251, budget: 94000000, rating: 9 },
{ title: "The Godfather: Part II", year: 1974, length: 200, budget: 13000000, rating: 8.9 },
{ title: "Shichinin no samurai", year: 1954, length: 206, budget: 500000, rating: 8.9 },
{ title: "Buono, il brutto, il cattivo, Il", year: 1966, length: 180, budget: 1200000, rating: 8.8 },
{ title: "Casablanca", year: 1942, length: 102, budget: 950000, rating: 8.8 },
{ title: "The Lord of the Rings: The Fellowship of the Ring", year: 2001, length: 208, budget: 93000000, rating: 8.8 },
{ title: "The Lord of the Rings: The Two Towers", year: 2002, length: 223, budget: 94000000, rating: 8.8 },
{ title: "Pulp Fiction", year: 1994, length: 168, budget: 8000000, rating: 8.8 }
];
// Define column structure / formatting
var columns = [
{ head: 'Movie title', cl: 'title', html: d3.f('title') },
{ head: 'Year', cl: 'center', html: d3.f('year') },
{ head: 'Length', cl: 'center', html: d3.f('length', length()) },
{ head: 'Budget', cl: 'num', html: d3.f('budget', d3.format('$,')) },
{ head: 'Rating', cl: 'num', html: d3.f('rating', d3.format('.1f')) }
];
// Previously done on every row data join. Now one and done.
var movies = data.map(row =>
columns.map(c =>
Object.assign({}, c, {html: c.html(row)})));
// create table
var table = d3.select('table');
var thead = table.append('thead').append('tr');
var tbody = table.append('tbody');
/**
* Toggle menu
*/
var toggles = d3.select('#toggles');
var labels = toggles.append('ul').selectAll('li')
.data(columns)
.enter().append('li')
.style('list-style', 'none')
.append('label');
labels.insert('input')
.attr('id', d => d.head)
.attr('class', 'toggle')
.attr('type', 'checkbox')
.property('checked', true);
labels.append('text')
.text(d => d.head);
toggles.append('button')
.attr('type', 'button')
.attr('onclick', 'checkAll()')
.text('Check all')
.on('click touch', change);
toggles.append('button')
.attr('type', 'button')
.attr('onclick', 'uncheckAll()')
.text('Clear selection');
toggles.on('change', change);
// helper functions
function length() {
var fmt = d3.format('02d');
return l => Math.floor(l / 60) + ':' + fmt(l % 60) + '';
}
function checkAll() {
d3.selectAll('.toggle').property('checked', true);
}
function uncheckAll() {
d3.selectAll('.toggle').property('checked', false);
}
function change() {
d3.transition().each(redraw);
}
change();
/**
* Update table on menu change
*/
function redraw() {
var checked = d3.selectAll('.toggle:checked')[0]
.map(x => x.id);
var checked_columns = columns.filter(x => checked.indexOf(x.head) != -1);
/**
* Table header
*/
var head = thead.selectAll('th')
.data(checked_columns,
d => d.head);
// Nothing to update
head.enter()
.append('th')
.attr('class', d3.f('cl'))
.text(d3.f('head'));
head.exit().remove();
/**
* Table body
*/
var checked_movies = movies.map(row =>
row.filter(c => checked.indexOf(c.head) != -1));
// Rows
var tr = tbody.selectAll('tr')
.data(checked_movies);
tr.enter().append('tr');
tr.exit().remove();
// Cells
var td = tr.selectAll('td')
.data(row => row, d => d.head);
td.exit().remove();
td.enter().append('td')
.attr('class', d3.f('cl'))
.html(d3.f('html'));
head.order();
td.order();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment