Demonstrates the the use of D3 to manage an array of tables. Via a button, the user will cycle through several steps which will mutate the underlying array of arrays, which at each step is fed to the table update function. For example, tables are added and removed from the array of tables, individual rows of tables are added and removed, and individual table cells are modified. The update function demonstrates the enter, exit and update patterns at the div/table level as well as at the table row level.
For bl.ocks.org users, the script should be viewed in its own window. See the script in action here
forked from boeric's block: D3 Dynamic Array of Tables
forked from devssunil's block: D3 Dynamic Array of Tables
xxxxxxxxxx
<html lang="en">
<head>
<meta charset="utf-8">
<title>d3 Array of Tables Demo</title>
<!-- Author: Bo Ericsson, bo@boe.net -->
<link rel=stylesheet type=text/css href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css" media="all">
<style>
body {
padding: 10px;
font-size: 12px;
}
.well {
padding-top: 0px;
padding-bottom: 0px;
width: 500px;
}
table {
font-size: 10px;
line-height: 10px;
}
td, th {
width: 33.3%;
}
label {
margin-bottom: 10px;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script>
'use strict';
// title div with label and button
var header = d3.select("body").append("div").attr("class", "well");
header.append("h3").text("Vaccine Record");
var taskLabel = header.append("label")
.attr("id", "taskLabel")
.html(" ");
var currTask = 1;
var taskButton = header.append("button")
.attr("class", "btn btn-primary")
.style("margin-bottom", "20px")
.style("width", "100%")
.style("text-align", "left")
.text("Start")
.on("click", function() {
this.blur();
// execute the task
tasks[currTask]();
// next task
currTask = ++currTask % tasks.length;
})
// container for array of tables
var tableDiv = d3.select("body").append("div").attr("id", "tableDiv1");
// initial data
var data;
var initialData = [
{ table: "At birth", rows: [
{ table: "Table1", row: "Row1", data: "DataT1R1", status:"pending" }
]
},
{ table: "Table2", rows: [
{ table: "Table2", row: "Row1", data: "DataT2R1" },
{ table: "Table2", row: "Row2", data: "DataT2R2" },
{ table: "Table2", row: "Row3", data: "DataT2R3" }
]
},
{ table: "Table3", rows: [
{ table: "Table3", row: "Row1", data: "DataT3R1" },
{ table: "Table3", row: "Row2", data: "DataT3R2" }
]
},
{ table: "Table4", rows: [
{ table: "Table4", row: "Row1", data: "DataT4R1" },
{ table: "Table4", row: "Row2", data: "DataT4R2" }
]
}
]
// tasks
function task0() {
update([]);
taskLabel.html("Cleared any existing tables");
taskButton.text("Next step: Initial load of tables");
}
function task1() {
data = JSON.parse(JSON.stringify(initialData));
update(data);
taskLabel.text("Step 1: Initial tables loaded");
taskButton.text("Next step: Add 4th row to Table 2");
}
function task2() {
var item = data[0].rows[0].data;
data[0].rows[0].data = item + " - Updated";
update(data);
taskLabel.text("Step 6: Changed data of row 1 of Table 1");
taskButton.text("Restart") ;
}
// task list
var tasks = [task0, task1, task2,];
// function in charge of the array of tables (is called from the tasks defined above)
function update(data) {
// get all divs in the table div
var divs = tableDiv.selectAll("div")
// after .data() is executed below, divs becomes a d3 update selection
//.data(data, function(d) { return d.table }) // key function to disable default by-index evaluation
.data(function(d) {
return data;
}, function(d) {
return d.table
}) // key function to disable default by-index evaluation
// for any deleted table, remove its div and contents (by using the exit function of the update selection)
divs.exit().remove();
// add new div(s); define divsEnter (all new divs), add each div and set id and class
var divsEnter = divs.enter().append("div")
.attr("id", function(d) { return d.table + "Div"; })
.attr("class", "well")
// add title h5 in new div(s)
divsEnter.append("h5").text(function(d) { return d.table; });
// add table(s) in new div(s)
var tableEnter = divsEnter.append("table")
.attr("id", function(d) { return d.table })
.attr("class", "table table-condensed table-striped table-bordered")
// append table head in new table(s) in new div(s)
tableEnter.append("thead")
.append("tr")
.selectAll("th")
.data(["Table Name", "Row Number", "Data Contents", "status"])
.enter().append("th")
.text(function(d) { return d; })
// append table body in new table(s) in new divs(s)
tableEnter.append("tbody");
// select all tr elements in the divs update selection
var tr = divs.select("table").select("tbody").selectAll("tr")
.data(function(d, i) { return d.rows; }, function(d) { return d.row }); // again we're using key function to disable by-index evaluation
// remove rows for missing data items
tr.exit().remove();
// add rows for new data items
tr.enter().append("tr");
// bind data to table cells
var td = tr.selectAll("td")
.data(function(d, i) { return d3.values(d); });
// add new cells
td.enter().append("td");
// update contents of table cells
td.text(function(d) { return d; })
}
</script>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js