Multiple taxonomies in a dropdown menus

July 29, 2010 | Wordpress tutorials | 5 Comments »

There was a question how to make multiple custom taxonomies dropdown menu, for a comment it would be too long, so I wrote this tutorial.

Firstly you should read the first post regarding dropdown taxonomy:
http://www.aroundwp.com/display-custom-taxonomy-terms-in-a-dropdown-menu/

So now we must modify original code a little of jumpto.php file.

Original code

<?php
// Solution for displaying custom taxonomy terms in a dropdown menu.
function dropdown_tag($taxonomy, $args = '' ) {
	$defaults = array('taxonomy' => 'my_taxonomy', // <- write taxonomy name
		'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
		'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC',
		'exclude' => '', 'include' => ''
	);
	$args = wp_parse_args( $args, $defaults );

	$terms = get_terms($taxonomy, array_merge($args, array('orderby' => 'count', 'order' => 'DESC')) );

	if ( empty($terms) )
		return;

	$return = generate_dropdown_tag( $terms, $taxonomy, $args );
	if ( is_wp_error( $return ) )
		return false;
	else
		echo apply_filters( 'dropdown_tag', $return, $args );
}

function generate_dropdown_tag( $terms, $taxonomy, $args = '' ) {
	global $wp_rewrite;
	$defaults = array(
		'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
		'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC'
	);
	$args = wp_parse_args( $args, $defaults );
	extract($args);

	if ( !$terms )
		return;
	$counts = $term_links = array();
	foreach ( (array) $terms as $term ) {
		$counts[$term->name] = $term->count;
		$term_links[$term->name] = get_term_link( $term->name, $taxonomy );
		if ( is_wp_error( $term_links[$term->name] ) )
			return $term_links[$term->name];
		$term_ids[$term->name] = $term->term_id;
	}

	$min_count = min($counts);
	$spread = max($counts) - $min_count;
	if ( $spread <= 0 )
		$spread = 1;
	$font_spread = $largest - $smallest;
	if ( $font_spread <= 0 )
		$font_spread = 1;
	$font_step = $font_spread / $spread;

	// SQL cannot save you; this is a second (potentially different) sort on a subset of data.
	if ( 'name' == $orderby )
		uksort($counts, 'strnatcasecmp');
	else
		asort($counts);

	if ( 'DESC' == $order )
		$counts = array_reverse( $counts, true );

	$a = array();

	$rel = ( is_object($wp_rewrite) && $wp_rewrite->using_permalinks() ) ? ' rel="term"' : '';

	foreach ( $counts as $term => $count ) {
		$term_id = $term_ids[$term];
		$term_link = clean_url($term_links[$term]);
		$term = str_replace(' ', '&nbsp;', wp_specialchars( $term ));
		$a[] = "\t<option value='$term_link'>$term ($count)</option>";
	}

	switch ( $format ) :
	case 'array' :
		$return =& $a;
		break;
	case 'list' :
		$return = "<ul class='wp-tag-cloud'>\n\t<li>";
		$return .= join("</li>\n\t<li>", $a);
		$return .= "</li>\n</ul>\n";
		break;
	default :
		$return = join("\n", $a);
		break;
	endswitch;

	return apply_filters( 'generate_dropdown_tag', $return, $term, $args );
}
?>

Now in this code we have two functions dropdown_tag and generate_dropdown_tag.

Function dropdown_tag

function dropdown_tag($taxonomy, $args = '' ) {
	$defaults = array('taxonomy' => 'my_taxonomy', // <- write taxonomy name
		'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
		'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC',
		'exclude' => '', 'include' => ''
	);
	$args = wp_parse_args( $args, $defaults );

	$terms = get_terms($taxonomy, array_merge($args, array('orderby' => 'count', 'order' => 'DESC')) );

	if ( empty($terms) )
		return;

	$return = generate_dropdown_tag( $terms, $taxonomy, $args );
	if ( is_wp_error( $return ) )
		return false;
	else
		echo apply_filters( 'dropdown_tag', $return, $args );
}

Function generate_dropdown_tag

function generate_dropdown_tag( $terms, $taxonomy, $args = '' ) {
	global $wp_rewrite;
	$defaults = array(
		'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
		'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC'
	);
	$args = wp_parse_args( $args, $defaults );
	extract($args);

	if ( !$terms )
		return;
	$counts = $term_links = array();
	foreach ( (array) $terms as $term ) {
		$counts[$term->name] = $term->count;
		$term_links[$term->name] = get_term_link( $term->name, $taxonomy );
		if ( is_wp_error( $term_links[$term->name] ) )
			return $term_links[$term->name];
		$term_ids[$term->name] = $term->term_id;
	}

	$min_count = min($counts);
	$spread = max($counts) - $min_count;
	if ( $spread <= 0 )
		$spread = 1;
	$font_spread = $largest - $smallest;
	if ( $font_spread <= 0 )
		$font_spread = 1;
	$font_step = $font_spread / $spread;

	// SQL cannot save you; this is a second (potentially different) sort on a subset of data.
	if ( 'name' == $orderby )
		uksort($counts, 'strnatcasecmp');
	else
		asort($counts);

	if ( 'DESC' == $order )
		$counts = array_reverse( $counts, true );

	$a = array();

	$rel = ( is_object($wp_rewrite) && $wp_rewrite->using_permalinks() ) ? ' rel="term"' : '';

	foreach ( $counts as $term => $count ) {
		$term_id = $term_ids[$term];
		$term_link = clean_url($term_links[$term]);
		$term = str_replace(' ', '&nbsp;', wp_specialchars( $term ));
		$a[] = "\t<option value='$term_link'>$term ($count)</option>";
	}

	switch ( $format ) :
	case 'array' :
		$return =& $a;
		break;
	case 'list' :
		$return = "<ul class='wp-tag-cloud'>\n\t<li>";
		$return .= join("</li>\n\t<li>", $a);
		$return .= "</li>\n</ul>\n";
		break;
	default :
		$return = join("\n", $a);
		break;
	endswitch;

	return apply_filters( 'generate_dropdown_tag', $return, $term, $args );
}

To make it work with multiple custom taxonomies we need to clone dropdown_tag function and change it’s name in 2 places.

// First taxonomy
function dropdown_tag($taxonomy, $args = '' ) {
	$defaults = array('taxonomy' => 'first_tax', // <- write taxonomy name
		'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
		'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC',
		'exclude' => '', 'include' => ''
	);
	$args = wp_parse_args( $args, $defaults );

	$terms = get_terms($taxonomy, array_merge($args, array('orderby' => 'count', 'order' => 'DESC')) );

	if ( empty($terms) )
		return;

	$return = generate_dropdown_tag( $terms, $taxonomy, $args );
	if ( is_wp_error( $return ) )
		return false;
	else
		echo apply_filters( 'dropdown_tag', $return, $args );
}

//Second taxonomy
function dropdown_tag_second($taxonomy, $args = '' ) {
	$defaults = array('taxonomy' => 'second_tax', // <- write taxonomy name
		'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
		'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC',
		'exclude' => '', 'include' => ''
	);
	$args = wp_parse_args( $args, $defaults );

	$terms = get_terms($taxonomy, array_merge($args, array('orderby' => 'count', 'order' => 'DESC')) );

	if ( empty($terms) )
		return;

	$return = generate_dropdown_tag( $terms, $taxonomy, $args );
	if ( is_wp_error( $return ) )
		return false;
	else
		echo apply_filters( 'dropdown_tag_second', $return, $args );
}

As you can see for a second taxonomy I used function dropdown_tag_second name on 23 and 40 lines.


Final code of jumpto.php to support multiple taxonomies in a dropdown menus.

<?php
// First taxonomy
function dropdown_tag($taxonomy, $args = '' ) {
	$defaults = array('taxonomy' => 'first_tax', // <- write taxonomy name
		'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
		'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC',
		'exclude' => '', 'include' => ''
	);
	$args = wp_parse_args( $args, $defaults );

	$terms = get_terms($taxonomy, array_merge($args, array('orderby' => 'count', 'order' => 'DESC')) );

	if ( empty($terms) )
		return;

	$return = generate_dropdown_tag( $terms, $taxonomy, $args );
	if ( is_wp_error( $return ) )
		return false;
	else
		echo apply_filters( 'dropdown_tag', $return, $args );
}

//Second taxonomy
function dropdown_tag_second($taxonomy, $args = '' ) {
	$defaults = array('taxonomy' => 'second_tax', // <- write taxonomy name
		'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
		'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC',
		'exclude' => '', 'include' => ''
	);
	$args = wp_parse_args( $args, $defaults );

	$terms = get_terms($taxonomy, array_merge($args, array('orderby' => 'count', 'order' => 'DESC')) );

	if ( empty($terms) )
		return;

	$return = generate_dropdown_tag( $terms, $taxonomy, $args );
	if ( is_wp_error( $return ) )
		return false;
	else
		echo apply_filters( 'dropdown_tag_second', $return, $args );
}

function generate_dropdown_tag( $terms, $taxonomy, $args = '' ) {
	global $wp_rewrite;
	$defaults = array(
		'smallest' => 8, 'largest' => 22, 'unit' => 'pt', 'number' => 45,
		'format' => 'flat', 'orderby' => 'name', 'order' => 'ASC'
	);
	$args = wp_parse_args( $args, $defaults );
	extract($args);

	if ( !$terms )
		return;
	$counts = $term_links = array();
	foreach ( (array) $terms as $term ) {
		$counts[$term->name] = $term->count;
		$term_links[$term->name] = get_term_link( $term->name, $taxonomy );
		if ( is_wp_error( $term_links[$term->name] ) )
			return $term_links[$term->name];
		$term_ids[$term->name] = $term->term_id;
	}

	$min_count = min($counts);
	$spread = max($counts) - $min_count;
	if ( $spread <= 0 )
		$spread = 1;
	$font_spread = $largest - $smallest;
	if ( $font_spread <= 0 )
		$font_spread = 1;
	$font_step = $font_spread / $spread;

	// SQL cannot save you; this is a second (potentially different) sort on a subset of data.
	if ( 'name' == $orderby )
		uksort($counts, 'strnatcasecmp');
	else
		asort($counts);

	if ( 'DESC' == $order )
		$counts = array_reverse( $counts, true );

	$a = array();

	$rel = ( is_object($wp_rewrite) && $wp_rewrite->using_permalinks() ) ? ' rel="term"' : '';

	foreach ( $counts as $term => $count ) {
		$term_id = $term_ids[$term];
		$term_link = clean_url($term_links[$term]);
		$term = str_replace(' ', '&nbsp;', wp_specialchars( $term ));
		$a[] = "\t<option value='$term_link'>$term ($count)</option>";
	}

	switch ( $format ) :
	case 'array' :
		$return =& $a;
		break;
	case 'list' :
		$return = "<ul class='wp-tag-cloud'>\n\t<li>";
		$return .= join("</li>\n\t<li>", $a);
		$return .= "</li>\n</ul>\n";
		break;
	default :
		$return = join("\n", $a);
		break;
	endswitch;

	return apply_filters( 'generate_dropdown_tag', $return, $term, $args );
}
?>

All modifications are done, now you can open for example sidebar.php and paste:

// First dropdown taxonomy
<select name="tag-dropdown" onchange="document.location.href=this.options[this.selectedIndex].value;">
<option value="#">Select...</option>
<?php dropdown_tag('first_tax', 'number=0&order=asc'); ?>
</select>
// Second dropdown taxonomy
<select name="tag-dropdown" onchange="document.location.href=this.options[this.selectedIndex].value;">
<option value="#">Select...</option>
<?php dropdown_tag_second('second_tax', 'number=0&order=asc'); ?>
</select>
p.s.
I think there is a better solution for multiple taxonomy dropdown, but this is my 5 cents.

5 Responses

  1. Hugo says:

    Woo thanks for the reply, thats a great solution. In the meantime i found a way to accomplish the same thing but with a different approach.

    Can i paste the code in the comment box?

    I just started using taxonomies with this new version of wordpress, i think its a great way to group posts and easily manage them in wp admin panel and also use them as a suport navigation in a website. Aroundwp.com tutorial “Display custom taxonomy terms in a dropdown menu” was a staring point to explore taxonomies, really cool.

    And what about custom post types? I will wait for a tutorial about this new wp feature.

    Keep up with good work.

  2. slashas says:

    hello Hugo,
    yes you can paste your code, just use [php] [/php] tags, example:

    //your code
    
  3. Hugo says:

    Woo, always learning. Ok so here´s my alternative solution:

    In functions.php add

    function get_terms_dropdown($taxonomies, $args){
    	$myterms = get_terms($taxonomies, $args);
    	$output ="";
    	foreach($myterms as $term){
    		$root_url = get_bloginfo('url');
    		$term_taxonomy=$term->taxonomy;
    		$term_slug=$term->slug;
    		$term_name =$term->name;
    		$link = $root_url.'/'.$term_taxonomy.'/'.$term_slug;
    		$output .="<option value='".$link."'>".$term_name."</option>";
    	}
    	$output .="";
    return $output;
    }
    

    and then in the taxonomy template add:

    Select Taxonomy terms

    $taxonomies = array('taxonomy-name');
    $args = array('orderby'=>'name','hide_empty'=>true);
    echo get_terms_dropdown($taxonomies, $args);
    

    Its a bit more flexible. Hope its helps wp developers.

    Keep up the good work

  4. Hugo says:

    Almost there, it didnt show the form, here it is:

    <form>
    <select name="tag-dropdown" onchange="document.location.href=this.options[this.selectedIndex].value;">
    <option value='#'>Select Taxonomy terms</option>
    $taxonomies = array('taxonomy-name');
    $args = array('orderby'=>'name','hide_empty'=>true);
    echo get_terms_dropdown($taxonomies, $args);
    </select>
    </form>
    
  5. I just started using taxonomies with this new version of wordpress, i think its a great way to group posts and easily manage them in wp admin panel and also use them as a suport navigation in a website. Aroundwp.com tutorial “Display custom taxonomy terms in a dropdown menu” was a staring point to explore taxonomies, really cool.
    +1

Leave a Reply