Search Filter results grouped by first character

header-tut-search-filter-grouped-results
For one of my clients’ projects, I needed to set up the following situation:

  • A search page for posts in a specific category. This was essential, as multiple of these search pages were required.
  • default lay-out:
    • a search box
    • anchor link buttons for 0-9 and A-Z linking to the posts where the title starts with that number or letter
    • and below that, all of the posts (or a filtered list after a search), grouped by the first character of the title
    • that character displayed above each character group.

Seemed simple enough, but turned out quite a search before I had the right answers!

Search & Filter Pro is a very handy plugin for creating search filters, so that was my first choice. But it does not allow for the post titles to be grouped by first character.

The solution was a combination of html, css and a bit of jquery:

The PHP/HTML:

  • the results.php file can be customized by adding it to the search-filter folder within your theme. That way, plugin updates will not cause any issues.
  • adding the ucwords command makes sure the first letter is always a capital. This is handy, because if the content manager forgets to Capitalize the post title, the script wouldn’t work.
  • each post is given a class of az plus its first character.
  • az is added because classes starting with numbers may cause problems.
  • the name added to each post title link allows for the creation of the anchor links at the top of the page.
  • the customized PHP/HTML in the results.php file:
<?php

if ( $query->have_posts() )
{
	?>
	
	<?php
	while ($query->have_posts())
	{
		$query->the_post();
		
		?>
			<?php $title = ucwords(get_the_title()); ?>
				<a name="<?php echo 'az' . $title[0]; ?>" class="<?php echo 'az' . $title[0]; ?>"href="<?php the_permalink(); ?>">
					<?php the_title(); ?>
				</a>
		<?php
	}
}
else
{
	echo "No Results Found";
}
?>

The jQuery:

  • at the top of the same results.php file I added the following script:
  • the bottom margin was added with jQuery because I could not find a way to target the last item with a specific class. Last-child does not work with classes, nor does last-of-type.
<script>
var $j = jQuery.noConflict();
$j(document).ready(function() {
	$j('a.az0:last').css({ marginBottom:"30px" });
	$j('a.az1:last').css({ marginBottom:"30px" });
	$j('a.az2:last').css({ marginBottom:"30px" });
	$j('a.az3:last').css({ marginBottom:"30px" });
	$j('a.az4:last').css({ marginBottom:"30px" });
	$j('a.az5:last').css({ marginBottom:"30px" });
	$j('a.az6:last').css({ marginBottom:"30px" });
	$j('a.az7:last').css({ marginBottom:"30px" });
	$j('a.az8:last').css({ marginBottom:"30px" });
	$j('a.az9:last').css({ marginBottom:"30px" });
	$j('a.azA:last').css({ marginBottom:"30px" });
	$j('a.azB:last').css({ marginBottom:"30px" });
	$j('a.azC:last').css({ marginBottom:"30px" });
	$j('a.azD:last').css({ marginBottom:"30px" });
	$j('a.azE:last').css({ marginBottom:"30px" });
	$j('a.azF:last').css({ marginBottom:"30px" });
	$j('a.azG:last').css({ marginBottom:"30px" });
	$j('a.azH:last').css({ marginBottom:"30px" });
	$j('a.azI:last').css({ marginBottom:"30px" });
	$j('a.azJ:last').css({ marginBottom:"30px" });
	$j('a.azK:last').css({ marginBottom:"30px" });
	$j('a.azL:last').css({ marginBottom:"30px" });
	$j('a.azM:last').css({ marginBottom:"30px" });
	$j('a.azN:last').css({ marginBottom:"30px" });
	$j('a.azO:last').css({ marginBottom:"30px" });
	$j('a.azP:last').css({ marginBottom:"30px" });
	$j('a.azQ:last').css({ marginBottom:"30px" });
	$j('a.azR:last').css({ marginBottom:"30px" });
	$j('a.azS:last').css({ marginBottom:"30px" });
	$j('a.azT:last').css({ marginBottom:"30px" });
	$j('a.azU:last').css({ marginBottom:"30px" });
	$j('a.azV:last').css({ marginBottom:"30px" });
	$j('a.azW:last').css({ marginBottom:"30px" });
	$j('a.azX:last').css({ marginBottom:"30px" });
	$j('a.azY:last').css({ marginBottom:"30px" });
	$j('a.azZ:last').css({ marginBottom:"30px" });							
});

The CSS:

<style>
/* code blow resizes the search box */
.searchandfilter { 
	width:25%; 
	float:left; 
	height:100px; 
}

/* code below creates the row of anchor link buttons next to the search box. */
/* handy if there are many results. */
#AZ { 
	float:left; 
	width:75%; 
	height:100px;
}

#AZ	a { 
	display:inline-block; 
	font-size:1em; 
	width:1.46em; 
	height:1.46em; 
	background:black; 
	color:white;
	text-align:center; 
	line-height:1.2; 
	text-transform:uppercase;
}

.search-filter-results a { display:block; }

/* code below creates the character above each group of posts */
.search-filter-results > a.az0:before,
.search-filter-results > a.az1:before,
.search-filter-results > a.az2:before,
.search-filter-results > a.az3:before,
.search-filter-results > a.az4:before,
.search-filter-results > a.az5:before,
.search-filter-results > a.az6:before,
.search-filter-results > a.az7:before,
.search-filter-results > a.az8:before,
.search-filter-results > a.az9:before,
.search-filter-results > a.azA:before,
.search-filter-results > a.azB:before,
.search-filter-results > a.azC:before,
.search-filter-results > a.azD:before,
.search-filter-results > a.azE:before,
.search-filter-results > a.azF:before,
.search-filter-results > a.azG:before,
.search-filter-results > a.azH:before,
.search-filter-results > a.azI:before,
.search-filter-results > a.azJ:before,
.search-filter-results > a.azK:before,
.search-filter-results > a.azL:before,
.search-filter-results > a.azM:before,
.search-filter-results > a.azN:before,
.search-filter-results > a.azO:before,
.search-filter-results > a.azP:before,
.search-filter-results > a.azQ:before,
.search-filter-results > a.azR:before,
.search-filter-results > a.azS:before,
.search-filter-results > a.azT:before,
.search-filter-results > a.azU:before,
.search-filter-results > a.azV:before,
.search-filter-results > a.azW:before,
.search-filter-results > a.azX:before,
.search-filter-results > a.azY:before,
.search-filter-results > a.azZ:before { 
	position:relative; 
	font-size:1.5em; 
	height:30px;
	display:block;
	top:0; 
	left:0;	
	text-align:left;
	line-height:1.4;
}

.search-filter-results > a.az0:before { content:"0"; }
.search-filter-results > a.az1:before { content:"1"; }
.search-filter-results > a.az2:before { content:"2"; }
.search-filter-results > a.az3:before { content:"3"; }
.search-filter-results > a.az4:before { content:"4"; }
.search-filter-results > a.az5:before { content:"5"; }
.search-filter-results > a.az6:before { content:"6"; }
.search-filter-results > a.az7:before { content:"7"; }
.search-filter-results > a.az8:before { content:"8"; }
.search-filter-results > a.az9:before { content:"9"; }
.search-filter-results > a.azA:before { content:"A"; }
.search-filter-results > a.azB:before { content:"B"; }
.search-filter-results > a.azC:before { content:"C"; }
.search-filter-results > a.azD:before { content:"D"; }
.search-filter-results > a.azE:before { content:"E"; }
.search-filter-results > a.azF:before { content:"F"; }
.search-filter-results > a.azG:before { content:"G"; }
.search-filter-results > a.azH:before { content:"H"; }
.search-filter-results > a.azI:before { content:"I"; }
.search-filter-results > a.azJ:before { content:"J"; }
.search-filter-results > a.azK:before { content:"K"; }
.search-filter-results > a.azL:before { content:"L"; }
.search-filter-results > a.azM:before { content:"M"; }
.search-filter-results > a.azN:before { content:"N"; }
.search-filter-results > a.azO:before { content:"O"; }
.search-filter-results > a.azP:before { content:"P"; }
.search-filter-results > a.azQ:before { content:"Q"; }
.search-filter-results > a.azR:before { content:"R"; }
.search-filter-results > a.azS:before { content:"S"; }
.search-filter-results > a.azT:before { content:"T"; }
.search-filter-results > a.azU:before { content:"U"; }
.search-filter-results > a.azV:before { content:"V"; }
.search-filter-results > a.azW:before { content:"W"; }
.search-filter-results > a.azX:before { content:"X"; }
.search-filter-results > a.azY:before { content:"Y"; }
.search-filter-results > a.azZ:before { content:"Z"; }

/* code below ensures only the first post instance of each character 
displays a grouping character above it */
.search-filter-results > a.az0 ~ a.az0:before,
.search-filter-results > a.az1 ~ a.az1:before,
.search-filter-results > a.az2 ~ a.az2:before,
.search-filter-results > a.az3 ~ a.az3:before,
.search-filter-results > a.az4 ~ a.az4:before,
.search-filter-results > a.az5 ~ a.az5:before,
.search-filter-results > a.az6 ~ a.az6:before,
.search-filter-results > a.az7 ~ a.az7:before,
.search-filter-results > a.az8 ~ a.az8:before,
.search-filter-results > a.az9 ~ a.az9:before,
.search-filter-results > a.azA ~ a.azA:before,
.search-filter-results > a.azB ~ a.azB:before,
.search-filter-results > a.azC ~ a.azC:before,
.search-filter-results > a.azD ~ a.azD:before,
.search-filter-results > a.azE ~ a.azE:before,
.search-filter-results > a.azF ~ a.azF:before,
.search-filter-results > a.azG ~ a.azG:before,
.search-filter-results > a.azH ~ a.azH:before,
.search-filter-results > a.azI ~ a.azI:before,
.search-filter-results > a.azJ ~ a.azJ:before,
.search-filter-results > a.azK ~ a.azK:before,
.search-filter-results > a.azL ~ a.azL:before,
.search-filter-results > a.azM ~ a.azM:before,
.search-filter-results > a.azN ~ a.azN:before,
.search-filter-results > a.azO ~ a.azO:before,
.search-filter-results > a.azP ~ a.azP:before,
.search-filter-results > a.azQ ~ a.azQ:before,
.search-filter-results > a.azR ~ a.azR:before,
.search-filter-results > a.azS ~ a.azS:before,
.search-filter-results > a.azT ~ a.azT:before,
.search-filter-results > a.azU ~ a.azU:before,
.search-filter-results > a.azV ~ a.azV:before,
.search-filter-results > a.azW ~ a.azW:before,
.search-filter-results > a.azX ~ a.azX:before,
.search-filter-results > a.azY ~ a.azY:before,
.search-filter-results > a.azZ ~ a.azZ:before { display:none; }
</style>

And this is the result:
screenshot tutorial wordpress search and filter plugin

Hope this helps you out as well, if so please post a reply!


foto Boris Hoekmeijer
My name is Boris Hoekmeijer, I'm a webdesigner and graphic designer.
I sometimes run into a problem for which I have to find my own solution because Google just won't tell me. That's when I climb behind my mechanical keyboard, and fire away until a tutorial materializes. One of the great things about the web: we can all help each other!
If this article has helped you, or if you have anything to add or ask, please leave a comment or share the post.
Cheers!

© 2017 ★ Published: April 7, 2017
Leave your thoughts

Leave a Reply

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