0

I have a website in Wordpress and a page with a list with letters like this:

A B C D E F G H I ...

This shows me all posts with the letter A for instance. That's nice, but I want it to make it easier for my users, so I want to get Ab and all of the posts starting with Ab if I click on A, beneath this list. Another example: I want to get Dc and all of the posts starting with the letters Dc if I click on D. I know that this is possible by making 26 pages containing the letters and the functions, but there must be a simpler way to do this.

Besides, I don't want 26 pages for such a simple thing. It would affect the SEO.

Can someone help me out with this?

  • It isn't entirely clear how you imagine this to work, but is sounds like you are asking for Javascript to create additional menus. – s_ha_dum Jul 29 '13 at 21:38
  • Yes, I think I have to use jQuery, which is no problem at all, but I am wondering if there is another way to fetch those results instead of making pages? So the posts, starting with Dc or Ab, should be fetched, which I can by adding pages with my function, but isn't that overhead? Than I have to make 26 pages, which sounds stupid to me... – Johan Jul 29 '13 at 21:39
  • How does this sound like: giving each post name an ID and then with jQuery, replacing the list I have with those posts and showing them if someone clicks on the specific anchor... I know that jQuery has contains, but can you select the first two letters too? – Johan Jul 29 '13 at 21:45
1

Maybe I've not understand your question, in this case sorry, my english is far from perfect.

I understand that you have a page template that show the letters list and when you click a letter, the same page show a list of posts where 'post_title' start with this letter.

Now you want that when you are showing that list, is possible to filter posts using 2 letters instead of one, where the first letter is the one choosen before.

Is this right? If so, this should works:

<?php
/**
 * Template Name: Capital Template
*/

get_header();

the_post();
$page_link = get_permalink();

$letter = isset($_GET['letter']) ? $_GET['letter'] : null;
// limit the 'letter' param to 2 chars
if ( $letter && strlen($_GET['letter'])>2 ) $letter = substr($letter, 0, 2);
?>

<?php
// PAGE FILTERS PART
$letters = array('A','B','C','D','E','F','G','H','I','J','K','L','M',
                 'N', 'O','P','Q','R','S','T','U','V','W','X','W','Z');
if ( ! $letter ) {
  // adjust the query args to fit your needs
  $args = array('posts_per_page' => 50, 'orderby' => 'post_title', 'order' => 'ASC');
  $posts = get_posts($args);
} else {
  global $wpdb;
  // adjust the query to fit your needs  
  $posts = $wpdb->get_results( $wpdb->prepare(
    "SELECT * FROM $wpdb->posts WHERE
    post_type = 'post' AND post_status = 'publish' AND
    post_title LIKE %s ORDER BY post_title ASC",
    $letter . '%'
  ) );
}
echo '<ul>';
foreach ( $letters as $l) {
  $param = $letter ? $letter.$l : $l;
  printf('<li><a href="%s?letter=%s">%s</a></li>',$page_link, $param, $param);
}
echo '</ul>';
if ($letter) {
  printf('<p id="#filter-remover"><a href="%s?letter=%s">%s</a>',
    $page_link, $letter,
    __('Back to capital letter &quot;' . $letter . '&quot; filter')
  );
  printf(', <a href="%s">%s</a><p>',
    $page_link,
    __('or remove capital letter filter at all.')
  );
}
?>

<?php
// PAGE CONTENT PART
global $post;
if ( ! empty($posts) ) :
  foreach ($posts as $post) {
    setup_postdata($post);
?>

<?php /*  YOUR LOOP CODE HERE */ ?>

<p><?php the_title(); ?></p>

<?php
}
else :
  echo '<p>';
  _e('Sorry, no posts match your criteria.');
  if ( $letter ) {
    printf('<br /><a href="%s">%s</a>',
  $page_link,
  __('Try to remove the capital letter filter.')
);
  }
  echo '</p>';
endif;
wp_reset_postdata();


get_footer();

Edit: jquery trick

One fault of my code above is that the filter shows all capital letter(s), even if there is no posts for that: if the filter 'A' not have post, also 'AB', 'AC' and so on will not have posts so, why show them? Using php you can loop posts and put only filter that have a chance to get some results, but this mean looping 2 times. I think there is a better solution: jQuery.

Note: this works only if you the query shows all posts, or better, all the posts you want to filter out (i.e. no LIMIT clause in sql query)

First of all, in 'FILTER' part, change the foreach loop in this:

echo '<ul class="letter-filters">';
foreach ( $letters as $l) {
  $param = $letter ? $letter.$l : $l;
  printf('<li><a href="%s?letter=%s" class="letter-filter">%s</a></li>',
    $page_link, $param, $param
  );
}
echo '</ul>';

Then in the loop code part, use something like this:

<?php
echo '<div id="posts-container" data-letter="' . $letter. '">';
if ( ! empty($posts) ) :
  foreach ($posts as $post) {
    setup_postdata($post);
   /*  YOUR LOOP CODE */
   $datacapital = $letter ? strtoupper( substr(get_the_title(), 0, strlen($letter)+1 ) ) : '';
?>
  <div class="post" id="post-<?php the_ID()?>" data-capital="<?php echo $datacapital; ?>">
  <p><?php the_title(); ?></p>
 </div>

 ...

 endif;
 echo '</div>';
 wp_reset_postdata();

Finally, the jQuery code:

<script>
// please, do not use jquery like so,
// register and enqueue it like every WP developer should do :)
// this is for semplicity of answer

jQuery().ready(function($) {
  if ( $('#posts-container').data('letter') != '' ) {
    var oldcapital = null;
    $('ul.letter-filters li').hide();
    $('.post').each(function() {
      var capital = $(this).data('capital');
      if ( ! oldcapital || (oldcapital != capital) ) {
        oldcapital = capital;
        $('a.letter-filter').each(function() {
           if ( $(this).text() == capital ) $(this).parent().show(); 
        });
        }
      });
    }
  });
</script>

Please note I'm not a js/jquery developer, maybe there is a more elegant/performant way to to do the same thing...

Of course this is not the full code of the page, just the relevant part.

Hope it helps.

  • Fantastic! This is truly wonderful. Thanks man, I can do a lot with this! – Johan Jul 30 '13 at 9:23
  • is there a way to define my own url? Because now, it is just outputting the posts on the same page in where to function goes, but I can't fetch the posts on a different url. Is this possible? – Johan Jul 30 '13 at 11:34
  • change $page_link = get_permalink(); with whatever you want – gmazzap Jul 30 '13 at 13:37
  • Thanks! Last question: how can I order the posts alphabetically? So sorting by post_title? In this case, the post are shown randomly, which is not what I want. I tried: $wpdb->posts.post_title", $letter, but that gave the post title 3 times... And tried this too post_title LIKE %s AND ORDER BY $letter, but not working... Can we discuss in chat btw? – Johan Jul 30 '13 at 15:04
  • 1
    I search you in chat and you were not online. So you want ot start with 2 letters when you open the page? If you don't filter for first letter, there are 676 combinations of 2 letters, you want user open page this or next year? :) Joking, but I don't think is a good idea – gmazzap Jul 30 '13 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.