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">&larr; &nbsp; 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 &nbsp; &rarr;</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 &nbsp; &rarr;</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
      1. Display a link to the previous page in <ifpreviousresults>
      2. Display pagination in <pagerblock>
      3. Display a link to the next page.
    • No
      1. Calculate number of pages required
      2. Display pagination in <for> loop
      3. Display a link to the next page.

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>.

  1. Set the CurrentPage variable using ``
  2. If there is a previous page (<ifpreviousresults>), provide a link to the previous page
  3. Display a list of pages and their link with <pagerblock>, specially highlighting CurrentPage
  4. 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.

  1. 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.
  2. We calculate the number of pages required: PageCount = [ ( (TotalEntryCount - 1) - ( (TotalEntryCount - 1) % PostsPerPage ) ) / PostsPerPage ] + 1. Clear as mud, right?
  3. Display a list of pages and their links with <for>
  4. Finally, provide a link to the next page

Including it in your own templates

  1. Add the DynamicSearchLink variable to any template you plan to use dynamic paging with. Don’t forget to add PostsPerPage and TotalEntryCount somewhere too – preferably in your HTML Head module.
  2. Add limit="$PostsPerPage" search_results="1" to your <entries> in templates that you plan to use dynamic paging with.
  3. Create a new template called Dynamic Pagination and include it in your main index where you’d like the page list: ``.

Acknowledgements

  1. Paginating the Main Index
  2. Pagination for Static Templates