Skip to content

Instantly share code, notes, and snippets.

@willzjc
Last active January 6, 2018 22:39
Show Gist options
  • Save willzjc/35304abadb55ad81da939d202523b601 to your computer and use it in GitHub Desktop.
Save willzjc/35304abadb55ad81da939d202523b601 to your computer and use it in GitHub Desktop.
Chord diagram transition - Other CCY
license: mit
/*** Define parameters and tools ***/
var csvfilter = "";
var ccyfilter = "";
var width = 760,
height = 820,
outerRadius = Math.min(width, height) / 2 - 120,//100,
innerRadius = outerRadius - 10;
var dataset = "y2017.json";
//string url for the initial data set
//would usually be a file path url, here it is the id
//selector for the <pre> element storing the data
//create number formatting functions
var formatPercent = d3.format("%");
var numberWithCommas = d3.format("0,f");
//create the arc path data generator for the groups
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
//create the chord path data generator for the chords
var path = d3.svg.chord()
.radius(innerRadius - 4);// subtracted 4 to separate the ribbon
//define the default chord layout parameters
//within a function that returns a new layout object;
//that way, you can create multiple chord layouts
//that are the same except for the data.
function getDefaultLayout() {
return d3.layout.chord()
.padding(0.03)
.sortSubgroups(d3.descending)
.sortChords(d3.ascending);
}
var last_layout; //store layout between updates
var regions; //store neighbourhood data outside data-reading function
/*** Initialize the visualization ***/
var g = d3.select("#chart_placeholder").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("id", "circle")
.attr("transform",
"translate(" + width / 2 + "," + height / 2 + ")");
//the entire graphic will be drawn within this <g> element,
//so all coordinates will be relative to the center of the circle
g.append("circle")
.attr("r", outerRadius);
//this circle is set in CSS to be transparent but to respond to mouse events
//It will ensure that the <g> responds to all mouse events within
//the area, even after chords are faded out.
/*** Read in the neighbourhoods data and update with initial data matrix ***/
//normally this would be done with file-reading functions
//d3. and d3.json and callbacks,
//instead we're using the string-parsing functions
//d3.csv.parse and JSON.parse, both of which return the data,
//no callbacks required.
d3.csv("regionsfish.csv", function(error, regionData) {
if (error) {alert("Error reading file: ", error.statusText); return; }
regions = regionData;
//store in variable accessible by other functions
//regions = d3.csv.parse(d3.select("#regions").text());
//instead of d3.csv
updateChords(dataset);
//call the update method with the default dataset
}); //end of d3.csv function
/* Create OR update a chord layout from a data matrix */
function updateChords( datasetURL ) {
d3.json(datasetURL, function(error, matrix) {
if (error) {alert("Error reading file: ", error.statusText); return; }
//var matrix = JSON.parse( d3.select(datasetURL).text() );
// instead of d3.json
/* Compute chord layout. */
layout = getDefaultLayout(); //create a new layout object
layout.matrix(matrix);
/* Create/update "group" elements */
var groupG = g.selectAll("g.group")
.data(layout.groups(), function (d) {
return d.index;
//use a key function in case the
//groups are sorted differently
});
groupG.exit()
.transition()
.duration(1500)
.attr("opacity", 0)
.remove(); //remove after transitions are complete
var newGroups = groupG.enter().append("g")
.attr("class", "group");
//the enter selection is stored in a variable so we can
//enter the <path>, <text>, and <title> elements as well
//Create the title tooltip for the new groups
newGroups.append("title");
//Update the (tooltip) title text based on the data
groupG.select("title")
.text(function(d, i) {
return numberWithCommas(d.value)
+ " Total Google Interest for "
+ regions[i].name;
});
//create the arc paths and set the constant attributes
//(those based on the group index, not on the value)
newGroups.append("path")
.attr("id", function (d) {
return "group" + d.index;
//using d.index and not i to maintain consistency
//even if groups are sorted
})
.style("fill", function (d) {
return regions[d.index].color;
});
//update the paths to match the layout
groupG.select("path")
.transition()
.duration(1500)
//.attr("opacity", 0.5) //optional, just to observe the transition////////////
.attrTween("d", arcTween( last_layout ))
// .transition().duration(100).attr("opacity", 1) //reset opacity//////////////
;
//create the group labels
newGroups.append("svg:text")
.attr("xlink:href", function (d) {
return "#group" + d.index;
})
.attr("dy", ".35em")
.attr("color", "#fff")
.text(function (d) {
return regions[d.index].name + ' (' + (100* ((d.endAngle - d.startAngle) / 2)/Math.PI).toFixed(1) + '%)';
});
//position group labels to match layout
groupG.select("text")
.transition()
.duration(1500)
.attr("transform", function(d) {
d.angle = (d.startAngle + d.endAngle) / 2;
//store the midpoint angle in the data object
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")" +
" translate(" + (innerRadius + 26) + ")" +
(d.angle > Math.PI ? " rotate(180)" : " rotate(0)");
//include the rotate zero so that transforms can be interpolated
})
.text(function (d) {
return regions[d.index].name + ' (' + (100* ((d.endAngle - d.startAngle) / 2)/Math.PI).toFixed(1) + '%)';
})
.attr("text-anchor", function (d) {
return d.angle > Math.PI ? "end" : "begin";
});
/* Create/update the chord paths */
var chordPaths = g.selectAll("path.chord")
.data(layout.chords(), chordKey );
//specify a key function to match chords
//between updates
//create the new chord paths
var newChords = chordPaths.enter()
.append("path")
.attr("class", "chord");
// Add title tooltip for each new chord.
newChords.append("title");
// Update all chord title texts
chordPaths.select("title")
.text(function(d) {
if (regions[d.target.index].name !== regions[d.source.index].name) {
return [numberWithCommas(d.source.value),
" Google Rating for ",
regions[d.source.index].name,
regions[d.target.index].name,
"\n",
numberWithCommas(d.target.value),
" Google Rating for ",
regions[d.target.index].name,
regions[d.source.index].name
].join("");
//joining an array of many strings is faster than
//repeated calls to the '+' operator,
//and makes for neater code!
}
else { //source and target are the same
return numberWithCommas(d.source.value)
+ " exports ended in "
+ regions[d.source.index].name;
}
});
//handle exiting paths:
chordPaths.exit().transition()
.duration(1500)
.attr("opacity", 0)
.remove();
//update the path shape
chordPaths.transition()
.duration(1500)
//.attr("opacity", 0.5) //optional, just to observe the transition
.style("fill", function (d) {
return regions[d.source.index].color;
})
.attrTween("d", chordTween(last_layout))
//.transition().duration(100).attr("opacity", 1) //reset opacity
;
//add the mouseover/fade out behaviour to the groups
//this is reset on every update, so it will use the latest
//chordPaths selection
groupG.on("mouseover", function(d) {
chordPaths.classed("fade", function (p) {
//returns true if *neither* the source or target of the chord
//matches the group that has been moused-over
return ((p.source.index != d.index) && (p.target.index != d.index));
});
});
//the "unfade" is handled with CSS :hover class on g#circle
//you could also do it using a mouseout event:
/*
g.on("mouseout", function() {
if (this == g.node() )
//only respond to mouseout of the entire circle
//not mouseout events for sub-components
chordPaths.classed("fade", false);
});
*/
last_layout = layout; //save for next update
}); //end of d3.json
}
function arcTween(oldLayout) {
//this function will be called once per update cycle
//Create a key:value version of the old layout's groups array
//so we can easily find the matching group
//even if the group index values don't match the array index
//(because of sorting)
var oldGroups = {};
if (oldLayout) {
oldLayout.groups().forEach( function(groupData) {
oldGroups[ groupData.index ] = groupData;
});
}
return function (d, i) {
var tween;
var old = oldGroups[d.index];
if (old) { //there's a matching old group
tween = d3.interpolate(old, d);
}
else {
//create a zero-width arc object
var emptyArc = {startAngle:d.startAngle,
endAngle:d.startAngle};
tween = d3.interpolate(emptyArc, d);
}
return function (t) {
return arc( tween(t) );
};
};
}
function chordKey(data) {
return (data.source.index < data.target.index) ?
data.source.index + "-" + data.target.index:
data.target.index + "-" + data.source.index;
//create a key that will represent the relationship
//between these two groups *regardless*
//of which group is called 'source' and which 'target'
}
function chordTween(oldLayout) {
//this function will be called once per update cycle
//Create a key:value version of the old layout's chords array
//so we can easily find the matching chord
//(which may not have a matching index)
var oldChords = {};
if (oldLayout) {
oldLayout.chords().forEach( function(chordData) {
oldChords[ chordKey(chordData) ] = chordData;
});
}
return function (d, i) {
//this function will be called for each active chord
var tween;
var old = oldChords[ chordKey(d) ];
if (old) {
//old is not undefined, i.e.
//there is a matching old chord value
//check whether source and target have been switched:
if (d.source.index != old.source.index ){
//swap source and target to match the new data
old = {
source: old.target,
target: old.source
};
}
tween = d3.interpolate(old, d);
}
else {
//create a zero-width chord object
///////////////////////////////////////////////////////////in the copy ////////////////
if (oldLayout) {
var oldGroups = oldLayout.groups().filter(function(group) {
return ( (group.index == d.source.index) ||
(group.index == d.target.index) )
});
old = {source:oldGroups[0],
target:oldGroups[1] || oldGroups[0] };
//the OR in target is in case source and target are equal
//in the data, in which case only one group will pass the
//filter function
if (d.source.index != old.source.index ){
//swap source and target to match the new data
old = {
source: old.target,
target: old.source
};
}
}
else old = d;
/////////////////////////////////////////////////////////////////
var emptyChord = {
source: { startAngle: old.source.startAngle,
endAngle: old.source.startAngle},
target: { startAngle: old.target.startAngle,
endAngle: old.target.startAngle}
};
tween = d3.interpolate( emptyChord, d );
}
return function (t) {
//this function calculates the intermediary shapes
return path(tween(t));
};
};
}
/* Activate the buttons and link to data sets */
d3.select("#y2011").on("click", function() {
updateChords( "y2011.json" );
csvfilter="2011";
//disableButton(this);
});
d3.select("#y2012").on("click", function() {
updateChords( "y2012.json" );
csvfilter="2012";
//disableButton(this);
});
d3.select("#y2013").on("click", function() {
updateChords( "y2013.json" );
csvfilter="2013";
task_delete_tables();
//disableButton(this);
});
d3.select("#y2014").on("click", function() {
updateChords( "y2014.json" );
csvfilter="2014";
task_delete_tables();
//disableButton(this);
});
d3.select("#y2015").on("click", function() {
updateChords( "y2015.json" );
csvfilter="2015";
//disableButton(this);
task_delete_tables();
});
d3.select("#y2016").on("click", function() {
updateChords( "y2016.json" );
csvfilter="2016";
//disableButton(this);
task_delete_tables();
});
d3.select("#y2017").on("click", function() {
csvfilter="2017";
updateChords( "y2017.json" );
//disableButton(this);
task_delete_tables();
});
function injectHTML(inject_content){
//step 1: get the DOM object of the iframe.
var iframe = document.getElementById('target_iframe');
alert(iframe);
var html_string = '<html><head></head><body><p>' + inject_content + '</p></body></html>';
/* if jQuery is available, you may use the get(0) function to obtain the DOM object like this:
var iframe = $('iframe#target_iframe_id').get(0);
*/
//step 2: obtain the document associated with the iframe tag
//most of the browser supports .document. Some supports (such as the NetScape series) .contentDocumet, while some (e.g. IE5/6) supports .contentWindow.document
//we try to read whatever that exists.
var iframedoc = iframe.document;
if (iframe.contentDocument)
iframedoc = iframe.contentDocument;
else if (iframe.contentWindow)
iframedoc = iframe.contentWindow.document;
if (iframedoc){
// Put the content in the iframe
iframedoc.open();
iframedoc.writeln(html_string);
iframedoc.close();
} else {
//just in case of browsers that don't support the above 3 properties.
//fortunately we don't come across such case so far.
alert('Cannot inject dynamic contents into iframe.');
}
}
/*
function disableButton(buttonNode) {
d3.selectAll("button")
.attr("disabled", function(d) {
return this === buttonNode? "true": null;
});
}
*/
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="details">
<h1>Regional Currency Sentiments</h1>
<div id="yearbuttons">
<!-- <button id="y2013" class="">2013</button>
<button id="y2014" class="">2014</button>
<button id="y2015" class="">2015</button>
<button id="y2016" class="">2016</button> -->
<button id="2017" class="current">2017</button>
</div>
<!--This script is to highlight each year button while on it-->
<script type="text/javascript">
$('#yearbuttons button').on('click', function(){
$('button.current').removeClass('current');
$(this).addClass('current');
});
</script>
<div id="legend">
<table class="table1">
<tr>
<td bgcolor="#FFFFFF" width="10%">
</td>
<td width="90%"><h3>Regions</h3>
</td>
</tr>
<tr>
<td bgcolor="#FF00FF" width="10%">
</td>
<td><a class="two" id="NA" href = "#" onclick="ccyfilter='USD';" >Americas</a>
<table class="table2">
<tr>
<td><h3>Currencies</h3></td>
</tr>
<tr>
<td>CAD<br/>USD<br/>MXN<br/>COP<br/>BRL<br/>CLP<br/>PEN<br/>ARS</td>
</tr>
</table>
</td>
</tr>
<tr>
<td bgcolor="#0000FF">
</td>
<td><a class="two" id="NA" href = "#" >Europe</a>
<table class="table2">
<tr>
<td><h3>Countries</h3></td>
</tr>
<tr><td>EUR<br/>GBP<br/>USD<br/>CZK<br/>RUB<br/>PLN<br/>HUF<br/>CHF<br/>TRL</td>
</tr>
</table>
</td>
</tr>
<tr>
<td bgcolor="#6495ED">
</td>
<td><a class="two" id="NA" href = "#">Middle East & Africa</a>
<table class="table2">
<tr>
<td><h3>Countries</h3></td>
</tr>
<tr>
<td>
USD<br/>EUR<br/>GBP<br/>TRL<br/>ILS<br/>ZAR<br/>MAD<br/>SOS
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td bgcolor="#F4A460">
</td>
<td><a class="two" id="NA" href = "#" >Emergent Nations</a>
<table class="table2">
<tr>
<td><h3>Countries</h3></td>
</tr>
<tr>
<td>USD<br/>MXN<br/>TRY<br/>ILS<br/>CNHZ<br/>SGD<br/>HKD<br/>KRW<br/>BRL<br/>TWD<br/>ZAR<br/>PLN<br/>HUF<br/>CZK<br/>RUB
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</div>
<div id="chart_placeholder"></div>
<div class="table_control"></div>
<div class="table_placeholder"></div>
<script type="text/javascript" src="chord.js"></script>
</body>
</html>
name color
ARS #FF00FF
AUD #0000FF
BRL #6495ED
CAD #F4A460
CHF #8E8E38
CLP #C6E2FF
CNH #D8BFD8
CNY #97FFFF
COP #00EEEE
CZK #FF00FF
DKK #0000FF
EUR #6495ED
GBP #F4A460
HKD #8E8E38
HUF #C6E2FF
ILS #D8BFD8
KRW #97FFFF
MAD #00EEEE
MXN #FF00FF
NOK #0000FF
NZD #6495ED
PEN #F4A460
PLN #8E8E38
RUB #C6E2FF
SGD #D8BFD8
SOS #97FFFF
TRL #00EEEE
TRY #FF00FF
TWD #0000FF
USD #6495ED
ZAR #F4A460
body {
background: white;
width:1150px;
}
h1 {
font-size: 220%;
text-align: center;
font-family: verdana;
color: gray;
margin-top:0px;
}
h2 {
font-size: 130%;
font-family: verdana;
text-align: center;
color: black;
}
h3 {
font-size: 130%;
font-family: verdana;
text-align: center;
color: gray;
line-height: 100%;
}
h4 {
font-size: 100%;
font-family: verdana;
text-align: justify;
color: black;
}
h5 {
font-size: 100%;
font-family: verdana;
text-align: center;
color: black;
}
h6 {
font-size: 100%;
font-family: verdana;
text-align: left;
color: gray;
margin-top:12px;
}
p {
font-family: verdana;
font-size: 80%;
text-align: center;
}
#chart_placeholder {
text-align: center;
float:right;
color:#fff;
width: 750px;
height: 830px;
}
.details {
float:right;
width:350px;
}
/*
.dependencyWheel {
font: 10px sans-serif;
}*/
#circle circle {
fill: none;
pointer-events: all;
}
path.chord {
stroke: #000;
stroke-width: .10px;
transition: opacity 0.3s;
}
#circle path.fade {
opacity: 1;
}
#circle:hover path.fade {
opacity: 0;
}
/*text is regions name only on chord diagram and scroll text*/
text {
fill: black;
font-family: Arial Narrow,Arial,sans-serif;
text-align: center;
font-size: 14px;
}
svg {
font-size: 10px;
color: green;
min-height: 100%;
min-width: 100%;
}
.yearbuttons{/*area*/
float: left;
margin-right: 50px;
width: 400px;
}
button{/*this are the year buttons*/
background-color: white;
color: white;
font-size : 20px;
font-family: Arial Narrow,Arial,sans-serif;
border-color: white;
/* border-radius: 2em; */
border-style: solid;
cursor:pointer;
}
.current{
background-color: white;
color: black;
font-size : 20px;
font-family: Arial Narrow,Arial,sans-serif;
border-color: black;
/* border-radius: 2em; */
}
#legend {/*regions*/
float:left;
font-size: 14px;
width: 215px;
}
/*regions as well*/
table.table1{
}
/*countries*/
table.table2 {
position: absolute;
top:180px;
left:1050px;
white-space: nowrap;
border-collapse: collapse;
display: none;
}
table.table2 td {
font-family: verdana;
font-size: 14px;
float: left;
}
p {
font-family: verdana;
font-size: 80%;
text-align: center;
}
.link {
margin-left: 30px;
width:300px;
height:50px;
float: left;
}
.scroll {
position:absolute; /*on top of vis*/
top:0;
left:0px;
}
.scroll2 {
float:left;
}
/* unvisited link */
a.one:link {
color: #3CBCBC;
text-decoration: none;
}
/* visited link */
a.one:visited {
color: #54C571;
}
/* mouse over link */
a.one:hover {
color: #2414ff;
}
/* selected link */
a.one:active {
color: #3CBCBC;
}
/*this are the links to the table not to other pages*/
/* mouse over link */
a.two:hover + table {
display: table;
color: black;
}
a.two:click + table {
display: table;
color: black;
}
/* unvisited link */
a.two:link {
font-family: verdana;
color: black;
text-decoration: none;
}
/* visited link */
a.two:visited {
font-family: verdana;
color: black;
}
/* mouse over link */
a.two:hover {
font-family: verdana;
color: gray;
}
/* selected link */
a.two:active {
font-family: verdana;
color: black;
}
/*subframe*/
table.table2a {
position: absolute;
top:140px;
left:1050px;
white-space: nowrap;
border-collapse: collapse;
}
table.table2a iframe {
border: 0;
}
table.table2a td {
font-family: verdana;
font-size: 14px;
float: left;
}
p {
font-family: verdana;
font-size: 80%;
text-align: center;
}
.link {
margin-left: 30px;
width:300px;
height:50px;
float: left;
}
.scroll {
position:absolute; /*on top of vis*/
top:0;
left:0px;
}
.scroll2 {
float:left;
}
/* unvisited link */
a.one:link {
color: #3CBCBC;
text-decoration: none;
}
/* visited link */
a.one:visited {
color: #54C571;
}
/* mouse over link */
a.one:hover {
color: #2414ff;
}
/* selected link */
a.one:active {
color: #3CBCBC;
}
/*this are the links to the table not to other pages*/
/* mouse over link */
/* a.two:hover + table {
display: table;
color: black;
} */
a.two:click + table {
display: table;
color: black;
}
/* unvisited link */
a.two:link {
font-family: verdana;
color: black;
text-decoration: none;
}
/* visited link */
a.two:visited {
font-family: verdana;
color: black;
}
/* mouse over link */
a.two:hover {
font-family: verdana;
color: gray;
}
/* selected link */
a.two:active {
font-family: verdana;
color: black;
}
body {
}
.table_placeholder {
position: absolute;
top:180px;
left:950px;
white-space: nowrap;
padding-top: 0px;
padding-bottom: 0px;
min-width: 500px;
}
.table_placeholder table{
margin=1px;
}
.well {
padding-top: 0px;
padding-bottom: 0px;
min-width: 500px;
}
.h3, h3 {
text-align: left;
}
label {
margin-bottom: 10px;
}
.table1 table {
border-collapse: separate;
}
h3, .h3 {
text-align: left;
}
'use strict';
// title div with label and button
var header = d3.select(".table_placeholder").append("div").attr("class", "well");
header.append("h3").text("Notable events relating to selected CCY " + ccyfilter)
.attr("text-align", "left")
.attr("class","h3class")
;
var taskLabel = header.append("label")
.attr("id", "taskLabel")
.html("&nbsp;");
header.append("br")
var currTask = 0;
var taskButton1 = header.append("button")
.attr("class", "btn btn-primary")
.style("margin-bottom", "20px")
.style("width", "200px")
.style("text-align", "left")
.style("margin-left", "1px")
.text("Data Relations")
.on("click", function() {
this.blur();
// execute the task
showmatrix("interests.csv");
// next task
// currTask = ++currTask % tasks.length;
})
var taskButton2 = header.append("button")
.attr("class", "btn btn-primary")
.style("margin-bottom", "20px")
.style("width", "200px")
.style("text-align", "left")
.style("margin-left", "1px")
.text("Show Matrix")
.on("click", function() {
this.blur();
// execute the task
showmatrix("matrix.csv");
// next task
// currTask = ++currTask % tasks.length;
})
var button_clear = header.append("button")
.attr("class", "btn btn-primary")
.style("margin-bottom", "20px")
.style("width", "200px")
.style("text-align", "left")
.style("margin-left", "1px")
.text("Clear")
.on("click", function() {
this.blur();
// execute the task
task_delete_tables();
// next task
// currTask = ++currTask % tasks.length;
})
// container for array of tables
var tableDiv = d3.select(".table_placeholder").append("div").attr("id", "tableDiv1");
// initial data
var data;
var initialData = [
{ table: "Notable Events", rows: [
{ col1: "abc", col2: "Row1", col3: "DataT1R1" },
{ col1: "sdfasdf", col2: "Row1", col3: "DataT1R1" },
{ col1: "asdfasdf", col2: "Row2", col3: "DataT1R2" }
]
}
]
// tasks
function task_delete_tables() {
// clear any existing tables (by providing an empty array)
// update([]);
// var table = d3.select("wells").select("table").selectAll("tr")
var divs = tableDiv.selectAll("div");
ccyfilter="";
divs.remove();
// taskLabel.html("Cleared any existing tables");
}
function task_initialize() {
// load initial tables
data = JSON.parse(JSON.stringify(initialData));
update(data);
console.log(data);
taskLabel.text("Step 1: Initial tables loaded");
}
function task_initialize_csv() {
data = JSON.parse(JSON.stringify(initialData));
update(data);
update([]);
d3.text("interests.csv", function(csvdata) {
var divs = tableDiv.selectAll("div")
// after .data() is executed below, divs becomes a d3 update selection
.data(data, // new data
function(d) { return d.table // "key" function to disable default by-index evaluation
})
var divsEnter = divs.enter().append("div")
.attr("id", function(d) { return d.table + "Div"; })
.attr("class", "well")
// add title in new div(s)
divsEnter.append("h5").text(function(d) { return d.table; });
// add table 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)
tableEnter.append("thead")
.append("tr")
.selectAll("th")
.data(["Currency Pair", "Time", "Related Information"]) // table column headers (here constant, but could be made dynamic)
.enter().append("th")
.text(function(d) { return d; })
// append table body in new table(s)
tableEnter.append("tbody");
var parsedCSV = d3.csv.parseRows(csvdata);
var tr = divs.select("table").select("tbody").selectAll("tr")
.data(parsedCSV).enter()
.append("tr")
.selectAll("td")
.data(function(d) { return d; }).enter()
.append("td")
.text(function(d) { return d; });
});
}
function task_update_insert() {
// add 4th row to table 2
data[0].rows.push({ table: "Table2", row: "Row4", data: "DataT2R4" });
update(data);
taskLabel.text("Step 2: Added 4th row to Table 2");
}
function showmatrix(filename){
header.select('h3').text("Notable events relating to selected CCY " + ccyfilter);
data = JSON.parse(JSON.stringify(initialData));
update(data);
update([]);
d3.text(filename, function(csvdata) {
var divs = tableDiv.selectAll("div")
// after .data() is executed below, divs becomes a d3 update selection
.data(data, // new data
function(d) { return d.table // "key" function to disable default by-index evaluation
})
var divsEnter = divs.enter().append("div")
.attr("id", function(d) { return d.table + "Div"; })
.attr("class", "well")
// add title in new div(s)
divsEnter.append("h5").text(function(d) { return d.table; });
var parsedCSV = d3.csv.parseRows(csvdata);
// add table 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)
tableEnter.append("thead")
.append("tr")
.selectAll("th")
.data((parsedCSV[0])) // table column headers (here constant, but could be made dynamic)
.enter().append("th")
.text(function(d) { return d; })
// append table body in new table(s)
tableEnter.append("tbody");
parsedCSV.splice(0,1);
// Filter
if ( filename.includes('interest')){
for (var i = parsedCSV.length - 1; i >= 0; i--) {
// Filter filter
if (!parsedCSV[i][1].includes(csvfilter)) {
console.log(parsedCSV.splice(i,1));
}
// Filter currency
if (!parsedCSV[i][0].includes(ccyfilter)) {
console.log(parsedCSV.splice(i,1));
}
}
}
var tr = divs.select("table").select("tbody").selectAll("tr")
.data(parsedCSV).enter()
.append("tr")
.selectAll("td")
.data(function(d) { return d; }).enter()
.append("td")
.text(function(d) { return d; });
});
}
function task_updated() {
// change the content of row 1 of table 1
var item = data[0].rows[0].data;
data[0].rows[0].data = item + " - Updated";
update(data);
taskLabel.text("About To restart");
taskButton.text("Restart") ;
}
// task list (array of functions)
var tasks = [task_delete_tables,task_initialize,task_update_insert,task_updated]
// function in charge of the array of tables
function update(data) {
// select all divs in the table div, and then apply new data
var divs = tableDiv.selectAll("div")
// after .data() is executed below, divs becomes a d3 update selection
.data(data, // new data
function(d) { return d.table // "key" function to disable default by-index evaluation
})
// use the exit method of the d3 update selection to remove any deleted table div and contents (which would be absent in the data array just applied)
divs.exit().remove();
// use the enter metod of the d3 update selection to add new ("entering") items present in the data array just applied
var divsEnter = divs.enter().append("div")
.attr("id", function(d) { return d.table + "Div"; })
.attr("class", "well")
// add title in new div(s)
divsEnter.append("h5").text(function(d) { return d.table; });
// add table 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)
tableEnter.append("thead")
.append("tr")
.selectAll("th")
.data(["Currency Pair", "Time", "Related Information"]) // table column headers (here constant, but could be made dynamic)
.enter().append("th")
.text(function(d) { return d; })
// append table body in new table(s)
tableEnter.append("tbody");
// select all tr elements in the divs update selection
var tr = divs.select("table").select("tbody").selectAll("tr")
// after the .data() is executed below, tr becomes a d3 update selection
.data(
function(d) { return d.rows; }, // return inherited data item
function(d) { return d.row } // "key" function to disable default by-index evaluation
);
// use the exit method of the update selection to remove table rows without associated data
tr.exit().remove();
// use the enter method to add table rows corresponding to new data
tr.enter().append("tr");
// bind data to table cells
var td = tr.selectAll("td")
// after the .data() is executed below, the td becomes a d3 update selection
.data(function(d) { return d3.values(d); }); // return inherited data item
// use the enter method to add td elements
td.enter().append("td") // add the table cell
.text(function(d) { return d; }) // add text to the table cell
}
[[6, 3, 7, 0, 7, 3, 8, 3, 4, 3, 3, 4, 4, 3, 8, 7, 5, 7, 3, 2, 1, 5, 8, 5,
6, 9, 7, 2, 8, 4, 1],
[0, 3, 1, 2, 0, 0, 0, 9, 6, 6, 6, 6, 0, 1, 8, 6, 2, 7, 7, 7, 0, 0, 1, 3,
5, 9, 1, 2, 6, 7, 9],
[3, 2, 8, 5, 9, 2, 0, 4, 2, 5, 2, 1, 7, 9, 8, 6, 2, 9, 5, 4, 0, 6, 0, 3,
9, 6, 9, 0, 3, 1, 8],
[3, 2, 4, 1, 4, 7, 0, 3, 4, 0, 3, 2, 9, 3, 1, 5, 0, 6, 6, 2, 3, 6, 8, 5,
7, 4, 6, 7, 9, 3, 8],
[5, 6, 4, 8, 7, 7, 2, 9, 5, 0, 6, 6, 7, 2, 9, 9, 2, 1, 7, 6, 8, 5, 6, 1,
2, 2, 5, 0, 8, 4, 5],
[8, 5, 8, 9, 7, 7, 1, 6, 6, 3, 1, 5, 8, 2, 2, 6, 9, 4, 2, 1, 4, 1, 6, 9,
1, 2, 2, 5, 8, 6, 8],
[2, 9, 2, 1, 1, 6, 5, 7, 8, 8, 1, 3, 8, 1, 3, 2, 5, 4, 3, 3, 5, 1, 1, 6,
1, 0, 8, 7, 6, 2, 5],
[6, 0, 0, 2, 3, 7, 6, 8, 5, 2, 7, 8, 1, 7, 5, 5, 9, 2, 7, 8, 9, 1, 2, 7,
8, 4, 3, 5, 7, 4, 0],
[1, 4, 5, 1, 8, 6, 0, 5, 0, 8, 8, 2, 7, 0, 6, 5, 7, 6, 3, 4, 1, 2, 8, 9,
0, 3, 4, 7, 7, 4, 6],
[2, 0, 1, 5, 7, 8, 5, 7, 1, 4, 6, 1, 3, 0, 7, 6, 5, 1, 8, 9, 1, 3, 6, 3,
1, 0, 2, 3, 5, 6, 0],
[6, 0, 4, 9, 6, 8, 4, 2, 9, 1, 5, 7, 1, 1, 6, 6, 5, 8, 7, 4, 3, 8, 2, 7,
8, 3, 0, 9, 5, 0, 2],
[3, 4, 2, 4, 2, 8, 1, 7, 2, 0, 9, 4, 7, 9, 9, 0, 1, 2, 2, 4, 0, 5, 0, 1,
0, 5, 9, 0, 8, 9, 7],
[9, 3, 3, 4, 4, 8, 7, 8, 2, 2, 6, 1, 2, 6, 2, 6, 9, 4, 9, 9, 2, 2, 4, 6,
1, 8, 3, 7, 8, 5, 3],
[9, 7, 4, 3, 2, 4, 9, 6, 9, 2, 4, 6, 4, 6, 3, 2, 1, 9, 7, 9, 6, 1, 4, 3,
7, 8, 5, 7, 9, 8, 7],
[3, 5, 3, 3, 0, 0, 6, 7, 9, 9, 3, 5, 1, 9, 2, 4, 9, 8, 3, 6, 8, 8, 9, 1,
8, 0, 3, 6, 3, 7, 1],
[5, 7, 2, 9, 9, 8, 6, 3, 1, 6, 6, 4, 1, 6, 1, 6, 7, 1, 0, 8, 7, 2, 5, 6,
5, 5, 4, 5, 6, 0, 3],
[9, 1, 4, 8, 3, 0, 7, 7, 8, 2, 8, 6, 2, 4, 1, 1, 9, 5, 0, 3, 3, 4, 5, 8,
3, 7, 3, 9, 9, 0, 7],
[0, 5, 7, 9, 6, 9, 2, 2, 6, 6, 2, 7, 4, 6, 9, 1, 3, 7, 6, 1, 9, 3, 3, 8,
8, 9, 8, 2, 1, 4, 3],
[9, 7, 9, 4, 6, 3, 1, 3, 5, 1, 4, 2, 7, 4, 5, 9, 6, 7, 7, 2, 3, 6, 0, 3,
0, 0, 6, 1, 4, 3, 5],
[9, 5, 5, 7, 0, 2, 9, 8, 5, 6, 6, 5, 5, 0, 1, 1, 8, 7, 1, 2, 6, 8, 3, 0,
8, 7, 5, 0, 1, 3, 7],
[2, 0, 6, 9, 3, 8, 5, 4, 5, 1, 4, 0, 5, 6, 6, 2, 6, 0, 4, 7, 7, 7, 1, 8,
6, 9, 9, 6, 7, 9, 7],
[1, 8, 4, 0, 1, 3, 8, 3, 5, 5, 3, 3, 8, 1, 0, 2, 6, 1, 3, 9, 2, 4, 5, 8,
3, 5, 9, 5, 5, 2, 3],
[3, 4, 3, 2, 9, 7, 5, 4, 2, 8, 0, 7, 9, 8, 8, 3, 2, 6, 8, 2, 1, 5, 3, 1,
4, 5, 1, 0, 0, 8, 5],
[7, 1, 4, 7, 3, 5, 0, 8, 2, 9, 4, 1, 9, 7, 0, 3, 9, 7, 8, 5, 3, 9, 3, 6,
8, 5, 7, 0, 8, 0, 2],
[5, 5, 0, 9, 0, 8, 2, 6, 2, 6, 6, 8, 1, 0, 1, 6, 4, 0, 7, 2, 8, 6, 0, 3,
1, 8, 6, 8, 3, 5, 6],
[1, 5, 7, 3, 9, 8, 7, 6, 7, 0, 6, 7, 7, 4, 4, 0, 0, 8, 8, 5, 2, 0, 6, 3,
1, 7, 1, 7, 7, 8, 4],
[3, 1, 5, 9, 1, 5, 1, 3, 0, 3, 3, 4, 9, 5, 1, 7, 1, 4, 6, 9, 7, 8, 3, 2,
7, 5, 7, 8, 3, 8, 1],
[4, 1, 6, 3, 5, 0, 3, 1, 9, 1, 9, 5, 2, 8, 1, 3, 8, 9, 8, 8, 1, 6, 1, 8,
3, 1, 1, 8, 8, 3, 4],
[5, 0, 1, 4, 0, 3, 0, 5, 5, 8, 2, 3, 4, 1, 3, 2, 0, 3, 4, 1, 0, 1, 2, 9,
7, 4, 2, 5, 8, 8, 4],
[1, 8, 4, 1, 6, 1, 5, 1, 6, 3, 2, 6, 7, 5, 7, 7, 6, 4, 5, 8, 3, 6, 9, 9,
3, 4, 4, 5, 0, 4, 7],
[4, 8, 1, 0, 7, 1, 9, 5, 1, 4, 0, 4, 7, 6, 5, 3, 3, 3, 1, 4, 5, 4, 3, 9,
4, 1, 3, 2, 3, 8, 8]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment