Customize Categories on the ClassiPress Search Form

The ClassiPress Search Form includes a dropdown list of ads categories, which allows refining search results by a selected category.

ClassiPress Search Form
ClassiPress Search Form

It uses the WordPress function wp_dropdown_categories() to generate categories dropdown list HTML with a set of options that provides the ClassiPress function cp_get_dropdown_categories_search_args(). This function has a filter cp_dropdown_search_bar_args which you can use for complete customizing the Categories dropdown.

This is how it looks by default:

Default ClassiPress search categories dropdown list
Default ClassiPress search categories dropdown list

Below you will find the filter specification and some useful customization examples.

Filter ‘cp_dropdown_search_bar_args’ parameters

  • 'show_option_all'(string) Text to display for showing all categories. Default “All Categories”
  • 'show_option_none'(string) Text to display for showing no categories. Default empty.
  • 'option_none_value'(string) Value to use when no category is selected. Default empty.
  • 'orderby'(string) Which column to use for ordering categories. Accepts term fields (‘name’, ‘slug’, ‘term_group’, ‘term_id’, ‘id’, ‘description’, ‘parent’), ‘count’ for term taxonomy count. Default ‘name’.
  • 'pad_counts'(bool) Whether to pad the quantity of a term’s children in the quantity of each term’s “count” object variable. Defaults to ClassiPress option Search Categories >> Show Count.
  • 'show_count'(bool|int) Whether to include post counts. Accepts 0, 1, or their bool equivalents. Defaults to ClassiPress option Search Categories >> Show Count.
  • 'echo'(bool|int) Whether to echo or return the generated markup. Accepts 0, 1, or their bool equivalents. Default 1.
  • 'hierarchical'(bool|int) Whether to traverse the taxonomy hierarchy. Accepts 0, 1, or their bool equivalents. Defaults to ClassiPress option Search Categories >> Hierarchy.
  • 'depth'(int) Maximum depth. Defaults to ClassiPress option Search Categories >> Depth.
  • 'tab_index'(int) Tab index for the select element. Default 2.
  • 'name'(string) Value for the ‘name’ attribute of the select element. Default ‘scat’. Don’t change this!
  • 'id'(string) Value for the ‘id’ attribute of the select element. Defaults to the value of $name. Don’t change this!
  • 'class'(string) Value for the ‘class’ attribute of the select element. Default ‘searchbar’.
  • 'selected'(int|string) Value of the option that should be selected. Default 0.
  • 'value_field'(string) Term field that should be used to populate the ‘value’ attribute of the option elements. Accepts any valid term field: ‘term_id’, ‘name’, ‘slug’, ‘term_group’, ‘term_taxonomy_id’, ‘taxonomy’, ‘description’, ‘parent’, ‘count’. Default ‘term_id’.
  • 'taxonomy'(string|array) Name of the category or categories to retrieve. Default ‘ad_cat’.
  • 'hide_empty'(bool) True to skip generating markup if no categories are found. Defaults to ClassiPress option Search Categories >> Hide Empty.
  • 'required'(bool) Whether the <select> element should have the HTML5 ‘required’ attribute. Default false.
  • 'walker'(Walker) The custom walker object instance. You can completely change the HTML output for the categories dropdown using your custom Walker object. Default instance of Walker_CategoryDropdown.

Customize Categories dropdown examples

Examples provided with code snippets which you can add in a custom plugin or child theme functions.php file. Alternatively, Code Snippets plugin can be used (more details in the instruction).

1. Basic example – change some parameters

add_filter( 'cp_dropdown_search_bar_args', function( $args ) {
	$args['orderby']      = 'count';
	$args['order']        = 'DESC';	
	$args['show_count']   = true;
	$args['hierarchical'] = false;
	return $args;
} );

In this example a plain list of categories ordered by the ads count. By the way, it works fine only if hierarchy disabled.

See how it looks now:

ClassiPress search categories ordered by ad counts
ClassiPress search categories ordered by ad counts

2. Advanced example – Collapse sub categories in dropdown.

Following example uses JS lib Select2 to enable more options for displaying dropdown list. For example, it adds the search box on the list to enable typing autocomplete. But the main feature is that it makes sub categories collapsible and expandable, what is super useful if you have a long list of categories. When you open the dropdown, you see the list of only parent categories, which you can expand to see child categories.

This example has a little more complex code snippet, but you can add it the same way as previous one.

add_action( 'wp_head', function () { ?>
<style>
	.select2-container {
		font-size: 1rem;
		max-width: 100%!important;
	}
	#select2-scat-container, .select2-selection__arrow {
		height: 100%!important;		
		line-height: 2.2rem!important;		
	}
	.select2-selection--single {
		min-height: 2.4375rem;
	}
	#select2-scat-container {
		text-align: left;
	}
</style>
<script>
jQuery( function( $ ) {
	( function( d ) {
		let s = d.createElement( 'script' );
		s.async = true;
		s.src = 'https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/js/select2.min.js';
		if ( d.head ) d.head.appendChild( s );
		s.onload = function() {
			$( ".search-category-wrap #scat" ).select2( {
				//minimumResultsForSearch: Infinity 
			} );
			let optgroupState = { };
			$( "body" ).on( 'click', '.select2-container--open .select2-results__group', function() {
				$( this ).siblings().toggle();
				let id = $( this ).closest( '.select2-results__options' ).attr( 'id' );
				let index = $( '.select2-results__group' ).index( this );
				optgroupState[id][index] = !optgroupState[id][index];
			} );
			$( ".search-category-wrap #scat" ).on( 'select2:open', function() {
				$( '.select2-dropdown--below' ).css( 'opacity', 0 );
				setTimeout( () => {
					let groups = $( '.select2-container--open .select2-results__group' );
					let id = $( '.select2-results__options' ).attr( 'id' );
					if ( !optgroupState[id] ) {
						optgroupState[id] = { };
					}
					$.each( groups, ( index, v ) => {
						optgroupState[id][index] = optgroupState[id][index] || false;
						optgroupState[id][index] ? $( v ).siblings().show() : $( v ).siblings().hide();
					} );
					$( '.select2-dropdown--below' ).css( 'opacity', 1 );
				}, 100 );
			} );
		};
	} )( document );
} );	
</script>
<?php } );

add_action( 'wp_enqueue_scripts', function() {
	wp_enqueue_style( 'select2-css', 'https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css', array(), '4.0.13', 'all' );
} );

add_filter( 'cp_dropdown_search_bar_args', function( $args ) {
	$args['walker'] = new ArThemes_Walker_Search_CategoryDropdown();
	return $args;
} );

class ArThemes_Walker_Search_CategoryDropdown extends Walker_CategoryDropdown {
	
	public function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
		if ( 0 == $depth ) {
			$cat_name = apply_filters( 'list_cats', $category->name, $category );
			$output .= "<optgroup class=\"level-$depth\" label=\"".$cat_name."\" >";
		}		
		
		parent::start_el( $output, $category, $depth, $args, $id );
	}
	
	public function end_el( &$output, $object, $depth = 0, $args = array() ) {
		if ( 0 == $depth ) {
			$output .= '</optgroup>';
		}		
	}
}

Now we use walker parameter to add an extended instance of Walker_CategoryDropdown class, which wraps sub category elements in to optgroups that used by Select2 lib to make them collapsible.

The result see on image below:

Collapsed search categories list

Collapsed search categories dropdown list

Like