Interactive tables - sorting

Where are we?

You know how to create and style tables. Let’s make tables interactive.

This page’s goals

By the end of this page, you should be able to make a table sortable. Users will be able to click on table columns to sort tables the way they want. You’ll use a jQuery plugin to do the work.

Understanding the task

Suppose Ted and Fred both want to buy dog toys. Ted wants the best he can find. Fred just wants something cheap.

Ted and Fred visit a site that sells dog toys. Ted wants a good toy, so he’d like to see the toys with the highest ratings listed first:

Sort by rating

Figure 1. Sort by rating

Fred wants to see the cheapest toys listed first:

Sort by price

Figure 2. Sort by price

We can give them both what they want by letting them choose how they want the table sorted. They could click on the column titles to sort. You can try the page.

jQuery plugins

A plugin is a JavaScript program that you can add to jQuery. It extends jQuery, that is, makes jQuery do something extra. There are hundreds of plugins, for everything from graphing, image handling, chat, ..., well, you name it. You can check the list.

There are three steps to using a plugin:

  1. Add the plugin JS file to your page.
  1. Set up the HTML and CSS the plugin needs.
  1. Call the plugin.

Adding the plugin

A plugin is just a JavaScript file. You add it to your page like any other JS file: with a <script> tag in the header.

Set up your HTML and CSS

Some plugins require special set up in HTML or CSS. But you’ve seen that before. Take the jQuery function addClass(). (It’s a normal part of jQuery, not from a plugin.) It adds a class to an element.

Suppose we had this code:

$("#best_dog").addClass("champion");

It tells JS to find an element with the id best_dog, and add the class champion to it.

The code isn’t going to work if you haven’t already set up an element with the id best_dog in the HTML, and created a class called champion in the CSS.

The same thing with plugins. You can’t tell a plugin to graph some data if you don’t tell it what data to graph. You can’t tell a plugin to shrink an image if you don’t tell it what image to shrink.

That’s what I mean by “set up your HTML and CSS.” You need to prepare the things that the plugin will manipulate.

Calling the plugin

Once you’ve added a plugin, you treat it as if it was built-in to jQuery. Most plugins create new functions, like drawGraph() or playSound(). You call the functions, as if they were part of jQuery to begin with.

Using tablesorter

Let’s do these three things with the tablesorter plugin:http://tablesorter.com/. It lets users click on column headers to sort a table.

Adding the plugin

Normally, you would download the plugin to your computer, and then upload it to your server. Some plugins also come with CSS files, images, and other things that you need to upload. Look at the plugin’s documentation to figure out exactly what to do with it.

tablesorter needs just one JS file. For convenience, I’ve put the file on CoreDogs. You can add it to your pages by inserting the following line in the <head> section of each page you want to use it on.

<script type="text/javascript" src="http://coredogs.com/resources/jquery.tablesorter-2.0.3.min.js"></script>

Figure 3. Adding tablesorter

Do this with your live projects, if you want.

Set up your HTML and CSS

tablesorter requires that you:

  • Use <thead> and <tbody> tags in your table.
  • Use <th> tabs inside <thead>.
  • Use <td> tabs inside <tbody>.

Here’s some code for the dog toys table. It doesn’t do any sorting yet – it’s just to get us started.

<table>
  <thead>
    <tr>
      <th>Catalog<br>number</th>
      <th>Name</th>
      <th>Photo</th>
      <th>Average<br>rating</th>
      <th>Price</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>243243</td>
      <td>Ball of Chasing</td>
      <td><img src="ball.jpg" alt="Ball of chasing"></td>
      <td>3.9</td>
      <td>4.99</td>
    </tr>
    <tr>
      <td>593922</td>
      <td>Blue Chewey</td>
      <td><img src="blue_chewey.jpg" alt="Blue chewey"></td>
      <td>4.8</td>
      <td>12.99</td>
    </tr>
    <tr>
      <td>293944</td>
      <td>Cookie Bone</td>
      <td><img src="cookie_bone.jpg" alt="Cookie bone"></td>
      <td>3.5</td>
      <td>3.99</td>
    </tr>
    <tr>
      <td>948322</td>
      <td>Cookie Car</td>
      <td><img src="cookie_car.jpg" alt="Cookie car"></td>
      <td>3.6</td>
      <td>3.99</td>
    </tr>
    <tr>
      <td>882030</td>
      <td>Cookie Hydrant</td>
      <td><img src="cookie_hydrant.jpg" alt="Cookie hydrant"></td>
      <td>3.2</td>
      <td>3.99</td>
    </tr>
    <tr>
      <td>323822</td>
      <td>Cookie Shoe</td>
      <td><img src="cookie_shoe.jpg" alt="Cookie shoe"></td>
      <td>4.1</td>
      <td>3.99</td>
    </tr>
    <tr>
      <td>392866</td>
      <td>Rope Twist</td>
      <td><img src="rope.jpg" alt="Rope twist"></td>
      <td>4.3</td>
      <td>11.99</td>
    </tr>
    <tr>
      <td>298882</td>
      <td>Chew Shoes</td>
      <td><img src="shoes.jpg" alt="Chew shoes"></td>
      <td>2.1</td>
      <td>17.95</td>
    </tr>
  </tbody>
</table>

Figure 4. Initial toy code

Everything should be familiar. There’s a head (lines 2 to 10), and a body (lines 11 to 68). The head has one table row. Each column heading uses the <th> tag. The tablesorter plugin needs <th>s so it can identify column headings.

Each row in the body describes a single product. The third column has an image with a thumbnail photo of the product.

The table looks like this so far:

Unstyled table

Figure 5. Unstyled table

We want to add CSS styles to make it look like this:

Styled table

Figure 6. Styled table

We have to make some changes:

Unstyled table changes

Figure 7. Unstyled table changes

The font family, size, and color needs to be changed for all the text. The header needs to have its color flipped around: white text on a dark background. The cells with number values – rating and price – need to be aligned to the right. The cells in the body need a border.

Here’s some code to do the job:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Sorting a table</title>
    <style type="text/css">
      body {
        font-family: Verdana, Helvetica, sans-serif;
        font-size: 12px;
        color: #585858;
      }
      #dog_toys {
        border-spacing: 3px;
      }
      #dog_toys thead th {
        color: white;
        background-color: #683900;
        padding: 4px;
      }
      #dog_toys tbody td {
        border: 1px dotted #683900;
        padding: 2px;
      }
      #dog_toys tbody td.catalog_id {
        text-align: center;
      }
      #dog_toys tbody td.photo {
        text-align: center;
      }
      #dog_toys tbody td.rating {
        text-align: center;
      }
      #dog_toys tbody td.price {
        text-align: right;
      }
    </style>
  </head>
  <body>
    <table id="dog_toys">
      <thead>
        <tr>
          <th>Catalog<br>number</th>
          <th>Name</th>
          <th>Photo</th>
          <th>Average<br>rating</th>
          <th>Price</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td class="catalog_id">243243</td>
          <td class="name">Ball of Chasing</td>
          <td class="photo"><img src="ball.jpg" alt=""></td>
          <td class="rating">3.9</td>
          <td class="price">4.99</td>
        </tr>
        <tr>
          <td class="catalog_id">593922</td>
          <td class="name">Blue Chewey</td>
          <td class="photo"><img src="blue_chewey.jpg" alt="Blue chewey"></td>
          <td class="rating">4.8</td>
          <td class="price">12.99</td>
        </tr>
        <tr>
          <td class="catalog_id">293944</td>
          <td class="name">Cookie Bone</td>
          <td class="photo"><img src="cookie_bone.jpg" alt="Cookie bone"></td>
          <td class="rating">3.5</td>
          <td class="price">3.99</td>
        </tr>
        <tr>
          <td class="catalog_id">948322</td>
          <td class="name">Cookie Car</td>
          <td class="photo"><img src="cookie_car.jpg" alt="Cookie car"></td>
          <td class="rating">3.6</td>
          <td class="price">3.99</td>
        </tr>
        <tr>
          <td class="catalog_id">882030</td>
          <td class="name">Cookie Hydrant</td>
          <td class="photo"><img src="cookie_hydrant.jpg" alt="Cookie hydrant"></td>
          <td class="rating">3.2</td>
          <td class="price">3.99</td>
        </tr>
        <tr>
          <td class="catalog_id">323822</td>
          <td class="name">Cookie Shoe</td>
          <td class="photo"><img src="cookie_shoe.jpg" alt="Cookie shoe"></td>
          <td class="rating">4.1</td>
          <td class="price">3.99</td>
        </tr>
        <tr>
          <td class="catalog_id">392866</td>
          <td class="name">Rope Twist</td>
          <td class="photo"><img src="rope.jpg" alt="Rope twist"></td>
          <td class="rating">4.3</td>
          <td class="price">11.99</td>
        </tr>
        <tr>
          <td class="catalog_id">298882</td>
          <td class="name">Chew Shoes</td>
          <td class="photo"><img src="shoes.jpg" alt="Chew shoes"></td>
          <td class="rating">2.1</td>
          <td class="price">17.95</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

Figure 8. Added styles

The changes in the look are all made by CSS. But I changed the HTML as well. Why? To create things I could hook the CSS rules to.

Changing the HTML

I wanted to make it easy to hook CSS rules to the things that needed to change their look. Here’s what I did.

<table id="dog_toys">
  <thead>
	<tr>
	  <th>Catalog<br>number</th>
	  <th>Name</th>
	  <th>Photo</th>
	  <th>Average<br>rating</th>
	  <th>Price</th>
	</tr>
  </thead>
  <tbody>
	<tr>
	  <td class="catalog_id">243243</td>
	  <td class="name">Ball of Chasing</td>
	  <td class="photo"><img src="ball.jpg" alt="Ball of chasing"></td>
	  <td class="rating">3.9</td>
	  <td class="price">4.99</td>
	</tr>
	<tr>
	  <td class="catalog_id">593922</td>
	  <td class="name">Blue Chewey</td>
	  <td class="photo"><img src="blue_chewey.jpg" alt="Blue chewey"></td>
	  <td class="rating">4.8</td>
	  <td class="price">12.99</td>
	</tr>
...
  </tbody>
</table>

Figure 9. Adding names to the HTML

First, I gave the table an id (line 1). As we will see, this is enough for almost all of the CSS rules I need to make.

But some of the columns needed special treatment. For example, the body’s photo column needs to be centered. And the price needs to be aligned to the right.

The price is right? Ack! Bad pun! Boo!

I gave each column (each <td> tag) a class. Then I could style the classes to get the alignment I wanted (center, right, whatever). You can see this on line 13, 14, and so on.

CC
CC

You gave the table an id on line 1, but on line 13 you gave the <td> a class. Why not give the <td> an id as well? Like <td id="catalog_id">. Wouldn’t that be more consistent?

Renata
Renata

Oo, oo, I know!

Kieran
Kieran

Go ahead, Renata.

Renata
Renata

Because you can only use the same id once per page. If you used <td id="catalog_id"> on line 13, you couldn’t do that again on line 20.

Kieran
Kieran

That’s right! If you give two things the same id, you might get strange results. But you can use the same class as much as you want.

Adding the CSS

Now that I have the names added to the HTML, I can use them in the CSS.

body {
  font-family: Verdana, Helvetica, sans-serif;
  font-size: 12px;
  color: #585858;
}
#dog_toys {
  border-spacing: 3px;
}
#dog_toys thead th {
  color: white;
  background-color: #683900;
  padding: 4px;
}
#dog_toys tbody td {
  border: 1px dotted #683900;
  padding: 2px;
}
#dog_toys tbody td.catalog_id {
  text-align: center;
}
#dog_toys tbody td.photo {
  text-align: center;
}
#dog_toys tbody td.rating {
  text-align: center;
}
#dog_toys tbody td.price {
  text-align: right;
}

Figure 10. The styles

The rule in lines 1 to 5 sets font information for the entire page. The rest of the rules start with #dog_toys, so they apply only to the table. The rule in lines 6 to 8 applies to entire table. The next rule styles the table header, and the one after that styles the cells in the body. The rest of the rules set the classes of the columns.

Renata
Renata

You added a class to the product name column: <td class="name">. But you didn’t use the class in the CSS. Why?

Kieran
Kieran

Good question. Clients often want changes to pages. I added the name class to make future changes to that column easier.

It isn’t strictly necessary. I could have left it out. That would still be OK.

Exercise: More color table styling

Make your color table look like this:

More styles

The text is right aligned in some of the cells. The text color for the numbers matches the name of the color.

There is no striping. It tends to interfere with the sorting you’ll do later.

Upload your solution to your server. Put the URL below.

(Log in to enter your solution to this exercise.)

Calling the plugin

The last step is to call the plugin. Here’s code to add to the <head> of the page.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="http://coredogs.com/resources/jquery.tablesorter-2.0.3.min.js"></script>
<script type="text/javascript">
  $(document).ready(function(){ 
    $("#dog_toys").tablesorter(
      { headers: {
        2: {
            sorter: false
        }
      } 
    } ); 
  }); 
</script>

Figure 11. Calling the plugin

Line 1 gets jQuery from Google. Line 2 gets the tablesorter plugin from CoreDogs. Lines 4 to 12 are executed when the page has been loaded into the browser.

Line 5 is where the real action is. To make the table sortable, all I have to do is this:

$("#dog_toys").tablesorter();

This makes every column in the table sortable. The user only needs to click on the column headings.

The problem is, I don’t want all the columns to be sortable. Sorting on the photo column doesn’t make a lot of sense. So I want the plugin to make that column not sortable.

That’s what lines 6 to 10 do. They set options for the headers (line 6), setting the photo column (line 7) to not sortable (line 8).

Why is there a 2 for the photo column (line 7)? That’s the column’s index. The first column is has an index of 0. The second column has an index of 1. The third column has an index of 2. The photo column is the third column, so I use an index of 2 in line 7.

Working out the syntax – what goes where – is messy. I took the easy way out. I found this in the plugin’s documentation:

For example, to disable sorting on the first two columns of a table: headers: { 0: { sorter: false}, 1: {sorter: false} }

I just copied it, changed the 0 to a 2, and got rid of the other column (the 1). I do this whenever I can – look for an example of what I want to do, copy it, and change it if necessary.

You can try the final page.

Exercise: Sorting the color table

Make your color table sortable, on all columns.

Hint: .tablesorter() is enough.

Upload your solution to your server. Put the URL below.

(Log in to enter your solution to this exercise.)

Summary

On this page, you learned how to make sortable tables using a jQuery plugin.

What now?

You’ll do more table exercises on the next page. Make sure you do them! It’s the only way to learn.


How to...

Lessons

User login

Log in problems? Try here


Dogs