How does the Custom Pagers module work?

The Custom Pagers module is the One Last Thing that sold me on Drupal. It allows administrators a bit more flexibility with paging through node types than Drupal gives you by default. From the description:

Custom Pagers allows administrators to define context-sensitive previous/next pagers for any node type. The list of nodes to be cycled through is generated by a user-selectable view, and each pager can be displayed above or below the node body or in a sidebar block. This makes it possible to duplicate the paging functions of forum.module and book.module, as well as more complex stuff like comic strip navigation. Requires token.module and views.module.

It was the "comic strip navigation" point that sold me, since that's what I'm using Drupal to do -- to host and serve up my webcomic.

Still, it's a new module and like most new modules it's under-documented. That's not a criticism -- it's pretty standard practice to create the functionality first and provide documentation second. But as a new Drupal user, who is still trying to get a handle on even the most basic of Drupal functionality, I admit to being a little lost. So this is an account of my attempts to use and understand the Custom Pagers module.

I hope that this topic will:

  • help people who know more about this module figure out what I'm doing wrong, and point me in the right direction
  • help people who are officially documenting this module figure out what trouble spots need extra attention
  • perhaps contribute to the documentation effort in the event that I get something right, and it proves useful. :)

So onward...

Installation

To install the Custom Pager you need:

  1. the custom pager module
  2. basic views module
  3. the token module

All three of these must be activated in the Modules area of the Admin section.

Use

On the Issues for Custom Pagers area is a post entitled "Sounds good - docs??" In the back-and-forth in that post, Eaton describes how the Custom Pagers module works:

Regarding setup, it works like so:

You create a new pager, and specify what kinds of nodes it applies to. Then, you specify what view should be used to generate the context that the pager will be stepping through. Then you say whether you want the pager to appear above or below the node body (or both), or whether you want it to appear in a dedicated sidebar block.

Each pager can also be themed individually -- allowing a simple 'next/prev' text link on one node type but elaborately themed arrows and rollover icons for image nodes. It's now also possible to have multiple pagers per node -- one that pages through 'all nodes by current node's author' and another that pages through 'all nodes that share the current node's main taxonomy term', both displayed on the same page.

Essentially you are telling the custom pager where the data is coming from (the content type) and where it is being displayed (the specific view). Then you define how the pager appears in relation to that view (above the node/below the node/above and below the node/in a sidebar). This gives you a basic pager that you can then build on to make more complex as needed.

To create a new custom pager, you go to the Site Building area in your Admin page and click on the Custom Pagers link, which takes you to the Custom Pagers admin page. From there you click on the Add a new custom pager link which takes you to the Add custom pager screen.

On this screen are a number of fields you must populate with information to create your custom pager:

Title (Required field): This is where you name your custom pager. This is a required field in that you must put something in here to create the field successfully, but the only purpose it appears to serve is to allow you to identify it -- it does not show up as a possible field in CCK, for example, nor does it show up as a possible field when you are creating a View.

Node types (Required field): The description for this field is "The node types this custom pager will apply to." It consists of a list of all the content types that are available, including any you have created with CCK. The field seems to be used to choose what type of content type you will be paging through. For example, on my site I created a CCK content type called "Help Desk," which is used for creating one of my webcomics. By selecting "Help Desk" from this field I'm telling the module that any content created with this content type will be something this pager will be sorting through.

Pager view (Required field): The description for this field is "The view to use when generating this pager." This drop-down list contains every view that has been created with the Views module. Selecting a view from this list tells the custom pager module where the custom pager will actually be displayed. For example, I have created a view called hd_comic that I use to display the latest Help Desk webcomic on the front page of my site. By selecting hd_comic from this list, I am telling the custom pager that hd_comic is where the custom pager will be displayed, and the "Help Desk" content type (that I previously selected) is where the data for the pager will be pulled from.

Pager position (Required field): The description for this field is "The node type(s) this custom pager will apply to." this is a little confusing, since it seems to be pretty much the same description as the Node type field. What it actually is, is a drop-down list that allows you to specify how the custom pager will appear in relation to the node it is paging through:

  • Above the node's body - the custom pager will be displayed above the view you selected from the Pager view field
  • Below the node's body - the custom pager will be displayed below the view you selected from the Pager view field
  • Both above and Below the node's body - the custom pager will be displayed both above and below the view you selected from the Pager view field
  • In a sidebar block - I haven't had a chance to use this one, so I don't know whether this places the view in one of your sites sidebars, or if it creates a sidebar next to the node itself in order to contain the paging links.

View arguments: This is not a required field. The description for this field is "A return-delimited list of arguments to pass into the selected view."

To be honest, I'm not really clear on what the view arguments do. My guess is that the list of allowable view arguments are found in the Placeholder tokens below, and that by entering each of those placeholder tokens in this field (one token per line, each item separated by the return key) you can get your pager to store information that you use to "do stuff."

I fully realize that "do stuff" is not a particularly helpful phrase. Think of it as a working man's variable.

Placeholder tokens: When you click on the link to expand this item, the description for this field is "The following placeholder tokens can be used when passing arguments into the view. Each will be replaced with the correct values at runtime."

My guess is that these are a list of values that can be put in the View arguments field in order to, you guessed it, "do stuff." However, I think using these arguments require a great deal more familiarity with Drupal and specifically the API than I have.

However, to create a basic pager, you don't need to use arguments. All you have to do is:

  1. Create a new custom pager
  2. Name the custom pager
  3. Select the content type the custom pager will be using to determine what content it is paging through
  4. Select the view that the custom pager will appear with
  5. Select how the custom pager will appear in relation to the view
  6. Save your custom pager

In theory your custom pager will appear with that view as soon as it is created.

Potential problems

I say "in theory" because at the moment, on my live site, the custom pager module does not work... on my test bed site, however, I have been able to get the custom pager to appear. There are a number of important differences between the test and live site (most signficiantly, different versions of MySQL) that make figuring out WHY one is working and the other isn't well beyond my capabilities. However, after beating my head repeatedly against the live site I've come up with a few questions that I think are important, and that if the answers are known in advance I think will minimize problems with this module:

  1. Is it possible to create a view that makes it possible for a custom pager to function? Using filters and arguments in a view can theoretically make it possible for the view to have only one piece of content in it, giving the pager nothing to actually page through. What happens if you create a custom pager associated with such a view? What is the best/safest way to create a view that is compatible with a custom pager?
  2. Are there any other Drupal modules that actively interfere with the custom paging module? Do any modules need to be turned off in order for the custom pager module to function correctly?
  3. What is the minimum version of mysql that needs to be installed in order for the custom pager module to work? Is it possible that someone running a 3.x or 4.0 version of mysql will be unable to use this module correctly?

That's all I have. Keep in mind that this information may be completely wrong, because I may have completely misunderstood how the custom pager module was designed and how it works. Hopefully Eaton will see this and clarify everything I got wrong...

Comments

puccia’s picture

Interesting post. I'm also trying to figure out how the custom pager works, and I think there are a couple of points in need of a revision (my opinion, may be wrong).

First, my experience is that node types are not used "to choose what type of content type you will be paging through". They are used to choose on which nodes the custom pager will show up, according to their type. Thus, it happens (at least to me) that a custom pager also shows up on nodes which are not included in the view (say, you have a view filtered by a taxonomy term and you apply the custom pager to all nodes of type story. The pager will show up on any story, even if the story belongs to a different category and is filtered out of the view).

I am less sure about the second point, but my guess is that the arguments work with the arguments (the field named 'arguments') in the view (which are optional and a bit underdocumented). For what I understand, the argument works like a grouping element, that can be turned into a filter if you assign a value to it.

ubersoft’s picture

You may be right about the node types -- I can't say for sure, because I couldn't get the custom pager to show up on my live site at all, and I could only get it to show up once and a while on my test site (pretty consistently at first, and now not so much).

I'd like Eaton to talk a bit more about how arguments work. :)

eaton’s picture

...I got it into my head that I'd make a videocast demoing how to set the module up, and discovered that videocasts take TONS of work. Heh. For the time being, a copy of the videocast in progress is at http://jeff.viapositiva.net/custom_pager.mov -- It'll be up on the Lullabot site when I get the kinks ironed out.

The basic series of steps though, is something this:

  1. Make a custom node type for your comics.
  2. Make a view that only shows your comics -- also, make sure it's sorted in the way you want your comics browsed. Creation date, etc.
  3. Create a custom pager, and make sure it's filtered to that node type.
  4. Choose the view that you just built as the 'Pager view'.
  5. Visit a node of that type.

That's all that should be necessary for a very simple application. if you start putting additional filters on it, it's *definitely* possible to create a view that doesn't actually contain any nodes. Creating a view filtered by type, and taxonomy term, but not tagging any nodes with that taxonomy term for example -- that'll give you an empty list and a missing pager.

It sounds like you want to do something a little more complex -- using a pager that ONLY steps through comics for a particular strip. If you're using multiple content types to do that, you can remove the 'content type' filter on the View, and instead add an argument: 'Node: Type' to the view definition. Once you've done THAT, you can set up your pager to show on all the content types you're using as comics. THEN, in the 'View arguments' block, put: [type]

That's the token that represents the node type of the node currently being viewed. It'll pass that in to the view when it builds its list.

If that doesn't make sense, definitely let me know and I'll try to put something more detailed together.

--
Lullabot! | Eaton's blog | VotingAPI discussion

--
Eaton — Partner at Autogram

ubersoft’s picture

... it sounds like I'm not using views correctly.

What I'd done was create a block teaser list with a filter that specified all of a single term -- I thought that was enough.

robhamm’s picture

I swear I'm not being intentionally obtuse, but for some reason I'm having cognitive dissonance when it comes to "getting" the instructions for adding the first/last links. I'm sure the fault is mine, but if you wouldn't mind too much, could you break it down into baby steps for me? I mean, like, "Open this document on your server. Look for where it says this. Now type this in."

Again, sorry to be a bother. I know that in the past I've asked questions only to realize that the answer was right in front of me, but this time I am honestly clueless after reading the instructions.

TIA

Rob Hamm
http://www.bluecrashkit.com (my current webcomic and means of support)
http://www.syberfang.com (my upcoming webcomic)

greeneo’s picture

Any way to get this on the front page and taxonomy pages?

eaton’s picture

Custom Pagers can only add pagers to nodes -- there's already a themable system pager on listing pages like taxonomy and the /node page.

--
Lullabot! | Eaton's blog | VotingAPI discussion

--
Eaton — Partner at Autogram

ubersoft’s picture

The system pager is themable? I had no idea. I was under the impression that you really couldn't change a darn thing about the way it worked...

xerexes’s picture

Hey all true but if you want to use custom pager instead of the views pager on the teaser view (and with webcomic where you're going to want to create a view showing 1 comic) just delete "$teaser == false &&" from line 64 in the module file.

I am using it on frightnight.org so far without any issues...

Right now I'm trying to figure out how to add a "last" link which would go to the most recent node in the view you've selected.

jacoder’s picture

I thought I would post an example of how to return a list of node Id's that can be used in the pager node list of the Custom Pager module using php. This snippet came about because I did not want to create a view just yet of all my image nodes. I merely wanted to allow users to page through images once they had clicked on a thumbnail.

This snippet returns an array of nid's for type "image" and status = 1 (published). You can change the type to whatever you like and even the status if you prefer. But this snippet will populate, and then return, an array containing only the nid of each node based on the type you declare - image type in this case.

Simply cut and paste this code into the "Use PHP Snippet" text box under "Pager Node List" of the Custom Pager module.

$query = "SELECT n.nid FROM {node} n WHERE n.type = 'image' AND n.status = 1";
$results = db_query($query);
while ($row = db_fetch_array($results)) {
extract($row);
$nodeList[] = $nid;
}
return $nodeList;

The drawback to this method is when a user clicks an image thumbnail and is redirected to the view of the image, the pager allows, and displays, the navigation for all image nodes in the database, and not just image nodes relevant to one gallery or album. I plan on working on a hack to add the ability to select images by category (gallery album), or perhaps I may just breakdown and use a view for the images since paging can be done by gallery using views. Nevertheless, perhaps this code will help someone else who is trying to figure out how to select your own node list without having to setup a view first.

jacoder

mattcasey’s picture

Thanks, this snippet also still works Panels 3.9 and with custom pagers 6.x-dev

derjochenmeyer’s picture

I just spent some time on figuring out why my custom pager did not show up anywhere.

The answer is: i used a node-mynodetype.tpl.php in my theme directory to theme my nodetype a bit, nothing crazy but i removed the $content output to build my own stuff.

It seems the custom pager is created in the $content.

----------------------
okay.cool

LaurenH’s picture

Is it possible, perhaps using tokens, to have a pager show up in a node for each taxonomy term to which a node belongs?

For example, I have a site that utilizes taxonomy to organize image nodes into "galleries". While I can easily make a custom pager that allows users to page through *all* images in the Gallery term, if something is filed into a subterm I can't seem to figure out how to also output a pager that pages through only the images within that subterm. I suppose I could create a pager for the terms manually, however I will not be the primary person adding images to the site and thus I can't expect others to create a new pager every time they add a new taxonomy subterm (or as it is now, what they see as a "gallery").

I could just be missing something obvious, but if someone could explain whether this is even possible or not, I'd be very grateful! Thanks!

Zoologico’s picture

Just FYI.

I had the same problem with custom pagers not showing up, but I realized that they are a part of your node and are accessed as all other items in a node using CONTEMPLATE:

I found the following and inserted it into my templates and they worked great:

Top pager:

print $node->content['custom_pager_top'][1]['#value']

Bottom pager:

print $node->content['custom_pager_bottom'][1]['#value']

Works great after inserted each of those where I want them to appear.

Hope this helps or perhaps your problems are beyond the scope of this "solution"?

Nimo’s picture

This doesn't work for me.

My $node->content seems to be completely free from anything related to custom_pager regardless of how I do.

To display it in a block works but nothing else.

Zoologico’s picture

You should try to create a new node associated with the View associated with that pager.

I found that I had to do that for the variables to show up sometimes.

Lostmonkey’s picture

I am looking for the same thing, did you figure anything out?

:-) Mikkel

Anonymous’s picture

My behavior of full node was first to list the picture and then the body of the node (users use it as a description) but after using this module now the body gets on top of the image. Somebody get the same problem or know how to resolve it? I tried with pager
# Above the node's body
# Below the node's body
and
# Both above and Below the node's body
but with no luck.

druryjeff’s picture

For me, the big issue was the absence (by design) of $node->content in my node.tpl.php file. This snippet - <?php print $node->content['custom_pager_top'][1]['#value']; ?> - worked as advertised. Thanks.

HunterElliott’s picture

Just a note to those who have the snippet above not working for them... If you have the Devel module installed, look at the "devel info" either via "dsm" or the "dev render" items. If using the Dev Render tab, scroll down to your Content item, expand it and then expand your Custom_Pager element - custom_pager_top, _bottom, etc. Take the Array number and replace it where druryjeff used the number 1. i.e., print $node->content['custom_pager_**'][***]['#value']; ... where ** = top, bottom, whatever the pager is, and where *** = the number of the array you've set up in your Custom Pagers.

While this is probably very obvious to many people, some of the newer folks (like myself) may not initially "get" that the numeric value in that snippet refers to the "id number" referencing a particular custom pager you would have setup for a particular piece of content. In my case, the value needed was "2" and that's why "1" wasn't working for me, because "1" was a pager for a different content type. It was something I'd overlooked.