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

In this instalment we’ll continue our twin-track approach of mixing a little JavaScript revision with learning some new HTML. In this case, we’ll revise JavaScript’s error handling mechanism (throw, try & catch), and learn how to use the HTML <select> tag to create dropdown menus and multiple-selection lists.

We won’t be updating our date and time prototypes, but we will be using them in example HTML pages, so in this instalment our two tracks come into direct contact with each other for the first time. We’ll use an HTML page with multiple dropdowns to allow users to select a date, and then render that date in many formats using our pbs.Date prototype. We’ll also use JavaScript’s error handling features to respond appropriately when a user attempts to render an impossible date like the 31st of February 2010.

Finally, the challenge set at the end of this instalment will also combine our prototypes with HTML forms, and JavaScript error handling.

You can download my solution to the challenge set in the previous instalment, and all the code samples for this instalment in a single ZIP file here.

Solution to PBS 31 Challenge

The challenge set at the end of the previous instalment was to add four static functions to the date and time prototypes we’ve been building up over recent instalments. Because the code for these prototypes is now very long, I’m only including the relevant excerpts below. You can find my full solution in this instalment’s ZIP file (pbs31-challengeSolution.js).

JavaScript Error Handling (Revision)

When writing code, errors are very much a game of two halves – determining that something has gone wrong, and deciding what to do in response. To write good code, you need the ability to separate the code for these two very different tasks from each other. This is always true, but it is especially true when you are writing re-usable code like custom JavaScript prototypes. The same prototype should be usable in all kinds of scenarios – you should be able to use it on any web page, in shell scripts, in server-side JavaScript code, and so on.

What you absolutely do not want to end up writing is something like:

What is wrong with this code? Well – it will only work on a web page with an element with the ID errors, and, whether you want it or not, your response to trying to divide by zero to always be writing out the message “You can’t divide by zero!”. Needless to say, this function will not behave properly when used in a shell script or within server-side Javascript code.

We have totally blended the detection of the error with our response, and that’s the problem.

In JavaScript, the mechanism for separating error detection from the response to that error relies on the three related keywords throw, try & catch.

Flagging an Error (throw)

When your code detects an error, it should respond by throwing an error using the throw keyword. You’ll find lots of examples similar to the one below throughout my versions of our date and time prototypes:

You use the throw keyword to throw an object representing the error that has occurred. You can define your own error prototypes if you like, but you don’t have to (and we haven’t been, and won’t be in this series). JavaScript provides a number of error prototypes we can choose from on a case-by-case basis as appropriate, including the following:

Error
The generic error prototype – you can always use this prototype. Many programmers never use any error prototype other than this one.
RangeError
Appropriate when a value is of the expected type, but its value falls outside some acceptable range. E.g. you got a negative number, but you need a positive one.
TypeError
Appropriate when a value is not of the expected type. E.g. you need a boolean but you got a string, or, you need an array and you got a callback.

JavaScript defines a number of other error prototypes, but they are for JavaScript’s own use rather than for our use as programmers, e.g. SyntaxError, when we write code that the JavaScript interpreter can’t understand.

The constructors for all these prototypes expect a string describing the error as the first argument, in other words, they expect an error message as the first argument.

Responding to an error (try & catch)

We don’t have to write our own code for catching errors that are thrown if we don’t want to. We can let the JavaScript interpreter deal with them. If an error is not dealt with by our code and is left to the interpreter to deal with, we call it an unhandled error. When running as a shell script an unhandled error will cause the interpreter to halt execution of the script and print out an error message, perhaps including a stack trace. When running in a web page unhandled errors result in the thread of execution that experienced the error halting, and an error message being written to the web/error/JavaScript console. In reality, that makes unhandled exceptions on the web utterly invisible to users – their experience is simply that the page stops behaving as expected for no obvious reason. As a general rule, unless you’re writing shell scripts, you probably want to handle your errors so you can provide some meaningful information to the user.

To handle your own errors, you need to wrap the code that could generate an error inside a try block, and add your code for dealing with that error inside the matching catch block.

For example, save the following file into the same folder as pbs.datetime.js (from this instalment’s ZIP file), and run it with NodeJS (or in an editor that supports code execution like CodeRunner):

This produces and unhandled error.

We can turn this into a handled error like so:

In the parentheses after the keyword catch we define a name for the object representing the error thrown from within the try block. The scope of this name will be the catch block. Think of this like naming the arguments to functions.

All the standard JavaScript error objects contain a data attribute named .message which holds the error message as a string. We can use this to add extra information into our error messages to users:

Executing this code now results in the following being written to the console:

oops - can't do that! (invalid day, month, year combination)

These are all very contrived examples, to get a better idea of what’s going on, let’s use our date & time prototypes within a web page. Open the file pbs32a.html from this instalment’s ZIP file in a browser (make sure the file pbs.datetime.js exits in the same folder).

This page lets you specify a date using three dropdown menus, and then render that date in four different formats. We’ll look at how the dropdowns work in the second half of this instalment, for now, what I want to draw your attention to is what happens when you press the button to render the date. If you press the button with a sane date like the 5th of April 2017, you’ll see the page displays that date in International, European, American, and English formats. It probably won’t surprise you to learn that it does so using our pbs.Date prototype.

Now, let’s see what the page does when you ask it to do the impossible – to render the 31st of February 2001.

You’ll see that the page responds in a sane way. It doesn’t just write something to the console (where you’ll probably never see it) and then die. The button’s event handler catches the error and uses jQuery to show a human-friendly error message and set the content of each of the output regions to three question marks.

Below is the entire click handler for the button:

For now, please accept that $years.val(), $months.val() & $days.val() return the values selected in the dropdown menus, and focus instead on how errors are dealt with.

The handler starts by creating a pbs.Date object using all default values (no arguments passed to the constructor). Then, the handler does all the risky stuff, i.e. dealing with user input, within a try block. Accompanying that try block is the catch block which specifies what to do should the code inside the try block throw an error.

The key point is that when we wrote the pbs.Date prototype, we had no idea that it might one day be used on a web page where errors should be written to a <div> with the ID error_out. The code within the prototype simply detects that there is a problem, and throws an error. How that error should be responded to is defined within the page using the API, not within the API itself.

HTML Selects

In HTML, dropdown menus like those used in the above example are known as selects, and they are defined using the HTML tags <select> & <option>. The dropdown menu itself is described by the <select> tag, and each option within the dropdown by a separate <option> tag.

As we discussed in the previous instalment, all HTML form inputs are designed to produce name-value pairs. With dropdowns, the name attribute is set on the <select> tag, and each <option> tag defines the value it represents. Like checkboxes and individual radio buttons, dropdowns should be labeled with a <label> tag, either by wrapping the entire dropdown and the text describing it within a <label> tag, or, by giving the dropdown an ID, and associating a separate <label> tag to the dropdown with the for attribute.

The text the user sees for each option is independent of the value that option represents, as illustrated with the following sample dropdown:

The user sees the contents of the <option> tags, while the value part of the name-value pair is determined by the value attribute on the selected option.

Aside:

A quick note for those of you using the CodeRunner editor, if you set the execution language to HTML (the dropdown next to the run button, not the syntax highlighting setting), you can ‘run’ HTML directly in the CodeRunner console as shown in this screenshot:

HTML in CodeRunner

By default, the first option in a dropdown is automatically selected, but you can have any option be the default by adding the attribute selected="selected" to the <option> tag of your choice.

Options can also be arranged into labeled groups with the optgroup tag. For example, we can enhance our example above like so:

Note that the groupings are purely for presentation, the group labels can’t be selected because they are not actually options within the menu.

HTML selects don’t have to be rendered as a dropdown menu, they can also be rendered as a scrollable list. You can switch between modes using the size attribute. If the size is 1, you have a dropdown, if the size is greater than 1, you have a scrollable list. The HTML 5 spec does not say sizes between 1 and 4 are not allowed, but some browsers (Safari for example) will never render a scrollable menu with a size smaller than 4, regardless of what value you give the size attribute. If you set it to 1 you get a drop down, if you set it to 2 you get a four-row tall scrollable list, same if you set it to 3, and obviously the same if you set it to 4. For numbers above 4 Safari starts to behave as expected, expanding the scrollable list to the requested size.

Finally, selects can allow multiple values be selected at the same time by setting the attribute multiple="multiple" on the <select> tag. Allowing multiple selections results in the select always being rendered as a scrollable list rather than a dropdown. To select multiple elements you have to use the same key combinations you would use to select multiple files in your OS’s file manager, so cmd+click on a Mac. When multiple options are selected, the form data will contain multiple name-value pairs for the select – the name of the select paired with each selected value.

Personally, I find scrollable lists ugly and multiple selection difficult for users to figure out, so I avoid using either the size or multiple attributes. If I need users to select multiple values, I prefer to give them a collection of checkboxes click on instead.

The file pbs32b.html in this instalment’s ZIP file contains a sample form with examples of both uses of the <select> tag, and a button to show the resulting name-value pairs. Both approaches to labelling are also demonstrated:

Manipulating HTML Selects with jQuery

All examples in this section can be executed in the web console on pbs32b.html from this instalment’s ZIP file (shown above).

Like with checkboxes and radio buttons, you can access the name of a <select> using jQuery’s .attr() function with the string 'name' as the first argument. For example, you can get the name of the days dropdown with:

You can change the name by passing the new name as a second argument.

You can get the value of the currently selected option(s) within a <select> element by calling jQuery’s .val() function on the <select> element. Ordinarily, the value will be returned as a string, but if the select allows multiple selections (multiple="multiple", .val() will always return an array, even when no options are selected, or just one option is selected.

You can see .val()‘s normal behaviour in action by running the code below which gets the value of the currently selected day option:

You can see how multi-selects behave with the following snippet which shows the values of all currently selected fillings:

The .val() function can also be used to set one or more options by passing the appropriate value as an argument. For example, we can set the taco day to Sunday with:

You can also use .val() to select multiple options in a multi-select. The code below sets the fillings to beef, cheese, beans, and sweet peppers:

Note that the value of individual options can be accessed and set by using .val() on a specific option rather than on the select as a whole.

You don’t have to control selection using .val() on the select, you can also use .prop() with a first argument of 'selected' on option elements to get or set their selected status. For example, we can determine whether or not cheese is a selected filling with:

Note the use of the attribute selector we learned about in instalment 28, and the use of the second argument to the $() function to limit the search to options within a specific select.

We can also use this technique to set the selected state of any given option by passing a second argument to .prop(). For example, we can set taco day to Monday and select chilli peppers as a filling with:

Notice that regular selects behave rather like radio buttons – when a given option is selected, the others become un-selected automatically. Multi-selects on the other hand behave more like independent checkboxes – selecting chilli peppers did not deselect any other options.

Finally, hand-coding long sequences of options can be very tedious. It’s often advantageous to add a DOM ready event handler to populate a select with options using some kind of loop. You can see three examples of this technique in action in the file pbs32a.html from this instalment’s ZIP file. The raw HTML does not define a single option in any of the three dropdowns:

Instead, all three of the dropdowns are populated using jQuery in a DOM ready event handler:

Note the use of jQuery’s $() function with an HTML tag as the first argument to create new HTML elements, the use of jQuery’s .val() and .text() functions to set the value and text of the newly created option elements, and finally the use of jQuery’s .append() function to inject the newly created option elements into the select elements. Also notice that for each dropdown, jQuery’s .prop() function is used to select an appropriate default option.

A Challenge

Using the file pbs32a.html from this instalment’s ZIP file as either a starting point, or merely as a relevant example, create a web page that contains five dropdown menus allowing the user to select an hour, minute, day, month, and year, and a button that when pushed renders the selected date and time in ISO8601 format (the format outputted by pbs.DateTime.prototype.toString()), as well as all permutations of American and European date formats and 12 and 24 hour time formats. When the user chooses an impossible date, the page should handle that error in a sane way.

Final Thoughts

On our JavaScript track we have now built a collection of pretty full-featured prototypes for representing dates and times, we’ve revised how JavaScript error handling works, and what’s better, we’ve brought our prototypes into the browser and combined them with HTML forms using jQuery.

We will soon be staring on a whole new suite of JavaScript prototypes, but before we do, we’ll learn our first formal piece of software engineering – Test Driven Development (TDD). All software written by humans will inevitably contain bugs, but that’s no reason not to use sound methodologies in an attempt to systematically reduce the number of mistakes we make. That’s where TDD comes in. With TDD you start by defining the tests that your finished functions must pass before you even write a single character of code for the function itself. Then, when the function is written, you can check whether or not it does what you intended it to do by running your pre-defined tests against it.

As well as learning about TDD, we’ll also continue to explore HTML forms in the next instalment. I particular, we’ll be focusing on basic text input with text boxes and text areas. As similar as they sound, those two are actually very different beasts in HTML!