Tag Archives: pagination

“Posts per page” dropdown for BuddyPress single forum topic view

This morning I whipped up a little BuddyPress ditty for the CUNY Academic Commons that allows your members to select how many posts they’d like to see at a time when viewing a single forum topic. It’s not particularly beautiful (for one thing, it requires Javascript to work correctly, though it degrades gracefully by not showing up when no jQuery is available). For that reason, it’s probably not really appropriate for distribution in BuddyPress itself, at least not without some heavy cleanup. Anyway, here it is:

In your theme’s functions.php, place the following function:

<br />
/**<br />
 * Echoes the markup for the "number of posts per page" dropdown on forum topics<br />
 */<br />
function cac_forums_show_per_page_dropdown() {<br />
	global $topic_template;</p>
<p>// Get the current number, so we can preselect the dropdown<br />
	$selected = in_array( $topic_template->pag_num, array( 5, 15, 30 ) ) ? $topic_template->pag_num : $topic_template->total_post_count;</p>
<p>// Inject the javascript<br />
	?></p>
<p>jQuery(document).ready( function() {<br />
		jQuery('div#posts-per-page-wrapper').show();<br />
		jQuery('select#posts-per-page').change(function(){<br />
			var url = '?topic_page=1&num=' + jQuery(this).val();<br />
			window.location = url;<br />
		});<br />
	});</p>
<div id="posts-per-page-wrapper">Posts per page:<option value="5" > 5<option value="15" > 15<option value="30"  > 30<option value="total_post_count ?>"  total_post_count ) ?>> All</p>
</div>
<p><?php
}

Then you’ll have to call the function somewhere in your template. I chose to put mine in groups/forum/topic.php, right after the Leave A Reply button:

</p>
<p>

Finally, you’ll probably want to add some styles to your stylesheet. In particular, you’ll want to ensure that the dropdown doesn’t show up for users who have JS turned off. Here are the styles I’m using; adjust them to your taste.

<br />
div#posts-per-page-wrapper {<br />
	display: none;<br />
	position: absolute;<br />
	right: 0;<br />
	top: 0;<br />
	font-size: 11px;<br />
	color: #888;<br />
}<br />

New WordPress plugin: Boone’s Sortable Columns

Boone’s Sortable Columns is a new WordPress plugin to make it easier for developers of WordPress plugins and themes to create sortable data tables and lists. Like my recent Boone’s Pagination, this is not a plugin for end users but for developers. (And, by the way, Boone’s Sortable Columns goes with Boone’s Pagination like strawberries go with rhubarb. More on that in a minute.)

If you’re building a client site, you can activate the plugin directly in the WordPress Dashboard, and instantiate the class anywhere in your installation. Or, if you’re the developer of a theme or plugin that you’ll be distributing for wide use, you can simply copy the file boones-sortable-columns.php into your own plugin/theme (I recommend a directory called ‘lib’), and then require it manually when you want to do some sortin’.

The plugin is extensively documented inline. I highly recommend that you crack open the source if you have questions about the kinds of options that Boone’s Sortable Columns provides. But, as a quick introduction, here’s a simple example of how you might use the class in your own plugin. Let’s say you have a custom post type called ‘restaurant’, and you want to display a list of restaurants that is sortable by restaurant name, the date when the restaurant was added to the site, and the name of the person who submitted the restaurant (the post author). Here’s the code you might use for a simple table, with my comments and explanations inline.

<br />
// Include Boone's Sortable Columns. You only need to do this if you're not running it as a<br />
// standalone plugin. Obviously, you'll need to put the proper path for your plugin.<br />
require_once( WP_CONTENT_DIR . '/my-plugin-name/lib/boones-sortable-columns.php' );</p>
<p>// Define an array of column data.<br />
// For more details on these (and more!) arguments, see the plugin's inline docs.<br />
$cols = array(<br />
	array(<br />
		'name'		=> 'title',<br />
		'title'		=> 'Restaurant Name',<br />
		'css_class'	=> 'restaurant-name',<br />
		'is_default'	=> true<br />
	),<br />
	array(<br />
		'name'		=> 'author',<br />
		'title'		=> 'Creator',<br />
		'css_class'	=> 'creator'<br />
	),<br />
	array(<br />
		'name'		=> 'date',<br />
		'title'		=> 'Date Added',<br />
		'css_class'	=> 'date-added',<br />
		'default_order'	=> 'desc'<br />
	)<br />
);</p>
<p>// Create the sorting object based on this column data.<br />
$sortable = new BBG_CPT_Sort( $cols );</p>
<p>// Use some of the data from the $sortable object to help you build a posts query.<br />
// In this example, I've intentionally chosen sortable options that can be passed directly to the<br />
// 'orderby' param, because they are accepted directly by WP_Query (see http://codex.wordpress.org/Function_Reference/WP_Query#Order_.26_Orderby_Parameters for more details).<br />
// In real life, your query might require something more complex, like the building of a meta_query.<br />
$query_args = array(<br />
	'post_type'	=> 'restaurant',<br />
	'orderby'	=> $sortable->get_orderby,<br />
	'order'		=> $sortable->get_order<br />
);</p>
<p>// Fire the query<br />
$restaurants = new WP_Query( $query_args );</p>
<p>// Now let's create the table markup. Here's where the magic really happens.<br />
?></p>
<p>have_posts() ) : ?></p>
<table>
<thead>
<tr>
<p>have_columns() ) : ?><br />
			have_columns ) : $sortable->the_column() ?></p>
<th class="the_column_css_class() ?>"><br />
					<a href="the_column_next_link( 'url' ) ?>">the_column_title() ?></a>
				</th>
<tr>
		</thead>
<tbody>
<p>have_posts() ) : $restaurants->the_post() ?></p>
<tr>
<td class="restaurant-name"></td>
<td class="creator"></td>
<td class="date-added"></td>
</tr>
</tbody>
</table>
<p>

Boone’s Sortable Columns handles everything else for you. It figures out what the current orderby/order parameters are. It figures out what the href on the column headers should be. It even creates CSS selectors for the <th> element that match what WP itself uses in the ‘widefat’ tables on the Dashboard, so that you can take advantage of all the pretty JS and CSS built into the WP admin interface. In fact, if this were a Dashboard page, you could simplify the <thead> described above as follows:

</p>
<thead>
<tr>
have_columns() ) : ?><br />
	have_columns ) : $sortable->the_column() ?><br />
		the_column_th() ?></p>
</tr>
</thead>
<p>

The method the_column_th() will build the markup for you. Ain’t that the bee’s knees?

Together with Boone’s Pagination

Boone’s Sortable Columns is made more scrumptious when combined with Boone’s Pagination. Here’s a compressed (uncommented) version of the example above, this time with some pagination code.

<br />
require_once( WP_CONTENT_DIR . '/my-plugin-name/lib/boones-sortable-columns.php' );<br />
require_once( WP_CONTENT_DIR . '/my-plugin-name/lib/boones-pagination.php' );</p>
<p>$cols = array(<br />
	array(<br />
		'name'		=> 'title',<br />
		'title'		=> 'Restaurant Name',<br />
		'css_class'	=> 'restaurant-name',<br />
		'is_default'	=> true<br />
	),<br />
	array(<br />
		'name'		=> 'author',<br />
		'title'		=> 'Creator',<br />
		'css_class'	=> 'creator'<br />
	),<br />
	array(<br />
		'name'		=> 'date',<br />
		'title'		=> 'Date Added',<br />
		'css_class'	=> 'date-added',<br />
		'default_order'	=> 'desc'<br />
	)<br />
);</p>
<p>$sortable = new BBG_CPT_Sort( $cols );</p>
<p>$pagination = new BBG_CPT_Pagination();</p>
<p>$query_args = array(<br />
	'post_type'	=> 'restaurant',<br />
	'orderby'	=> $sortable->get_orderby,<br />
	'order'		=> $sortable->get_order,<br />
	'paged'		=> $pagination->get_paged,<br />
	'per_page'	=> $pagination->get_per_page<br />
);</p>
<p>$restaurants = new WP_Query( $query_args );</p>
<p>$pagination->setup_query( $restaurants );<br />
?></p>
<p>have_posts() ) : ?></p>
<div class="pagination">
<div class="currently-viewing">
			currently_viewing_text() ?>
		</div>
<div class="pag-links">
			paginate_links() ?>
		</div>
</p></div>
<table>
<thead>
<tr>
		have_columns() ) : ?><br />
			have_columns ) : $sortable->the_column() ?></p>
<th class="the_column_css_class() ?>"><br />
					<a href="the_column_next_link( 'url' ) ?>">the_column_title() ?></a>
				</th>
<tr>
		</thead>
<tbody>
		have_posts() ) : $restaurants->the_post() ?></p>
<tr>
<td class="restaurant-name"></td>
<td class="creator"></td>
<td class="date-added"></td>
</tr>
</tbody>
</table>
<div class="pagination">
<div class="currently-viewing">
			currently_viewing_text() ?>
		</div>
<div class="pag-links">
			paginate_links() ?>
		</div>
</p></div>
<p>

Sweet, huh? If you want to see some real-life, more complex examples of Boone’s Pagination and Boone’s Sortable Columns in use, check out Invite Anyone (where the data is a custom post type, as in the example above – see method invite_anyone_settings_mi_content()) or Unconfirmed (where the data actually comes from a custom query of the wp_signups table – look for the admin_panel_main() method).

You can get Boone’s Sortable Columns from the wordpress.org repo or follow its development on Github.

New WordPress plugin: Boone’s Pagination

The more I use custom post types in WordPress, the more I find myself leaving until the last minute (and often forgetting) the issue of pagination. WordPress has paginate_links() and a couple other functions to help make pagination easier, but it’s still kind of a pain, and I ended up rewriting certain common functions (like functions to get the per_page parameter out of the $_GET global, etc) in multiple projects.

So I took a little time to write a reusable class for a lot of these common functions. It’s called – tada! – Boone’s Pagination. This is not so much a plugin in itself (though if you plan to use it a lot on a client site, you can activate it as a plugin) as it is a helper for people building themes and plugins. Here’s how you use it:

<br />
require_once( dirname(__FILE__) . '/boones-pagination.php' ); // You only need this if you don't activate it as a plugin</p>
<p>$pagination = new BBG_CPT_Pag;</p>
<p>$my_query_args = array(<br />
	'post_type'	 => 'my_post_type',<br />
	'paged'		 => $pagination->get_paged,<br />
	'posts_per_page' => $pagination->get_per_page // This does all the work of fetching the pagination arguments out of the $_GET global<br />
);</p>
<p>$my_query = new WP_Query( $my_query_args );<br />
$pagination->setup_query( $my_query ); // Now that you've run the query, finish populating the object</p>
<p>if ( $my_query->have_posts() ) :<br />
	while ( $my_query->have_posts() ); $my_query->the_post();<br />
	the_title(); // Do whatever you'd normally do in The Loop<br />
endif;</p>
<p>$pagination->currently_viewing_text(); // eg "Viewing 11-20 of 34"<br />
$pagination->paginate_links(); // These are the links themselves<br />

I’ll keep adding handy functions to the class as I think of them, but you should feel free to extend it yourself. I’ve also added plenty of inline docs, so crack open the source to learn more about it. Follow Boone’s Pagination on Github.