Categories: Tutorials

Search Filter results grouped by first character


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:

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

This post was last modified on 26/06/2018 09:40

Boris Hoekmeijer

Share
Published by
Boris Hoekmeijer

Recent Posts

Agribusiness Service

Website en logo ontwerp voor Kookstudio Aalsmeer - voor uw kookclub, kookfeest of bedrijfsuitje in…

4 months ago

CardioThoracaal Chirurgie Zorgpad

Website en logo ontwerp voor Kookstudio Aalsmeer - voor uw kookclub, kookfeest of bedrijfsuitje in…

4 months ago

7huijzen Food Quality & Innovation Management

Website en logo ontwerp voor Kookstudio Aalsmeer - voor uw kookclub, kookfeest of bedrijfsuitje in…

6 months ago

Prime Housing

Website en logo ontwerp voor Kookstudio Aalsmeer - voor uw kookclub, kookfeest of bedrijfsuitje in…

6 months ago

Cor de Kroon

Website en logo ontwerp voor Kookstudio Aalsmeer - voor uw kookclub, kookfeest of bedrijfsuitje in…

8 months ago

Hoe leeg je de cache van je browser?

Building your WordPress website efficiently using the 10 tips I documented after years of experience.…

1 year ago