Dynamic pagination in Movable Type 6
During my Adventures Within Movable Type, I have worked out that, oh my god, there is no pagination for the blog index. That means that from the main listing of entries, you can’t go back in time! This is something that WordPress and friends have had since the beginning of time.
What the fuck! But, I have found a solution.
Laying the ground work
In the header, add this to the <head>
of the Blog Index
template:
<mt:SetVarBlock name="search_link">
<$mt:CGIPath$><$mt:SearchScript$>?IncludeBlogs=<$mt:BlogID$>
&template_id=<$mt:BuildTemplateID$>
&limit=<$mt:Var name="entries_per_page"$>
&archive_type=Index
&page=
</mt:SetVarBlock>
If you have a HTML Head
module that is included on every page, you can add the following. Otherwise, add it to every page you plan to use with dynamic pagination.
<$mt:GetVar name="search_link" strip="" trim="1" setvar="search_link"$>
Unfortunately you can’t add the DynamicSearchLink
variable globally in your HTML Head
module. The <$mt:BuildTemplateID$>
changes based on the template that contains it, and is required to point to the template ID of your blog index. If you use it in your HTML Head
, it will return the template ID of the header template, not he blog index template it needs to reference.
The PostsPerPage
variable sets the number of entries shown per page. Unfortunately, there is no way to programatically collect the value set in Movable Type’s Settings > Compose > Listing Default
, so we have to set it manually here.
By default, search links are forwarded to mt-search.cgi
in the Movable Type CGI directory. In my instance, I am hosting Movable Type on a custom subdomain – it would ordinarily return http://cms.fortressofdoom.me/mt-search.cgi
. This domain is hosted at adamroe.me
, so I would prefer a link to something on this domain. I created a custom search forwarder to fill this need. If you prefer, you can implement that and use it as your search provider instead of <$mt:CGIPath$><$mt:SearchScript$>
.
Back to your Blog Index
template. Modify your <entries>
tag as follows:
<entries limit="$PostsPerPage" search_results="1"></entries>
The limit
attribute specifies how many posts to show, and the search_results
attribute indicates to mt-search.cgi
that this <entries>
is the one to use for search results.
The Pagination Loop
Create a new template module called Dynamic Pagination
:
<mt:If name="TotalEntryCount" gt="$PostsPerPage">
<footer class="navigation"><div class="page-navigation">
<mt:If name="search_results">
<$mt:CurrentPage setvar="CurrentPage"$>
<mt:IfPreviousResults>
<span class="prev_page_link"><a href="<$mt:GetVar name="DynamicSearchLink"$><$mt:GetVar name="CurrentPage" op="--"$>" rel="prev">← Newer</a></span>
</mt:IfPreviousResults>
<mt:PagerBlock>
<mt:If name="__value__" eq="$CurrentPage">
<span class="cur_page_no"><$mt:GetVar name="__value__"$></span>
<mt:Else>
<span class="page_no"><a href="<$mt:GetVar name="DynamicSearchLink"$><$mt:GetVar name="__value__"$>"><$mt:GetVar name="__value__"$></a></span>
</mt:If>
</mt:PagerBlock>
<mt:IfMoreResults>
<span class="next_page_link"><a href="<$mt:GetVar name="DynamicSearchLink"$><$mt:GetVar name="CurrentPage" op="++"$>" rel="next">Older →</a></span>
</mt:IfMoreResults>
<mt:Else>
<$mt:GetVar name="TotalEntryCount" setvar="PageCount"$>
<$mt:SetVar name="PageCount" op="--"$>
<$mt:SetVar name="Modulo" value="$PageCount"$>
<$mt:SetVar name="Modulo" op="%" value="$PostsPerPage"$>
<$mt:SetVar name="PageCount" op="-" value="$Modulo"$>
<$mt:SetVar name="PageCount" op="/" value="$PostsPerPage"$>
<$mt:SetVar name="PageCount" op="++"$>
<mt:For from="1" to="$PageCount">
<mt:If name="__first__">
<span class="cur_page_no">1</span>
<mt:Else>
<span class="page_no"><a href="<$mt:GetVar name="DynamicSearchLink"><$mt:Var name="__index__"$>"><$mt:Var name="__index__"$></a></span>
</mt:If>
</mt:For>
<span class="next_page_link"><a href="<$mt:GetVar name="DynamicSearchLink">2" rel="next">Older →</a></span>
</mt:If>
</div></footer>
</mt:If>
What the fuck, right? It looks more complicated than it actually is.
- How many entries? If there less entries than
PostsPerPage
, stop. - Is this page being rendered by
mt-search.cgi
?- Yes
- Display a link to the previous page in
<ifpreviousresults>
- Display pagination in
<pagerblock>
- Display a link to the next page.
- Display a link to the previous page in
- No
- Calculate number of pages required
- Display pagination in
<for>
loop - Display a link to the next page.
- Yes
The part with dynamic generation
The first part of the template runs only when the template is called through mt-search.cgi
, that is, the part between <if name="search_results">
and <else>
.
- Set the
CurrentPage
variable using `` - If there is a previous page (
<ifpreviousresults>
), provide a link to the previous page - Display a list of pages and their link with
<pagerblock>
, specially highlightingCurrentPage
- If there is a next page (
<ifmoreresults>
), provide a link to the next page
The part with static generation
This second part only runs when <if name="search_results">
returns false
. This means, it is generated statically. Because <pagerblock>
only works with dynamic templates, we need to generate our pagination manually.
- This section runs on the static home page, or
CurrentPage = 1
. Obviously, there are no negative pages, so there is no need for a previous link. - We calculate the number of pages required:
PageCount = [ ( (TotalEntryCount - 1) - ( (TotalEntryCount - 1) % PostsPerPage ) ) / PostsPerPage ] + 1
. Clear as mud, right? - Display a list of pages and their links with
<for>
- Finally, provide a link to the next page
Including it in your own templates
- Add the
DynamicSearchLink
variable to any template you plan to use dynamic paging with. Don’t forget to addPostsPerPage
andTotalEntryCount
somewhere too – preferably in yourHTML Head
module. - Add
limit="$PostsPerPage" search_results="1"
to your<entries>
in templates that you plan to use dynamic paging with. - Create a new template called
Dynamic Pagination
and include it in your main index where you’d like the page list: ``.