WordPress Theme Lesson 12: Featured Posts, Dealing with Multiple Loops

In this lesson we’ll add the featured posts section formed as a jQuery slider on top of the front page. By placing it on the front page template we need to adress the issue of creating multiple loops on the one and same page. This lesson accumulates many of the lessons so far in this tutorial; we need to write a custom query code, fetch post thumbnails in a specific image size, and include libraries and scripts to make our slider work.

We begin with registering and enqueuing the necessary scripts for our jQuery slider, for which we will use the jQuery Tools library. We will then add the initializing slider function call in our <head>, and finally write the custom query loop in our index.php to fetch posts from our featured posts category.

There are many jQuery-based slider plugins you can use (see for instance 13 excellent jQuery sliders), or you can even write your own based on the jQuery library. I chose to use jQuery Tools, a bundle of jQuery plugins where we are to use Scrollable and Navigator. Read through the guides and demos in case you want to read up on how our slider works.

Registering and Enqueuing Scripts

In the previous lesson we learned how to include javascript libraries in WordPress the right way. jQuery Tools is not one of WordPress’s included libraries, so we need to register it providing its CDN path before we enqueue it. Keep in mind that we need the full library since Navigator isn’t included in the min bundle. The jQuery Tools depends on jQuery core library being loaded first.

We open up our functions.php and write a PHP function hooked onto the init hook:

functions.php:

function wpthemetutorial_add_js() {
	if (!is_admin()) {
		wp_register_script('jquery-tools', 'http://cdn.jquerytools.org/1.2.5/all/jquery.tools.min.js', array('jquery'));
		wp_enqueue_script('jquery-tools');
	}
}
add_action('init', 'wpthemetutorial_add_js');

If you refresh your site and take a look at the source code, the jQuery and jQuery Tools should be included, either where you put the wp_head() or the wp_footer(). Great! Up next is to initialize the slider in a jQuery document ready function.

WordPress Codex Function references:

Initializing the Slider Script

In our <head> section we need to add only one javascript function call, scrollable(), inside a jQuery document ready function, but obviously we need it to be run after the jQuery libraries have been loaded. As shown in the previous lesson we hook onto the wp_head hook, which ensures that the jQuery libraries have been loaded first because they were hooked onto the much earlier init hook. Also remember that WordPress loads jQuery in no conflict mode.

In our functions.php we add another PHP function which hooks onto the wp_head hook:

functions.php:

function wpthemetutorial_add_init_js() {
	?>
	<script type="text/javascript">
		jQuery.noConflict();
		jQuery(document).ready(function($) {
			jQuery(".scrollable").scrollable().navigator();
		});
	</script>
	<?php
}
add_action('wp_head', 'wpthemetutorial_add_init_js');

If you refresh your site now, you should see this piece of javascript right at the end of the <head> part. It initialize Scrollable on all elements with the class scrollable as well as Navigator which handles our slider’s navigation buttons. But before we add the HTML elements to form the slider, I need to explain how we deal with multiple loops in the one and same page.

WordPress Codex Function references:

Dealing with Multiple Loops

What we want is to create two separate loops where each fetches different posts. The problem with multiple loops on the same page is the global core $wp_query value. It is loaded in the blog header and is fed arguments from e.g. GET, creating an array of posts. All loops use the $wp_query object, even though we don’t refer to this by name. The loop functions have_posts() and the_post() are just convenience wrappers – they are identical to $wp_query->have_posts() and $wp_query->the_post(), respectively.

The thing is, $wp_query can only be called once. One way to get around this is re-using the query by calling the WordPress function rewind_posts(), or we could simply create a new query object instead of using $wp_query. I will use the last method, creating a new query object for our featured posts so that we can use the $wp_query for our normal loop of posts. This is less work as we don’t need to alter the code we already have in our index.php. The WordPress Codex explains and shows different examples of handling multiple loops if you want to learn more about this topic.

We also want to prevent showing the same post in both the featured posts section and the normal loop below. If the writer choose to mark a very recent publised post as featured, we may risk showing the same post twice in the same screen. To solve this we store an array of post IDs when we loop through featured posts, and in our original loop we add a line of code which skips the current post if its ID is in our array.

Custom query for Fetching Featured Posts

Using the method explained above we don’t need to alter our existing loop in our index.php, except adding the one line to prevent duplicate posts. Let’s first add the custom loop. Just above and before the original loop we create a new query object and write a loop using this object, but otherwise the procedure is the same as a normal loop.

In our custom query we want to fetch 9 posts from the category named ‘Featured’ (replace the name if you chose another category name), so we get three on each slide.

We also need to add some extra HTML to make our jQuery slider work, such as navigation elements and dividing the posts three by three in each slide/div element. In our index.php, add this piece of code before the original loop, but right after <div class="content">:

index.php:

<div id="featured-scrollable">
	<div class="scrollable">
		<h3>Featured Posts</h3>
		<div class="navi"></div>
		<div class="items">
			<?php $counter = 0; $perslide = 3; ?>
			<div class="scrollable-item">
			<?php $my_query = new WP_Query('category_name=Featured&posts_per_page=9');
			while ($my_query->have_posts()) : $my_query->the_post();
				$do_not_duplicate[] = $post->ID;
				if ($counter++ > $perslide) { $counter = 1; ?></div><div class="scrollable-item"><?php } ?>
				<div class="item">
					<?php if (has_post_thumbnail()) : the_post_thumbnail('featuredposts-thumbnail'); endif; ?>
					<h2><a href="<?php the_permalink(); ?>" rel="bookmark" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2>
				</div>
				<?php endwhile; ?>
			</div>
		</div>		
	</div>
	<div class="featured-scrollable-nav">
		<a class="featured prev left"></a>
		<a class="featured next right"></a>
	</div>
	<div style="clear:both;"></div>
</div>

If you look closely at the loop you’ll see we create a new WP_Query object and stores it in $my_query. We then refer to this object when calling have_posts() and the_post(). At this point we’ve created a loop without touching the global $wp_query object. As arguments to WP_Query we add the category name and the number of posts we want to fetch. Then for each post we store the ID in the array $do_not_duplicate, which we will later use in our original loop to prevent duplicates.

The values $counter, $perslide and the line inside the loop immidiately before <div class="item"> makes sure we loop through three posts before we close the <div> and start a new <div class="scrollable-item">.

Remember from Lesson 8 where we defined an image size specific for our featured posts section? We’ve put the shorthand name into use, featuredposts-thumbnail, as argument when we fetch the post thumbnail, giving us just the right size we need to fit three posts nicely next to each other.

Prevent Duplicates

We need to do one more thing before we’re done writing the featured posts section, which is to add a line in our original loop below to prevent duplicates. We created an array $do_not_duplicate looping through our featured posts, and we need to make sure no posts with any of these IDs are repeated in the normal loop. Scroll further down index.php and find our original loop line:

if (have_posts()) : while (have_posts()) : the_post();

Make a new line below this, and write:

if (in_array($post->ID, $do_not_duplicate)) continue;

This checks whether or not the current post ID resides in the array $do_not_duplicate, and if it does, it continues to the next post, skipping the one we were at.

Our slider will not be visible or work before we add styling to it. Let’s do that!

WordPress Codex Function references:

Styling our Featured Posts Slider

I’ve copied most of my CSS from the guide provided by jQuery Tools’s website and then modified it to my needs. In your style.css add:

style.css:

/* SCROLLABLE FEATURED */
.scrollable {
	position: relative;
	overflow: hidden;
	width: 490px;
	height: 185px;
}
.scrollable .items {
	width: 2000em; /* Must be large, but not too large */
	position: absolute;
	clear: both;
}
.items div.scrollable-item { 
	float: left; 
	width: 490px; 
	margin-top: 8px; 
}

#featured-scrollable {
	background-color: #ffffff;
	border: 1px solid #dadcde; 
	padding: 15px;
	margin-bottom: 20px;
}
#featured-scrollable h3 {
	font-family: Arial, Verdana, sans-serif;
	font-size: 18px;
	color: #4f5051;
	float: left;
}
#featured-scrollable .items div.scrollable-item .item { float: left; width: 140px; margin: 0 11px; height: 155px; }
#featured-scrollable .items div.scrollable-item .item img { border: 1px solid #71869f; }
#featured-scrollable .items div.scrollable-item .scrollable-postthumbnail { width: 140px; }
#featured-scrollable .items div.scrollable-item .item h2 { padding-top: 4px; font-size: 13px; }

#featured-scrollable .featured-scrollable-nav { 
	display: block; 
	width: 100px;
	margin: 15px auto 0 auto; 
	padding-left: 35px;
}
#featured-scrollable .featured-scrollable-nav a { 
	cursor: pointer; 
	margin-right: 10px;
	background: url("images/slider-arrows.png") no-repeat 0 0;
	font-size: 1px;
	display: block; 
	height: 30px;
	width: 30px;
	float: left;
}
#featured-scrollable .featured-scrollable-nav a.right { background-position: 0 -30px; margin-right: 0; }
#featured-scrollable .featured-scrollable-nav a.disabled { visibility: hidden; }
#featured-scrollable .featured-scrollable-nav a.left:hover { background-position: -30px 0; }
#featured-scrollable .featured-scrollable-nav a.right:hover { background-position: -30px -30px; }

.navi {
	margin-left: 440px;
	margin-top: 5px;
	width: 200px;
	height: 20px;
}
.navi a {
	width: 8px;
	height: 8px;
	float: left;
	margin: 3px;
	background: url("images/navigator.png") 0 0 no-repeat;
	display: block;
	font-size: 1px;
}
.navi a:hover { background-position: 0 -8px; }
.navi a.active { background-position: 0 -16px; }

Our featured posts slider

Click here to download the images used in this CSS code, unzip and put the images into the images folder in your theme folder.

Refresh the front page and see that the slider works. Three posts from your chosen category are displayed with the post thumbnail and title, three on each slide. The right and left buttons are not displayed if there are no more posts in the given direction. We also have working navigation “dots” in the upper right hand corner. And if you flip through your posts you should also not see any duplicates.

This concludes Lesson 12 of the WordPress Theme Tutorial. Go to the next lesson, Page Templates.