Textpattern tips, tutorials and code snippets

Enable pagination with article_custom article listings

By default, Textpattern only allows pagination using the <txp:article /> tag – <txp:article_custom /> does not. This is the best way I’ve been able to come up with to enable pagination with article_custom article lists, and I’d like to share the method with you.

Required plugins

  1. adi_gps
  2. adi_calc
  3. rah_repeat

Get started

<txp:adi_gps name="page" quiet="1" />
<txp:variable name="article-count" value="0" />
<txp:variable name="article-limit" value="10" /> <!--Set this to whatever you want-->
<txp:if_variable name="page" value=""><txp:variable name="page" value="1" /></txp:if_variable>
<txp:adi_calc name="offset" value='<txp:variable name="page" />' subtract="1" />
<txp:adi_calc name="offset" multiply='<txp:variable name="article-limit" />' />

Duplicate the article_custom tag that you are trying to paginate, paste it before the “real” one, and set limit="9999". Make it a container tag with just <txp:adi_calc name="article-count" add="1" /> in it.

Right after that article_custom tag, add this line: <txp:adi_calc name="page-count" value='<txp:variable name="article-count" />' div='<txp:variable name="article-limit" />' ceiling="1" />.

Next, in the “real” article_custom tag that you want to paginate, set limit='<txp:variable name="article-limit" />' and offset='<txp:variable name="offset" />''.

Page Navigation – Option #1: Google list of links

This makes a simple unordered list of page number links. It doesn’t make separate first/last or prev/next links, but I’m sure those would be possible with some effort.

<ul class="pagination">
<txp:rah_repeat limit='<txp:variable name="page-count" />' value="1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20" >
<li>
<txp:if_variable name="page" value='<txp:rah_repeat_value />' >
 <txp:rah_repeat_value />
<txp:else />
 <a href="?page=<txp:rah_repeat_value />" ><txp:rah_repeat_value /></a>
</txp:if_variable>
</li>
</txp:rah_repeat>
</ul>

If you have other url variables that you are using to filter articles lists using adi_gps, you can preserve these between pages by adding the necessary markup to the link. For example, the following line might be what you want if you are filtering by section, category, and a couple url variables (usually custom fields):

<a href="?page=<txp:rah_repeat_value />&amp;s=<txp:section />&amp;c=<txp:category />&amp;urlvar1=<txp:variable name="urlvar1" />&amp;urlvar2=<txp:variable name="urlvar2" />" ><txp:rah_repeat_value /></a>

Page Navigation – Option #2 – Drop-down page select

<form action='<txp:page_url type="request_uri" />' method="get">
<select name="page" onChange="this.form.submit();">
<txp:rah_repeat limit='<txp:variable name="page-count" />' value="1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20" >
<txp:if_variable name="page" value='<txp:rah_repeat_value />' >
<option selected value='<txp:rah_repeat_value />'><txp:rah_repeat_value /></option>
<txp:else />
<option value='<txp:rah_repeat_value />'><txp:rah_repeat_value /></option>
</txp:if_variable>
</txp:rah_repeat>
</select>
<noscript><input type="submit" value="Go!"></noscript>
</form>

If you have other url variables that you are using to filter articles lists using adi_gps, you can preserve these between pages by adding extra select elements before the closing </form> tag. You can hide these extra select elements from being displayed with a simple .hidden { display: none; } CSS rule. Here is an example:

<select class="hidden" name="urlvar1">
<txp:if_variable name="urlvar1" value="">
<option selected value=""></option>
<txp:else /><option selected value='<txp:variable name="urlvar1" />'></option>
</txp:if_variable>
</select>

Any comments, please post either here or on the forum thread.

3 Comments Comment feed

Here’s a version that achieves the same thing without using any plug-ins:

<txp:php>
	// Initial setup
	global $variable;
	$variable["article-limit"] = 10; // Set to whatever you want
	$variable["article-count"] = 0;
	if(isset($_GET["page"])) { $variable["page"] = $_GET["page"]; }
	else { $variable["page"] = 1; }
	$variable["offset"] = ($variable["page"]-1)*$variable["article-limit"];
</txp:php>
<txp:article_custom section="whatever sections you'd like" limit="9999" status="4">
	<txp:php>
		// Count the articles
		global $variable;
		$variable["article-count"]++;
	</txp:php>
</txp:article_custom>
<txp:php>
	// Determine the page count
	global $variable;
	$variable["page-count"] = ceil($variable["article-count"] / $variable["article-limit"]);
</txp:php>
<txp:article_custom section="whatever sections you'd like" pgonly="0" status="4" limit='<txp:variable name="article-limit" />' offset='<txp:variable name="offset" />' />
<txp:php>
	// Output pagination
	global $variable;
	if(($variable["page"]+1) <= $variable["page-count"]) {
		echo "<div class=\"older\"><a href=\"?page=". ($variable["page"]+1) ."\">Older articles &raquo;</a></div>";
	}
	if($variable["page"]-1) {
		echo "<div class=\"newer\"><a href=\"?page=". ($variable["page"]-1) ."\">&laquo; Newer articles</a></div>";
	}
</txp:php>

Pagination is an easy task with a little XPath and this plugin

<txp:etc_query 
data='<txp:article_custom limit="999">
<a href=''<txp:permlink />'' id=''link-to-<txp:article_id />''><txp:title /></a>
</txp:article_custom>' 
query="a[@id='link-to-?id' or '?id'='' and position()=1]" 
replace="following-sibling::a[position()=5]/text()=Next;preceding-sibling::a[position()=5]/text()=Prev"
specials="query">
{preceding-sibling::a[position()=5]}{preceding-sibling::a[position()<5]}{?}{following-sibling::a[position()<5]}{following-sibling::a[position()=5]}
</txp:etc_query>

Add a comment

Use Textile help to style your comments