This post is part 24 of 31 in the series Programming by Stealth

In this instalment we’ll take our JavaScript skill up a level, learning how to write code that is designed to be re-used by ourselves or by others. When you solve a problem that you know you’ll need to solve again, it’s worth putting in a little extra effort to make your code as easy to re-use as possible. You may decide to share that code with others, or you may not, but either way, it’s in your interest to write it using some simple best practices.

Re-usable code without documentation is all but useless, so, we’ll also learn how to create great API documentation as you code. We’ll learn to do this using the free and open source tool JSDoc.

As a worked example, we’ll re-write our link fixer as an easily re-usable API, and while we’re at it we’ll also add in some extra functionality to make its behaviour more customisable, and hence, more useful to more people.

The sample files used in this instalment, as well as some needed libraries, can be downloaded as a ZIP file here. The examples assume you’ll save the files within the zip in a folder named pbs24 in the document root of your local web server.

Solution to Instalment 23’s Challenge

Before we get stuck into this instalment’s new content, let’s look at a solution to the challenge set at the end of the previous instalment. The challenge was to write a function to find all links in a page, check each to see if it’s internal to the site, or external, and if it’s external, to transform the link to have a target of _blank, a rel of noopener, and to inject an icon after the image to show that it will open in a new window/tab.

Below is my solution. As always, I want to stress that there are an infinity of correct solutions to any programming challenge, so, if your code works, then it’s just as correct as mine!

Writing Re-usable and Sharable Code

Whether you’re writing code for your own re-use in future projects, for sharing with a team, or for publishing to the world, you need to take some extra care to avoid your code having un-intended side-effects. The biggest potential danger is littering of the global scope. The reason you want to avoid using the global scope for everything is that the global scope can only contain one variable with any given name. If you use a globally scoped variable named x in your code, then your code conflicts with every other piece of code that uses a globally scoped variable named x. The fewer globally scoped names your code uses, the less likely it is to conflict with other code.

Many programming languages make use of a concept known as namespacing or packaging, to create a hierarchy of scopes. When you create a new API, you would place all your code in its own namespace, so your code would be completely separated from the global scope. In Java you organise your code into packages, generally named in reverse-DNS style – if I was publishing Java code I could package it as net.bartificer.projectName (Bartificer is my registered business name, and I own the domain bartificer.net). Perl uses a :: separated hierarchy, so the Perl module that drives www.xkpasswd.net is contained within the package Crypt::HSXKPasswd. In both of these examples, there would be/is zero littering of the global scope.

The bad news is that Javascript does not have a built-in mechanism for namespacing. However, a workaround has been developed that uses JavaScript objects, and the concept of function closures to simulate traditional namespaces. It’s not possible to keep the global namespace completely clean using this workaround, but, it does allow us to limit ourselves to a single globally-scoped variable for all our APIs.

Before the workaround can make any sense, I need to explain a few new JavaScript concepts – closures, the ternary operator, and self-executing anonymous functions.

Closures

In JavaScript, when you define a function within another function, the outer function’s scope gets baked into the inner function’s scope permanently, even when the outer function finishes executing. This capture of the external scope is referred to as a closure.

Consider the following code:

We could add this into a page as shown below:

The initialisation function runs exactly once – when the DOM becomes ready. When that function runs, a variable named counter is created, and given the value 0. This variable is created within the scope of the function (initClickCounter()), not within the global scope.

The next thing that happens as the function initClickCounter() executes is that another function is defined, and stored in another locally scoped variable named incrementCounter. We’ll refer to this as the inner function, since it’s defined within another function, specifically, initClickCounter(), which we’ll refer to as the outer function.

The inner function is only defined here, not executed. However, notice that it makes use of the variable counter, which exists in the outer function’s scope. It does not declare this variable (no var in front of it), so it does not have its own copy, it is instead reaching up into its containing scope to access it. It can do this because a copy of the outer function’s scope is permanently added to the inner function using JavaScript’s closure mechanism. The inner function does not get a copy of the variable, it gets a reference to it.

The last thing that happens when the outer function executes is that it adds the inner function to all paragraphs as a click hander.

Once the outer function finishes executing, the inner function has still not been executed even once, it has only been declared, and added as a click handler. Were it not for closures, the variable counter would have vanished into the ether when the outer function finished executing, but it has not – the inner function retains a reference to it.

We can now execute the inner function by clicking on the paragraph in the page. The first time you click, the counter will have a value of 0. It then gets incremented by 1, and alerted. The second time you click, it will be incremented and alerted again. Notice that the count goes up. If we had declared the variable within the inner function that would not happen, it would be a fresh copy each time, but because we are using a variable from the outer function’s scope, it is the same variable each time, so the count keeps incrementing.

Closures can be difficult to understand, as they are a kind of spooky action at a distance (to paraphrase Einstein), but they are absolutely vital to modern JavaScript programming.

Objects as Pseudo-Namespaces (And the Ternary Operator)

If you were to add all your variables, functions, and prototypes directly into the global scope, you would have to chose the names for each one very carefully. If you use a generic name, you are very likely to create an incompatibility with other pieces of code. Rather than trying to pick many unique names, it’s much simpler to pick one name, give it to an object, and add all your functions, variables, and prototypes as key-value pairs within that object.

You’ve already seen this technique in action – the PBS JavaScript playground used a single object named pbs, into which all the available functions were added as key-value pairs, hence you had pbs.say(), pbs.inputs(), and so on. pbs was a variable in the global scope that pointed to an object. That object contained a key named say that referenced a function to render text to the output area, and another key named inputs that referenced a function to read the values from the input text boxes.

This is the approach I recommend you take for all your re-usable code. Choose one name that’s likely to be pretty unique, create a single object with that name, and add all your variables, functions, and prototypes as key-value pairs to that object. I suggest you choose a name that’s likely to be quite unique, and, that references you, or the organisation you work for, in some way.

Remember that there is no reason not to nest these pseudo name-spaces – you could have pbs.util.x, pbs.util.y, as well as pbs.project1.x, and pbs.projec1.y, and so on.

Because my registered business name is Bartificer, I publish all my JavaScript APIs as bartificer.something. For example, I released the API that powers subnetcalc.it as bartificer.ip it contains a number of prototypes for modelling IP addresses and subnets, including bartificer.ip.IP, bartificer.ip.Subnet, and bartificer.ip.Netmask.

If you choose this approach, your code will inevitably be split across multiple .js files, and any one project will only use a sub-set of those files. So how do you declare your object in the first place? You could declare it in a sort of master file that must be included in every project, but that is needlessly cumbersome. A better approach is to declare the object in every file, but only if it does not already exist. This can be done using the following code snippet:

At first glance this is a very odd snippet of code. Your confusion will not be helped by the fact that it makes use of an operator we have not seen before, the so-called ternary operator.

The ternary operator consists of three parts, hence its name:

CONDITION ? VALUE_1 : VALUE_2

If CONDITION evaluates to true, the entire operator will evaluate to VALUE_1, otherwise it will evaluate to VALUE_2.

For example, we could create a variable named x, and set it to the value of another variable named y, if y is positive, or 0 otherwise like so:

You can test this in the JavaScript console. First run the following:

Then run the following:

Now that we understand the ternary operator, let’s look at our sample code again:

The CONDITION is simply pbs, VALUE_1 is also pbs, and VALUE_2 is a new empty object.

So, if pbs evaluates to true, then the entire operator evaluates to pbs, otherwise, it evaluates to a new empty object. The only way an object can evaluate to false is if it’s undefined. So, if the pbs object already exists, nothing changes, the line effectively becomes var pbs = pbs;. However, if the pbs object doesn’t exist yet, the line effectively becomes var pbs = {};, i.e. pbs gets created as a new object containing no keys.

Self-Executing Anonymous Functions

The final strange beast we need to learn about before we can look at the design pattern for simulating namespaces is the so-called self-executing anonymous function. A self-executing anonymous function is a function that is given no name, which gets created and executed in a single step.

In JavaScript, a pair of parentheses can have three different meanings, depending on where they appear in your code. Firstly, when they appear without an name, value, or keyword directly to their left, they simply act to group things together, e.g.:

Secondly, many JavaScript keywords make use of parentheses – e.g. if, while, for, and function.

Finally, if a pair of parentheses containing zero or more coma-separated arguments appears directly after a name or value that is not a keyword, JavaScript will try to execute what ever is to the left of the parenthesis as a function, using the values between the parentheses as arguments to that function, e.g.:

console.log evaluates to a function (console is an object, and log is a key within that object that contains a reference to a function), and by putting the parentheses containing the single argument 'test' directly after it, we call that function with 'test' as the only argument.

We can combine all that knowledge to form the following construction:

The first set of parentheses creates a group that gets evaluated first. That group contains an anonymous function, so the first set of parentheses evaluates to an function. The second set of parentheses appears directly to the right of the first, so they will execute the result of evaluating the contents of the first with 'test' as the only argument. In other words, the anonymous function we just created gets immediately executed. You can try it for yourself in the JavaScript console.

The above construction is hard to read, and would be even harder to read if the anonymous function contained even just a few lines of code, let alone hundreds. Hence, it’s usually written over multiple lines with the following indentation:

A Recipe for Namespacing in JavaScript

We are now ready to look at a very common design pattern for simulating namespaces in JavaScript. I think it’s a good idea to understand what’s happening, but that’s not essential – I think many JavaScript programmers copy-and-paste this design pattern over and over again without fully understanding what’s happening.

To illustrate the technique, let’s create a very simple API that contains just one function – helloWorld(), and present it to the world using pbs as a namespace. The code below should be saved in a stand-alone .js file, say pbs.helloWorld.js (included in this instalment’s ZIP file):

We could now include our simple little API into an existing web page like so:

Having done that, we could call the function like so:

For added context, let’s create a full web page that uses our simple API to generate an alert each time a paragraph is clicked (pbs24b.html in the ZIP file):

Auto-Generating API Documentation with JSDoc

Inspired by JavaDoc, JSDoc is a tool for automatically generating API documentation from JavaScript source files that contain specially formatted comments.

Installing JSDoc

JSDoc is actually written in JavaScript. The easiest way to install it is to use the Node.js JavaScript engine and it’s accompanying package manager, npm. Node is available cross platform, with simple installers for Windows and Mac, and there are packaged versions available for many popular Linux distributions.

Once you’ve installed Node, you should be able to use Node’s package manager to install JSDoc. The basic form of the command will be as follows:

npm install -g jsdoc

The -g means you would like the package installed globally, i.e. system-wide. To install system-wide you need admin privileges, so on Windows you should use a command prompt run as Administrator, and on Linux/macOS you should execute the command with root privileges, either directly, or via sudo. For example, on my Mac I used:

sudo npm install -g jsdoc

You should now be able to create documentation from any javascript file with a command of the form:

jsdoc myFile.js

This will build a documentation website describing myFile.js, and place all the HTML files etc. into a folder named out in the current directory. You can specify as many input files as you like, and JSDoc will build a single unified documentation site describing them all.

We can get more control over the generated document by creating a config file. The config file should be in JSON format, and can be passed to the command with the -c flag. You’ll find a copy of the config I’ll be using in the ZIP file as jsdoc.conf.json:

This very simple config does two things. Firstly, it sets a configuration variable on the default theme that suppresses JSDoc’s default behaviour of adding the code itself into the documentation. I find it just makes the documentation more difficult to read, but if you want to see what it looks like, just change the false to a true. Secondly, it enables JSDoc’s built-in but optional Markdown plugin. When this plugin is enabled, you can use Markdown syntax within JSDoc descriptions.

JSDoc Comments

I mentioned that JSDoc looks for specially formatted comments. JSDoc will try to interpret all comments starting with /** and ending with */. JSDoc is smart enough to ignore leading spaces and *s on multi-line comments. These special comments are referred to as doc comments. You can give a simple description of a function as you create it like so:

This is a very basic example that will result in very basic documentation. JSDoc supports so-called tags that allow you to add more information to your doc comments. These tags all start with the @ symbol. I don’t want to bore you with a definitive list of all available tags, instead, we’ll meet them organically as we go through the series. You can learn more about any tags we do mention, as well as all the other tags that exist, in the JSDoc documentation.

To get started, let’s look at documenting functions. When using an API, a function should be like a black box, what you care about is what goes in, and what comes out. If your function expects arguments, you should specify them in order using the @param tag, one tag per argument, and each tag starting on a new line. Each @param tag should take the following form:

@param {TYPE} ARGUMENT_NAME - DESCRIPTION

The TYPE should be a valid native JavaScrip type, like string, number or boolean, the name of a prototype, like Object, or, a reference to a custom type of your own creation (more on that later in the series). The ARGUMENT_NAME is just the name of the argument, and the description should be some text describing the argument. The type and description are optional, and if you don’t want to set a description, also leave out the dash preceding it. Oh – also, if there is a description, the dash should have exactly one space before it and one space after it.

To specify what a function returns, use the @returns tag:

@returns {TYPE} DESCRIPTION

You can leave out either the type or the description if you like (but not both).

Given what we know now, let’s re-write our sample function:

Note that we are using Markdown syntax to mark some items for rendering as code snippets, specifically, we are using the back-tick to do that.

Something else functions can do is throw exceptions. You can document this using the @throws tag. This tag takes the following form:

@throws {EXCEPTION_PROTOTYPE} DESRIPTION

Where EXCEPTION_PROTOTYPE is the prototype of the exception that could be thrown. If your function can throw multiple types of error, you should add multiple @throws tags to the doc comment.

We could re-write our function so it throws an exception on invalid arguments as follows:

Finally, before we move on from functions, I also want to mention the @example tag, which you can use to add sample code into your documentation. This tag works over multiple lines – everything until the next tag, or, until the end of the comment is considered part of the example. Let’s re-write our function one last time:

As a proper worked example, let’s create documentation for our simplistic pbs.helloWorld API.

The first thing we should do is add a doc comment to the very top of the file. This will form the homepage of the documentation. To do that, we’ll use two tags – @overview, and @author.

Because we use namespaces, we need to tell JSDoc that it should consider pbs a namespace. We do that by adding a doc comment directly above our declaration of the pbs variable, and ending that comment with the special tag @namespace.

Finally, we should add a doc comment to the helloWorld function. Because this function expects no arguments, returns no value, and throws no exceptions, the @param, @returns, and @throws tags are intentionally omitted.

This is how our file now looks:

You may notice that the overview contains a JSDoc tag that I have not mentioned yet, {@link pbs}. This in-line JSDoc tag can be used in any JSDoc description to insert a reference to a documented item. In this case, a link to the documentation about the pbs namespace.

We are now ready to generate our documentation. Start by opening a command prompt in the same folder as the pbs.helloWorld.js and jsdoc.conf.json files. From there, run the following command:

jsdoc pbs.helloWorld.js --destination docs-helloWorld -c jsdoc.conf.json

Assuming you extracted the contents of the ZIP file into a folder named pbs24 in the document root of your local web server, and, that your local web server is running, you should now be able to access the documentation you’ve just created at the URL http://localhost/pbs24/docs-helloWorld/.

A Challenge

The challenge this time is to create a first-pass at an API for rendering a clock showing the current time in any given timezone. Before we’re ready to do that, we need to look at a JavaScript API for converting between timezones.

A Quick Introduction to Moment.js

At the moment, the most powerful looking open source JavaScript library for manipulating dates is Moment.js, and it has an extension specifically for manipulating timezones. The two JavaScript files needed to use Moment.js‘s timezone features are included in the contrib folder within the zip file.

As we did with with URI.js, this is merely a sampler of what Moment.js can do, focusing on the features we need to achieve our goal. This is not a tutorial on Moment.js. You can find the full documentation at momentjs.com/docs.

We can create a moment object representing the current time in a given timezone as follows:

The timezone string should be a TZ string as defined in the IANA time zone database. Thankfully Wikipedia publishes a full listing of the database – the value we need is in the third column.

We can then access one or more aspects of the time as a string using the .format() function. For example, to see the hours and minutes separated by a colon we could use:

You can get a full listing of all the formatting characters here, but for our assignment we only need to know the following:

A Starting Point

Rather than starting with a blank canvas, start with the following two files (pbs24-assignment.html and pbs.renderClock.js in the ZIP file):

You don’t need to make any changes to this file. You can use it as-is to test that your clock function is working. This file must be located in the same folder as the contrib folder, and the pbs.renderClock.js file in order to function.

The JSDoc comment describing what the function should do is already in place, as is the start and end of the function.

The Assignment

You simply need to add the functionality into the pbs.renderClock() function in pbs.renderClock.js to make it actually do something.

How you make the function do its thing is entirely up to you, but I suggest the following basic design:

  • First, empty the span – to be sure you are working on an empty canvas, so to speak.
  • Create three spans, one for the hours, one for the minutes, and one for a separator character, and save them into three variables in pbs.renderClock()‘s scope, and then inject them into the span.
  • Create an inner function within pbs.renderClock() and give it a name. This function should get the current time, and reaching out into pbs.renderClock()‘s scope, use the variables there to update the hours and minutes to their currently correct value.
  • Create an interval that runs every 60 seconds and calls your inner function.
  • For bonus credit, can you make the separator blink? You might find jQuery’s .fadeTo() function useful.

Conclusions

We’ve learned how to use the magic of closures to package our code into re-usable libraries, and, we’ve learned how to use JSDoc to generate documentation for our library’s APIs. So far our APIs have been very simplistic – so simplistic some people might even argue that they don’t deserve to be called APIs at all! That will change in the next instalment, when we’ll create a powerful API for adding arbitrarily many clocks, each in any timezone, to a page in a configurable way. To do that we’ll need to learn another new concept – data attributes – a way of embedding data into an HTML element.

Tagged with:

This post is part 23 of 31 in the series Programming by Stealth

So far in this series we have been using jQuery to alter existing HTML elements by changing their attributes or style. In this instalment we take things to the next level, and learn how to use jQuery to create entirely new HTML elements, and inject them into the DOM, and hence, into the web page.

We’ll be working towards our first truly practical assignment in the series – a function that finds all links on a page, and if, and only if, they lead to an external page, alters them to open in a new tab, and appends an icon indicating that fact. In order to work up to that we need to learn five new things:

  1. How to build HTML elements with jQuery
  2. How to inject HTML elements into the DOM
  3. How to loop through each element represented by a jQuery object
  4. How to embed images directly into web pages using Data URLs
  5. How to use the 3rd-party library URI.js to interrogate URLs

There are four examples in this instalment, and a starting-point for the challenge. I’ve gathered them, and the other files they depend on, into a ZIP file which you can download here. It’s assumed that you’ll extract this ZIP file and place the five HTML files and one folder it contains into a folder named pbs23 in your local web server’s htdocs folder. The folder is particularly important because it contains a copy of the URI.js library, and if it’s not in the same folder as pbs23d.html and pbs23-assignment.html, those pages won’t work.

Solution to PBS 22 Challenge

But first, below is a solution to the challenge I set at the end of the previous instalment. I provided an HTML file as a starting point, and then set the following tasks:

  1. In the script element within the head element, declare a variable named blinkIntervalID with the value 0 (this variable will be in the global scope)
  2. Below your variable declaration, declare a function named toggleBlinking(). This function will take no arguments, and return nothing. If the current value of the global variable blinkIntervalID is 0, this function should create a new interval which will toggle the class highlighted on all paragraphs every second, and save the interval ID into the global variable blinkIntervalID. If the current value of the global variable blinkIntervalID is not 0, the function should cancel the timeout who’s ID is stored in the global variable blinkIntervalID, and set the variable to 0.
  3. Create an anonymous function that will execute when the DOM has finished loading. Inside this function, add an event handler to every paragraph that will call the function toggleBlinking() every time the user clicks on a paragraph.

Below is my solution to the assignment. Just a reminder that when it comes to programming, there are an infinity of possible correct solutions, so if your code works, but look different to mine, that’s just fine!

Creating HTML Elements with jQuery

We have already learned that jQuery heavily overloads functions – that is to say, the same function behave in different ways depending on what arguments are passed. So far, we know that the $() function implements all the following behaviours when passed different arguments:

  1. A String containing a CSS selector as the only argument – select all matching elements in the entire document. For example, select all links: $('a');
  2. A string containing a CSS selector as the first argument, and a jQuery object as the second argument – search the HTML elements represented by the jQuery object for all matching elements. For example, select all links within paragraphs: $('a', $('p'));
  3. A DOM object as the only argument – convert the DOM object to a jQuery object. For example, $(this) inside jQuery callbacks.
  4. A function object (callback) as the only argument – execute the function when the DOM becomes ready.

We can now add a fifth behaviour to that list – if you pass the $() function a HTML tag as a string, it will construct a new HTML element.

For example, to build a top-level heading with the text a header, you could do the following:

Similarly, I could use jQuery to build a link to my website as follows:

Note that jQuery will accept a full HTML tag with attributes and content all defined within the string. To illustrate this point, the following two lines of code produce the same result:

My preference is for the second style, so that’s what you’ll see me use in examples throughout this series.

When we create HTML elements in this way, they exist, but they are not part of the page. It’s almost like they are in a parallel dimension. For these elements to become visible, they need to be injected into to the DOM. JQuery provides a number of functions for doing this. These functions should be called on a jQuery object representing an existing element, they will then place the new element relative to the existing element in one of the following ways:

.before()
Injects the new element into the DOM directly before the existing element.
.after()
Injects the new element into the DOM directly after the existing element.
.prepend()
Injects the new element into the DOM inside the existing element as the first child element.
.append()
Injects the new element into the DOM inside the existing element as the last child element.

Let’s pause for an example. The HTML page below contains a heading followed by some paragraphs of text. We’ll use jQuery to inject an aside element as the last element within the body element containing the character count for the paragraphs.

We can get the character count for all the paragraphs with the following snippet:

We can create an aside tag with the following snippet:

Finally, we can inject this new element into the end of the body element with the following snippet:

Remember that we need all the above code to run after the DOM becomes ready.

Putting it all together, we get the following full HTML page (pbs23a.html in the ZIP file):

Looping Through a jQuery Object

As we know, jQuery objects represent zero or more HTML elements. It’s easy to apply basic changes to all elements an object represents – we’ve seen this many times already in the previous few instalments. For example, we can turn every paragraph in a page red with the following snippet:

However, sometimes we need to apply similar, but not identical, changes to each element represented by a jQuery object. In these kinds of situations, we need to loop through each element represented by the object one by one. Or – to put it another way, we need to iterate over the elements represented by the jQuery object. This is what jQuery’s .each() function is for. This function expects one argument, a callback, and it will execute that callback once for every element the object represents. Within the callback, the current DOM element will be available via the special this variable. As usual, to convert this DOM object to a jQuery object, pass it to the $() function, i.e. use $(this).

As an example, let’s alter our previous example so it also puts a count at the end of every paragraph.

The following snippet does the work:

Below is a full web page so you can see the snippet in context (pbs23b.html in the ZIP file):

Images Via Data URLs

Usually, a URL points to a location where data can be retrieved from, but, it’s possible to embed data directly into a URL using so-called data URLs. The part of a URL before the first : character is known as the URL’s scheme. We’re used to seeing the http, https, and perhaps ftp schemes, but there is also a data scheme. Using this scheme, it’s possible to encode base-64 encoded data directly into a URL.

For our purposes, data URLs will take the following form (the spec is a little broader, but we’ll be ignoring the other possibilities):

data:MIME/TYPE;base64,BASE_64_ENCODED_DATA

With MIME/TYPE being replaced with the appropriate MIME-Type for the data, and BASE_64_ENCODED_DATA being replaced with the actual data.

You can get the base64 encoded version of any file using the uuencode terminal command (Linux & Mac). The format of the command is as follows:

uuencode -m IN_FILE REMOTE_NAME

For data URLs, the remote name is irrelevant, but the command insists you pass one, so you can use anything at all for that argument. For example, if I had a file called tag-hash.png which contained an icon I wanted to use to represent a character count, I could determine its base64 encoding with the following command:

uuencode -m tag-hash.png boogers

This produces the following output:

For our purposes, we should ignore both the first and last lines. The data we want is between the header line and the final ==== line with the newline characters removed.

We could update our example to use this icon using the following snippet:

Again, we can put this all together into a full web page as follows (pbs23c.html in the ZIP file):

The big advantage to using data URLs within JavaScript code is that you can share the code with others without having to send them multiple files.

Introducing URI.js

The final piece we need to build our link enhancer is the ability to parse URLs into their component parts so we can analyse them. We could do this with regular expressions, but that’s not as straight forward as you might imagine – the specification defining valid URLs is actually quite complex.

When you encounter a common problem like this, re-inventing the wheel is not a good approach. Instead, you should look to see if there’s an open source project that has already solved your problem for you. I don’t mean copying and pasting snippets of code from a web forum, I mean using a well packaged and well documented library of code that has been specifically designed to be re-used.

When code has been properly designed to be re-used, it will have a well defined and well documented list of available variables, functions, and/or prototypes. Collectively, this documented collection of functions etc. is known as an Application Programming Interface, or API. The API should be all you need to know to make use of a well packaged code library. We’ve already used one such code library in this series – jQuery.

OK, so we need to process URLs, we can’t possibly be the only JavaScript programmers to need that functionality, so there’s probably a well regarded library that solves this problem out there somewhere. A little Googling would tell you that the best regarded JavaScript library for interacting with URLs is URI.js.

This will not be an exhaustive look at URI.js. The documentation on their site is very good, so I’ll leave learning more as an exercise for the reader. Instead, I just want to highlight the parts of the API we’ll need to achieve our goals. Also note that URI.js integrates with jQuery.

Firstly, we can create a URI object representing the URL of the current page as follows:

We can create a URI object from a jQuery object representing a link named $a as follows:

We can determine if a link is relative or absolute using the .is() function:

Finally, we can extract the full domain part of a URL using the .hostname() function:

You can read more about each of these functions, and learn about all the other functions that exist in URI.js’s documentation.

As a worked example, let’s create some code to add the class external to all links in a page that lead to a different site.

External links are those that are not internal. A link is considered internal if either of the following are true; the link is relative, or, the domain the link points to is the same as the domain of the current page.

Based on that, we could write a function to mark external links as external like so:

You can see this function in action in the full web page shown below (pbs23d.html in the ZIP file). Note that it includes CSS definitions to show links in green by default, and links with the class external in red. Also note that this page imports the URI.js library. Because the URI.js project does not provide a CDN, the code library file is included in the zip file in a folder named contrib. This folder must be present in the same folder as pbs23d.html for the library to be successfully imported.

Challenge

Using a slightly altered version of the fourth example (pbs23-assignment.html in the ZIP file) as your starting point, add the code needed to transform external links in the following ways:

  1. Set their target to _blank
  2. Set their rel attribute to noopener
  3. Add an icon after the link (the data URL for the icon is available in the global variable newWindowIconURL)

Conclusions

Hopefully, when you complete the assignment, you’ll have reached an important milestone in this series – our first truly practical piece of code that solves a common real-world problem. To get here we needed an understanding of HTML, CSS, the JavaScript language, and two third-party libraries – jQuery and URI.js.

In the next instalment we’ll tackle another real-world problem, we’ll create an embeddable clock that shows the time in a given timezone. This is something Allison needs for her website. She records her podcast live on Sundays at 5pm her time. To avoid timezone confusions, she would like visitors to her site to see a live clock showing the current time in her timezone.

We already know all the pieces we need to create the clock, the new skill we’ll be learning is how to package our code so as to make it easy to embed into an existing site, and hence, easily re-usable by others. In other words, we’ll be making our own library with its own API for others to re-use on their own pages.

Tagged with:

This post is part 22 of 31 in the series Programming by Stealth

In the previous instalments we experimented with jQuery using the web console on our dummy page. In this instalment we’ll learn how to embed JavaScript into web pages, and, how to attach our code so it gets triggered by browser events.

This instalment includes a number of examples. You can copy-and-paste the code out of the page, but for convenience I’ve zipped up all the files and you can download them here.

Read more

Tagged with:

This post is part 11 of 31 in the series Programming by Stealth

Finally, after many months of making Allison wait, it’s time to look at tables on web pages. We’ll start by describing the HTML markup for tables, and then look at how to style them with CSS.

Remember – tables are for one thing, and one thing only – displaying tabular data!

Read more

Tagged with:

This post is part 10 of 31 in the series Programming by Stealth

Continuing our look at CSS, in this instalment we’ll start by looking at how to style lists, then we’ll move on to look at some more CSS selectors, and we’ll finish with an introduction to a new CSS concept – pseudo-classes.

Read more

Tagged with:

This post is part 9 of 31 in the series Programming by Stealth

In the previous instalment we learned how to group multiple HTML tags together to define regions within a page, and then how to move those regions around by floating them, or positioning them explicitly. We’ll start this instalment with a little revision – there was a lot to digest last time! While re-visiting the layout from last time, we’ll also look at some of its limitations, and then we’ll move on to look at the CSS display property, how it can be used to alter layouts, and, how we can use it to improve on our demo layout.

Read more

Tagged with:

This post is part 8 of 31 in the series Programming by Stealth

In the previous instalment we learned about the CSS box model. Each HTML tag is represented as a box within the browser, and those boxes stack down the page, and inside each other to build up the web pages we see. We also learned how to use FireFox’s developer tools to actually see and inspect the boxes. In this instalment we’ll learn how to take one or more boxes out of the normal flow of the page, and position them elsewhere on the page.

Read more

Tagged with:

This post is part 7 of 31 in the series Programming by Stealth

In this instalment we’ll build on our basic understanding of CSS from previous instalment. We’ll start with some new CSS selectors, in the process, introduce two new HTML tag attributes, then we’ll move on to the CSS box model. Each HTML tag is represented in the page as a box, and all those boxes can be manipulated with CSS.

Read more

Tagged with:

This post is part 6 of 31 in the series Programming by Stealth

We have now learned enough HTML to encode basic page content, marking things as headings, paragraphs, lists, etc.. We have completely ignored the look of our pages so far – relying on our browsers’ default styles. The default styles, it’s fair to say, are pretty darn ugly, which is why almost every page on the web has at least some basic styling applied to override these defaults.

In the bad old days, HTML pages were styled by adding attributes directly into the HTML tags. This was very time-consuming, and it greatly reduced the re-usability of the HTML markup. Those attributes still exist in the HTML spec, but we have completely ignored them, and will continue to do so for the entire series. This is not the bad old days, so we now have access to a much better solution – Cascading Style Sheets, or CSS.

Read more

Tagged with:

Something I’ve always had a lot of trouble with is developing good colour schemes for web pages. (The fact that I’m rather colour blind does not help matters!) I generally end up falling back to a mono-chrome scheme where the site just uses many different shades of the same single colour. This works but often leads to sites that look a little boring. I need to skin a new web portal at work that I want to make look good and professional to speed up it’s adoption so I decided I just had to get to grips with this colour thing. There is no magic quick fix but here are two links I found in-valuable and that I’m sure will also be a great help for others trying to get to grips with this:

Tagged with:

keep looking »