23 Comments
Found in Tutorials
June 24, 2010
Fetching Posts by Category in WordPress with jQuery (the Easy Way)
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!

Mark Fasel said:
Exactly what I was looking for! Great tutorial!
Reply to comment
admin said:
Glad it was helpful! Please let me know if you have any issues. I threw this tutorial together late at night and I’m sure it could be improved upon.
Reply to comment
David Wood said:
This is exactly what I’m looking to do! Unfortunately I’m trying to alter a theme and I’m a bit of an amateur, having trouble implementing it. I’ve put the querySort.php into my theme folder and linked to it in the js file… as well as linking to the js file of course but it’s not working? HELP!
Reply to comment
admin said:
Hello David, if you have a link for me to check out I can try to troubleshoot it for you. Most of the time its a missing or misplaced div here or there! You can email me the link directly if you’d prefer and I’ll get back to you with an answer.
Reply to comment
David Wood said:
Could you link me to the source files? I have emailed you but I doubt you have the time to trawl through code!
Reply to comment
Tim Mon said:
Nice Job! Thanks for sharing this! Gorgeous site too… I like it.
Reply to comment
Caroline Keim said:
Great Tutorial!
However, I’m getting an error –
Fatal error: Call to undefined function query_posts() in querySort.php on line 7
Any idea what could be wrong?
Reply to comment
SK said:
Thanks for writing this up. I have some questions, I hope you don’t mind. The procedure described in part 1 appears as though it can be used to generate stripped down templates on the fly for the specific purpose of ajax .load or .get.
I’m currently building a WP site and I have a load more button at the bottom. With jQuery .get, I’m fetching the /page/2/ of a section for instance and appending it to the current page.
It works well, but I feel it could be faster since it currently fetches and has to parse through all the unnecessary parts of the subsequent pages.
Will using your code be applicable for things like the Load More button to retrieve a second page of results on the same home page? And if so, is it efficient? Even though my method is slow on the user-end, it is efficient for the server since WP can cache page/2/ page/3/ etc. However, since your code doesn’t seem to be part of a WP template, I’m afraid that important plugins like WP Super Cache and W3 Total Cache won’t work for high traffic blogs.
Reply to comment
Chad said:
Thanks for this. It is exactly what I’ve been looking for. My only problem is that I can’t get the other jquery script I was using to work inside the results container. Any suggestions?
Reply to comment
Jack Fearing said:
Hello, is there anyway to make pull the template path dynamically (using something like ) rather than the absolute path?
Reply to comment
Andrew Martin said:
Just wanted to say thanks a lot for the tutorial. This is my first time diving into Ajax and it was awesome.
I’ve modified a few things and taken this as a foundation; one thing I might suggest is to do it like this:
$.querySort = {
path_to_template: ”,
post_type: ‘review’,
number_of_posts: 5,
default_category: ”,
meta_key: ‘feature_flag’,
this_page: ‘post_name; ?>’
}
I only say this because I found it awesome to use that “this_page” variable to do some customization on the way the query uses the WP loop and thought this was a bit cleaner.
THANK YOU for posting this awesome tutorial.
Reply to comment
abid said:
good word
Reply to comment
Remi said:
I cant get this to work, you say: “Each anchor you create must have to category’s slug as the id. ”
But where do i put the id in:
Category Name
And in the beginning, where you say:
Can i put in the place of or does that have to be another loop?
Reply to comment
Renu said:
Thank you for this handy widget! I got it working now.
Maybe for the beginners its handy to mention that you have to add the line <script src="/querySort.js” type=”text/javascript”> to your header.
Anyway thanks
Reply to comment
Renu said:
Does anyone know how to exclude a certain categorie from the results the list displays?
I’m trying:
number_of_posts: -1,
cat: -4,
default_category: ‘werkzoekende’
}
// 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 + ‘%26cat%3D’ + $.querySort.cat );
but that doesnt seem to work
Reply to comment
marmont said:
C7mSBR http://sjI1mfH9Cx4hsDePoai2v.com
Reply to comment
Pharmb433 said:
Hello! aggcaee interesting aggcaee site! I’m really like it! Very, very aggcaee good!
Reply to comment
Pharmg109 said:
Very nice site!
Reply to comment
Pharmf627 said:
Hello! eecgeke interesting eecgeke site! I’m really like it! Very, very eecgeke good!
Reply to comment
Pharma836 said:
Very nice site!
Reply to comment
Yoshimi Rider said:
Amazing work!!! I’m working on a Commercial WordPress theme and I was wondering if it would be okay to use your code
Reply to comment
test said:
test
Reply to comment
Urson0Xk said:
QWpP1i http://www.2KFk8UxzgR3t2CjpiGYlWRZr9NzJwIs8.com
Reply to comment
Categories
About the Author
Nick Coates is a Designer & Developer living in North Carolina. He specializes in Web Design, Branding, and CMS Development, freelancing successfully for two years, with three years of agency experience under his belt. Other hobbies include nap-offs with his dog Pete, forgetting his wallet every time he leaves the house, and thinking about getting in shape.
Drinking Buddies
Recent Blog Entries
Recent Tweets
@lukejonesme That special is so good. His new special was disappointing only because Chewed Up was so unbelievably good. Hard to follow up. # 2011/08/30
I'm Listening