Adventures in JavaScript Development

Cycle Through List Elements With jQuery

| Comments

I’ve written several versions of this functionality, and each time I revisit it, it gets simpler and I feel silly for how complicated I made it before. The thing to remember when you’re working with jQuery is to always leverage the DOM. Christian Montoya has a good writeup about how he came to the same realization, and it’s worth a read.

In the meantime, here’s my latest iteration of cycling through items in an unordered list. In the example below, I’ve just put straight-up text in the list items, but they could contain entire divs of content if you wanted.

First, let’s assume we have this HTML:

1
2
3
4
5
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>

We’ll start by verifying that there’s more than one item before we do all the rest of the work. (Of course, if your list length doesn’t vary, this if isn’t necessary.)

1
2
3
4
5
var $list = $('#myList');

if ($list.length &gt; 1) {
  ...
}

Following the principles of progressive enhancement, we don’t want to include navigation elements in the HTML if they will only work with Javascript; rather, we want to add them with Javascript:

1
2
3
4
5
6
7
8
9
10
11
12
var $list = $('#myList');

if ($list.length &gt; 1) {
  // put the nav before the list
  $list.before('');

  // style the nav as needed
  $('#nav').css({textAlign: 'right'});
  $('#nav img').css({cursor: 'pointer'});
  $('#nav img:first').attr('src','backButton.gif');
  $('#nav img:last').attr('src','forwardButton.gif');
}

The comes the fun part: adding the behaviors to the nav buttons. This is where it pays to keep in mind the power of the DOM; in past iterations of this, I’ve seriously overthought the logic.

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
var $list = $('#myList');

if ($list.length &gt; 1) {
  // put the nav before the list
  $list.before('');

  // style the nav as needed
  $('#nav').css({textAlign: 'right'});
  $('#nav img').css({cursor: 'pointer'});

  // add the back button behavior
  $('#nav img:first').
    attr('src','backButton.gif').
    click(function() {
      $('li:visible',$list).
        hide().
        prev('li').
          show();
    });

  // add the forward button behavior
  $('#nav img:last').
    attr('src','forwardButton.gif').
    click(function() {
      $('li:visible',$list).
        hide().
        next('li').
          show();
    });

}

But what happens if there’s not a next li when you click on the forward button, or a previous li when you click on the back button?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var $list = $('#myList');

if ($list.length &gt; 1) {
  // put the nav before the list
  $list.before('');

  // style the nav as needed
  $('#nav').css({textAlign: 'right'});
  $('#nav img').css({cursor: 'pointer'});

  // add the back button behavior
  $('#nav img:first').
    attr('src','backButton.gif').
    click(function() {
      $('li:visible',$list).
        hide().
        prev('li').
          show();

      // if there wasn't a previous li,
      // show the last li in the list
      if ($('li:visible',$list).length

One last thing: we need to hide all the list items and then show the first one:

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
var $list = $('#myList');

if ($list.length &gt; 1) {

  // hide all the list items and show the first one
  $('li',$list).hide().eq(0).show();

  // put the nav before the list
  $list.before('');

  // style the nav as needed
  $('#nav').css({textAlign: 'right'});
  $('#nav img').css({cursor: 'pointer'});

  // add the back button behavior
  $('#nav img:first').
    attr('src','backButton.gif').
    click(function() {
      $('li:visible',$list).
        hide().
        prev('li').
          show();

      // if there wasn't a previous li,
      // show the last li in the list
      if ($('li:visible',$list).length

For extra fun:

  • Randomly reorder the list items before you add the rest of the code
  • Instead of show() and hide(), try fadeIn() and fadeOut()

Comments