In your home directory, make a folder called Development, if it doesn't exist. This is where we will keep all of the code for the class. Next, make sure that you are inside that folder, by checking the output of the following command:
pwdIf pwd shows that you are in a different directory, run cd ~/Development and check with pwd again.
Next, clone this repository by clicking the green button in the upper right corner, selecting SSH and copying the string that looks like git@github.com:code4policy/<REPO-NAME>.git (<REPO-NAME> will be the name of your repository). Then, in the terminal run the following:
git clone git@github.com:code4policy/<REPO-NAME>.git
Note that by default, git will clone the repository into a folder with name <REPO-NAME>. After the repo is cloned, open that directory (use cd).
D3.js charts won't work unless you're running a web server. This can be done locally with:
python3 -m http.server
Once you run this, you can open up the website by typing http://localhost:8000/ into the browser. You'll need to open up a new tab in the terminal to continue your work. Make sure to cd back into this project folder and then open up the project in sublime text with subl .
Now we're ready to start editing the code!
The problem with the code currently in this repository is that the HTML is ill-formed (there is no head and body). Also the CSS and the JavaScript is all in the same file as the HTML. Messy! I will demand that you always keep them separated for this class. Lets go ahead and do that.
Remember, a good HTML document has a head and body.
<!DOCTYPE html>
<html>
<head>
<title> Example Site </title>
</head>
<body>
</body>
</html>You can link a separate CSS file with the following code. Remember, linking CSS always happens in the <head> </head> of the document.
<link href="styles/style.css" rel="stylesheet" type="text/css">You can call a JavaScript file like with this code. In this case we're linking one peice of code (the D3 library itself) from a website, and another peice of code (our specific chart) form a local file. Javascript is customarily placed at the end of the <body> </body> of the document. It is usually the last line before you close the body tag.
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="scripts/chart.js"></script>Tasks:
-
Your task is to extract the parts of
example-chart.htmland move them into three separate files. Grab the styles and move them intostyles/style.css. Grab the javascript and move it intoscripts/chart.js. Finally, grab the valid HTML and move it intoindex.html. Now your directory structure should look something like this:. ├── data.tsv ├── example-chart.html ├── index.html ├── scripts │ └── chart.js └── styles └── style.css -
The next step is to link the CSS and Javascript to
index.html. Yourindex.htmlmight look something like this now:<!DOCTYPE html> <html> <head> <title> Example Site </title> <!--Link to StyleSheets in the head--> <link href="styles/style.css" rel="stylesheet" type="text/css"> </head> <body> <h1> Apple: The Profitable Fruit </h1> <p> If you bought apple stock a long time ago you're probably rich. That's because it went up really fast! See for yourself in the chart below. </p> <h2> Apple Stocks are Really Rising! </h2> <h3> ...more than any other fruit-based corporation. </h3> <!-- Run JavaScript scripts in the body --> <script src="//d3js.org/d3.v3.min.js"></script> <script src="scripts/chart.js"></script> </body> </html>
-
Commit and push to GitHub
Right now the chart works fine, however, that is because the chart is the only thing on the page. The CSS in these example D3 examples often assume the D3 is the only thing on the page. So if there were other things on the page, the CSS might also end up applying to those things as well! To avoid that, we must specify that the CSS only apply to the chart. Lets modify the CSS selectors to do just that.
If you look closely at index.html, you'll notice that there is no element in the HTML code for the chart. That's because the chart is being generated by the JavaScript file. After the HTML is initially loaded, the JavaScript code runs and creates an <svg></svg> element on the page containing the chart. (SVG stands for "Scalable Vector Graphic"). You can see that by right clicking on the chart and hitting "inspect" as shown below:
So lets suppose we wanted to add an id and a class attribute to that SVG tag. How would we do that without knowing JavaScript? Lets look at the code and try to deduce how.
You'll notice the SVG element in the image above contains a width and a height. We can first figure out how those came to be and then use the same mechanism to write additional attributes like class or id.
If you look inside the JavaScript file that generates the chart, and try to read it, you'll find the following:
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)Notice how that code is adding a width and a height attribute? We can add an id attribute in the same way.
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("class", "chart")
.attr("id", "apple-stock-chart")This change will change the SVG to include a class and an id
Finally, we can modify the CSS to only match this chart by adding a new id selector (#apple-stock-chart) to each style so that the style doesn't spill over and start to conflict with other charts. Your CSS may ultimately look like this:
body {
font: 10px sans-serif;
}
#apple-stock-chart .axis path,
#apple-stock-chart .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
#apple-stock-chart .x.axis path {
display: none;
}
#apple-stock-chart .line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
#apple-stock-chart .overlay {
fill: none;
pointer-events: all;
}
#apple-stock-chart .focus circle {
fill: none;
stroke: steelblue;
}Tasks:
-
Modify the HTML so that there is an empty div with the following attributes:
class=chartandid=apple-stock-chart.<div id='apple-stock-chart' class='chart'></div>
-
Modify the JavaScript so that it draws the chart on the div with id
apple-stock-chartrather than directly on thebody -
Modify the CSS so that it applies only to the div with id
apple-stock-chartand doesn't spill over to any other charts that may be on the page. -
Commit and push to GitHub
One important programming principle is to write code that is not redundant. This principle is known as writing DRY code ("Don't Repeat Yourself").
Suppose you wanted the same chart type on the page twice. Instead of copy/pasting all the code for a chart, writing DRY code would mean putting the contents of the JavaScript that draws the code into it's own function.
function drawLineChart(cssSelector){
// code to draw line chart goes here.
}This function above is named drawLineChart and takes one argument as input called cssSelector. It can then be called like this:
drawLineChart('#apple-stock-chart');In this case, I have just called the drawLineChart function with the CSS selector #apple-stock-chart. If I wanted to draw another chart into another part of the HTML, I would simply call the function again with a different selector as well, as shown below:
drawLineChart('#apple-stock-chart');
drawLineChart('#apple-stock-chart-2');Tasks:
-
Wrap the contents of
chart.jsin a function calleddrawLineChart. Then calldrawLineChartat the bottom of the page. -
Update
style.cssto use a class selector (.chart) instead of an id selector (#apple-stock-chart) -
Add a second
<div> toindex.htmlto insert a second apple stock chart:<div id='apple-stock-chart-2' class='chart'></div>
and update
chart.jsto call thedrawLineChartfunction twice as shown below:drawLineChart('#apple-stock-chart'); drawLineChart('#apple-stock-chart-2');
Update the styles so that only the second chart appears with a green line, while the first chart remains steelblue in color.

