60 Comments

Found in Tutorials

June 24, 2010

Fetching Posts by Category in WordPress with jQuery (the Easy Way)

Post to Twitter

Using some simple jQuery and PHP, we’ll create a Recent Posts widget that you can filter by category without an annoying page refresh. No need to create extra WordPress pages and templates! We’ll also apply a little jQuery animation so your container height will glide smoothly into place.

NOTE: For a loose example of this tutorial in action, check out the sorter on my legacy portfolio.

1. Create Your Template

First, we need to create a file called querySort.php and place the following code inside of it:

<?php
	// load wordpress into template. dont touch me!
	$path = $_SERVER['DOCUMENT_ROOT'];
	define('WP_USE_THEMES', false);
	require($path .'/wp-load.php');
	// ah, wordpress is loaded. balance has been restored.
	query_posts($_GET["query"]);
?>

<div id="queryContainer">
	<?php if(have_posts()) : ?><?php while(have_posts()) : the_post(); ?>
	<!-- place your post template here. -->
	<?php endwhile; ?>
	<?php endif; ?>
</div>

This is your entire template for the widget’s output. By including wp-load.php, we’re able to avoid the annoying need to declare the file as a WordPress template, create an empty Page, and apply said template to it. The most important part of this file is this line:

query_posts($_GET["query"]);

Upon each load, query_post will grab our query from a variable that jQuery passes to it. This variable contains, by default, options for the number of posts and a default starting category.

Style the loop as necessary. As long as the div “queryContainer” and the loop are maintained, you may style the output any way you’d like.

2. Sprinkle in Some jQuery

Create another file called querySort.js and place the following code inside of it:

jQuery(document).ready(function($) {
	// replace these default settings with your own
	$.querySort = {
		path_to_template: 'http://www.YOURSITE.com/wp-content/themes/YOURTHEME/',
		number_of_posts: 5,
		default_category: ''
	}

	// do the initial load.
	$("#querySort").load($.querySort.path_to_template + 'querySort.php' + '?query=showposts%3D' + $.querySort.number_of_posts + '%26category_name%3D' + $.querySort.default_category);

	//functions for the sorter
	$("#queryMenu a").click(function(){
		var thecat = $(this).attr("id");
		if (thecat == 'reset') {
			var query = '?query=showposts%3D' + $.querySort.number_of_posts + '%26category_name%3D' + $.querySort.default_category;
		} else {
			var query = '?query=showposts%3D' + $.querySort.number_of_posts + '%26category_name%3D' + thecat;
		}
		$("#querySort").animate({opacity: 0}, function() {
			$("#querySort").load($.querySort.path_to_template + 'querySort.php' + query, function() {
				height = $("#queryContainer").height() + 'px';
				$("#querySort").animate({opacity: 1, height:height});
			});
		});
		return false;
	});
});

Let’s break this down to make it easier to understand. Here are the default options provided by querySort:

	$.querySort = {
		path_to_template: 'http://www.YOURSITE.com/wp-content/themes/YOURTHEME/',
		number_of_posts: 5,
		default_category: ''
	}

You’ll need to add the absolute path to the template you’ll be using this with (dont forget the trailing forward slash). If you’ve installed WordPress in a subdirectory, make sure to update the url to reflect that. Number_of_posts controls precisely the number of visible posts at a time, and default_category is only really necessary if you wish to limit the visible posts to a specific category and its children.

// do the initial load.
	$("#querySort").load($.querySort.path_to_template + 'querySort.php' + '?query=showposts%3D' + $.querySort.number_of_posts + '%26category_name%3D' + $.querySort.default_category);

This loads the default, unsorted query as soon as the DOM is ready. Using the .load() function, jQuery loads querySort.php, appending a variable called query, which is then accessed by the wordpress function query_posts(). The contents of the div #querySort are replaced with the results. (if you customize this script in any way to add more filters, be sure your query is urlencoded.)

//functions for the sorter
	$("#queryMenu a").click(function(){
		var thecat = $(this).attr("id");
		if (thecat == 'reset') {
			var query = '?query=showposts%3D' + $.querySort.number_of_posts + '%26category_name%3D' + $.querySort.default_category;
		} else {
			var query = '?query=showposts%3D' + $.querySort.number_of_posts + '%26category_name%3D' + thecat;
		}
		$("#querySort").animate({opacity: 0}, function() {
			$("#querySort").load($.querySort.path_to_template + 'querySort.php' + query, function() {
				height = $("#queryContainer").height() + 'px';
				$("#querySort").animate({opacity: 1, height:height});
			});
		});
		return false;
	});

This is where the magic happens. This function accesses the div holding your sorting options, grabbing the ID of your link and replacing the query’s category name with its contents. Next, it fades out the #querySort div, loads the results of the new query, then fades them back in, fluidly adjusting the height of #querySort to match the new height of your content. This prevents ugly flickers or large gaps beneath the widget.

That’s all there is to it. One more step, and you should have a working widget!

3. Add the Widget to Your Theme

Now, assuming you know where you’re going to place the widget, you have but to place the following markup in your theme and apply your desired CSS styles.

<div id="queryMenu">
	<ul>
		<li><a href="#" id="categoryslug">Category Name</a></li>
		<li><a href="#" id="reset">All Posts</a></li>
	</ul>
</div>

<div id="querySort">
	<!-- leave me empty. -->
</div>

The #queryMenu div is very simple to set up. Each anchor you create must have to category’s slug as the id. This will be used by jQuery to execute the filter. IMPORTANT: To reset the sorter, create an anchor with ‘reset’ as the id. If, for some unimaginable reason, you have a category called Reset, you may want to change this to something else in your jQuery.

4. Enqueue and enjoy.

Upload your new files to your theme’s directory. Enqueue querySort.js and pat yourself on the back. You should now have a working jQuery sorter!