Adding A Custom Taxonomy Terms Widget To WordPress

The WordPress Categories Widget currently only handles the `category` taxonomy. I’ve modified it to allow the user to select a taxonomy, and tied in the Tag Cloud Widget code to give the user the choice of display formats: list, dropdown, and cloud. Multiple instances are possible, providing the user with an easy method for displaying links to user-built taxonomy terms.

`preg_replace_callback()` is used to fix the JavaScript for the dropdown menu; instead of generating the default `?query_var=value` format, it uses `get_term_link()` to generate the term URL.

[php]
function ucc_widgets_init() {
if ( !is_blog_installed() )
return;

register_widget( ‘WP_Widget_Taxonomy_Terms’ );

do_action( ‘widgets_init’ );
}

add_action( ‘init’ , ‘ucc_widgets_init’ , 1 );

class WP_Widget_Taxonomy_Terms extends WP_Widget {

function WP_Widget_Taxonomy_Terms() {
$widget_ops = array( ‘classname’ => ‘widget_taxonomy_terms’ , ‘description’ => __( "A list, dropdown, or cloud of taxonomy terms" ) );
$this->WP_Widget( ‘taxonomy_terms’ , __( ‘Taxonomy Terms’ ) , $widget_ops );
}

function widget( $args , $instance ) {
extract( $args );

$current_taxonomy = $this->_get_current_taxonomy( $instance );
$tax = get_taxonomy( $current_taxonomy );
if ( !empty( $instance[‘title’] ) ) {
$title = $instance[‘title’];
} else {
$title = $tax->labels->name;
}

global $t;
$t = $instance[‘taxonomy’];
$f = $instance[‘format’];
$c = $instance[‘count’] ? ‘1’ : ‘0’;
$h = $instance[‘hierarchical’] ? ‘1’ : ‘0’;

$w = $args[‘widget_id’];
$w = ‘ttw’ . str_replace( ‘taxonomy_terms-‘ , ” , $w );

echo $before_widget;
if ( $title )
echo $before_title . $title . $after_title;

$tax_args = array( ‘orderby’ => ‘name’ , ‘show_count’ => $c , ‘hierarchical’ => $h , ‘taxonomy’ => $t );

if ( $f == ‘dropdown’ ) {
$tax_args[‘show_option_none’] = __( ‘Select ‘ . $tax->labels->singular_name );
$tax_args[‘name’] = __( $w );
$tax_args[‘echo’] = false;
$my_dropdown_categories = wp_dropdown_categories( apply_filters( ‘widget_categories_dropdown_args’ , $tax_args ) );

$my_get_term_link = create_function( ‘$matches’ , ‘global $t; return "value=\"" . get_term_link( (int) $matches[1] , $t ) . "\"";’ );
echo preg_replace_callback( ‘#value="(\\d+)"#’ , $my_get_term_link , $my_dropdown_categories );

?>
<script type=’text/javascript’>
/* <![CDATA[ */
var dropdown<?php echo $w; ?> = document.getElementById("<?php echo $w; ?>");
function on<?php echo $w; ?>change() {
if ( dropdown<?php echo $w; ?>.options[dropdown<?php echo $w; ?>.selectedIndex].value != ‘-1’ ) {
location.href = dropdown<?php echo $w; ?>.options[dropdown<?php echo $w; ?>.selectedIndex].value;
}
}
dropdown<?php echo $w; ?>.onchange = on<?php echo $w; ?>change;
/* ]]> */
</script>
<?php

} elseif ( $f == ‘list’ ) {

?>
<ul>
<?php

$tax_args[‘title_li’] = ”;
wp_list_categories( apply_filters( ‘widget_categories_args’ , $tax_args ) );

?>
</ul>
<?php

} else {

?>
<div>
<?php

wp_tag_cloud( apply_filters( ‘widget_tag_cloud_args’ , array( ‘taxonomy’ => $t ) ) );

?>
</div>
<?php

}
echo $after_widget;
}

function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance[‘title’] = strip_tags( $new_instance[‘title’] );
$instance[‘taxonomy’] = stripslashes( $new_instance[‘taxonomy’] );
$instance[‘format’] = stripslashes( $new_instance[‘format’] );
$instance[‘count’] = !empty( $new_instance[‘count’] ) ? 1 : 0;
$instance[‘hierarchical’] = !empty( $new_instance[‘hierarchical’] ) ? 1 : 0;

return $instance;
}

function form( $instance ) {
//Defaults
$instance = wp_parse_args( (array) $instance , array( ‘title’ => ” ) );
$current_taxonomy = $this->_get_current_taxonomy( $instance );
$current_format = esc_attr( $instance[‘format’] );
$title = esc_attr( $instance[‘title’] );
$count = isset( $instance[‘count’] ) ? (bool) $instance[‘count’] : false;
$hierarchical = isset( $instance[‘hierarchical’] ) ? (bool) $instance[‘hierarchical’] : false;

?>
<p><label for="<?php echo $this->get_field_id( ‘title’ ); ?>"><?php _e( ‘Title:’ ); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id( ‘title’ ); ?>" name="<?php echo $this->get_field_name( ‘title’ ); ?>" type="text" value="<?php echo $title; ?>" /></p>

<p><label for="<?php echo $this->get_field_id( ‘taxonomy’ ); ?>"><?php _e( ‘Taxonomy:’ ); ?></label>
<select class="widefat" id="<?php echo $this->get_field_id( ‘taxonomy’ ); ?>" name="<?php echo $this->get_field_name( ‘taxonomy’ ); ?>">
<?php

$args = array(
‘public’ => true ,
‘_builtin’ => false
);
$output = ‘names’;
$operator = ‘and’;

$taxonomies = get_taxonomies( $args , $output , $operator );
$taxonomies = array_merge( $taxonomies, array( ‘category’ , ‘post_tag’ ) );
foreach ( $taxonomies as $taxonomy ) {
$tax = get_taxonomy( $taxonomy );
if ( empty( $tax->labels->name ) )
continue;
?>
<option value="<?php echo esc_attr( $taxonomy ); ?>" <?php selected( $taxonomy , $current_taxonomy ); ?>><?php echo $tax->labels->name; ?></option>
<?php

}

?>
</select></p>

<p><label for="<?php echo $this->get_field_id( ‘format’ ); ?>"><?php _e( ‘Format:’ ) ?></label>
<select class="widefat" id="<?php echo $this->get_field_id( ‘format’ ); ?>" name="<?php echo $this->get_field_name( ‘format’ ); ?>">
<?php

$formats = array( ‘list’ , ‘dropdown’ , ‘cloud’ );
foreach( $formats as $format ) {

?>
<option value="<?php echo esc_attr( $format ); ?>" <?php selected( $format , $current_format ); ?>><?php echo ucfirst( $format ); ?></option>
<?php

}

?>
</select></p>
<input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id( ‘count’ ); ?>" name="<?php echo $this->get_field_name( ‘count’ ); ?>"<?php checked( $count ); ?> />
<label for="<?php echo $this->get_field_id( ‘count’ ); ?>"><?php _e( ‘Show post counts’ ); ?></label><br />

<input type="checkbox" class="checkbox" id="<?php echo $this->get_field_id( ‘hierarchical’ ); ?>" name="<?php echo $this->get_field_name( ‘hierarchical’ ); ?>"<?php checked( $hierarchical ); ?> />
<label for="<?php echo $this->get_field_id( ‘hierarchical’ ); ?>"><?php _e( ‘Show hierarchy’ ); ?></label></p>
<?php

}

function _get_current_taxonomy( $instance ) {
if ( !empty( $instance[‘taxonomy’] ) && taxonomy_exists( $instance[‘taxonomy’] ) )
return $instance[‘taxonomy’];
else
return ‘category’;
}
}
[/php]


## Changelog
### 02 September 2010
Updated JavaScript to deal with multiple dropdowns on the same page by using the unique identifier `$w`.

## References
[The complete guide to creating widgets in WordPress 2.8](http://justintadlock.com/archives/2009/05/26/the-complete-guide-to-creating-widgets-in-wordpress-28)
[/wp-includes/default-widgets.php](http://core.trac.wordpress.org/browser/trunk/wp-includes/default-widgets.php)

12 thoughts on “Adding A Custom Taxonomy Terms Widget To WordPress

  1. Really useful widget thank you. You say multiple instances are possible and yes they do appear BUT only one works at a time (at least in my experience). I’ve used the code exactly as you have displayed above. Any ideas?

  2. I just tested this out locally; I have three instances of the Taxonomy Terms Widget running in the footer of this site, two with identical settings except for the title. Which theme are you using?

  3. This is a development site but take a look at http://www.stevegraham.me which is using a child of twenty-ten.

    You will see that I have added two dropdowns; one for Business Directory i.e. custom taxonomy ‘business’ and another showing a dropdown of ‘post_tags’.

    I tested this with just the first and it works fine but as soon as I add the second it stops functioning. Similarly, if I swap over and have Tags its fine then add Business and the first stops working.

  4. Thanks Jennifer. As you can see I am developing a directory using custom taxonomy within custom posts and your mod of the category widget has saved me a whole lot of trouble.

  5. Hi,

    I have installed your Plugin, and all is well. However, I must be missing something, because:
    – I am always shown all posts from all custom taxonomies
    – the selected c.t. does not remain selected (in the dropdown)

    Contrary to that, I am trying to select one of the taxonomies and get shown only the posts with that taxomony.

    You can look at this on http://regional.internet-dienste.biz (it is in German, but you will recognize the widget in the sidebar.

    Any help is appreciated.

  6. OK, the first part seems to have solved itself – by some miracle (or amounts of coffee), I discovered the Taxonomy Terms Widget, and by including this, instead of custom menus, as used previously, only the selected custom taxonomy related posts are shown.

    However, the second issue still prevails: as soon as I select a taxonomy, the drop-down box is reset upon displaying the list of posts.

  7. Hello there,
    Great line of code there, it should be in core of WordPress for a long time by now.
    Anyways on line 121 you are missing a semicolon in your translation statement

    
    

    Should be

    
    

    Still love this little thing, I use it all the time 🙂

Comments are closed.