FateJudgement FateJudgement - 4 months ago 14
HTML Question

How to write data in JSON or CSV?

I am currently making a table which shows data in a bar graph and used data arrays until this point as a means for the bars. I have reached a point where I would like to externalise this data (which I already know how to) however I have no clue at all how I would go about converting these data arrays into external .JSON or even CSV format.

Here is my code currently:



<!DOCTYPE html>
<html>
<head>
<meta>
<meta name="description" content="Bar Graph Showing the Amount of Resources Being Used per Project " />
<meta charset="utf-8">
<title>Resources per Program</title>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>

<style type="text/css">
h1 {
font-size: 35px;
color: darkblue;
font-family: Helvetica;
border-bottom-width: 3px;
border-bottom-style: dashed;
border-bottom-color: black;
}

h2 {
font-size: 20px;
color: darkred;
font-family: Helvetica;
margin-left: 900px;
margin-top: -40px;
margin-bottom: 70px
}

h3 {
font-size: 13px;
color: red;
font-weight: bold;
}

.label {
font-size: 20px;
color: darkgrey;
font-family: sans-serif;
border-bottom-width: 3px;
border-bottom-style: dashed;
border-bottom-color: black;
}

html {
background: linear-gradient(white, #a6a6a6);
}

.legend {
font-family: sans-serif;
font-size: 17px;
font-weight: normal;

}

#myTooltip {
position: absolute;
text-align: left;
width: 150px;
height: auto;
min-height: 20px;
padding: 2px;
font: 12px sans-serif;
background-color: rgb(102, 178, 255);
border: 2px solid rgb(0, 0, 204);
color: #5E99BD;
border-radius: 8px 8px 8px 8px;
pointer-events: none;
padding: 11px;
}

#myTooltip:before {
box-sizing: border-box;
display: inline;
font-size: 18px;
width: 100%;
line-height: 1;
color: rgb(0, 0, 204);
content: "\25BC";
position: absolute;
text-align: center;
top: 100%;
left: -2px;
}
</style>
</head>

<body>
<h1>Resources used per Program</h1>

<p>Choose Month:
<select id="label-option">
<option value="April">April</option>
<option value="May">May</option>
<option value="June">June</option>
<option value="July">July</option>
<option value="August">August</option>
<option value="September">September</option>
</select>
</p>
<h3>*Hold down the Selector and Drag onto Desired Option* (Touch Screen Users)</h3>

<script type="text/javascript">
var width = 1700
var height = 500
var emptyVar = 0
var dataArrayProjects = ['2G', 'AB', 'BC', 'CD', 'DE', 'EF', 'FG', 'GH']
var April = [2.5, 2.1, 1.3, 15.2, 1, 4, 1, 4]
var May = [2.5, 2.1, 1, 14.8, 1, 4, 2, 6]
var June = [2.5, 2.1, 1, 14.8, 1, 4, 2, 6]
var July = [2.5, 3.4, 2, 14.8, 1, 3.5, 2.5, 6]
var August = [2.5, 3.4, 2.5, 14.8, 1.2, 3.5, 2.15, 6]
var September = [2.5, 3, 2, 13.5, 1, 3.5, 2.5, 6]

var clicked = true;

d3.select("#label-option").on("change", change)

function change() {
var data = April;
if (this.selectedIndex == 1){
data = May;
} else if (this.selectedIndex == 2){
data = June;
} else if (this.selectedIndex == 3){
data = July;
} else if (this.selectedIndex == 4){
data = August;
} else if (this.selectedIndex == 5){
data = September;
}
canvas.selectAll("rect")
.data(data)
.on("mouseover", onMouseOver)
.on("mouseout", onMouseOut)
.attr("width", emptyVar)
.attr("height", 50)
.attr("fill", function(d, i) {
return color[i%8]
})
.attr("y", function(d, i) {
return i * 55
})

bars.transition()
.duration(1500)
.delay(200)
.attr("width", function(d) {
return widthScale(d);
});

texts = canvas.selectAll(".label")
.data(data)
.attr("x", function(d) {
return widthScale(d) + 10;
})
.attr("fill", function(d, i) {
return color[i%8]
})
.attr("y", function(d, i) {
return (i * 55) + 25
})
.style("opacity", 0)
.text(function(d, i) {
return d;
})

texts.transition()
.duration(1800)
.delay(180)
.style("opacity", 1)
}

var widthScale = d3.scale.linear()
.domain([0, 16])
.range([0, width - 60]);

var heightScale = d3.scale.ordinal()
.domain(dataArrayProjects)
.rangePoints([10, height - 85]);

var color = ["#1F45FC", "#87AFC7", "#87AFC7", "#151B54", "#1F45FC", "#151B54", "#1F45FC", "#151B54"]

var xAxis = d3.svg.axis()
.ticks("20")
.scale(widthScale);

var yAxis = d3.svg.axis()
.scale(heightScale)
.orient("left");

var canvas = d3.select("body")
.append("svg")
.attr("width", width + 250)
.attr("height", height)
.append("g")
.attr("transform", "translate(130, 0)");

var bars = canvas.selectAll("rect")
.data(April)
.enter()
.append("rect")
.on("mouseover", onMouseOver)
.on("mouseout", onMouseOut)
.attr("width", emptyVar)
.attr("height", 50)
.attr("fill", function(d, i) {
return color[i%8]
})
.attr("y", function(d, i) {
return i * 55
})

var texts = canvas.selectAll(".label")
.data(April)
.enter()
.append("text")
.attr("class", "label")
.attr("x", function(d) {
return widthScale(d) + 10;
})
.attr("fill", function(d, i) {
return color[i%8]
})
.attr("y", function(d, i) {
return (i * 55) + 25
})
.text(function(d, i) {
return d;
})
.style("opacity", 0)

canvas.append("g")
.attr("transform", "translate(0, 430)")
.attr("font-family", "Helvetica")
.attr("font-size", "15px")
.call(xAxis);

canvas.append("g")
.attr("font-family", "Helvetica")
.attr("font-size", "15px")
.style("fill", "black")
.attr("class", "y axis")
.call(yAxis);

bars.transition()
.duration(1500)
.delay(200)
.attr("width", function(d) {
return widthScale(d);
})

texts.transition()
.duration(1800)
.delay(180)
.style("opacity", 1)

var yAxisLine = canvas.append("line")
.attr("x1", -3)
.attr("y1", 0)
.attr("x2", -3)
.attr("y2", 436)
.attr("stroke-width", 6)
.attr("stroke", "black");

var legend = canvas.append("g")
.attr("class", "legend")
.attr("width", 450)
.attr("height", 300)
.attr("x", 1000)
.attr("y", 0)

legend.append("text")
.text("All Projects")
.attr("fill", "black")
.attr("stroke-width", 1)
.attr("x", 1300)
.attr("y", 20)
legend.append("text")
.text("All Core Capabilities")
.attr("fill", "black")
.attr("stroke-width", 1)
.attr("x", 1300)
.attr("y", 50)
legend.append("text")
.text("Projects and Core Capabilities")
.attr("fill", "black")
.attr("stroke-width", 1)
.attr("x", 1300)
.attr("y", 80)
legend.append("text")
.text("Click Circles to Highlight Corresponding Bar")
.attr("fill", "darkred")
.attr("font-size", 8.5)
.attr("stroke-width", 1)
.attr("x", 1323)
.attr("y", 110)

legend.append("circle")
.attr("r", 8)
.attr("fill", "#1F45FC")
.attr("cx", 1275)
.attr("cy", 14.5)
.on("click", function(){
var rects = d3.selectAll("rect").filter(function(){
return this.attributes.fill.nodeValue == "#1F45FC";
});
(clicked) ? rects.attr("stroke", "limegreen").attr("stroke-width", 3) : rects.attr("stroke-width", 0);
clicked = !clicked;
});

legend.append("circle")
.attr("r", 8)
.attr("fill", "#87AFC7")
.attr("cx", 1275)
.attr("cy", 44.5)
.on("click", function(){
var rects = d3.selectAll("rect").filter(function(){
return this.attributes.fill.nodeValue == "#87AFC7";
});
(clicked) ? rects.attr("stroke", "limegreen").attr("stroke-width", 3) : rects.attr("stroke-width", 0);
clicked = !clicked;
});

legend.append("circle")
.attr("r", 8)
.attr("fill", "#151B54")
.attr("cx", 1275)
.attr("cy", 74.5)
.on("click", function(){
var rects = d3.selectAll("rect").filter(function(){
return this.attributes.fill.nodeValue == "#151B54";
});
(clicked) ? rects.attr("stroke", "limegreen").attr("stroke-width", 3) : rects.attr("stroke-width", 0);
clicked = !clicked;
});

var tooplTipDiv = d3.select("body").append("div")
.attr("id", "myTooltip")
.style("opacity", 0);

function onMouseOver(d){

var tooltipDiv = d3.select("#myTooltip");

tooltipDiv.transition()
.duration(200)
.style("opacity", 1);

tooltipDiv.html( "Click for Resource Allocation over 6 Months")
.style("left", (parseFloat(widthScale(d))) + "px")
.style("cursor", "pointer")
.style("top", function(d){
return d3.event.pageY - this.offsetHeight - 17 + "px"
})
.style("color", "#333333");
}

function onMouseOut(d){
var tooltipDiv = d3.select("#myTooltip");
tooltipDiv.transition()
.duration(500)
.style("opacity", 0);
}

</script>
<h2>Resources</h2>
</body>
</html>





Please ignore the tooltips as they are being worked on currently. What I would like to know is how I can extract the data arrays used in the code (e.g. April-September and dataArrayProjects), convert them to .JSON or CSV and still make sure the graph works the way I would like it to. Please make sure that the selector still works as the changing data based on month is a core part of the table.

Answer

Start simple by creating an object that contains some of the main parts of the data

var data = {
  projects: ['2G', 'AB', 'BC', 'CD', 'DE', 'EF', 'FG', 'GH'],
  months: {
    April: [2.5, 2.1, 1.3, 15.2, 1, 4, 1, 4],
    May : [2.5, 2.1, 1, 14.8, 1, 4, 2, 6],
    //......
    September : [2.5, 3, 2, 13.5, 1, 3.5, 2.5, 6]
  }

}

Now instead of using variable April use data.months.April and for dataArrayProjects use data.projects

As you get various parts working add more of the other hard code variables to the object.

When you have that working start looking at ways to loop over data.months to do what you need in chart without code duplication and using dynamic properties and values.

Then finally convert it all to json which is a simple step

The months might be easier as an array also. You will know better as you fine tune the data structure and loops in your code.

months: [ 
     {month:'April', data: [2.5, 2.1, 1.3, 15.2, 1, 4, 1, 4]},
     {month: 'September', data: [2.5, 3, 2, 13.5, 1, 3.5, 2.5, 6]}
]
Comments