Use jQuery to reorder your WP posts on the fly

13 Aug

If you use WP for a lot more than just publishing a blog and using the ready made themes and plugins, then I bet you know a whole lotta stuff can be done with the normal list of posts on your blog index. One such thing (and a highly desirable feature) is to be able to reorder your posts according to the various ordering options that are available with ‘query_posts‘ (or ‘WP_Query‘ for that matter). Usually, if you’re to modify the loop to display the posts ordered in a specific manner, you’d create a new ‘WP_Query’ object or pass the parameters to ‘query_posts’ and invoke it right before the loop starts. But using a simple technique that is already used by WP, we’ll learn how to reorder the posts list, by modifying ‘query_posts’ right from the frontend, using jQuery.

Checkout the demo: Demo

Prerequisites:
1. Obviously, you should know WP a little deeper on the technical terms. Precisely, knowledge of ‘The_Loop‘ and ‘query_posts / WP_Query‘ is required.
2. Basic jQuery.

Done nuf’ talking, let’s get code stained!

I assume you’ve used WP’s default ‘Categories’ widget. This widget displays the categories as a dropdown or as a list. When displaying the categories as a dropdown, selecting a category from the dropdown automatically redirects you to the archive page of that category. We’re going to use the same trick to get our job done. Checkout the ‘default-widgets.php’ file from the wp-includes folder in your WP installation for the Javascript we’re going to use (line no. 444).

Make a new template, name it ‘Ordered posts’. Add the following code in it:

<?php
/*
 * Template Name: Ordered Posts
*/
get_header();  ?>
<div id="content">
    <?php query_posts('order=DESC'); ?>
    <?php if ( have_posts() ){ ?>
	<?php  while ( have_posts() ) : the_post() ?>
        <div <?php echo post_class(); ?>>
            <h3><?php the_title(); ?> | <small><?php the_time('F jS, Y'); ?></small></h3>
            
            <?php the_excerpt('Read more...'); ?>
        </div>
    <?php endwhile; ?>
<?php } ?>
</div>
<?php
get_sidebar();
get_footer();

This is pretty simple. We’re making a new template to display the posts, and the default order is date descending. We need to call ‘query_posts’ explicitly with one parameter to display all posts, or the loop will display the content of the current page. We’ll change this very soon. Next, we display the title, the date posted and the excerpt for each post.
Create a new page through the dashboard, name it ‘Reorder Posts’ and assign it this template. Visit this page and you have the posts displayed in the default order i. e. recent ones first.
Now modify the template, and add the following code to it, just after

<div id="content">

and before

<?php query_posts('order=DESC');  ?>

Code:

<div id="sorter-container">
        <select id="order-by">
            <option value="date-desc" <?php echo (!isset($order) || $order == '' || $order == 'date-desc')? 'selected="selected"':''; ?>>Date Desc. (default)</option>
            <option value="date-asc" <?php echo ($order == 'date-asc')? 'selected="selected"':''; ?>>Date Asc</option>
            <option value="date-mod" <?php echo ($order == 'date-mod')? 'selected="selected"':''; ?>>Date Modified</option>
            <option value="title-desc" <?php echo ($order == 'title-desc')? 'selected="selected"':''; ?>>Title Desc.</option>
            <option value="title-asc" <?php echo ($order == 'title-asc')? 'selected="selected"':''; ?>>Title Asc.</option>
            <option value="comment" <?php echo ($order == 'comment')? 'selected="selected"':''; ?>>Comments Count</option>
        </select>
    </div>

This will add the dropdown with the various ordering options to select from, right above our posts list. The embedded php code checks what value is currently assigned to the ‘$order’ variable, and keeps the respective option from the drop down selected.
The options that we’re adding are:

  1. Date Asc. – Order according the ascending order of date published (the very first post will appear first).
  2. Date Desc.(default) – The default order, recent one appears first.
  3. Date Modified – The post which was modified recently, appears first.
  4. Title Desc. – Alphabetically descending order of the title, Z…A.
  5. Title Asc. – Alphabetically ascending order of the title, A…Z.
  6. Comment Count – The most commented appear first.

We get to the appropriate redirection part using the Javascript/jQuery code. Modify the template again, and add the following code, just after

<div id='sorter-container'>...</ div>

and before

<?php query_posts('order=DESC');  ?>

Code:

<script type="text/javascript">
        var orderby = jQuery('#order-by');
        var str;
        orderby.change(function(){
        	str = jQuery(this).val();
             window.location.href = "<?php echo home_url(); ?>/reorder-posts/?o="+str;
        });
    </script>

This code is straight forward. When we select an option (which triggers the ‘onchange’ event, handled by ‘change‘ in jQuery) from the dropdown, we’re redirected to the current page with the selected option’s value as a url parameter, ‘o’. We need to handle this parameter using php.

( Please use the correct page slug here. I named my page as ‘Reorder Posts’, hence got the slug as ‘reorder-posts’.)

To handle the url parameter ‘o’, update the template and add the following code just after

 get_header() ?>

and just before

<div id="content">

.

<?php
if( isset($_GET['o']) && $_GET['o'] != '')
          {
              $order = $_GET['o'];
              switch($order)
              {
                case 'date-asc': $orderby = 'order=ASC';
                            $msg = 'Date Ascending';
                              break;
                          
                case 'date-desc': $orderby = 'order=DESC';
                            $msg = 'Date Descending(default)';
                              break;
                          
                case 'date-mod': $orderby = 'orderby=modified';
                                $msg = 'Date Modified';
                               break;

                case 'title-asc': $orderby = 'orderby=title&order=ASC';
                                $msg = 'Title A-Z';
                                break;
                            
                case 'title-desc': $orderby = 'orderby=title&order=DESC';
                                $msg = 'Title Z-A';
                                break;
                            
                case 'comment': $orderby = 'orderby=comment_count';
                                $msg = 'Comment Count';
                                break;
              }
          }
          else
          {
              $orderby = 'order=DESC';
              $msg = 'Date Descending (default)';
          }
?> 

This checks if the url parameter ‘o’, is set and not blank, then assigns its value to the ‘$order’ variable. Depending on the value of ‘o’, form the arguments variable, ‘$orderby’ that should be passed to ‘query_posts’ to order the posts accordingly. If it isn’t set or set to something that we haven’t handled, then fall back to the default, date descending. We also form an appropriate message to display.

Change ‘query_posts(‘order=DESC’)’ to ‘query_posts($orderby)’ as

<?php query_posts($orderby); ?>

Add the message that tells how the posts are ordered currently, just after the

<script>...</script>

.

Code:

<h2 id="sort-heading">Posts ordered by:<?php echo $msg; ?></h2>

All done! Visit this page in your blog/site, and try selecting an option from the drop down. It will reorder posts accordingly! Instead of creating a new template, you can even use this code to modify your ‘index.php’ to have re-order able posts list right on your blog’s index/home. Optionally you can set this page as the home page for your blog. Just make sure you change the url used for redirection in the Javascript code accordingly.
Check the demo here: Demo.

Comments, suggestions are welcome!

16 Responses to “Use jQuery to reorder your WP posts on the fly”