List Taxonomy Terms By Letter

This code implements a shortcode to list terms of a selected taxonomy.
The shortcode takes the following parameters:

  • taxonomy – the slug of the taxonomy to list.  Default: category
  • hide_uncategorized – hide the ‘uncategorized’ category.  Default: true
  • hide_description – hide the description of each term.  Default: true
  • limit – the number of terms to show per page.  Note that this will be ignored if necessary to show all terms for a letter on a single page.  This will ensure that letters are not split across pages.  Default: 10

To list the terms, put the shortcode in your Page or Post.  For example, to list the terms of the taxonomy ‘Lodging’ with the descriptions, you would use the following shortcode:

[mam_list_terms taxonomy=’lodging’ hide_description=0]

Put the code below in your functions.php.  Sample CSS to style the pagination is shown below the code.

add_shortcode('mam_list_terms','mam_list_terms_by_letter');
function mam_list_terms_by_letter($atts) {
	extract( shortcode_atts( array(
	   'taxonomy' => 'category',      // The slug of the taxonomy to list
	   'hide_uncategorized' => true,  // Hide the 'uncategorized' category
	   'hide_description' => true,    // Hide the term description
	   'limit' => 10,                 // Show this many term entries per page
	), $atts ) );
	$tax = get_taxonomy($taxonomy);
	if ($tax) {
      $tax_name = $tax->labels->singular_name;
   } else {
      $err_msg = "No taxonomy found for slug $taxonomy";  // This will show in the error message
   }

   $args = array('orderby' => 'name', 'order' => 'ASC');
   if ($hide_uncategorized) $args['exclude'] = '1';
   $terms = get_terms($taxonomy,$args);
   ob_start();
   if (is_array($terms) && count($terms) > 0) {
      // For some unknown reason, $terms has no [0] entry at times, so renumber.
      $terms = array_merge($terms,array());
      $page = mam_get_paged();
      $start = mam_get_start($terms,$page,$limit);
      $end = mam_get_end($terms,$page,$limit);
      $currletter = '';
      echo '<ul class="term_list">';
      for ($i=$start;$i <= $end;++$i) {
         if ($i < sizeof($terms)) {
            $term =  $terms[$i];
            $termletter = strtoupper(substr($term->name,0,1));
            if ($currletter != $termletter) {
               if ($currletter != '') echo '</ul>';
               $currletter = $termletter;
               echo "<h2> - $termletter - </h2>";
               echo '<ul>';
            }
            echo "<li class='term_entry'>$tax_name: <a href='" . get_term_link( $term ) . "'" . ' title="' . sprintf( __( "View all posts in %s" ), $term->name ) . '" ' . '>' . $term->name.'</a> </p> ';
            if (!$hide_description) echo '<p>Description: '. $term->description . '</p>';
            echo '</li>';
         }
      }
      echo '</ul>';
      mam_paginate(sizeof($terms),$limit);
   } else {
      echo '<h2>No terms found</h2>';
      echo "<p>Taxonomy $taxonomy. $err_msg</p>";
   }
   return ob_get_clean();
}
function mam_get_paged() {
   if(isset($_GET['page'])){
      $page = $_GET['page'];
   } elseif (get_query_var('paged')) {
      $page = get_query_var('paged');
   } elseif (get_query_var('page')) {
      $page = get_query_var('page');
   } else {
      $page = 1;
   }
   return $page;
}
function mam_paginate($numrows,$limit) {
   $big = 999999999; // need an unlikely integer

	if ( ceil($numrows / $limit) > 1 ) {
	   $links = paginate_links( array(
	      'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
	      'format' => '?paged=%#%',
	      'current' => max( 1, mam_get_paged() ),
	      'total' => ceil($numrows / $limit),
	      'prev_next' => true,
	      'type' => 'array',
	   ) );
	   echo '<div class="term-nav">';
	      echo '<ul class="term-list">';
	         foreach ($links as $link) {
	            echo "<li>$link</li>";
	         }
	      echo '</ul>';
	   echo '</div>';
	}
}
function mam_get_start(&$terms,$page,$limit) {
   // Find the index of the first $terms entry whose first letter is
   // the same as the one determined by the page number.
   $ndx = ($page - 1) * $limit;  // The default first record index
   $first_letter = strtoupper(substr($terms[$ndx]->name,0,1));
   $prev = $ndx;
   while (--$prev > -1) {
      $prev_letter = strtoupper(substr($terms[$prev]->name,0,1));
      if( $prev_letter != $first_letter) break;
      $ndx = $prev;
   }
   return $ndx;
}
function mam_get_end(&$terms,$page,$limit) {
   // Find the index (+1) of the last $terms entry whose first letter is
   // the same as the one determined by the page number and the limit.
   $ndx = min( count($terms) - 1, (($page - 1 ) * $limit) + $limit - 1);
   $last_letter = strtoupper(substr($terms[$ndx]->name,0,1));
   $next = $ndx;
   while (++$next < count($terms) ) {
      $next_letter = strtoupper(substr($terms[$next]->name,0,1));
      if ($next_letter != $last_letter) break;
      $ndx = $next;
   }
   return $ndx;
}

Here is some sample CSS to style the pagination. Place this at the end of your style.css file.

/* Styles for list taxonomy by letter */
.term-nav  ul li {
   float: left;
   padding-left: 10px;
   list-style: none;
}
.term-nav .current {
   color: red;
}

5 Responses to List Taxonomy Terms By Letter

Leave a Reply

Your email address will not be published. Required fields are marked *

*