In this short project we’ll work with the United States Bill of Rights. Starting with some simple markup and the body content, we’ll use jQuery to generate a table of contents and some simple user interface features.
1. The Plain Old Thing
Let’s start with this very basic HTML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
Also, you’ll want to make a file called
styles.css in the same folder containing these styles:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
What you should notice about this document is that each Article starts with an
h2 heading then the text of the article is in a paragraph following it. Looking at the document’s
head section you’ll see that it include a CSS stylesheet but nothing else. Open this page in your browser to get a sense of the text.
Next create a second file in your project directory named
application.js and open it.
application.js add the following:
Refresh your browser and you should see an alert box indicating that the
application.js file was loaded. Check the RESOURCES tab in Chrome and make sure jQuery is downloading properly. Then you’re good to go for some real development!
3. Back to Top
We want to insert new content. The process goes something like this:
- Find the places you want the content
- Create the content
- Stick it in that spot
So where do we want the link? It’d be tempting to put the link after every paragraph since each article is just one, but that seems a little sloppy. If there were introductory paragraphs or something they might get links too. Each article is wrapped in a DIV tag with the class name
article so let’s find those DIVs and stick the link just inside the closing DIV tag.
We need a jQuery selector. If you’re familiar with CSS then writing selector statements is super easy. In this case we want DIV tags with the class name
article so we just write
"div.article". We’ll also need to wrap our jQuery in the document ready lines, so start with this in your
1 2 3
Refresh your browser and you’ll see…no change. We might have selected all the article DIVs, but we didn’t do anything with them. When I’m not sure about a selector I like to first add some CSS attributes to the matched objects. That gives me a visual confirmation that jQuery is finding the things I want it to find. Modify your middle line in
application.js so it’s like this:
Refresh your browser and pink borders should pop around each article. The CSS method sets a CSS property on each element that the selector matched. One thing I love about Chrome is how you can now do "Inspect Element" on those article
divs and it’ll show you, right in the souce code, the CSS that has been dynamically applied. We know our selector is working!
We know where the content goes, we’ve got the content, now let’s put it in there. There are several methods for inserting content in jQuery that each have a slightly different purpose. We want to stick content "inside but at the end of" the matched elements. This is an append operation which we can accomplish like this:
.css line with that one, refresh your browser, and your Back to Top links should appear. You’ve dynamically created content within the HTML page!
On Your Own: The #top Anchor
These links are great, and when you click on the link from the last article, it will most certainly send you to the top. The problem however, is that it is only the ‘#’ notation that is making this work in the browser currently.
<a href='#'> by itself will get you the same behavior in this example as
<a href='#top'>. But
<a href='#'> is not very explicit, and the default on click with
<a href='#'> is to take you to the top of the current page. So what happens when you a) want to be explicit, as all good developers should, and b) want to target a different article/link? You need an anchor. Insert a named anchor like
<a id='top'> within that
h1 at the top of the page and check that your links still work. Now experiment with moving your anchor around in other tags and checking the results.
4. Table of Contents
Jumping back to the top is great and all, but what most users are going to want is to jump from the top to the article they’re interested in. We need to build a table of contents on the fly. How’s that possible?
- Create a ToC heading and unordered list near the top of the page
- Find all the
h2s, they are the names of the articles
- Insert the article names as list items into the UL
idanchors into each of the
- Link the Table of Contents item to the
Create a ToC Heading and Unordered List
We’ve already practiced creating a variable to hold HTML then inserting that HTML. Store
"<h2 id='toc_header'>Table of Contents</h2>" into a variable and insert it into the markup just below the existing H1. Instead of using
append like we did before, here you need
after so it goes outside the closing H1 tag.
Then, just under that heading, insert an unordered list (UL) with the id attribute set to
'toc_list'. The tricky thing here is that you probably want to use a selector to find the ToC
h2, but how can we do that without getting all the
h2s? Use the CSS-style virtual attribute
The id attribute provides a unique identifier for an element within the document.
The most important aspect of the id attribute is that it must be absolutely unique. Unlike the class attribute, which may apply the same value to many elements in a page, an id that’s applied to an element must not match an id used anywhere else on the same page.
Note that the id attribute cannot be applied to the following elements:
Refresh the page in your browser, use the Inspect Element tool, and make sure your new HTML is getting injected properly.
Finding the Titles and Inserting them into the ToC
First, on your own, write a selector which finds all the article
h2s and sets their background color to #CCF. Make sure it’s not selecting the heading ToC heading.
Now that you’ve found the
h2s, we need to grab their content and create the list items. Our selector is finding the collection of
h2s, then we can use the
each method to run instructions on each element of the collection. Here’s how it’ll look:
1 2 3
We pass a
each holding the instructions we want run on each element. Remember that we bundle it into a function so the instructions don’t get executed when the script is first read, they wait until the function is called.
We want to pull the text out of the object. How do we get to the one object we’re looking at within the collection? We can try using the special variable
this like so:
1 2 3 4
Refresh your browser and you won’t see any alert boxes popping up. Look at your developer pane and you’ll see an error like
Object #<an HTMLHeadingElement> has no method 'text'. You get this error because within the
each method, the
this variable refers to the plain DOM object. It isn’t a jQuery object, so we can’t call a jQuery method like
.text or else we see this error.
But it allows us to show another usage style for the
$ jQuery reference. Modify your code block to pass
$ like so:
1 2 3 4
Now refresh your page and you should see a bunch of popups with the individual article titles. It works! Now, what were we trying to do again? We wanted to insert these titles into the ToC list. Instead of alerting the title, let’s build it into an
li like this:
Then, on your own, write a selector to find the ToC UL and
listItem. Refresh your browser and you should see a plain text Table of Contents.
Our ToC is nice for reading and printing, but it should be linked. We want to click on an article title in the ToC and jump to the article further down the page. To accomplish this interaction we need to:
- Take the title and convert it to a "slug" usable in a URL
- Insert anchors in the individual article
h2s which have the
idset to that slug
- Link the list items in the ToC to that slug
Creating a Slug
We already have the
title variable which holds name of the article like "Article X". We need to create a slug version of that, conventionally all lowercase and spaces replaced by underscores like
title = line.
Refresh your browser and you’ll just see the normal titles in alert boxes. As a first step I want to use the jQuery method
.trim() which cuts any whitespace off the frontend or backend of our string. Now those lines will look like this:
Right after your
trim() call, add on a call to
.toLowerCase() to convert it to lower case. Then we need the
.replace() method which takes two parameters: the string to find and the string to replace it with. Use it to replace a space with an underscore. Combining them all gives me this line:
Refresh your browser to check that the slugs look good and we can move on.
Insert the Target Anchors
Now that we have the slug we can setup the target anchors. Within the
each block that we’ve been working in, remember that
this is referring to the
h2. We want to inject the anchor inside that
h2. Let’s create the anchor and insert it in one step. We’ll use a handy jQuery method called
attr. We’ll call
attr on the jQuery version of
this, which remember represents each of our
h2s. And then we’ll pass two arguments to
attr, the first of which declares the attribute we want to add:
id, the second argument is the value of that attribute, which in our case is the previously defined variable slug.
Link to the Targets
We need to add links into the
listItem. On your own, work with the
var list_item= line to include a link tag where the
href points to
article_x is the current slug.
alert lines you have and refresh your browser. Your ToC should be fully functional!
5. Hiding Content
There’s one more feature I want in our document. Underneath the title of each article I want a
(hide) link which, when clicked, hides the body of the article and changes the link to say
(show). Here’s what we need to do:
- Create the hide link
- Attach a
clickevent handler that…
- Hides the article content
- Changes the link text
Creating the link itself is the easy part. You already have the selector for all article
h2s and the
each block of instructions, so we’ll continue to work within that
each block. Add these two lines to create a simple link and insert it after the
1 2 3
You’ll notice that
$(). We’ll need that jQuery functionality soon. The second line inserts the link object after the
h2. Refresh your browser and you’ll see the links appear, but when you click them nothing meaningful happens.
Working with the Click Event
We need to add behavior that will be executed when that link is clicked. In between the two lines you just wrote, add this:
1 2 3
What is that? The
on method binds the given event to the given function. In this case, the event we’re listening for is
click, which is fired when there is a mouse click on that element.
on takes a
function parameter which holds the code that will be executed when the click happens. Here our function takes a parameter
event which effectively creates a local variable named
event that contains a bunch of information about when and where the click happened. So far we’re not using that variable for anything. Then inside the function we get the link with
this, turn it into a jQuery object with
$(), and call the
siblings method. This method returns the set of all "sibling" objects in the DOM, the objects that share the same parent/wrapper object as this one. In our case that will be all DOM objects inside the article DIV. Once those siblings are found it calls
hide on them to hide them from view.
Now that the
click listener is attached to
toggleLink we need to insert the link into the DOM. Use this line outside of the
Try it in your browser. It kinda works, right? What’s the main issue?
We can fix that by filtering the
siblings matcher. Change
siblings('p') so it’ll only match siblings which are paragraphs and retry it. Now your article titles won’t disappear.
Revealing the Text
Hiding is cool and all, but how about revealing? If we click the link again it should reveal the hidden text. In jQuery there’s the
hide method we just used and there’s
show which works exactly the same. We could use an if/else block to say "when this link is clicked, if the text is visible then hide it, otherwise reveal it." That’d work, but it’s a common enough use case that jQuery makes it easier on us.
Several methods come in pairs like
show. Many such pairs have a third instruction that toggles between them, looking at the element and figuring out which one should be done. In this case, the toggle method is called
toggle. All we need to do is change our method call from
Try that out in your browser.
Changing the Link Text
It works great but it looks stupid. When the text is hidden the link still says "hide" – it should switch to saying "show." It’d be nice if there were some toggle-like function to change text and there is discussion about it existing in the future. For now, though, we have to toggle the link text manually.
We’ll do it in two steps:
- Figure out what the text should be
- Set the link to that text
Here’s the logic to figure out the text: "If the link currently says
'(hide)' then the text should be
'(show)', otherwise it should be
Present in several languages, the ternary operator is one of those things that looks crazy but is really handy. Here’s how it’s constructed:
The condition is evaluated to true or false. If it’s true then the
what_to_do_if_true instruction will be executed and the result stored into
result. If the condition was not true the
what_to_do_if_false is executed and it’s result put into
In our case, here’s how we’ll use it:
Setting the Link Text
newText will hold the value of what we want the link to say after this click. Figure out how to use the
text method to set the text of the link to
Try it out in your browser and it’s functionally good, but there’s a usability issue.
Stop Jumping Around, Browser!
click event, it’s also doing the normal things it does when you click a link – trying to load the page or anchor. Our actual link tag points to
event into the
click method signature. All you need to do is add this as the first line inside your
Refresh your browser and try it out; there should be no more jumping around. Our hide/show functionality is complete!
6. Refactoring to a plugin
Plugins make jQuery an excellent language for sharing re-usable pieces of code. As we saw in this example, we created a script that goes through a page featuring
div.article sections with
h2 tags and built up a table of contents to place under the
h1. We also using lots of jQuery functions that operated on selected tags, for example,
$('div.article').each(.... We’re going to create our own method that can operate on tags using jQuery’s plugin architecture.
Here’s how we’re going to setup our plugin and call it when the document loads:
1 2 3 4 5 6 7
By adding a function to
$.fn we can access it when selecting tags. In our case we select all of our
div.article tags and call our function. We also pass in the header to the plugin function so it will know where to put our ToC.
Only a few changes need to be made to our code in order to use it inside the plugin:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Now we are free to distribute this plugin among our team or publicly for the world to use to build tables of contents for their article lists.
- Created and worked with variables
- Used text manipulation methods like
- Used the ternary operator
- Responded to a click event
- Inserted, hid, and displayed content
- Used a variety of selectors with IDs, Classes, and Virtual Attributes
- Refactored our script into a reusable plugin