From 61ce3cfb679164bf601a1197ffb033c0579c20b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Tue, 28 Jul 2015 21:38:57 +0200 Subject: [PATCH 01/15] missing closing parenthesis and semicolon --- 07-d3setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/07-d3setup.md b/07-d3setup.md index 085d3f6..9de40c4 100644 --- a/07-d3setup.md +++ b/07-d3setup.md @@ -56,7 +56,7 @@ The first thing we need, is of course our data, which is stored in 'nations.json D3 provides a handy function to read in `json`-files: ~~~{.d3} -d3.json("resources/nations.json", function(nations) { } +d3.json("resources/nations.json", function(nations) { }); ~~~ This line probably needs a little explanation and we'll go through it bit by bit: From bb37a89757b4207c845c9853b84f57ad75025c7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Tue, 28 Jul 2015 21:39:09 +0200 Subject: [PATCH 02/15] fix typos --- 07-d3setup.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/07-d3setup.md b/07-d3setup.md index 9de40c4..614efdb 100644 --- a/07-d3setup.md +++ b/07-d3setup.md @@ -90,7 +90,7 @@ fill now. We'll have a picture frame (an SVG-element), our drawing area (a g-element), and in that drawing area, we'll have separate elements for both axes and the area for our circles. -Firt, we need to link the JavaScript and HTML environement so that we have writing access +Firt, we need to link the JavaScript and HTML environment so that we have writing access to the HTML. To do this, we use the `.select()`. This lets us grab an element by specifying its ID. @@ -111,7 +111,7 @@ This is equivalent to writing:

~~~ -in the HTML file. We chose to append because we now have access to the SVG element without the need to seperately select it by ID. +in the HTML file. We chose to append because we now have access to the SVG element without the need to separately select it by ID. We also create the canvas inside the frame: From 6d190fdcdfcbf96c667b5e00718c4d72b533c4b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Tue, 28 Jul 2015 22:24:24 +0200 Subject: [PATCH 03/15] keep the new challenge in its box --- 07-d3setup.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/07-d3setup.md b/07-d3setup.md index 614efdb..137380c 100644 --- a/07-d3setup.md +++ b/07-d3setup.md @@ -149,10 +149,10 @@ canvas.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); > # Time for a challenge I think! {.challenge} > Let us consolidate our understanding of SVGs and D3 selectors. - +> > 1. Add a circle element to the HTML using the SVG markup we learnt in lesson 3. > 2. Use `d3.select` to get a reference to the circle. > 3. Once the circle reference is obtained, make the radius 40px, the border black and the colour green. - +> > HINT: use the `attr` and `style` methods on the circle object obtained. From 77e8bac8a46d10fdc843c1f8e4c301ccaaa20ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Tue, 28 Jul 2015 22:29:17 +0200 Subject: [PATCH 04/15] fix typo --- 07-d3setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/07-d3setup.md b/07-d3setup.md index 137380c..be50f02 100644 --- a/07-d3setup.md +++ b/07-d3setup.md @@ -90,7 +90,7 @@ fill now. We'll have a picture frame (an SVG-element), our drawing area (a g-element), and in that drawing area, we'll have separate elements for both axes and the area for our circles. -Firt, we need to link the JavaScript and HTML environment so that we have writing access +First, we need to link the JavaScript and HTML environment so that we have writing access to the HTML. To do this, we use the `.select()`. This lets us grab an element by specifying its ID. From de0fa3866d2fde3d98779b232ae178ff82d7dabf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Tue, 28 Jul 2015 22:53:07 +0200 Subject: [PATCH 05/15] make it clear(er) in the challenge that we want a new --- 07-d3setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/07-d3setup.md b/07-d3setup.md index be50f02..8b584b9 100644 --- a/07-d3setup.md +++ b/07-d3setup.md @@ -150,7 +150,7 @@ canvas.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); > # Time for a challenge I think! {.challenge} > Let us consolidate our understanding of SVGs and D3 selectors. > -> 1. Add a circle element to the HTML using the SVG markup we learnt in lesson 3. +> 1. Create a new SVG element and a circle element using the SVG markup we learnt in lesson 3. > 2. Use `d3.select` to get a reference to the circle. > 3. Once the circle reference is obtained, make the radius 40px, the border black and the colour green. > From 5b894d005c34f0086a71bb75f410d9aa2929f965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Tue, 28 Jul 2015 22:54:12 +0200 Subject: [PATCH 06/15] making the canvas actually show up, using a border ... so we see when it's size changes ... and we show iterative conception --- 07-d3setup.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/07-d3setup.md b/07-d3setup.md index 8b584b9..89cd080 100644 --- a/07-d3setup.md +++ b/07-d3setup.md @@ -113,7 +113,18 @@ This is equivalent to writing: in the HTML file. We chose to append because we now have access to the SVG element without the need to separately select it by ID. -We also create the canvas inside the frame: +We can open our HTML file in a browser and see that only the heading is actually visible on the page. +It is normal as our drawing is currently empty. +To materialize our empty drawing and be sure it is here, let's add a thick red border around it, by adding the following in the `main.css` file: + +~~~{.css} +svg { + border: 5px solid red; +} +~~~ + +Refreshing the page should make it clear that our empty drawing actually exists. +Now, we also create the canvas inside the frame: ~~~{.js} // Create canvas inside frame. @@ -139,6 +150,8 @@ frame.attr("width", frame_width); frame.attr("height", frame_height); ~~~ +Refreshing the page will show us the new size for the SVG drawing. + The canvas element will have to fit nicely into the frame. To make it fit, we set a transform attribute and use the translate function. From b8cd351820663030e6e267ea1bb6eed8f54a7468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Wed, 29 Jul 2015 08:54:45 +0200 Subject: [PATCH 07/15] adding a second challenge to help playing with the transform:translate() and to understand the direction of the reference frame --- 07-d3setup.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/07-d3setup.md b/07-d3setup.md index 89cd080..13e2316 100644 --- a/07-d3setup.md +++ b/07-d3setup.md @@ -169,3 +169,12 @@ canvas.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); > > HINT: use the `attr` and `style` methods on the circle object obtained. +> # Understanding the "transform". {.challenge} +> +> +> 1. Use Javascript code to Create a new circle inside our "canvas", positioned in 0, 0, with a radius of 5px. +> 2. Check that the circle now shows up. +> 3. Play with the values that are put for the "translate" transform in order to understand what is the reference frame used. +> +> HINT: refresh your page in your browser every time you do a modification. + From 60c5bba90ad9fe07539a674dc99c1971bacb241b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Wed, 29 Jul 2015 08:55:00 +0200 Subject: [PATCH 08/15] increased margin so the text don't get cut at the bottom --- 07-d3setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/07-d3setup.md b/07-d3setup.md index 13e2316..0ca22b4 100644 --- a/07-d3setup.md +++ b/07-d3setup.md @@ -135,7 +135,7 @@ Let's set up the dimensions for our elements that we want to use: ~~~{.js} // Set margins, width, and height. -var margin = {top: 19.5, right: 19.5, bottom: 19.5, left: 39.5}; +var margin = {top: 21.5, right: 21.5, bottom: 21.5, left: 39.5}; var frame_width = 960; var frame_height = 350; var canvas_width = frame_width - margin.left - margin.right; From 21f2316f90a12a89edee0aa487ee6ec823d5d9cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Wed, 29 Jul 2015 09:01:25 +0200 Subject: [PATCH 09/15] referencing code/nations.json as the other one (resources/nations.json) is un-pre-processed --- 07-d3setup.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/07-d3setup.md b/07-d3setup.md index 0ca22b4..c819b30 100644 --- a/07-d3setup.md +++ b/07-d3setup.md @@ -56,13 +56,13 @@ The first thing we need, is of course our data, which is stored in 'nations.json D3 provides a handy function to read in `json`-files: ~~~{.d3} -d3.json("resources/nations.json", function(nations) { }); +d3.json("code/nations.json", function(nations) { }); ~~~ This line probably needs a little explanation and we'll go through it bit by bit: * `d3.json()` is called the function call. In this case, we have a function that reads in a json file, parses it, and is also able to do something with the parsed data on the way. -* The first argument `"resources/nations.json"` tells the function where to get the data we want to have parsed. +* The first argument `code/nations.json"` tells the function where to get the data we want to have parsed. * `function(...){...}` is called the callback function. It is a so-called 'inline' function, which means it has no name (we're only operating in the object space here). This also means we can't use this function anywhere else in our code. The code we put inside the curly brackets is the code that's run once d3.json() is called and the data is loaded. * D3 assigns the name `nations` to the parsed object it returns. We can only use 'nations' within the callback function, this means our code only knows of `nations` inside the curly brackets. * What seems unusual, but is actually quite common, is that this function call doesn't return anything. It is simply executed and displayed (if we tell it to), but no value is returned. From 276cf001b6861353dbc3d998b8aa043437ea5105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Wed, 29 Jul 2015 09:50:47 +0200 Subject: [PATCH 10/15] pushing the `update` function to the beginning as it will allow for easier intermediate testing --- 09-d3exit.md | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/09-d3exit.md b/09-d3exit.md index 514b336..92f555c 100644 --- a/09-d3exit.md +++ b/09-d3exit.md @@ -15,6 +15,27 @@ Our plot is pretty busy. We might not want to display everything all the time. The goal for this lesson is to update the plot based on what kind of data we want to display. +First, we will reorganize our Javascript program. +It currently mixes two concerns: + +- one-time initialization: setting up the SVG element and its sub elements, positioning and sizing them, etc; +- data manipulation (everything related to the `dot` variable), that we actually might want to execute again when data changes. + +To be able to execute the data-manipulation code multiple times, we will isolate it in a new function that we decide to name `update`, and call this function (so that the code is actually executed). + +~~~{.js} +// define the function with the data-manipulation code +function update() { + var dot = data_canvas.selectAll(".dot").data(nations, function(d){return d.name}); + + dot.enter().append("circle")......... +} + +// call the function once +update(); +~~~ + +Now we can resume our original task: plotting only a sub-part of the data. First, we need to find a way to filter our data. We use the function `filter` to do this. Similar to previous functions (e.g. `map`), this function iterates over each of the elements in the array `nations`, temporarily calling it `nation`. It only includes elements in the new array `filtered_nations` if the function evaluates to 'true' for that element. Here this will be the case for nations whose population in 2009 was larger than 10,000,000. @@ -69,7 +90,7 @@ if (this.checked) { // adding data points This `if`-statement gets executed every time a checkbox is checked. To add the data points, we can use the `push`-function, which adds one object to an array at a time. First, we filter the nations we want to add, calling them `new_nations`. Next, we are looping through all new nations and add one at a time to the array `filtered_nations`. -We also have to initialise `filtered_nations` at the top of our script. Remember that there is a difference between the object and the name space, so in order to keep `nations` the way it is, we need to map the values instead of just using `=`. +We also have to initialise `filtered_nations` at the top of our script, or at least before our `update` function. Remember that there is a difference between the object and the name space, so in order to keep `nations` the way it is, we need to map the values instead of just using `=`. ~~~{.js} var filtered_nations = nations.map(function(nation) { return nation; }); @@ -93,23 +114,8 @@ A good, brief explanation of this linking between data and elements on the page > # Another new dimension {.challenge} > 1. Have the colour of circles represent the region. Use category20() to make a scale. You will then need to add `.style("fill", function(d) { <-- fill in this bit ---> });` to the enter() function. -As a last step, let's move `enter()` and `exit()` into a separate function. This will become useful when we want to update the data from different elements on the page. - -~~~{.js} -function update() { - var dot = data_canvas.selectAll(".dot").data(filtered_nations, function(d){return d.name}); - - dot.enter().append("circle").attr("class","dot") - .style("fill", function(d) { return colorScale(d.region); }); - .attr("cx", function(d) { return xScale(d.income[d.income.length-1]); }) // this is how attr knows to work with the data - .attr("cy", function(d) { return yScale(d.lifeExpectancy[d.lifeExpectancy.length-1]); }) - .attr("r", function(d) { return rScale(d.population[d.population.length-1]); }); - - dot.exit().remove(); -} -~~~ - -This means that we now have to call the update function from our event listener after updating `filtered_nations` based on the checkbox change: +As we have isolated the data-processing code in the `update` function, we can now refresh the data every time the checkbox is clicked. +This means that we now have to call the `update` function from our event listener after updating `filtered_nations` based on the checkbox change: ~~~{.js} d3.selectAll(".region_cb").on("change", function() { @@ -124,8 +130,6 @@ d3.selectAll(".region_cb").on("change", function() { }); ~~~ -In order to create the plot when we first load the page, we will also have to call `update()` outside of our event listeners once. - By the end of this lesson, your page should look something like this: From 6251b3bf22caef49a946163af21cf56e15552862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Wed, 29 Jul 2015 09:53:26 +0200 Subject: [PATCH 11/15] use "refreshData" instead of "update" as a function name to avoid confusion with enter/update/exit --- 09-d3exit.md | 14 +++++++------- 10-d3update.md | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/09-d3exit.md b/09-d3exit.md index 92f555c..aff4f20 100644 --- a/09-d3exit.md +++ b/09-d3exit.md @@ -21,18 +21,18 @@ It currently mixes two concerns: - one-time initialization: setting up the SVG element and its sub elements, positioning and sizing them, etc; - data manipulation (everything related to the `dot` variable), that we actually might want to execute again when data changes. -To be able to execute the data-manipulation code multiple times, we will isolate it in a new function that we decide to name `update`, and call this function (so that the code is actually executed). +To be able to execute the data-manipulation code multiple times, we will isolate it in a new function that we decide to name `refreshData`, and call this function (so that the code is actually executed). ~~~{.js} // define the function with the data-manipulation code -function update() { +function refreshData() { var dot = data_canvas.selectAll(".dot").data(nations, function(d){return d.name}); dot.enter().append("circle")......... } // call the function once -update(); +refreshData(); ~~~ Now we can resume our original task: plotting only a sub-part of the data. @@ -90,7 +90,7 @@ if (this.checked) { // adding data points This `if`-statement gets executed every time a checkbox is checked. To add the data points, we can use the `push`-function, which adds one object to an array at a time. First, we filter the nations we want to add, calling them `new_nations`. Next, we are looping through all new nations and add one at a time to the array `filtered_nations`. -We also have to initialise `filtered_nations` at the top of our script, or at least before our `update` function. Remember that there is a difference between the object and the name space, so in order to keep `nations` the way it is, we need to map the values instead of just using `=`. +We also have to initialise `filtered_nations` at the top of our script, or at least before our `refreshData` function. Remember that there is a difference between the object and the name space, so in order to keep `nations` the way it is, we need to map the values instead of just using `=`. ~~~{.js} var filtered_nations = nations.map(function(nation) { return nation; }); @@ -114,8 +114,8 @@ A good, brief explanation of this linking between data and elements on the page > # Another new dimension {.challenge} > 1. Have the colour of circles represent the region. Use category20() to make a scale. You will then need to add `.style("fill", function(d) { <-- fill in this bit ---> });` to the enter() function. -As we have isolated the data-processing code in the `update` function, we can now refresh the data every time the checkbox is clicked. -This means that we now have to call the `update` function from our event listener after updating `filtered_nations` based on the checkbox change: +As we have isolated the data-processing code in the `refreshData` function, we can now refresh the data every time the checkbox is clicked. +This means that we now have to call the `refreshData` function from our event listener after updating `filtered_nations` based on the checkbox change: ~~~{.js} d3.selectAll(".region_cb").on("change", function() { @@ -126,7 +126,7 @@ d3.selectAll(".region_cb").on("change", function() { } else { // remove data points from the data that match the filter filtered_nations = filtered_nations.filter(function(nation){ return nation.region != type;}); } - update(); + refreshData(); }); ~~~ diff --git a/10-d3update.md b/10-d3update.md index 207dccb..2ded97e 100644 --- a/10-d3update.md +++ b/10-d3update.md @@ -28,16 +28,16 @@ To get the index (rather than the actual year), we can simply subtract the first var year_idx = parseInt(document.getElementById("year_slider").value)-1950; ~~~ -Updating the year becomes quite simple. All we need to do is add another event listener that changes the year the moment we touch the slider. The event we want to listen for is called `input`. We then execute the `update()` function we wrote earlier. +Updating the year becomes quite simple. All we need to do is add another event listener that changes the year the moment we touch the slider. The event we want to listen for is called `input`. We then execute the `refreshData()` function we wrote earlier. ~~~{.js} d3.select("#year_slider").on("input", function () { year_idx = parseInt(this.value) - 1950; - update(); + refreshData(); }); ~~~ -So far, the update function only knows how to handle new data (`.enter`) and removed data (`.exit`), but not what to do when we update data. +So far, the `refreshData` function only knows how to handle new data (`.enter`) and removed data (`.exit`), but not what to do when we update data. In addition to `d3.enter()` and `d3.exit()`, D3 also offers `d3.transition` to handle updating data. First, we need to define how to transition between data points. We might want to interpolate between to values linearly over the duration of 200 ms, like this: ~~~{.js} From e5a7514a89088777e61ac75c439a166b009438a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Wed, 29 Jul 2015 10:05:06 +0200 Subject: [PATCH 12/15] update text about the use of "concat" (vs "push" in previous versions) --- 09-d3exit.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/09-d3exit.md b/09-d3exit.md index aff4f20..0bb7788 100644 --- a/09-d3exit.md +++ b/09-d3exit.md @@ -87,8 +87,8 @@ if (this.checked) { // adding data points } ~~~ -This `if`-statement gets executed every time a checkbox is checked. To add the data points, we can use the `push`-function, which adds one object to an array at a time. -First, we filter the nations we want to add, calling them `new_nations`. Next, we are looping through all new nations and add one at a time to the array `filtered_nations`. +This `if`-statement gets executed every time a checkbox is checked. To add the data points, we can use the `concat`-function, which concatenates two arrays and returns a new array. +First, we filter the nations we want to add, calling them `new_nations`. Next, we concatenate this new array to the existing one and save it back to the array `filtered_nations`. We also have to initialise `filtered_nations` at the top of our script, or at least before our `refreshData` function. Remember that there is a difference between the object and the name space, so in order to keep `nations` the way it is, we need to map the values instead of just using `=`. From 3318f275948e4e77aacc2badd891b565a6e434fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Wed, 29 Jul 2015 10:55:10 +0200 Subject: [PATCH 13/15] adding a challenge to create checkboxes automatically --- 10-d3update.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/10-d3update.md b/10-d3update.md index 2ded97e..3e6c3bb 100644 --- a/10-d3update.md +++ b/10-d3update.md @@ -156,6 +156,10 @@ function calc_mean(region_data) { > # Using different data formats {.challenge} > What if you don't have your data in JSON format? Change your code to load in nations.csv instead of nations.json and have it produce the same plot. +> # Generate the checkboxes automatically {.challenge} +> Currently, we have manually created checkboxes in the HTML file. +> Using the `region_names` variable that is a list of all region names, create the checkboxes using javascript and/or d3. + By the end of this lesson, your page should look something like this: From 61b07c46c6e588a340c9f5227bbf7cba2efd9b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Wed, 29 Jul 2015 10:55:33 +0200 Subject: [PATCH 14/15] adding a challenge to fill the region_names automatically --- 10-d3update.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/10-d3update.md b/10-d3update.md index 3e6c3bb..358e92d 100644 --- a/10-d3update.md +++ b/10-d3update.md @@ -160,6 +160,13 @@ function calc_mean(region_data) { > Currently, we have manually created checkboxes in the HTML file. > Using the `region_names` variable that is a list of all region names, create the checkboxes using javascript and/or d3. +> # Get the region names from the data {.challenge} +> The `region_names` array is currently filled in manually. +> You want to replace this by an automatic extraction from the actual data file. +> +> - using the `nations` data and the `map` function, extract the `region` of each nation, +> - using the `d3.set` function that creates a set (without duplicate values) and the `.values` function on a set (that return an array), filter the `region_names` array so that it does not contain duplicates anymore + By the end of this lesson, your page should look something like this: From f90696d44846b745b57b34df4e6d9071172a9be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Emonet?= Date: Wed, 29 Jul 2015 23:26:06 +0200 Subject: [PATCH 15/15] updating all challenges to use level2 headings --- 06-json.md | 6 +++--- 07-d3setup.md | 4 ++-- 08-d3enter.md | 4 ++-- 09-d3exit.md | 6 +++--- 10-d3update.md | 12 ++++++------ 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/06-json.md b/06-json.md index 4789099..943fcfe 100644 --- a/06-json.md +++ b/06-json.md @@ -90,7 +90,7 @@ cat_list.push({weight : 6 , past_weight_values : [5.9, 5.3, 6.1], name : 'Snowba This process is called 'nesting'. -> # Nesting {.challenge} +> ## Nesting {.challenge} > 1. Append the array by a third cat, not entering a name or weight. > 1. Do all animals have to have the same attribute fields? > 1. Use the console of your browser to read the values of your object. @@ -124,7 +124,7 @@ to convert it into a string. JavaScript provides an easy way to do this. Data can get converted using `JSON.stringify()`. -> # Arrays of objects {.challenge} +> ## Arrays of objects {.challenge} > 1. Append a third cat to the array, not entering a name or weight. > 1. Do all animals have to have the same attribute fields? > 1. Use the console of your browser to read the values of your object. @@ -149,7 +149,7 @@ When the map function is called using `cat_list.map`, it loops through all eleme in `cat_list`, calls each temporarily `cat`, and creates a new list `dog_list`, which will have one dog per cat. The function `concat` simply concatenates two strings. -> # How much do dogs weigh? {.challenge} +> ## How much do dogs weigh? {.challenge} > 1. Let's assume dog misters weigh twice as much as their feline version. Make > the new array reflect this. diff --git a/07-d3setup.md b/07-d3setup.md index c819b30..b264da1 100644 --- a/07-d3setup.md +++ b/07-d3setup.md @@ -160,7 +160,7 @@ a transform attribute and use the translate function. canvas.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); ~~~ -> # Time for a challenge I think! {.challenge} +> ## Time for a challenge I think! {.challenge} > Let us consolidate our understanding of SVGs and D3 selectors. > > 1. Create a new SVG element and a circle element using the SVG markup we learnt in lesson 3. @@ -169,7 +169,7 @@ canvas.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); > > HINT: use the `attr` and `style` methods on the circle object obtained. -> # Understanding the "transform". {.challenge} +> ## Understanding the "transform". {.challenge} > > > 1. Use Javascript code to Create a new circle inside our "canvas", positioned in 0, 0, with a radius of 5px. diff --git a/08-d3enter.md b/08-d3enter.md index 9bfa8e6..3b95a0a 100644 --- a/08-d3enter.md +++ b/08-d3enter.md @@ -69,7 +69,7 @@ canvas.append("g") We add a transform attribute to move the axis to the bottom of the plotting area (instead of having it across the top). There are a number of transform options, but here we are just using `translate` and pass in the amount to shift the axis in the x and y directions, respectively. Here we shift it only in the y direction (i.e. down) by an amount given by height of the canvas. We also give it a class, just in case we might want to select the axis later in our code. -> # We might need a y-axis, too {.challenge} +> ## We might need a y-axis, too {.challenge} > 1. Create a linear scale for the y-axis, with 10 being the minimum and 85 being the maximum value. Then, add the axis to the canvas. We're slowly getting there. Having our two axes, we can now finally add our data. @@ -112,7 +112,7 @@ The attributes `cx` and `cy` define the position of the centre of the circle and arbitrary number... for now. -> # A new dimension {.challenge} +> ## A new dimension {.challenge} > Change the code so that the radius of the circles represents the population. First, create a 'sqrt' scale with a minimum of 0 and a maximum of 5e8. The range should be between 0 and 40. Also, don't forget to include a mapping function for the scale for population. diff --git a/09-d3exit.md b/09-d3exit.md index 0bb7788..fec294d 100644 --- a/09-d3exit.md +++ b/09-d3exit.md @@ -46,7 +46,7 @@ var filtered_nations = nations.filter(function(nation){ }); ~~~ -> # Filtering by region {.challenge} +> ## Filtering by region {.challenge} > You might have noticed that our data contains information about the region in > which a country is. > @@ -108,10 +108,10 @@ Whereas before `enter()` was used to append new elements to the plot, `exit()` i A good, brief explanation of this linking between data and elements on the page can be found [here](http://bost.ocks.org/mike/join/). This article discusses the three important functions used for this: `enter`, `exit`, and a third function `update` that we will get to shortly. -> # Removing elements {.challenge} +> ## Removing elements {.challenge} > 1. Using an `else` case after the `if` statement, create a filter that removes elements from `filtered_data` that correspond to the checkbox that was just unchecked. (i.e. `else { filtered_nations = <--- fill in this bit --->}`). -> # Another new dimension {.challenge} +> ## Another new dimension {.challenge} > 1. Have the colour of circles represent the region. Use category20() to make a scale. You will then need to add `.style("fill", function(d) { <-- fill in this bit ---> });` to the enter() function. As we have isolated the data-processing code in the `refreshData` function, we can now refresh the data every time the checkbox is clicked. diff --git a/10-d3update.md b/10-d3update.md index 358e92d..b4bf406 100644 --- a/10-d3update.md +++ b/10-d3update.md @@ -64,7 +64,7 @@ dot.transition().ease("linear").duration(200) > * elastic(a, p) - simulates an elastic band; may extend slightly beyond 0 and 1. > * [more here](https://github.com/mbostock/d3/wiki/Transitions#d3_ease) -> # Play time {.challenge} +> ## Play time {.challenge} > D3 is incredible versatile. Try out different transitions and if you have time, maybe try drawing rectangles instead of circles. Next, we might want to create a tooltip. Let's go have a look at what's already out there. @@ -147,20 +147,20 @@ function calc_mean(region_data) { } ~~~ -> # The master challenge {.challenge} +> ## The master challenge {.challenge} > It's time to put together everything you've learned. Write code that displays (and updates) the mean values that we just computed as little crosses in the graph for the different regions. -> # ...style! {.challenge} +> ## ...style! {.challenge} > Add axis labels and make the fonts pretty. -> # Using different data formats {.challenge} +> ## Using different data formats {.challenge} > What if you don't have your data in JSON format? Change your code to load in nations.csv instead of nations.json and have it produce the same plot. -> # Generate the checkboxes automatically {.challenge} +> ## Generate the checkboxes automatically {.challenge} > Currently, we have manually created checkboxes in the HTML file. > Using the `region_names` variable that is a list of all region names, create the checkboxes using javascript and/or d3. -> # Get the region names from the data {.challenge} +> ## Get the region names from the data {.challenge} > The `region_names` array is currently filled in manually. > You want to replace this by an automatic extraction from the actual data file. >