Scripts should moved into their own files instead of embedding them directly inside of the HTML. For example, if you move your JavaScript into a file called fragmentViz.js
, then you can include it in an html page like this:
<script src="fragmentViz.js"></script>
In modern JavaScript, var
has been replaced with const
and let
. For example, instead of writing:
var someConstant = 5;
let someVariableIWillModify = 7;
We now write:
const someConstant = 5;
let someVariableIWillMody = 7;
Using const
and let
make it clear to the reader what references will change and which won't. Fundamentally, let
variables can be redefined and cosnt
variables cannot be. for example, this code is invalid:
const a = 5;
a = 6; // error!
... but this code is valid:
let a = 5;
a = 6;
Note that const
should be used whenever you are not going to reassign a variable. Just because you modify the value does not mean you are reassigning. For example, this is valid:
const myList = [];
myList.push(5); // modifying the *value* but not reassigning the *reference*
In JavaScript, if I have a variable called userName
and I want to make a string containing the phrase "Hello " + username
, I should use JavaScript string templating (called template literals:
const userName = "Ryan";
const greeting = `Hello ${userName}`;
Doing this avoids strange errors when you try to add a boolean/float and a string together.
For example, you have:
// Create SVG element
svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
This will append a new svg
element to the current body
, always at the end. This was fine for the prototype, but now, since we might not always want the svg
element added to the end of the body, we should create it in the HTML markup and then select it with D3. For example, in the body
tag:
<svg id="tupleValueGraph" width="500px" height="400px"></svg>
Then, to get it with D3:
svg = d3.select("#tupleValueGraph")
.attr(..);
For example, you have:
.attr("stroke-width", 2)
.attr("stroke", "blue");
Instead, it is better to give this particular type of element a class (which you are already doing via .attr("class", "dataline")
, but should probably do with the explicit .classed("dataline", true)
) and then use CSS to style the element. For example, after removing the two lines above, you could create a styles.css
with this:
.dataline {
stroke-width: 2px;
stroke: blue;
}
... and then include this style sheet in the HTML document by adding a link
element to the head
:
<link rel="stylesheet" type="text/css" href="styles.css">
This lets us re-use the dataline
class and styles across the whole application. It also helps centralize where all the style information is located.
The code you have in graphData.html
isn't very modular. We could make it a lot better by creating a JavaScript class:
class TupleValueGraph {
constructor(svgID) {
this.svgID = svgID;
this.svg = d3.select(`#${svgID}`);
}
loadAndDisplayJSON(jsonFileName) {
// code to load the json file and update the
// visualization, using this.svg
}
// other methods...
}
This will let you write much cleaner code when things get more complicated, and will make your D3 visualization much more modular, allowing us to use it in multiple places!
One extra note -- once you split things up into HTML / CSS / JS files, you might find that opening the HTML file with
file://
in your browser doesn't work anymore. If this is the case, you can start a simple webserver in the same folder as your files:... and then you should be able to access things via
http://localhost:8000/
.