By mattyoung on
I have a problem with multiple different pagers on one page. The paging url are all the same, like "my-page?page=1". So clicking on any one of the pager would move all of them to the same page. It seems Drupal's pager is limited to one single pager per page? Is there anyway to allow multiple different pager control?
Comments
Just thought about this a
Just thought about this a little bit. I'm pretty sure having multiple different pagers on a same page is not possible. In order to allow multiple pagers, they would have to be server side stateful and this is just not how Drupal works. Am I correct?
Perhaps some more
Perhaps some more information about what you're trying to do would help here. There are ways to have multiple pagers on a single page. The first one that comes to my mind is a panel page with two views, each with it's own pager. I somehow feel this isn't what you want. But I'm not sure what you do want, so could you elaborate a bit more?
I'm rendering multiple image
I'm rendering multiple image galleries with
image_gallery_page(null, $term->tid). This function does this inside:then it renders its pager like this:
You can see it here: http://www.gsprint.com/photography
The top two galleries have multiple pages. Click any of the pager links and you can see both galleries move to the same page in sync.
Thanks for posting the link.
Thanks for posting the link. I understand your problem completely now and you are in a bit of a pickle. pager_query is the cause of your problems http://api.drupal.org/api/function/pager_query/6 If you look at the second line of the code, it does $page = $_GET['page'], which effectively sets all pager_query calls to the same page. I don't have an elegant solution for you, but I've got one that will work. It goes like this:
1 - Theme your pagers to set different GET variables. For instance portfolio 1's pager could use URLs like /photography?page1=X and portfolio 2's pager could use URLs like /photography?page2=X
2 - In your code, before you call pager_query for portfolio1, set $_GET['page'] = $_GET['page1'] and likewise for the other portfolios
To cover the case where the user navigates to page 2 in portfolio 1, then navigates to page 2 in portfolio 2 I would also stash the values of the pagers in the user's session. The value of $_GET['page'] would then be $_GET['pagex'] if set, otherwise $_SESSION['pagex'] if set, otherwise NULL.
Of course there are other ways to do it. One that came to mind is to use a custom module to register a path that manages the state of the pagers. You would then theme the pagers to pass the appropriate information to that path, which would handle managing the state of the pagers, then redirect to the page that renders the galleries. You could also use AJAX to only replace the current fieldset when a pager is clicked.
I've been using Drupal for a long time and am a bit surprised that a request as simple as this requires so much work to accomplish. It's got me thinking about proposals for D7 to improve the pager API.
Thank you for your reply.
Thank you for your reply. I'll need some times to digest this.
Drupal's pager is stateless and uses global variables internally. So there can only be one pager at a time. I think what you suggest can work to allow multiple pagers on a single browser page. But if the user open another browser page visiting the same page, then the pagers session variables will get overridden. But I can live with the single browser page limit.
>You could also use AJAX to only replace the current fieldset when a pager is clicked.
I was just wondering about how to "ajaxified' the Drupal pager, ajaxified pager should fall back to full page refresh if no javascript. I don't know how to accomplish this. I don't even know how to construct the pager url to make this happen.
>I've been using Drupal for a long time and am a bit surprised that a request as simple as this requires so much work to accomplish. It's got me thinking about proposals for D7 to improve the pager API.
I hope you will come up with some great solutions to this problem. This is not an easy nut to crack. The Wicket Java web framework is designed to solve this problem by making pages server side stateful: every browser page has a corresponding server side page map holding the page state. You can add any number of pager to a page and the framework keep track of the state. But one annoying shortcoming is if session timeout, the page cannot be reloaded and user is face with a page session timeout screen.
Again, thank you so much for your reply.
I see your using 6.x... If
I see your using 6.x... If I'm correct this should be pretty simple. I've done it with 5.x...
Take a look at the Drupal API for the function theme_pager(). The key is the $element variables value being changed. I'm not an expert, but I believe using conditionals based on the $element variable is what you need.
So maybe your first pager would have $element = 0 and for the second it would be equal to 2....
Nice tip!
I never noticed that before, the the docs say it pretty clearly: http://api.drupal.org/api/function/theme_pager $element is for using multiple pagers on the same page. It looks like the default theme_pager() doesn't try to help you out though. It should be pretty straightforward to override theme_pager and use a static variable to increment $element each time it's called. I'm going to test it out real quick. I'll report my findings.
Almost there!
Well, I quickly threw together a panel page with the same view in two different columns. I added some code to keep a running count of the number of pagers themed. Here's the new code:
So what I got was pager URLs like http://mysite.com/testpanel?page=2,3 The pagers themselves show the correct page selected, but the views are still showing the same content. At this point, I'm not sure whether the problem is in Views or Panels, but I'm sure that it's solvable. Since you are using your own custom menu callback, you shouldn't have any problem anyhow.
You also need to pass in the
You also need to pass in the same $element in the
pager_query()call.It's great there is at least a way to make multiple pagers. It would be nice if the pager is an object you allocate so it can control this $element in both end of
pager_query()andtheme('pager',....I'm half asleep so sorry in
I'm half asleep so sorry in advance if I don't make sense... Here's an example that I used. I've never used panels and only have done the multiple pagers on the same page with SQL queries. I don't understand what your trying to do with the above code, but here's a sample....
So the first part I'm using the default pager value....
Where is your call to
Where is your call to
pager_query()? It needs to have the same $element value pass in.I'm anxious to see how this work. I just don't see how to can work from looking at the code. I wait for your good news.
Sorry, I just noticed your
Sorry, I just noticed your post before I was going to bed... I shouldn't have just posted just those two lines... here's my full example... I used guestbook, which I actually posted in my page-user.tpl and then the query for user nodes which I posted in my user_profile.tpl.
Guestbook....
Get user's nodes....
And then I added my theme_pager() function to my template file so that each pager could be styled differently...
Does it work? Say you put
Does it work? Say you put pager1 at page 4 and move pager2 to page 2, does pager1 stay at page 4?
Yup... That's the idea
Yup... That's the idea behind it... I can page to the 3rd of 4th page of results for the users nodes, while still seeing the first page of users guestbook entries. $element makes each pager independent of each other unless their $element shares the same value.
I see how this work. Each
I see how this work. Each pager url has that ?page argument loaded with every pager's position. That's how it figures out where every other pages is at when any of the pager link is clicked.
I just realize $element must be 0,1,2,3,4 sequentially and that it must be idempotent for each pager instance. I cannot see how to make this $element value play nice with pagers from different independent modules. There is no central "broker" to allocate $element value. Let say we have two modules A and B, both render pagers. How do we make them play together? Modules need to have some way to "allocate" their pager $element value. Such that it's guarantee the same every time for a give uri.
You made an ad hoc way to assign $element value. Since everything is under your control, this is workable.
I'm not seeing how this can work for independent modules.
Multiple Pagers, Unique IDs, Plays Well With Other Modules
I just discovered this as well ($element must be sequential 0,1,2,3,... etc.) or it won't work (I'm using D6). I also discovered there is a global variable $pager_total (http://api.drupal.org/api/global/pager_total/6). It's an array of the pagers on a given page starting with index 0.
To let my module's pager play with other pagers rendered on a given page and not overwrite any of them this is what I did:
Unfortunately other modules must also do something like this since the burden is on the module developer to manage the pager id. If a subsequently loaded module explicitly sets its pager id then it will likely overwrite mine or a pager ahead of mine in the array.
The resultant URL shows:
?page=[results page index]
if there's only one pager on the page, otherwise it shows:
?page=[results page index]%2C[pager id]