Reputation: 11
I´ve seen this nice d3 Dashboard. I was wondering if it is possible to switch the csv-file to another file by clicking on a button.
Is that even possible?
This is the link to the dashboard:
http://bl.ocks.org/farazshuja/4a582fdeaa1f46f885ffa1776346fdec
The part where the csv file is parsed, needs to be changed to "data2.csv" by clicking on a button.
<script>
var freqData;
d3.csv("data.csv", function(data) {
freqData = data.map(function(d) { return {
State: d.State,
freq: {
low: +d.low,
mid: +d.mid,
high: +d.high
}}
});
dashboard('#dashboard',freqData);
});
</script>
I want to switch the csv-files like in this example: http://bl.ocks.org/enjalot/1525346
<script>
var prices_csv = function()
{
var parse = d3.time.format("%m/%d/%Y").parse;
d3.csv("prices.csv", function(prices)
{
//prices is an array of json objects containing the data in from the csv
console.log("prices:", prices)
data = prices.map(function(d)
{
//each d is one line of the csv file represented as a json object
console.log("d", d)
month = parse(d.month).getMonth();
console.log("month:", d.month, month)
//we slice the dollar sign off then convert to a number with the + sign
//slicing works like "$216".slice(1) gives you 216,
//you can also give it a range like "$216 asdf".slice(1,4) gives you 216
p = d.price
price = +p.slice(1)
console.log("price:", p, price);
return {"month": month, "value":price} ;
})
console.log("data", data)
bars(data);
})
}
</script>
I tried to adapt it like in the example but without success so far. I am a pure beginner in javascript and d3.js and therefore I hope someone can help me out with it.
UPDATE:
The first part (changing data files (csv) by button) seems to be working great. However, there is another challenge. The structure is the as follows: There is a div that contains various dashboards. The dashboards are loaded with "object" as external files. By using a tree-menu with two buttons "2018" and "2019" I would like, depending on the year chosen, that data1 "d1" or data2 "d2" is displayed in the dashboards.
This is the first menu button for 2018 that loads the div "sales1". "sales1" loads various external html files via object. There, only the "d1" (data for 2018 from the dashboard file) shall be loaded:
<li><a href="#" type="#sales1" id="buttonsales1">units FTP</a></li>
<script>
$(document).ready(function(){
$("#buttonsales1").click(function(){
$("#sales1").toggle();
$("#startscreen").hide();
$("#sales2").hide();
});
});
</script>
Below the first menu button for 2018, there should be a second menu button for 2019. When clicked, it loads the same div "sales1" but this time the external dashboard files show data2 "d2" (data for 2019).
This is the div "sales1" which loads the dashboards via object:
<div id="sales1">
<div id="left">
<div class="label" data-toggle="toggle" data-target="#sales1desbox2">
<h2>units sold sales region center</h2>
<p>by months and sales rep.</p>
</div>
<!-- START: Label description. -->
<div id="sales1desbox2" class="togglebox">
<div class="description">
by month and sales region.
</div>
</div>
<!-- END: Label description. -->
<!-- This is the first dashboard -->
<object class="ltrl" type="text/html" data="sales/1/dashboard_center_sales.html">
</object>
</div>
<div id="right">
<div class="label" data-toggle="toggle" data-target="#sales1desbox3">
<h2>units sold sales region east</h2>
<p>by months and sales rep.</p>
</div>
<!-- START: Label description. -->
<div id="sales1desbox3" class="togglebox">
<div class="description">
by month and sales region.
</div>
</div>
<!-- END: Label description. -->
<!-- This is the second dashboard -->
<object class="ltrl" type="text/html" data="sales/1/dashboard_east_sales.html">
</object>
</div>
</div>
<!-- END: div "sales1" -->
The adapted dashboard looks like this now:
<style>
....
....
....
</style>
<body>
<!-- here are the buttons to control the two csv data sets. -->
<button id="d1">Data 1</button><button id="d2">Data 2</button><br />
<div id='dashboard'>
</div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// here are the event listeners to control the buttons
d3.select("#d1").on("click", function(d, i) {
data1();
});
d3.select("#d2").on("click", function(d, i) {
data2();
});
function dashboard(id, fData) {
var barColor = "steelblue";
.... rest is the same until the part where the data is parsed from the two different csv:
<!-- Here the data data1 (d1) for 2018 -->
<script>
var freqData;
function data1() {
clearDashboard();
d3.csv("data.csv", function(data) {
filteredData = data.filter(function(row) {
return row['KPI'] == 'A';
});
freqData = filteredData.map(function(d) {
return {
Month: d.Month,
freq: {
S40411: +d.S40411,
S40412: +d.S40412,
S40413: +d.S40413,
S40414: +d.S40414
}
};
});
dashboard('#dashboard',freqData);
});
}
// calls the data1 onload
data1();
//clears the dashboard used in data1 and data2
function clearDashboard() {
var myNode = document.getElementById("dashboard");
while (myNode.firstChild) {
myNode.removeChild(myNode.firstChild);
}
}
<!-- Here the data data2 (d2) for 2019 -->
function data2() {
clearDashboard();
d3.csv("data2.csv", function(data) {
filteredData = data.filter(function(row) {
return row['KPI'] == 'A';
});
freqData = filteredData.map(function(d) {
return {
Month: d.Month,
freq: {
S40411: +d.S40411,
S40412: +d.S40412,
S40413: +d.S40413,
S40414: +d.S40414
}
};
});
dashboard('#dashboard',freqData);
});
}
</script>
</body>
To make it more visual, I´ve created a small grafic
UPDATE 2:
There is a menu with buttons for 2018 and for 2019. It looks something like this:
2018 Units FTP 2019 Units FTP
Both have the same data structure but different data. Therefore there are now two different functions within the external dashboard file: function data1() and function data2(), each referring to different csv files (2018, 2019).
The first button “2018, Units FTP” calls the div “sales1”:
<li><a href="#" type="#sales1" id="buttonsales1">units FTP</a></li>
The second button does the same but for 2019. So where is the difference?
Div “sales1” contains various dashboards that are embedded with object tag:
<div id="sales1">
<object class="ltrl" type="text/html" data="sales/0/dashboard_east_sales.html"></object>
…
…
…
</div>
I want that the second button calls the same div “sales1” with the same dashboards but instead of choosing by default “function data1()” it should call “function data2()” within the dashboard (dashboard_east_sales.html).
UPDATE 3:
I made a Codepen to show exactly what I am trying to achieve:
This is the index.html where the dahboard is embedded via object tag: https://codepen.io/robx360/pen/wbpoQM
And this is the dashboard file itself: https://codepen.io/robx360/pen/pmpNWN
As you can see, the buttons from the index file should trigger the changes of the datasets. As of now the buttons are located within the dashboard file. thats what I want to change.
UPDATE 4:
<!–– those buttons shall have the functionality of the buttons within the dashboard file that is embedded with object tag ––>
<li><a href="#" type="#sales1" id="buttonsales1">units FTP 2018</a></li>
<li><a href="#" type="#sales1" id="buttonsales1">units FTP 2019</a></li>
<!-- This part is currently located in the external Dashboard file (dashboard.html) -->
<!-- here are the buttons to control the two csv data sets -->
<button id="d1">Data 1 (should be units FTP 2018)</button>
<button id="d2">Data 2 (should be units FTP 2019)</button>
<!–– The event listeners must point to the object tag ID "dashboard1", how? ––>
<script>
// here are the event listeners to control the buttons
d3.select("#d1").on("click", function(d, i) {
data1();
});
d3.select("#d2").on("click", function(d, i) {
data2();
});
</script>
<div id="sales1">
<div id="right">
<object id="dashboard1" style="width:900px; height:600px; type="text/html" data="dashboard.html">
</object>
</div>
</div>
Upvotes: 0
Views: 576
Reputation: 71
Sure it is possible :) You can add two buttons like in the second example to the code from the first example. I'm assuming the csv files are similar and the graphs are the same just the data will be different. You can add more logic if you are looking to have different charts. I've worked out an example to get you started.
...styles
<body>
<!-- here are the buttons to control the two csv data sets -->
<button id="d1">Data 1</button><button id="d2">Data 2</button><br />
<div id="dashboard"></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// here are the event listeners to control the buttons
d3.select("#d1").on("click", function(d, i) {
data1();
});
d3.select("#d2").on("click", function(d, i) {
data2();
});
function dashboard(id, fData) {
var barColor = "steelblue";
....continue with all of the code from the first example....
Replace the ending script with these two functions to control the loading of the two csv files, as well as the function to clear the nodes created from the previous csv.
<script>
var freqData;
function data1() {
clearDashboard();
d3.csv("data.csv", function(data) {
freqData = data.map(function(d) {
return {
State: d.State,
freq: {
low: +d.low,
mid: +d.mid,
high: +d.high
}
};
});
dashboard("#dashboard", freqData);
});
}
// calls the data1 onload
data1();
//clears the dashboard used in data1 and data2
function clearDashboard() {
var myNode = document.getElementById("dashboard");
while (myNode.firstChild) {
myNode.removeChild(myNode.firstChild);
}
}
function data2() {
clearDashboard();
d3.csv("./data2.csv", function(data) {
freqData = data.map(function(d) {
return {
State: d.State,
freq: {
low: +d.low,
mid: +d.mid,
high: +d.high
}
};
});
dashboard("#dashboard", freqData);
});
}
</script>
</body>
EDIT:
To have two dashboard you rename dashboard to dashboard1 and add another named dashboard2
<div id="dashboard1"></div>
<div id="dashboard2"></div>
And then in your data1 and data2 functions you target those divs
...
dashboard("#dashboard1", freqData);
...
dashboard("#dashboard2", freqData);
Edit the clearDashboard function to accept a parameter that will determine what div to clear out
function clearDashboard(dashboard) {
var myNode = document.getElementById(dashboard);
while (myNode.firstChild) {
myNode.removeChild(myNode.firstChild);
}
}
And set the argument of that function to the div to clear out
...
clearDashboard("dashboard1");
...
clearDashboard("dashboard2");
Upvotes: 3