Category Archives: Mr. Computer

Don’t be lazy, dare to be Semantic! The Free Code Camp Tribute Project

Chingu Cohorts is a fantastic subgroup of Free Code Camp. They set up collaborative programming experiences among members of FCC on a roughly monthly schedule to help them develop their professional coding abilities. I have been taking part for the last two months or so, and have met great people, put together a solid project (/pengo), and generally learned a ton.

This round, I signed up for the FCC Speedrun. The goal is to complete all the FCC projects in five weeks. I may not acheive that goal, but set a few additional goals for myself.

  1. Create a standard “boilerplate” semantic webpage structure that will get improved each project.
  2. Learn to do unit testing, and test driven development in general.
  3. Come to love CSS.
  4. Develop a sustainable workflow that I can apply in a professional setting.

I just completed the first project – the Tribute Page. Two aspects I’ll discuss here are semantic design and using JavaScript for static webpages, i.e. “why use JavaScript for static webpages, Peter!?”

Semantics

Semantics is a fancy name for the proper user of HTML in a webpage. Semantics means using the right tags for the right situation. It helps someone read the code and figure out what’s what, but also helps automated web crawlers identify specific pieces of information. HTML5 introduced many new tags, like <article> and <figure> that offer more descriptive markup. When designing webpages, I usually find I need tags that don’t exist. Tags like or – not the “ that shows up in the page tab, but a title splash area. But, it’s ok in these cases to just add either class or id attributes, or to just be creative. For example, my title splash zone is denoted as a special <section> above the main <article>.

<section>
  <h1>Adolf Seilacher</h1>
  <span>(March 15, 1925 - April 26, 2014)</span>
  <h2>Linked the deep ocean with prehistoric life</h2>
</section>
<article>
  <section>
    It is said that old warriors never die, they just fade away.
    ...

At the bottom of the page, I put a standard footer that will appear (better and better!) in each project. Each is inside its own <div> and placed appropriately using specific class attributes.

HTML:

<footer>
  <div class="copyright">© 2017 Peter Martinson</div>
  <div class="github"><a href="https://github.com/peterjmartinson/chingu-fcc-speedrun-challenge/tree/master/frontend/tribute-page">FCC : Tribute 1.0</a></div>
  <div class="license">MIT License</div>
</footer>

CSS:

footer .copyright {
  width: 32%;
  text-align: left;
  padding-left: 1%;
}

footer .github {
  width: 33%;
  text-align: center;
}

footer .license {
  width: 32%;
  text-align: right;
  padding-right: 1%;
}

JavaScript

I chose to put only the footer in index.html, but the rest of the page is injected from app.js.

var output = '';

output += '<section>';
output += '<h1>Adolf Seilacher</h1>';
...
var tag = document.getElementById("app");
tag.innerHTML = output;

Why? There are a couple reasons, besides the fact that I like doing things the hard way, to learn. First, reusability. All future pages can use the same basic index.html and CSS, but will need their own .js file. Ultimately, all these pages will be loaded dynamically into a portfolio page, and I think it will be useful to have them already JavaScripted. Second, proof of principle. I’m not using a framework because I want to force myself to get deep into JavaScript. I’ll use some jQuery, but want to try to limit that to AJAX stuff and whatever may get crazy across sundry browsers. Third, testing. Though there is no test here, I want to begin implementing unit tests, which means you need your pages to be slapped in with JavaScript.

That’s it. Go see the finished product in CodePen, and the source code at GitHub.

Don’t return the call – Callback instead!

Callbacks took me a while to understand, while they are a fundamental part of JavaScript, and especially Node.js. The concept finally clicked while working on a Slack slash command with the Chingu Penguins cohort, called Pengo. The key take away is that there are two categories of functions – those that use return, and those that use callbacks. A function that sends a HTTP request needs a callback, while one that does internal operations can simply use return.

When the Slack user invokes /pengo, one of several useful programming tips is recalled from a MongoDB database on mLab. The steps required are:
1. receive POST request from Slack
2. Request document from mLabs database
3. Receive quote response from the database
4. Format the quote in a JSON object
5. Send the JSON object back to Slack

The place callbacks clicked for me is step 3. pengo.js sends the request to a function, getQuote.atRandom(), which queries the database and serves the response back to pengo.js to play with. The problem is that it may take time for the database query to run, and the getQuote.atRandom() may complete before the query is finished.

My initial construction of getQuote.atRandom() was the following:

atRandom : function() {
  Quote.count({}, function(err, N) {
    if (err) callback(err);
    var id = Math.floor(Math.random() * N);
    Quote.find({ quote_id : id }, function(err, result) {
      if (err) return err;
      else return result;
    });
  });
}

Now, if pengo.js calls the function with var quote = getQuote.atRandom();, quote will always end up undefined. This is because the return statement is reached before the database query finishes its run. The solution here is to use a callback.

Callbacks are functions within other functions that fire off when the parent function has completed. JavaScript is designed to pause the parent function until a response returns after a request was sent. In other words, you dump the return statement and replace it with a callback.

The way I implemented this is as follows. First, replace the return with a callback. Note, you just call it callback:

atRandom: function(callback) {
  Quote.count({}, function(err, N) {
    if (err) callback(err);
    var id = Math.floor(Math.random() * N);
    Quote.find({ quote_id : id }, function(err, result) {
      if (err) callback(err);
      else callback(null, result, id);
    });
  });
}

Notice a few things. The callback accepts multiple parameters, but the first is designated for any error conditions. If there’s no error, set the first parameter to null. The savvy reader will also notice that, while my function implements a callback, it also invokes two callbacks, because there are two calls to the database.

Second, do the business in pengo.js within the callback function:

getQuote.atRandom(function(err, quote) {
  if (err) console.error(err);
  //
  // 'quote' is now the response object
  // do with it what you will!
  //
  var data = quote.text;
  response.send(data);
});

The guts of this statement is within the function, or callback, which waits until the HTTP request has completed before running.

It’s a slight difference in how to write a function (using callback instead of return), but the returns are great.