This post is part 23 of 30 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 30 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 21 of 30 in the series Programming by Stealth

In the previous instalment we took our first tentative steps into the browser. We learned about the Javascript console, the concept of the Document Object Model, or DOM, and we introduced the jQuery library.

Our initial introduction to jQuery was very superficial, now, it’s time to dive in deeper, and get much more rigorous in our understanding. We’ll look at how to use jQuery to select specific HTML elements on the page, and then, how to manipulate their styling, and their HTML attributes.

For this instalment we’ll still be using the Javascript console on the PBS dummy page. From the next instalment on, we’ll be embedding our JavaScript directly into our web pages, so this will be the last time we use the dummy page.

Read more

Tagged with:

Taming the TerminalIn the previous instalment we finished a five-part series on SSH. Before moving on, lets take a moment to step back and look at the big-picture. The five SSH instalments are all part of the now long-running series on networking. We have been working our way through the networking stack since instalment 23. We started at the bottom of the stack, and have worked our way up. We are not exploring protocols in the Application Layer.

In this instalment we’re moving on from SSH to HTTP, the protocol that powers the world wide web.

Before we look at some HTTP-related terminal commands, we need a basic understanding of how HTTP works, so that’s what this instalment is all about.

Read more

Tagged with:

As described in a post earlier today, I have made some significant changes to this site. The short version is that I’ve started to use WordPress as a CMS (content management system). While the WordPress APIs provide a good range of functions for doing CMS-like things, the web interface is disappointingly lacking in even basic CMS features. Thankfully, WordPress’s plugin architecture has allowed the community to fill in the gaps.

Read more

Tagged with:

This site started life in the early 2000s as a pure blog powered by the Serendipity blogging engine and hosted on free shared hosting provided by MiNDS>, the IT society of Maynooth University, where I was a researcher in the Computer Science department at the time. The first big change came in the summer of 2006 when I moved the blog from MiNDS> to this domain. As well as moving the blog, I also moved my personal website, though the two remained separate entities which I had to mange separately. While moving the blog I took the opportunity to change blogging engines from Serendipity to WordPress. This was an early version of WordPress, so its evolution from blogging engine to content management system (or CMS) still had a long way to go (arguably it still does). As WordPress’s pages feature evolved, I eventually did away with the standalone site, adding just a handful of pages into WordPress. At that point WordPress became my entire website. It was a viable solution because I really just needed a few simple ‘about the stuff I do’ pages, and the blog.

This month, while preparing for the release of the new version of my XKPasswd open source library, I realised that I needed more from this site. While the blog is still important, and will continue to contain most of the information hosted on the site, it won’t be the view though which most of that information will be accessed. A reverse-chronological list of all posts on all topics is not actually an optimal way of presenting content! This site serves as the anchor of my online presence simple because this is the URL I give out when ever I’m asked where people can find me online. I sometimes wonder if podcast listeners aren’t starting to think that Busschots is just my middle name, and that from bartb.ie is actually my surname! This site has not been a particularly good home page, not because there isn’t useful content, but because it’s been ineffectively presented.

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:

I am well aware that tables for layout are a BAD BAD idea and have stopped using them for such perverted things years ago with just one exception, forms. I started doing my forms in lists because IMO that makes sense but clients were always grumpy when web forms weren’t layed out in the traditional two column way and short of creating a mess of Divs I always ended up falling back to tables for forms. Not anymore! I’ve FINALLY found a nice way of doing forms so that the XHTML is simple, elegant and more importantly, semantically correct while still keeping to a nice two column layout.

Read more

Tagged with:

Now that the worst of the ‘browser wars’ finally seems to be behind us and now that JavaScript can easily communicate with servers to get data without page re-freshes via AJAX one has to wonder if there are any real uses left for applets. My conclusions would be that yes there are still some uses for applets on the web but they are few and far between. Anyone who uses an applet in this day and age should have a bloody good reason to do so because your browser should not have to load a JVM just to view a web page unless that JVM is providing something spectacular that actually adds something to your page and that cannot be done with the core web technologies (XHTML, CSS, JS, AJAX).

Read more

Tagged with: