Jump to content

Images pagination


nikola

Recommended Posts

  • 1 year later...
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);

...
...
...

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

Hi,

I dont this get working for me!

My example based on Simple Gallery Tutorial from Joss, as there is in TUT_gallery_functions.inc:

function albumGrid() {
	$albumimages = wire("page")->gallery;
	$albumtitel = wire("page")->title;
	$text = wire('page')->body;
	//
	$anzbilder = count(wire("page")->gallery);
	$thumbsize = wire("page")->gallery_thumbnail_size;
	$out = " ";
    
	foreach ($albumimages as $albumimage) {
 
        $out .= "<a href='{$albumimage->url}' title='{$albumimage->description}' class='colorbox' rel='group'>";
        $out .= "<img src='{$albumimage->size($thumbsize, $thumbsize)->url}'>";
        $out .= "</a>";
 
	}
	echo "<div class='albumgrid'>{$out}</div>";
}

Note: the field-name of the images in the page is gallery.

The gallery contains 25 images and it should paginate after each 8 images.

So, my changes of function albumGrid() to get pagination are:

function albumGrid() {
$photos = wire("page")->gallery;

$limit = 8; 
$start = ($input->pageNum-1) * $limit; 
$images = wire("page")->gallery->slice($start, $limit);
$total = count(wire("page")->gallery);
$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 $a->renderPager();

}

When I make the source like nikola got it worked, I only get an output of the last 8 images. The pagination is correct, but each page of pagination contains the same last 8 images of 25.

 
Can you help please, what I am doing wrong?
Link to comment
Share on other sites

Nothing jumps out in the code to me. Double check that you have "allow page numbers" enabled in your template settings for whatever template your $page is using. 

Link to comment
Share on other sites

Nothing jumps out in the code to me. Double check that you have "allow page numbers" enabled in your template settings for whatever template your $page is using. 

I checked again, I allowed page numbers for the overview of all galleries and this pagination works perfekt. But I allowed also the page numbers for the template of each single gallery and this I dont get work.

I understand the code not at all - when I call the function albumGrid() it makes an array of slices over all containing images, i.e. above must be 3 slices each 8 images plus 1 with 1 image. it´s correct??

And I get the pagination correct with 4 pages! But in the pages are always the same 8 images!

So I think its not a question of pagination - that works - but how can I put the exact images in the array-slices?

Maybe it´s missing a loop?

When

$limit = 8;
$start = ($input->pageNum-1) * $limit;
$images = wire("page")->gallery->slice($start, $limit);

and when I include in template 'TUT_gallery.php' albumGrid():

<div>
  <?php 
                             
    // Render the Album List
                             
        albumGrid();
                             
    //
  ?>
</div>    

I think above is calling only once, so $start is always the same but slice should be

1. page (0,8)

2. page (8,8)

3. page (16,8)

4. page (24,8)

This maybe the reason of having the same images in the slices!?

Link to comment
Share on other sites

Where does this bit of a code appear? In a function, or out in the main body of the template file?

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

I ask because I see $input and wire('page'). If this is within a function, then you need to be using wire('input') rather than $input. It's feasible that if you've got error reporting turned off you might not notice if $input is out of scope and undefined. 

Another possible consideration might be if you are rendering a page within another page. There doesn't seem to be indication that's taking place here, but something to consider just in case. 

Link to comment
Share on other sites

Where does this bit of a code appear? In a function, or out in the main body of the template file?

Based on Simple Gallery Tutorial from Joss, it´s a function in TUT_gallery_functions.inc ( I think like blog.inc ) and the template TUT_gallery.php call this with 'albumGrid();'

I ask because I see $input and wire('page'). If this is within a function, then you need to be using wire('input') rather than $input.

 

Ok, this make sense - because I´d changed Nikolas code all the '$page->'´s to 'wire("page")->' to get it run for the index-page.

Thanks, I´ll test this tomorrow, it´s to late now in Austria and post again.

Link to comment
Share on other sites

I ask because I see $input and wire('page'). If this is within a function, then you need to be using wire('input') rather than $input. 

That´s great ryan - this work´s now

$start = (wire('input')->pageNum-1) * $limit;

 thank you!!!

Link to comment
Share on other sites

Hi again,

for one more thing to this pagination I need some help please.

Now the pagination is correct and displays on each page 15 thumbs and a click on thumb shows the greater picture (colorbox). Viewing throug the greater pictures  colorbox shows only the 15 pictures per page and after 15th begins again with 1st of same page!

Such a scroll through the greater pictures is not the very common.

How can I do that it shows after the 15th the first picture of next page?

Here the full code:

function albumGrid() {
    $photos = wire("page")->gallery;
    $albumtitel = wire("page")->title;
    $thumbsize = wire("page")->gallery_thumbnail_size;
    $limit = 15; 
    $start = (wire('input')->pageNum-1) * $limit; 
    $images = wire("page")->gallery->slice($start, $limit);
    $total = count(wire("page")->gallery);
    $a = new PageArray();

    foreach($photos as $unused) {
        $a->add(new Page()); 
    }
    
    $a->setTotal($total); 
    $a->setLimit($limit); 
    $a->setStart($start);
	
    echo "<div style='margin-left:25px;'><h3>$albumtitel ($total Bilder)</h3></div>";
    	
	foreach($images as $image) {
        $out .= "<a href='{$image->url}' title='{$image->description}' class='colorbox' rel='group'>";
        $out .= "<img src='{$image->size($thumbsize, $thumbsize)->url}'>";
        $out .= "</a>";
	}	

	// Pagination
 
	$out .="<div class='clearfix'></div><div class='span8'>";
	$out .= $a->renderPager(array(
	    'nextItemLabel' => "Nächste",
	    'previousItemLabel' => "Vorige",
        'listMarkup' => "<ul class='MarkupPagerNav'>{out}</ul>",
        'itemMarkup' => "<li class='{class}'>{out}</li>",
        'linkMarkup' => "<a class='zeigalbum' href='{url}'>{out}</a>"      
    ));
	$out .="</div>";
 
	echo "<div class='albumgrid' style='clear:both;padding-bottom:50px;'>{$out}</div>";
}

Link to comment
Share on other sites

iewing throug the greater pictures  colorbox shows only the 15 pictures per page and after 15th begins again with 1st of same page!

Such a scroll through the greater pictures is not the very common.

How can I do that it shows after the 15th the first picture of next page?

Sorry, I'm not fully understanding the question. Might need a screenshot to understand what you mean?

Link to comment
Share on other sites

Sorry, I'm not fully understanding the question. Might need a screenshot to understand what you mean?

img_gall.jpg

Whithin the colorbox it always shows only the 15th images per Page and next is again the first of page one (red arrow) - but when 15th I want that the next picture shown is the first picture of the 2nd Page (green arrow).

You can see it better on my Site: http://pwire.wels-neustadt.at/albums/mozartschule-strassenfest/

Link to comment
Share on other sites

Whithin the colorbox it always shows only the 15th images per Page and next is again the first of page one (red arrow) - but when 15th I want that the next picture shown is the first picture of the 2nd Page (green arrow).

You can see it better on my Site: http://pwire.wels-neustadt.at/albums/mozartschule-strassenfest/

I think the question is more for the gallery script you are using than for PW. It all depends how the gallery/lightbox of yours want the data. I think most of those scripts support just that kind of usage how it works now (supporting already visible stuff), but of course there might be other means also (some kind of json or xml feed that it reads), or "hidden html"...

  • Like 1
Link to comment
Share on other sites

I think most of those scripts support just that kind of usage how it works now (supporting already visible stuff), 

Hi, apeisa

you are right - but I think somebody have a solution to a gallery with PW and it´s normal use to slide through pictures with lightbox all over the images and and not only per page. Maybe I had taken the wrong approach with the code above.

I am on the first steps with PW and I am sure that it must be possible to combine the features of PW´s pagination with those of ligthbox. Or have I missed a PW-gallery-script I do not know?

The albumGrid function above knows all images and all slices of images, and PW can paginate, but I have no more idea of coding this together so that it works on a practical manner I mean.

Link to comment
Share on other sites

It's not too simple task. I would probably build it independent from any ready made gallery/lightbox script, since making them work in that scenario nicely might be a bit too challenging. Maybe if they have some hook that allows you to do something custom on last click (pull new images with ajax in this case / or redirect to next page and open first image in this case) might do it.

Also from UI side, I don't think many users except it to change pagination in that scenario. Or maybe using different kind of gallery there: http://galleria.io/ ?

  • Like 1
Link to comment
Share on other sites

I think Antti is right here that the lightbox plugin would need some feature enabling it to load it's own images (ajax or otherwise) to go beyond what's actually present on the page. What you have here are two different systems of pagination.

I am wondering if you could trick the lightbox into it–you could render those first 15 images as you are now, but then render links for the remaining (perhaps hidden to the user) but have your lightbox plugin somehow recognize them as part of the gallery. For example:

<a class='gallery' href='photo1.jpg'><img src='photo1thumb.jpg'></a>
<a class='gallery' href='photo2.jpg'><img src='photo2thumb.jpg'></a>
...
<div style='display: none;'>
  <a class='gallery' href='photo16.jpg'><img src='1pixel.gif'></a>
  <a class='gallery' href='photo17.jpg'><img src='1pixel.gif'></a>
  ...
</div>
  • Like 1
Link to comment
Share on other sites

 Or maybe using different kind of gallery there: http://galleria.io/ ?

I looked at this galleria, but it´s more a slider than a gallery, is´nt it? And it´s not quite what I would have in this case.

but then render links for the remaining (perhaps hidden to the user) but have your lightbox plugin somehow recognize them as part of the gallery. For example:

Ok, this is very tricky coding, let´s see if I can do that.

Thanks!! And any other idea or help is welcome!

Link to comment
Share on other sites

  • 3 years later...

Hi. I also needed a solution for Images Pagination and came up with this solution. It only works on PW 3 with the new PaginatedArray class.

My Situation: I have a image field with about 150 images. I want to output these Images with a PagerNav. The same i use on $pages->find().

This is the function wich I wrote to get this working for PageImages.

/**
     * Renders a pagination based on files using the PaginatedArray Class. Overrides the input parameter $files with the sliced result
     * and returns the rendered pagination.
     * @param $files ... the full Pageimages WireArray
     * @param int $perPage ... items per Page
     * @param $pagerOptions ... standard Pager Options as used in MarkupPagerNav.module
     * @return string ... rendered pagination
     */
    public function renderFilePagination(&$files,$perPage=10,$pagerOptions) {
        $total = count($files);
        if($total <= $perPage)
            return '';
        $pagerArray = new PaginatedArray();
        $pagerArray->setLimit($perPage);
        $pagerArray->setTotal($total);
        $pagerArray->setStart(($this->input->pageNum - 1) * $perPage);
        $pagerArray->import($files->slice($pagerArray->getStart(), $pagerArray->getLimit()));
        $files = $pagerArray; // overwrite $files
        $ret = '<div class="paginationInfo uk-text-center uk-text-small uk-margin-top">'.$pagerArray->getPaginationString().'</div>';
        $ret .= $this->modules->MarkupPagerNav->render($pagerArray,$pagerOptions);
        return $ret;
    }

This function has to be available in your template files. Perhaps you need to remove the public. I am using it in in a custom module.

Now in your template file you have your images field for ex.: $page->images (multiple Images).

You can call the function like this:

$pagination = $modules->KaTemplateHelper->renderFilePagination($page->images,$perPage=40,array(
    'listMarkup' => '<ul class="uk-pagination">{out}</ul>',
    'itemMarkup' => "\n\t<li class=\"{class}\">{out}</li>",
    'linkMarkup' => '<a href="{url}"><span>{out}</span></a>',
    'currentLinkMarkup' => '<span>{out}</span>',
    'currentItemClass' => 'uk-active',
    'nextItemLabel' => '»',
    'previousItemLabel' => '«'
));

The third array parameter is completely optional. I only use it for changing the standard page nav markup.
If you use the standard markup then call:

$pagination = $modules->KaTemplateHelper->renderFilePagination($page->images,40);

-----------------------

After the call:

$page->images only contains the subset wich will be display on this page.
$pagination contains the rendered HTML Markup for $pagination.

Perhaps this helps someone. I know this is not fully flexible implemented, but this is only a snipped for me that I change as i need it.

 

 

  • Like 4
Link to comment
Share on other sites

  • 2 months later...

Hi!

I have a problem with pagination.
My site structure is like this:
– Work
    – Project 1
    – Project 2
    – Project 3

Every project-page has a thumbnail I want to display.
I have a slider that creates pagination automatically with a structure like <div id="slide1"></div>, <div id="slide2"></div>, etc.
I want to have 4 thumbnails per slide.

My problem is, that the order and number of images is messed up.
Here is my code:

function albumList(){
 
    // Get the list of albums 
    $albums = wire("pages")->find("parent=/work/, template=project, sort=sort");
  $albums_total = wire('pages')->get("/work/")->numChildren;
  $images_per_page = 4;
  $slides = round($albums_total / $images_per_page);
 
 //Create Slides
    for($i = 0; $i < $slides; $i++) {
  
  $start = ($i) * $images_per_page;
  $slide_id = $i + 1;
  $images_limited = $albums->slice($start, $images_per_page);
  
  echo ("<div class='slide' id='slide{$slide_id}'><div class='grid'>");
 
    //Display Images
    foreach($images_limited as $album) {

        // if there's no thumbnail no need to do anything
        if(!$album->thumbnail) continue;

        // save srcset tag to a variable
        $bgset = $album->thumbnail->bgset('half', 'lazyload item size1of2', array('quality' => 70));

        $out .="<a href='{$album->url}' $bgset><img src='site/templates/img/plus-icon.svg' class='info-button'>";
        $out .="<div class='item-info'><div class='info-container-center'><h3>{$album->thumbnail->tags}</h3><h2>Für {$album->title}</h2><p>{$album->thumbnail->description}</p></div></div>";
        $out .="</a>";
        echo $out;
    }
    
    echo ("</div></div>");
    
    }
    
}

Any help would be highly appreciated!
Thx!

Link to comment
Share on other sites

@jploch, looks like good case to use my proposed $wirearray->chunk() for. :)

See this post for the hook you would need to add in order to use chunk()...

I'm not a fan of echoing markup within functions (nothing wrong with it, just a personal preference) so I would do this:

In a new include/partial named album_list.php...

<?php
$images_per_slide = 4;
// exclude pages with no thumbnail in the selector
$albums = $pages->find("parent=/work/, template=project, thumbnail!='', sort=sort");
// chunk albums into groups
$albums_chunked = $albums->chunk($images_per_slide);
// ditch the last group if it has less than the number of images per slide (assuming that's what you want)
if( count(end($albums_chunked)) < $images_per_slide ) array_pop($albums_chunked);
?>

<?php foreach($albums_chunked as $key => $slide): ?>
    <div class="slide" id="slide<?= $key + 1 ?>">
        <div class="grid">
            <?php foreach($slide as $album): ?>
                <a href="<?= $album->url ?>" <?= $album->thumbnail->bgset('half', 'lazyload item size1of2', array('quality' => 70)) ?>>
                    <img src="/site/templates/img/plus-icon.svg" class="info-button">
                    <div class="item-info">
                        <div class="info-container-center">
                            <h3><?= $album->thumbnail->tags ?></h3>
                            <h2>Für <?= $album->title ?></h2>
                            <p><?= $album->thumbnail->description ?></p>
                        </div>
                    </div>
                </a>
            <?php endforeach; ?>
        </div>
    </div>
<?php endforeach; ?>

Then wherever you want to output the slides...

include $_SERVER['DOCUMENT_ROOT'] . '/site/templates/partials/album_list.php';

Or if you prefer...

echo $files->render('partials/album_list');

 

  • Like 2
Link to comment
Share on other sites

@Robin S

Thanks for your quick reply!
Your code works better. The number of images is now correct, but the order is still not right.
I want the images to be displayed in the order they are sorted in PW (so the user can sort them with dragging in the page tree).

I also noticed that I can't login to the processwire backend, after I created the init.php file in my site directory.
When I delete it, it works. Is there anything else I have to do? (Running PW 3.0.42.)

Any suggestions?
With my own code I felt more confident because I can understand better how it works, even if it may be bad practise.

Link to comment
Share on other sites

1 hour ago, jploch said:

The number of images is now correct, but the order is still not right.

The only thing affecting the order of the images is the sort within the selector. You can check the order right after you get the albums:

$albums = $pages->find("parent=/work/, template=project, thumbnail!='', sort=sort");
echo $albums->each("<p>{title}</p>");

This should list the pages in the same order as they appear in the page tree. Unless you have specified automatic sort settings on the parent page or template, but I doubt you would have done that as it would prevent manually sorting the pages. If the album pages are listed in the right order but the images within each slide are not in the position you want then that is a CSS issue.

 

1 hour ago, jploch said:

I also noticed that I can't login to the processwire backend, after I created the init.php file in my site directory.

Not sure what is going on there. There's nothing in the chunk() hook that should affect logging in.

But you don't really need to add chunk() as a new WireArray method if it's causing you difficulties and you only need to use it for this one application - you can just do the equivalent within your template/include/function instead:

$images_per_slide = 4;
$albums = $pages->find("parent=/work/, template=project, thumbnail!='', sort=sort");
$albums_chunked = array();
for($n = 0; $n + $images_per_slide <= $albums->count(); $n += $images_per_slide) {
    $albums_chunked[] = $albums->slice($n, $images_per_slide);
}
// now iterate...

 

  • Like 1
Link to comment
Share on other sites

@Robin S

Thanks for your Help!
The order was messed up, even when I echoed out the title.

I found out that the order is correct when I change this line

$albums = $pages->find("parent=/work/, template=project, thumbnail!='', sort=sort");

to:

$albums = $pages->find("parent=/work/, template=project, sort=sort");


Now I only have one problem.
I want to display all thumbnails, even when there are just 6.
So it should be one slide with 4 and one with the remaining 2.

Link to comment
Share on other sites

8 hours ago, jploch said:

The order was messed up, even when I echoed out the title.

I'm puzzled by the idea that the thumbnail part of the selector could change your sort order - by using thumbnail!='' we are saying that we don't want any pages that don't have a thumbnail (because in that case you can't show their thumbnail in the slide). So that will exclude some pages if there are any without a thumbnail, but it shouldn't change the sort order of the pages that are matched.

 

8 hours ago, jploch said:

Now I only have one problem.
I want to display all thumbnails, even when there are just 6.
So it should be one slide with 4 and one with the remaining 2.

If you are using my example that uses chunk() then remove this:

// ditch the last group if it has less than the number of images per slide (assuming that's what you want)
if( count(end($albums_chunked)) < $images_per_slide ) array_pop($albums_chunked);

Or if you are using my second example then change the for() line to:

for($n = 0; $n < $albums->count(); $n += $images_per_slide) {

 

  • Like 1
Link to comment
Share on other sites

  • 2 years later...
On 8/29/2011 at 3:03 PM, ryan said:

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.

Just stumbled across this older post and need to make an addition to @ryans post:

You need to add: 

...
// make this to give MarkupPagerNav what it needs
$a = new PageArray();
$a->setDuplicateChecking(false);  // <-- add this line!
...

just below the PageArray creation - otherwise this won't work, as you will always having only 1 item in the final PageArray.

  • Like 2
Link to comment
Share on other sites

  • 8 months later...

I too am grappling with this issue for an image gallery page that I'm trying to paginate.

My template file contains code for groups of things in general (e.g. blogroll), laid out in a similar way to the desired gallery page. The blogroll is working just fine so I don't want to make a whole different file just for the image gallery, I just want to use different logic within the same template. I suppose I should clarify: my image-gallery template file is very short: just a php include of the blogroll template. Inside the blogroll template I have different logic for image gallery versus blogroll where applicable.

I do have the page template set to allow pagination in the admin side.

I like the code solutions presented previously in the thread that involve piggybacking onto the MarkupPagerNav module, since I'm using pagination for my blogroll anyway.

? My question is, I'm wondering if there is (or could one day be) a function in the ProcessWire API that as a one line command, converts images on a page to a (temporary) page array, each element of which contains one image? ?The idea being that the resultant page array could be used directly for pagination purposes just like any other page array, which is handy for image gallery situations such as this. It seems like it's a common issue people are facing.

For now and for my site's situation, even for the solutions that piggyback off MarkupPagerNav, it seems like a bunch of extra code to add to a template that is otherwise working fine (I mean for blogroll purposes it's working perfectly). I really like the idea of passing a page array directly to MarkupPagerNav (with limit in the selector, I mean) without keeping track of total, start, and slice. So for now I'll probably instead from the admin office make a bunch of child pages from that page, each containing one image, and get the desired page array from that so I can handle the pagination with the same type of code as I've used for my blogroll.

Link to comment
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...