Multiple taxonomies in a dropdown menus

July 29, 2010 | Wordpress tutorials | 9 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.

9 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

    • John says:

      Hey thanks for the alternative code! Would it be possible for you to guide me where exactly I add the Taxonomy terms in the taxonomy template?

      Would it great if you could upload the full code online.

      And thanks a ton to Slashas for the original code :)

  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

  6. Thomas says:

    Hi

    Thanks for this tutorial. I have come across an issue though. When selecting from the dropdown it shows the page of that term with the associated content, however I’m not sure which template it is calling.

    I’m assuming it’s calling the archive.php template? Problem is that I have created seperate content type templates and now I want the taxonomy term page generated by the drop down to use the sample content type template. Short of creating taxonomy-mytax.php files what other solutions would you recommend?

  7. Lindsay says:

    Thanks Hugo. Your code saved me!

    Slashes, your solution worked wonderfully for me on my development site. I had a sidebar drop-down of four different taxonomies, ways to navigate a menu. But, when I moved to production, one of my drop-downs wouldn’t populate. I looked through all of my slugs to make sure there wasn’t a conflict, then I adjusted the ‘largest’ and ‘number’ inputs to see if they were set too low for my actual data. But, to no avail–I couldn’t figure out what the problem was.

    Finally, I tried Hugo’s code and it worked first try.

    Great work and thanks to both of you. What would we do without this open source community?

  8. Most weblogs often copy other information sites or sites of newspapers and magazines. Subscribe to this weblog here I like that you will find unique content articles that one could hardly come across elsewhere. Luckily, there are even now these kinds of information sites, make sure you go on! I can no longer see the popular media. It can be there so much garbage prepared, I bear it no additional soon. A actually pleasant weblog, with thanks.

Leave a Reply