Jump to content
nikola

Images pagination

Recommended Posts

I've set up a gallery page that uses "gallery" template. The gallery page will contain lots of images but I want to display only 20 per page. How can I accomplish pagination for this type of action?

I don't want to set up children pages that will contain 20 images per page, rather let the Processwire do the pagination from one page.

Thanks

Share this post


Link to post
Share on other sites

Yes, I have. I know how to return an array of pages and paginate them, but I need similar but different approach. I have only one page that contains images for gallery, it doesn't have parent page nor it spans across children pages with images.

The page will contain lots of images and I want to set pagination to have 20 images per page but I don't know how to make pager limitation based on one page.

Share this post


Link to post
Share on other sites

You should track the page number and have to adjust the "start" and "limit" selectors of images array using the find() or filter() methods.

Instead:

$results = $pages->find("start=0, limit=n"); 

You could use:

$results = $images->find("start=0, limit=n");

to "paginate" the images on the page. And I hope that

$pagination = $results->renderPager();
echo $pagination;

will still work.

Share this post


Link to post
Share on other sites

Unfortunately it doesn't work. I've tried various combinations and can't make it work... Ryan, any tips about the way it can be done?

Share this post


Link to post
Share on other sites

I think that pagination works only with pageArrays, so no help here. Building custom pagination for images is not that hard though, I'll provide you a starting point when I get to computer.

Share this post


Link to post
Share on other sites

Try something like:

$all_images = $page->images;
$total = count($all_images);
$images_per_page = 4;
$all_pages = round($total / $images_per_page);
$start = ($input->pageNum - 1) * $images_per_page;
$images_limited = $all_images->slice($start, $images_per_page);

foreach($images_limited as $img):
$thumb = $img->size(200, 120);
echo "\n<img src='{$thumb->url}' width='{$thumb->width}' height='{$thumb->height}' alt='' />";
endforeach;

Share this post


Link to post
Share on other sites

I've not tried seddass's solution, but it looks right on. I'm using some of his code in my example too. So here's another option, which is to piggyback onto the MarkupPagerNav module, even though you aren't dealing with pages.

<?php

// get the images you are going to display
$items_per_page = 4;
$start = ($input->pageNum - 1) * $items_per_page;
$total = count($page->images);
$images = $page->images->slice($start, $items_per_page);

// make this to give MarkupPagerNav what it needs
$a = new PageArray();

// add in some generic placeholder pages
foreach($images as $unused) $a->add(new Page());

// tell the PageArray some details it needs for pagination
// (something that PW usually does internally, for pages it loads)
$a->setTotal($total);
$a->setLimit($items_per_page);
$a->setStart($start);

// output your images
foreach($images as $p) {
  $img = $p->img;
  echo "<img src='{$img->url}' alt='{$img->description}' />";
}

// output the pagination navigation
echo $a->renderPager();

Btw, an images field on a page isn't going to scale infinitely. At some point, you are going to find it difficult to manage, sort, etc. So I would still place some limits on yourself for the max number of images you are going to attach to a single page.

Edited by ryan
Corrected typo, changed $images_per_page to $items_per_page
  • Like 4
  • Thanks 2

Share this post


Link to post
Share on other sites

Thanks guys, there is no reason for me to post yet another example anymore :)

Btw, an images field on a page isn't going to scale infinitely. At some point, you are going to find it difficult to manage, sort, etc. So I would still place some limits on yourself for the max number of images you are going to attach to a single page.

That will be hard when we get drag & drop magic working. It will be so much fun to add more and more images to single field! ;)

Share this post


Link to post
Share on other sites

I was unable to get images with pagination based on Ryan's method.

I've decided to tako another route and follow Ryan's advice to make children pages underneath "Gallery" page that will contain 20 images per page.

I use this code to merge them together, but yet again can't use pagination.


<?php

foreach($page->children() as $gallery) {

if(!count($gallery->images)) continue;

foreach($gallery->images as $image) {
$thumb = $image->size(142, 92);
echo "<a href='{$image->url}' rel='colorbox'><img src='{$thumb->url}' width='{$thumb->width}' height='{$thumb->height}' class='photo' /></a>";
}

}

?>

Probably it isn't the smartest way to do it but it gets the job done ... all I need is now to paginate them so I can have 20 images per page...

Share this post


Link to post
Share on other sites

You mentioned that pagination wasn't working–can you provide more detail about what it is doing? Also, double check that page numbers are supported in your template settings, under the "URLs" tab. Without that turned on, pagination will not work.

Share this post


Link to post
Share on other sites

I think he is trying to output all of the images from all of the child pages at once and later he is trying to paginate the $images array instead to paginate the child pages. Hope I am wrong here.

Nikola, lets clear you mind.  8)

1)

Try to create a "galleries" template with a few child pages with "gallery" template. You should to be able to paginate the child pages as described at  http://processwire.com/api/modules/markup-pager-nav/. The pagination steps should to be one page per pagination step (i.e. limit=1). It should to be working. Haven't tried it.

2)

In each "gallery" template with "images" field you could use your code below:

foreach($page->images as $image):
     $thumb = $image->size(142, 92);
     echo "\n<a href='{$image->url}' rel='colorbox'><img src='{$thumb->url}' width='{$thumb->width}' height='{$thumb->height}' class='photo' /></a>";
endforeach;

Hope i have helped.

Share this post


Link to post
Share on other sites

PW actually won't attempt pagination with limit=1. It needs at least limit=2 before it'll attempt to determine totals needed for pagination. This is an optimization that lets the system run more quickly, since so many parts in PW use limit=1 (and this is the first instance where a limit=1 need has turned up in pagination).

The more I think about it, I have to imagine that pagination wasn't working before because page numbers must have been turned off in the template. That's the only reason I can think of why our previous examples may have not worked on his site.

One option for single-page pagination is to just use next/prev buttons. $page->next() and $page->prev() return the next and previous sibling pages, making this type of pagination very easy. i.e.

<?php
$prev = $page->prev();
$next = $page->next();

if($prev->id) echo "<a href='{$prev->url}'>Previous Page</a> ";
if($next->id) echo "<a href='{$next->url}'>Next Page</a> ";

You wouldn't want to do this with something that has thousands of pages, but it would be a good solution for smaller pagination groups.

Share this post


Link to post
Share on other sites

I still haven't figured this out yet.

When using Ryan's code I get following errors:

Exception: Method Pageimages::renderPager does not exist or is not callable in this context (in C:\inetpub\wwwroot\pw\wire\core\Wire.php line 231)

#0 C:\inetpub\wwwroot\pw\site\templates\gallery.php(46): Wire->__call('renderPager', Array)

#1 C:\inetpub\wwwroot\pw\site\templates\gallery.php(46): Pageimages->renderPager()

#2 C:\inetpub\wwwroot\pw\wire\core\TemplateFile.php(88): require('C:\inetpub\wwwr...')

#3 [internal function]: TemplateFile->___render()

#4 C:\inetpub\wwwroot\pw\wire\core\Wire.php(267): call_user_func_array(Array, Array)

#5 C:\inetpub\wwwroot\pw\wire\core\Wire.php(229): Wire->runHooks('render', Array)

#6 C:\inetpub\wwwroot\pw\wire\modules\PageRender.module(194): Wire->__call('render', Array)

#7 C:\inetpub\wwwroot\pw\wire\modules\PageRender.module(194): TemplateFile->render()

#8 [internal function]: PageRender->___renderPage(Object(HookEvent))

#9 C:\inetpub\wwwroot\pw\wire\core\Wire.php(267): call_user_func_array(Array, Array)

#10 C:\inetpub\wwwroot\pw\wire\core\Wire.php(229): Wire->runHooks(

If I use seddass's method I can't paginate either.

I tried the solution with one page that holds images and with children pages that contain images and still no go.

I'm attaching the screenshot how should it look like...

post-354-132614278871_thumb.jpg

Share this post


Link to post
Share on other sites

Looking at your error message, I see where it came from. There was an error in my earlier example (sorry). At the end of it, it should be:

// output the pagination navigation
echo $a->renderPager(); 

rather than $images->renderPager(); 

  • Like 1

Share this post


Link to post
Share on other sites

It works! Thanks Ryan for your help (others included :))

Share this post


Link to post
Share on other sites

Hmm, It doesn't work as intended, Images are repeating themselves.

I tried different approach:

I have Gallery page in the root of the website, and Gallery page has children. I didn't put the limit on number of images that can appear on any of the children.

I use this code to grab all image from all the children pages.

I need to paginate them with the limit of 16 per page.

<?php
        
echo "<div class='photo-gallery'>";

$photos = $pages->get('/foto/');

foreach($photos->children as $photo) {

    foreach($photo->images as $p) {
          
          $t = $p->size(142, 92);
          echo "<a rel='colorbox' href='$p->url'><img src='{$t->url}' alt='{$t->description}' width='{$t->width}' height='{$t->height}' class='photo' /></a>";
    
    }	

}

echo "</div>";

If I use

<?php foreach($photo->images->find("limit=16") as $p) {

the limit count doesn't work right... and pagination doesn't work either.

Template has numbering turned on.

Share this post


Link to post
Share on other sites
Hmm, It doesn't work as intended, Images are repeating themselves.

I'm not sure which solution we're talking about, because there have been a few posted. Can you post the code for the solution you were using? I'm guessing it would be an easy fix, but just need the context.

<?php foreach($photo->images->find("limit=16") as $p) {

The above will only cycle through the first 16 images on any page. Then it would move on to the next page in your $photos->children loop and display the first 16 photos from the next page. But it's not going to do anything for pagination.

If you want to keep things from getting overly complex, I'd recommend either focusing on paginating the images from a single page (like the example below) or paginate multiple pages where each page has 1 image. I think we can find straightforward solutions for either of those.

<?php 

$limit = 16; 
$start = ($input->pageNum-1) * $limit; 
$images = $page->images->slice($start, $limit); 

foreach($images as $image) {
    // ...
}

Share this post


Link to post
Share on other sites

Thanks, I've manage to solve it and ended up using this combination:

<?php
        
echo "<div class='photo-gallery'>";

$photos = $pages->get('/foto/');

$limit = 16; 
$start = ($input->pageNum-1) * $limit; 
$images = $page->images->slice($start, $limit);
$total = count($photos->images);

$a = new PageArray();

foreach($images as $unused) $a->add(new Page()); 

$a->setTotal($total); 
$a->setLimit($limit); 
$a->setStart($start); 

foreach($images as $image) {
	$thumb = $image->size(142, 92);
	echo "<a rel='colorbox' href='$image->url'><img src='{$thumb->url}' alt='{$thumb->description}' width='{$thumb->width}' height='{$thumb->height}' class='photo' /></a>";
}	

echo "</div>";

echo "<div class='clear'></div>";

$start = $a->getStart(); 
$end = $start + count($a);  
$total = $a->getTotal(); 
$num = $input->pageNum; 
$lastNum =  ceil($total / $a->getLimit());

echo "<p class='numbering'>Prikazano fotografija: $start - $end od $total | stranica $num od $lastNum</p>"; 

echo $a->renderPager(array(
'nextItemLabel' => "Sljedeća",
'previousItemLabel' => "Prethodna",
)); 

Share this post


Link to post
Share on other sites

Glad you got it working. Thanks for posting the final code.

Share this post


Link to post
Share on other sites

Hello there,

i am trying such simple image "pagination" which ryan described in post #9 - pagination works but page 1 displays still all 4 images (should display just 2 of them) - but there is a second page which then displays the last two pictures.

Here is the code:

<?php
/**
* Page template
*
*/
include("./header.inc");
echo "<h1>" . $page->headline . "</h1>";
echo "<h1><?=$page->title?></h1>";
echo "<h2><?=$page->album_description?></h2>";
echo "<ul class='images'>";
// get the images you are going to display
$items_per_page = 2;
$start = ($input->pageNum - 1) * $items_per_page;
$total = count($page->images);
$images = $page->images->slice($start, $images_per_page);
// make this to give MarkupPagerNav what it needs
$a = new PageArray();
// add in some generic placeholder pages
foreach($images as $unused) $a->add(new Page());
// tell the PageArray some details it needs for pagination
// (something that PW usually does internally, for pages it loads)
$a->setTotal($total);
$a->setLimit($items_per_page);
$a->setStart($start);
foreach($images as $p) {
   $thumb = $p->size(100, 100); // specify your own width/height
   echo "<li style='width:100px; height:100px; float:left; margin:5px;'>"; // better to use a stylesheet
   echo "<a href='{$p->url}' class='lightbox' rel='gallery'>";
   echo "<img src='{$thumb->url}' alt='{$thumb->description}' /></a>";
   echo "</li>";
}
echo "</ul>";
echo "<br style='clear: both;' />";
// output the pagination navigation
echo $a->renderPager();

include("./footer.inc");

Any idea why it does not work as it should?

Kind regards,

Christian

Share this post


Link to post
Share on other sites

<?php

$items_per_page = 2;

$start = ($input->pageNum - 1) * $items_per_page;

$total = count($page->images);

$images = $page->images->slice($start, $images_per_page);

Notice the typo?

Share this post


Link to post
Share on other sites

@Soma: Thank you very very much! Works perfectly now.

Here the corrected original code from post #9, which works fine as shown below - just, as Ryan already mentioned, don't forget do activate the support of page numbers in your template settings, under the "URLs" tab...

<?php
// get the images you are going to display
$items_per_page = 4;
$start = ($input->pageNum - 1) * $items_per_page;
$total = count($page->images);
$images = $page->images->slice($start, $items_per_page);
// make this to give MarkupPagerNav what it needs
$a = new PageArray();
// add in some generic placeholder pages
foreach($images as $unused) $a->add(new Page());
// tell the PageArray some details it needs for pagination
// (something that PW usually does internally, for pages it loads)
$a->setTotal($total);
$a->setLimit($items_per_page);
$a->setStart($start);
// output your images
foreach($images as $p) {
$img = $p->img;
echo "<img src='{$img->url}' alt='{$img->description}' />";
}
// output the pagination navigation
echo $a->renderPager();

Kind regards,

Christian

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...