This post is part 29 of 33 in the series Programming by Stealth

In this instalment we’ll continue with our twin-track approach of revising JavaScript prototypes, and learning about HTML forms.

We’ll start by moving our JavaScript revision out of the PBS playground, and over to NodeJS, getting you much better error reporting. Then we’ll have a look at my sample solution to the challenge from the previous instalment, and we’ll eradicate another bad smell from the prototype. We’ll come face-to-face with the implications of the fact that variables don’t contain objects, but references to objects. If you don’t bear that fact in mind, you can end up with spooky action at a distance that seems like the worst kind of black magic. The kind of bugs that baffle, mystify, and drive you nutty as squirrel poo!

We’ll then switch gears back to HTML forms, where we’ll learn about a very powerful technique for including scalable vector-based icons in your form elements. These very special icons are known as glyph icons, and while rolling your own is a significant undertaking, you don’t have to, because you can use icon sets created by others. We’ll learn about glyph icons using the free and open source glyph icon set from Font Awesome.

You can download a ZIP file containing the sample solution to the previous challenge, and, the example HTML file from today’s examples here.

Taking Our Prototype Revision out of the PBS Playground

While doing my own homework (writing a sample solution to the challenge I set in the previous instalment) I came to the realisation that we have out-grown the PBS playground. It was designed as a temporary home in which we could learn the basics before moving into the browser proper.

The biggest shortcoming with the playground is its poor error reporting. Sure, it gives you an error message, but it can’t tell you which line within your code triggered that error. When you’re working on small tasks requiring just a few lines of code this is not a problem, but our prototypes are hundreds of lines long now!

We absolutely need a way of testing our prototypes as we build them that will give us detailed error reporting.

By far the simplest solution is to install a command-line JavaScript engine like NodeJS (Node for short). With Node installed you can save your code to a text file with a .js file extension, and then run it with a command of the form:

node myFile.js

Node is free, open source, and cross-platform, so anyone can play along. Node is also quick and easy to install. The Node website will offer you two downloads, an LTS (Long Term Support) version, and the very latest version. The LTS version is labeled as recommended for most users, and that’s what I always install.

While Node gives us a place to run our code, it doesn’t give us a place to edit our code. You can literally use any plain-text text editor, but realistically, you’re going to want to use a programming editor with features like syntax highlighting and bracket matching. Earlier in the series I suggested the free and open source editor Atom for editing your HTML and CSS files. You can use Atom for your JavaScript files too, and it will give you features like syntax highlighting, code auto-completion, and bracket matching.

So now we have a nice editor, and a place to run our code. Will it just work?

Nope, but don’t worry, you just need to make two very small changes to get your code working in our new environment:

  1. un-comment the namespace declaration (var pbs = pbs ? pbs : {};) at the top of your code. This was only commented out because of the playground’s idiosyncrasies – it’s needed everywhere but in the playground.
  2. Replace all occurrences of pbs.say with console.log. As its name suggests, pbs.say() is a feature of the PBS playground, not a standard JavaScript feature.

Some code editors can do much more than just editing code – they can also run it right within the editor. I recently discovered an editor like this which I’ve fallen in love with, and am now using to do all my code samples and sample solutions for this series. It can run NodeJS code, it does syntax highlighting and bracket matching, and it even understands the code you’ve written enough to suggest auto-completions of function names etc. as you type.

The editor I’m describing is Code Runner 2. It’s only available for macOS, and it costs €14.99. It’s available directly from their website, or, from the MacApp Store. The Mac App Store version is limited by macOS’s sandboxing, so while it can give you syntax highlighting and things like that, it can’t run NodeJS code. Thankfully, the Code Runner people have added a feature to the App Store version of their app that tells you when you hit such a limitation, and provides you with really simple instructions for converting your App Store purchase into a license key for the non-App Store version which you can download from their website. This conversion is really quick and easy, and costs nothing.

It’s obviously easier to buy direct, then you won’t have to go through the conversion process, but if you have iTunes credit, the fact that you can use it and then convert is very useful.

Code Runner 2 Screen Shot

Solution to PBS 28 Challenge

Below is my solution to the challenge from the previous instalment, written to run via NodeJS rather than in the PBS playground.

I’d like to start by drawing your attention to my implementations of the pbs.Date.prototype.american() and pbs.Date.prototype.european() functions. To avoid code duplication, both call pbs.Date.prototype.international() when invoked in setter mode (i.e. with arguments).

You can also see that all the setters in the pbs.Date prototype now call the helper function isValidateDMYCombo() to ensure it’s not possible to set an invalid date like the 31st of April 2016. Creating the helper function has allowed us to avoid massive code duplication.

At this stage our prototypes are coming on nicely, but, they still have some shortcomings.

The biggest remaining problem is a subtle but very important one, and it only affects the pbs.DateTime prototype. What makes this prototype different? Instances of pbs.Date and pbs.Time contain only basic data (numbers), but, instances of pbs.DateTime contain objects – each instance of pbs.DateTime contains an instance of both pbs.Date, and pbs.Time.

A point I stressed early in the series is that variables can store numbers, strings, booleans, or references to objects. When a variable contains a value like the number 4, the string 'boogers', or the boolean true, it actually contains that value. An object can’t be stored directly in a variable. What the variable actually contains is a reference to the object, not the object itself. The object itself resides somewhere in memory, and could potentially contain a lot of data. What the variable stores is in effect the memory address of the object’s entry point. Think of it like a street address.

This subtle difference between basic values and objects becomes very important when you assign one variable equal to the value stored in another.

When you have a variable that holds a basic value like a number, and assign another variable equal to it, the number gets copied, so now each variable has its own copy of the number. Changing the number stored in one of the variables has no effect on the value stored in the other. We can prove this to ourselves with this simple code snippet:

When you run the above, you get the following, totally unsurprising, output:

initial value of x: 4
value of y when set equal to x: 4
after adding 10 to y we have: x=4 & y=14

Variables that ‘contain’ objects do not behave like this. Why? Because they contain references to the objects, not the objects themselves.

When you have a variable that ‘contains’ an object and then create another variable and assign it equal to the first, what gets copied is the reference, not the object. You now have two copies of the same ‘address’, so you have in effect created an alias to the object. The object effectively has two names, but there is still only one object. If you alter the object via one of its names, the value ‘contained’ in the other will also change. This kind of spooky action at a distance can really catch you out if you’re not careful!

Forgetting that variables can only hold references to objects results in some of the most brain-bending bugs imaginable. You could easily loose your sanity as changing one variable inexplicably (to you) breaks something hundreds of lines removed in your code. Finding these kinds of bugs can be really tricky, so you really want to avoid them. That’s why I’ve been repeating the fact that objects contain references to variables so often in this segment – don’t think it’s possible to over-emphasise the point!

The code snippet below illustrates this spooky action at a distance for you:

Running the above produces the following output:

x represents the time 5:30:00PM
y represents the time 5:30:00PM
after altering y to 9:00:00AM x is now also 9:00:00AM

If you remember that variables contain references to objects, then this output makes perfect sense: y was set equal to the same reference as x, so of course they are the same object, but if you forget that variables contains references to objects rather than the objects themselves, this behaviour will catch you by surprise every time.

At the moment, the accessor methods in pbs.DateTime are returning references to the objects contained within the instances, not references to copies of those objects. This will lead to unwanted and unexpected behaviour in one of two ways:

Running this code produces the following output:

dt represents: 2015-05-01 05:00:00
after editing t, dt now represents 2015-05-01 10:00:00

Because the constructor saved a reference to t into the new object dt instead of a copy of t, altering t produces spooky action at a distance.

We also get similar spooky action at a distance when we use the accessor methods to get one of the internal values:

This produces the following output:

dt originally represents 2016-12-25 00:00:00
dt now represents 2017-12-25 00:00:00

We never explicitly altered dt, but, dt changed.

What’s the solution? Cloning!

Constructors and accessor methods that make use of objects need to store or return references to copies, or clones, of these objects, not merely copies of the original references. To make this possible, every prototype you write should contain a function named .clone(), which should return a new object that represents the same values as stored within the instance being cloned.

A clone function is basically a deep copy – if a piece of data is a value like a number, string, or boolean, just copy it, if it’s an object, clone it.

Let’s start with the simple case, and create a clone function for our pbs.Time prototype:

As you can see, for simple objects, clone functions are very simple things. You just need to ensure that what’s returned is a reference to a brand new object that represents the same data as the object the .clone() function was called on. We can do that by simply calling the constructor with the current internal values as arguments. (Yet another example of avoiding code duplication.)

We can see this simple clone function in action like so:

This produces the following output:

t1=05:00:00 & t2=05:00:00
t1=09:00:00 & t2=04:00:00

As you can see, the clone starts off as an identical copy of the original, and then both can be altered without affecting the other.

Adding a clone function to pbs.Date will be very similar.

Because pbs.DateTime objects contain objects, that prototype’s .clone() function is a little more complex. Before we can create its .clone() function, we need to update the accessor methods so they clone the pbs.Date and pbs.Time objects when getting and setting. Because we wrote our constructor to use the accessor methods, we don’t need to make any changes there.

As an example, here is how we would update the .date() accessor:

The changes are very subtle – all we had to do was change return this._date; to return this._date.clone();, and this._date = d; to this._date = d.clone();. Similar changes need to be made to the other accessor (.time()).

Once that’s done, we can add a .clone() function just like we did for pbs.Date and pbs.Time.

Challenge

Add .clone() functions to your pbs.Date and pbs.Time prototypes. Next, update the accessors in your pbs.DateTime prototype to clone the values they get and set. Then, add a .clone() function to the pbs.DateTime prototype.

You’ll know your changes have worked when the following code behaves as expected, without any spooky action at a distance:

HTML Glyph Icons

In the previous instalment, we saw how we could use images to enhance the clarity of our buttons. The concept of adding an icon to help the user is sound, but using pixel-based images is not. The icons need to be scalable, so, we need some kind of vector-based solution.

Because this is a very common problem, an interesting solution has been devised that combines a collection of technologies to produce a solution that’s powerful, and yet simple to use. The solution combines scalable vector graphics, web fonts, and CSS, and the resulting icons are often generally referred to as glyphs, or glyph icons, and collections of these icons as glyph icon sets, or iconic fonts.

While pre-made glyph icon sets are very easy to use, creating your own is quite laborious. Thankfully, you don’t have to! You can buy commercial glyph icon sets like Glyphicons, or, you can use free open-source glyph icon sets like the one provided by Font Awesome. That’s what we’ll be using in this series.

Using Font Awesome

If you plan on using Font Awesome for real-world projects, you should create a free account on their CDN (content delivery network), and generate a project-specific download URL as described on their get started page.

For this series though, we’ll be using a download URL created with my account.

When you create your own download URL, you can choose which version of the icon set your link will lead to, and you can choose to use either a JavaScrip-based variant of the icon set which includes some extra automation, or a plain CSS variant. For simplicity, the link I generated for this series is to the plain CSS variant.

So, for our purposes, including Font Awesome into a web page is as simple as adding the following line inside the head section:

Once you’ve done this, you can turn any empty inline tag into an icon by adding two CSS classes to it: fa, and then the class for the icon you want. You can find all the icons, and their classes, using the icon search page on the Font Awesome website.

What tag you should use for these icons is a bit of a thorny issue. The Font Awesome website suggests using the <i> tag. Why? Because it takes up the least possible amount of space in your HTML source.

I would strongly advise against that approach – it’s semantic nonsense! The correct tag, semantically, is the <span>, so that’s what I’m going to use in all my examples.

So – as a quick example, assuming you have included Font Awesome into your page, you can add a thumbs-up icon anywhere in your page like so:

The sizing of the icon is determined by the font size, so if you include an icon in a header you’ll see it larger than when you include it in a paragraph.

Because these icons are actually characters in a font, their colour is determined by the text colour set for the part of the page where they appear.

So, to get icons rendered in the default way with the same size and colour as your text, you just create an empty <span> and give it the class fa, and the class for the icon you would like. However, you can do more! Font Awesome also defines a number of modifier classes which you can add as extra classes along with the two you always need.

You can make icons a little bigger than the text by adding the class fa-lg (for large), or you can make the icons bigger still with fa-2x, fa-3x, and so on up to fa-5x, which makes simply massive icons.

You can also control the rotation of your icons with the special classes fa-rotate-90, fa-rotate-180, and fa-rotate-270, and you can mirror them with fa-flip-horizontal and fa-flip-vertical.

Another thing you can do is add a subtle border around your icon by adding the class fa-border.

You can also make your ions effectively float left or right by adding the fa-pull-left or fa-pull-right classes. This is particularly useful when combined with large icon sizes and perhaps also borders.

There are also classes provided to make it easy to use these icons in bulleted lists. To do this, simply add the class fa-ul to the <ul> tag for the list, and add your icon as the first item within the <li> tag, and, with the additional class fa-li, e.g.:

Finally, you can stack two icons on top of each other to make compound icons. First, you create a <span> that will contain the two icons and give it the class fa-stack. If you want to make your whole stack bigger than normal, you can add fa-lg etc. to this outer span.

Then, you add the two icons inside this outer <span>. The first one will be below the second one. To make the icons stack properly, you’ll need to make one bigger than the other. You specify which you want as which by adding the class fa-stack-1x to the one you’d like to be the smaller of the two, and fa-stack-2x to the other. If you use a background icon that’s a solid shape, you might need to invert the foreground icon by adding the class fa-inverse to it.

As an example, you could stack an inverse Apple logo over a heart as follows:

You can also stack the larger logo over the smaller one, and you can add colours to one or the other. You could synthesise a large no photography sign like so:

Finally, bringing all this back to HTML forms, we can re-do our buttons from last time, but with nice icons instead of images:

Below is the file pbs29.html from the zip file for this instalment. It shows examples of all the uses of Font Awesome described above:

You can view your local copy of this file in your browser, or view a version on my web server here.

Final Thoughts

We’ll start the next instalment with more JavaScript prototype revision. First, with a look at my sample solution to the challenge set in this instalment, and then we’ll move on to add another important additional feature to all three of our prototypes – the ability to do comparisons.

We’ll then move on to learn about a W3C standard that is very important for HTML forms, especially forms that make use of glyph icons – ARIA (Accessible Rich Internet Applications).