Drawing Some Charts With D3

I have to admit, I was pretty intimidated by learning D3. This is the second part of the FreeCodeCamp data visualization section, the first part being React. After all the trouble I had learning React (or more to the point, finding anything current to learn React) I was dreading starting D3. As it turns out D3 is pretty simple, once you get the hang of the basics.

The Basics

I was surprised to find that D3 is a lot like (shudder) jQuery in syntax. Most methods return an object – allowing method chaining – which greatly simplifies the entire process. Once I started thinking of D3 in these terms the projects practically coded themselves.

The only other learning curve seems to be getting comfortable with svgs, which fortunately I have used in previous projects so there wasn’t much new there. In fact, I think most of the code I wrote for my D3 projects was to handle svgs and relatively little pertained to D3 or the data being used.

In a nutshell, D3 takes a whole lot of data and turns it into pictures. This is probably a great over-simplification which would likely irritate Mike Bostock (creator of D3), and really doesn’t do it justice, but there you go. Data to pictures.

Let’s Look At Some Code

This comes from a great, if outdated tutorial by Scott Murray written in the time of D3 v3, but all of this code will work in v4

First up, using D3 to add an SVG element to our page

const w = 500;
const h = 100;
const barPadding = 1; 

const svg = d3.select("body")
              .append("svg")
              .attr("width", w)
              .attr("height", h);

SVGs have default width and height attributes, so you do not necessarily have to specify these values, but I can’t imagine that the defaults will always be the size you’re after. So it’s good practice to specify these values.

D3 will loop through all provided data once it’s bound, applying your logic to each item in your dataset. That happens here:

svg.selectAll("rect")
   .data(dataset)
   .enter()
   .append("rect")
   .attr("x", (d, i) => {
     return i * (w / dataset.length);
   })
   .attr("y", (d) => {
     return h - d * 4;
   })
   .attr("width", w / dataset.length - barPadding)
   .attr("height", (d) => {
     return d * 4;
   })
   .attr("fill", (d) => {
     return "rgb(0, 0, " + (d * 10) + ")";
   });

I’ll leave it to you to read through Scott Murray’s tutorial to see what’s going on here. You can view the final results of this code here.

To Wrap This Up

D3 is different, but not scary. It’s powerful, but not difficult. Getting a simple chart onto the screen takes very little effort and the learning curve is not at all steep. Fear not the D3.

An Ode To Flexbox

A few months ago I made the courageous decision to not use Twitter Bootstrap anymore, and instead learn some CSS. I do not regret this decision even a little. Not too long ago I was peeking under the skirt of someone’s bootstrap website in Chrome Dev Tools and noticed something really odd: the custom bootstrap grid classes were just flexbox!

Okay, this is probably not news to most people, but to me it was kind of a big deal. I had moved away from bootstrap to learn flexbox and css grid for positioning, and then find out that what I just learned is what I had been using before. The biggest difference is that flexbox has native browser support, and bootstrap requires adding some pretty hefty libraries. Granted, you can get by with just bootstrap.css but if you wander into some of the other bootstrap classes you could find yourself in need of bootstrap.js, which requires adding jQuery. I had found myself adding in 3 libraries just to position content on the page, and that seemed just a little bit silly.

About That Flexbox

It turns out, flexbox is pretty simple to learn. There are a number of great resources out there, from my favorite site css-tricks.com to flexbox froggies and flexbox zombies. These last two are pretty entertaining and give you some good hands-on experience with flexbox.

The basic premise of flexbox seems to be creating either rows or columns as parent containers with:

.myRow {
  display: flex;
  flex-direction: row;
}

.myColumn {
  display: flex;
  flex-direction: column;
}

It’s pretty intuitive so far. We have to specify that the container is using flexbox, then we designate which direction to add the content. Worthy of note here is that the flex-direction: row is the default value and doesn’t have to be specified.

I’m not going to iterate through each available property, and I don’t intend this to be a tutorial. The remaining properties are all about how the content is displayed in the flex containers. Some handle spacing, some alignment, and there are plenty of tutorials (including those mentioned previously) which will give you a great idea of how flexbox works. I do, however, want beginners out there to know there are alternatives to Bootstrap.

But What’s Wrong With Bootstrap?

The answer to this, of course, is that there’s nothing wrong with Bootstrap. It is a well developed, well documented resource and I’m sure there are situations where I would be happy to use it. My initial statement is that it’s a bit unnecessary to import 3 huge libraries just to handle a little positioning. Bootstrap does make some tasks much easier, such as responsive design, but for me that’s not enough to justify adding it to a project. I am very fond of media queries and since I’ve discovered the wonder that is SCSS using those media queries is a piece of cake.

And Finally …

Since we’re on the topic of importing huge libraries for small tasks, I have to mention jQuery. Yes, it’s useful. Yes, it simplifies some very common tasks. Take for example, selecting items from the DOM:

/* selecting class "myClass" and changing the html to 
   "<em>Hello World</em>" and the text color to red in jQuery */

$(".myClass").html("Hello World)
             .css("color", "red");

/* doing the same in Vanilla JavaScript */

const myElement = document.querySelector(".myClass");

myElement.innerHTML = "<em>Hello World</em>";
myElement.style = "color: red";

The syntax for jQuery is much cleaner, being able to chain methods off of a single selector, and I believe at runtime (at least theoretically) the jQuery will execute quicker since it’s only searching the DOM once for a single selector (I have not tested this).

It’s not enough to get me to add jQuery to my projects. Just like the gains from Bootstrap are not enough to get me to use it either. There are situations where they both would have their uses, but for me it’s not in anything I’m currently working on. Also, there’s always the fact that React.JS is very jealous about controlling the DOM and doesn’t like to share. jQuery is all about DOM manipulation so there could be some turf wars.

Becoming More Than A Beginner

I imagine most everyone who sets out to learn coding will at some point look at someone else’s code. I try to do this as much as possible, and I especially like to see how others have solved the same problems I’m working on. It is in these moments that I often realize just how far I have to go.

I Am Relatively New To Javascript

And my code shows it. Take for example this exercise from the beginning algorithm section of the course I’m working on:

One of the simplest and most widely known ciphers is a Caesar cipher, also known as a shift cipher. In a shift cipher the meanings of the letters are shifted by some set amount.

A common modern use is the ROT13 cipher, where the values of the letters are shifted by 13 places. Thus ‘A’ ↔ ‘N’, ‘B’ ↔ ‘O’ and so on.

Write a function which takes a ROT13 encoded string as input and returns a decoded string.

All letters will be uppercase. Do not transform any non-alphabetic character (i.e. spaces, punctuation), but do pass them on.

My solution works. I know that if something works that’s the important thing, but I also know that for every solution I come up with, there’s a more elegant solution possible.

function rot13(str) { // LBH QVQ VG!
  var arrA = str.split('');
  for (var i = 0; i < arrA.length; i++) {
    if (arrA[i].match(/[a-z]/i)) {
      arrA[i] = translate(arrA[i]);
    } else {
      continue;
    }
  }
  return arrA.join('');
}

function translate(char) {
  var x = char.charCodeAt(0);
  var y = 0;
  if ((x - 13) < 65) {
    y = (x - 65);
    x = 13 - y;
    x = 91 - x;
  } else {
    x = (x - 13);
  }
  return String.fromCharCode(x);
}

rot13("SERR PBQR PNZC");

All things considered, it’s not a terribly difficult problem and it doesn’t necessarily require an overly complex solution. However, if I were sitting in a job interview and they asked me to code a solution to this problem (I don’t know if that would ever actually happen, as I’ve interviewed for exactly zero coding jobs at this point in my life) I would feel a lot better giving a more elegant solution just to show that my knowledge of Javascript is a bit deeper than the average beginner could learn in an afternoon.

Were I to solve this problem today, I would likely use Array.reduce() in place of the for (...) {...} loop, and rather than implementing a separate function to handle the math I’d use an inline function since I don’t need to call the math function anywhere else. So something like:

function rot13(str) { // LBH QVQ VG!
  return str.split('').reduce(function(a, b) {
    if (b.match(/[a-z]/i)) {
      var temp = function(x) {
        if ((x - 13) < 65) {
          x = 91 - (13 - (x - 65));
        } else {
          x = (x - 13);
        }
        return String.fromCharCode(x);
      };
      a.push(temp(b.charCodeAt(0)));
    } else {
      a.push(b);
    }
    return a;
  }, []).join('');
}

rot13("SERR PBQR PNZC");

As you can see, there’s not a great reduction in the number of lines of code, but the Intermediate Solution takes advantage of more advanced techniques which I feel would show a greater understanding of Javascript. I feel the math bit in the middle is the next portion to be improved upon, and I can’t wait to learn those things which would allow me to improve upon it.

What Does This Have To Do With Looking At Other’s Code?

I think Quincy Larson, creator of Free Code Camp, summed up my experience very well in this Youtube interview when he says, “Free Code Camp is essentially like self-learning together.” While there are many others currently doing the same course-work I’m doing, and many, many others who have already completed the course, when it comes down to it I’m learning all of this on my own. Sure, in the challenge text they may tell you to read some reference material, but anyone who can look at this reference page and then know how Array.reduce() works is a lot smarter than I am. So instead, I read others’ code to see how they use it and learn from their successes. Also, as I’ve mentioned before there are chatrooms, forums and message boards available to those needing help as well, but I generally try to find the solution on my own.

It’s fun to go back and re-solve old problems in new ways, and helps me see my progress. Having that kind of perspective really helps to keep me motivated.