Jump to content

Another Simple Photo Gallery Tutorial


thetuningspoon

Recommended Posts

I recently completed a website that had a very large gallery requiring multiple albums (categories) and 100+ images per album with pagination. The solution I developed accomplishes this with just 2 templates (gallery-index and gallery-album) and a single multi-image field for each album, allowing for quick, mass upload of images*. One of the great things about ProcessWire is that you can custom build something like an image gallery with just the tools that the template system and API provide out of the box, without going in search of modules.
 
Once we have the basic templates set up, we will use the excellent FancyBox jQuery script/plugin to add some slick Javascript "lightbox" functionality on top of it. The gallery will still work without FancyBox or with Javascript disabled; it will simply fall back to opening each image in a blank page.
 
So, without further ado...
 
 
1. Create a file named gallery-index.php in your site/templates/ folder with the following code. This will be the main page of your gallery. The code simply loops through all of the photo albums that are children of your main gallery page and uses the first image in the album as the cover photo:
 

<? include("./head.inc") ?>

<?
// Configure thumbnail width/height
$thumbWidth = 250;
$thumbHeight = 250;

// Create an array of the child pages that use the gallery-album template
$albums = $page->children('template=gallery-album');
?>

<h2><?= $page->title ?></h2>

<div class="gallery">    
    <ul class="gallery-row row">
      <?
      if(count($albums) > 0) {
        foreach($albums as $album) 
        {    
            // Grab the first image from the album and create a thumbnail of it
            $thumb = $album->images->first()->size($thumbWidth, $thumbHeight); 
      ?>
            <li class="col span4">
                <div class="gallery-album photoShadow">
                    <a href="<?= $album->url ?>" class="gallery-albumThumb" title="<?= $album->title ?>">
                        <img src="<?= $thumb->url ?>" alt="<?= $thumb->description ?>" />
                        <h4 class="gallery-albumTitle"><?= $album->title ?></h4>
                    </a>
                </div><!-- /gallery-album -->
            </li><!-- /col -->
      <?
        }
      }
      ?>
    </ul><!-- /gallery-row -->
</div><!-- /gallery -->



<? include("./foot.inc") ?>
 

 
 
2. Add the gallery-index template in the ProcessWire admin under Setup->Templates. This template does not require any fields, although you may want to add a body field for outputting additional content to the page.
 
3. Create a file named gallery-album.php in your site/templates/ folder. This template will be used to both hold and display the images in your albums. Here we will be loading the fancybox plugin as well, so make sure you've downloaded it here: http://fancyapps.com/fancybox/ and uploaded the /fancybox/ folder to your site/templates/scripts/ folder. 
 
We are appending the fancybox files to the $config->scripts and $config->styles array before outputting them in our head.inc file so that we're only loading that code on the album pages. So make sure you are outputting those arrays in the <head></head> section of your head.inc file along with your other scripts & styles, like so: 
 

<? foreach($config->scripts as $file) { ?><script type="text/javascript" src="<?= $file ?>"></script> 
    <? } ?>

<? foreach($config->styles as $file) { ?><link rel="stylesheet" type="text/css" href="<?= $file ?>" /> 
    <? } ?>
 
 

Please note that you will also have to include jQuery in your head.inc file before your other scripts, if you're not already including it.
 

So here is our gallery-album.php. Notice also that we are calling the FancyBox script and customizing some of its options at the bottom of the file:

<? 
$config->styles->append($config->urls->templates . "scripts/fancybox/jquery.fancybox.css"); 
$config->styles->append($config->urls->templates . "scripts/fancybox/helpers/jquery.fancybox-thumbs.css?v=1.0.7");
$config->scripts->append($config->urls->templates . "scripts/fancybox/jquery.fancybox.pack.js"); 
$config->scripts->append($config->urls->templates . "scripts/fancybox/helpers/jquery.fancybox-thumbs.js?v=1.0.7");



// Configure thumbnail width/height & number of photos to display per page
$thumbWidth = 150;
$thumbHeight = 150;
$imagesPerPage = 32;



// Make ProcessWire pagination work on the images field (see  for full explanation of this)
$start = ($input->pageNum - 1) * $imagesPerPage;
$total = count($page->images);
$images = $page->images->slice($start, $imagesPerPage);
// Create a new pageArray 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
$a->setTotal($total);
$a->setLimit($imagesPerPage);
$a->setStart($start);

include("./head.inc")
?>

<?= $a->renderPager() ?>

<div class="upOneLevel"><a href="<?= $page->parent->url ?>">← Albums</a></div>

<h2><?= $page->title ?></h2>

<div class="album">    
    <ul class="album-row row">
      <?
      if(count($images) > 0) {
        foreach($images as $image) 
        {    
            $thumb = $image->size($thumbWidth, $thumbHeight); 
      ?>
            <li class="album-photo darkenOnHover col span3">
                <a href="<?= $image->url ?>" rel="fancybox-gallery" class="fancybox" title="<?= $image->description ?>">
                    <img src="<?= $thumb->url ?>" alt="<?= $thumb->description ?>" />
                    <!-- Uncomment this line if you want descriptions under images <p class="album-photoDescription"><?= $image->description ?></p>--> 
                </a>
            </li>
      <?
        }
      }
      ?>
    </ul><!-- /album-row -->
</div><!-- /album -->

<div class="group"><?= $a->renderPager() ?></div>

<script type="text/javascript">
    $(document).ready(function() {
        $(".fancybox").fancybox({
            prevEffect    : 'elastic',
            nextEffect    : 'elastic',
            loop : false,
            mouseWheel: true,
            helpers    : {
                title    : {
                    type: 'outside'
                },
                thumbs    : {
                    width    : 100,
                    height    : 60
                }
            }
        });
    });
</script>

<? include("./foot.inc") ?>
 
 

4. As we did before, add the gallery-album template in the ProcessWire admin. Assign the images field to it, and go into the URLs tab and make sure Page Numbers are allowed.
 
5. Create a page in the ProcessWire admin for the gallery index using the gallery-index template. You'll probably want to give it a title like "Gallery".
 
6. Underneath your Gallery page, create child pages that use the gallery-album template, one page for each album you want to create. Name them however you'd like.
 
7. Go into each album page you created and populate the Images field with your images. Just drag-and-drop. It's as simple as that! If you want to add a description for each image, you can also add it here. If you have more than 32 images (or whatever value you set the $imagesPerPage variable to), the pagination will kick in and split the album into multiple pages. 
 
8. Finally, add in the CSS. The CSS is really up to you, but I'm including a good starting point below. This includes a handy responsive grid system I built for my sites, as well as a .photoShadow class I developed which gives your album covers a cool 3D Polaroid look using pure CSS.

/********* Helper Classes **********/

.row:after,
.group:after { 
    content: ""; 
    display: block; 
    height: 0; 
    clear: both;
  visibility: hidden;
}

.row { 
    ; /* Remove left gutter */
    margin-top: 0;
    margin-right: 0;
    margin-bottom: 0;
    padding: 0;
    zoom: 1; /* IE7 */
    position: relative;
}

.col {
    display: block;
    float:left;
    margin-left: 2%; /* Gutter size */
    margin-top: 0;
    margin-right: 0;
    margin-bottom: 0;
    padding: 0;
    zoom: 1;
    width: 95.99999999996%;
}

.span1 {width: 6.33333333333%;}
.span2 {width: 14.66666666666%;}
.span3 {width: 22.99999999999%;}
.span4 {width: 31.33333333332%;}
.span5 {width: 39.66666666665%;}
.span6 {width: 47.99999999998%;}
.span7 {width: 56.33333333331%;}
.span8 {width: 64.66666666664%;}
.span9 {width: 72.99999999997%;}
.span10 {width: 81.3333333333%;}
.span11 {width: 89.66666666663%;}
.span12 {width: 97.99999999996%;}

.photoShadow {
    position: relative;
    border: 5px solid #fff;
    background: #fff;
    
    -moz-box-shadow: 0px 0px 2px #ccc;
    -o-box-shadow: 0px 0px 2px #ccc;
    -webkit-box-shadow: 0px 0px 2px #ccc;
    -ms-box-shadow: 0px 0px 2px #ccc;
    box-shadow: 0px 0px 2px #ccc;
}

    .photoShadow:before {
        z-index: -1;
        content: "";
        display: block;
        position: absolute;
        width: 104%;
        height: 16px;
        bottom: -5%;
        left: -2%;
        overflow: hidden;
        border-radius: 50% 50% 0 0;
        box-shadow: inset 0px 8px 5px #999;
    }

.darkenOnHover  {
    opacity: .8;
    
    -webkit-transition: opacity .2s;
    -moz-transition: opacity .2s;
    -ms-transition: opacity .2s;
    -o-transition: opacity .2s;
    transition: opacity .2s;
}
    .darkenOnHover:hover  {
        opacity: 1;
        
        -webkit-transition: opacity .1s;
        -moz-transition: opacity .1s;
        -ms-transition: opacity .1s;
        -o-transition: opacity .1s;
        transition: opacity .1s;
    }
 
 
/********** Blocks **********/
 

.gallery {
}
    .gallery-album a:hover {
        text-decoration: none;
    }
    .gallery-albumTitle {
        font-size: 1.1em;
        text-align: center;
        margin: .2em ;
    }
    .gallery-album {
        -webkit-transition: all .2s;
        -moz-transition: all .2s;
        -ms-transition: all .2s;
        -o-transition: all .2s;
        transition: all .2s;
    }
    .gallery-album:hover {
        -webkit-transition: all .2s;
        -moz-transition: all .2s;
        -ms-transition: all .2s;
        -o-transition: all .2s;
        transition: all .2s;
    
        -webkit-box-shadow: 0 0 3px #555;
        -moz-box-shadow: 0 0 3px #555;
        -ms-box-shadow: 0 0 3px #555;
        -o-box-shadow: 0 0 3px #555;
        box-shadow: 0 0 3px #555;
    }
 
.album-photo img {
    margin-bottom: 6px;
    border: 1px solid #ddd;
}
 
.upOneLevel {
    font-size: 1.1em;
    margin-bottom: .4em;
}
    .upOneLevel .icon-circle-arrow-left {
        font-size: 1.5em;
        margin-right: .4em;
    }
    .upOneLevel a:hover {
        text-decoration: none;
    }
 
.MarkupPagerNav {
    margin: 1em 0; 
    font-family: Arial, sans-serif;
    float: right;
}
    .MarkupPagerNav li {
        float: left;
        list-style: none;
        margin: 0;
    }
    
    .MarkupPagerNav li a,
    .MarkupPagerNav li.MarkupPagerNavSeparator {
        display: block;
        float: left;
        padding: 2px 9px;                
        color: #fff;
        background: #2f4248;
        margin-left: 3px;
        font-size: 10px;
        font-weight: bold;
        text-transform: uppercase;
    }
                    
    .MarkupPagerNav li.MarkupPagerNavOn a,
    .MarkupPagerNav li a:hover {
        color: #fff;
        background: #db1174;
        text-decoration: none;
    }
    
    .MarkupPagerNav li.MarkupPagerNavSeparator {
        display: inline;
        color: #777;
        background: #d2e4ea;
        padding-left: 3px;
        padding-right: 3px;
    }

 

 
 
I think that's it! Just make sure you're including the CSS file in your head.inc inside the <head></head> tags and you should be all set.
 
If you come across any issues trying to implement the above (or find any of it confusing) please let me know below. Everyone is coming from different backgrounds and different experience levels. And if you find this tutorial useful, please feel free to let me know as well :)
 
 
* I should mention that although it is possible to create galleries in Processwire where each image is represented by its own page (and, as Ryan has mentioned, is often preferable since it is ultimately more scalable), sometimes the ease of using a single image field (which can upload and decompress zip files of images in mass) simply outweighs any drawbacks. If I had to create this gallery with the 1-image-per-page method, it would have taken hours to upload all of the images one-by-one without some sort of additional programming to automate the process.

  • Like 14
Link to comment
Share on other sites

Hi,

Thanks for this tutorial! Thanks for taking the time to write it. I haven't finished reading it yet, but it looks very comprehensive, thanks :). The question about image galleries has been coming up more often recently...

Edit:

Quick comment as I read...the term "single image field" might confuse some since you are not referring to an image field that only accepts one image (yet you state you uploaded multiple images), but you are stating you used one image field (that accepts multiple images), no? Maybe good to clarify that ;)

Finished reading: you give very clear, straightforward instructions. Many thanks!

Edited by kongondo
  • Like 2
Link to comment
Share on other sites

First question: I am not seeing an implementation of URL segments. Please explain to me (am new to this :)) why you need URL segments for this? Thanks.

You're right, that step should be unnecessary. Enabling page numbers should be enough.

And yes, the forum editor behaves very erratically sometimes!

Glad you found the tutorial to be user-friendly. Thanks for the feedback!

Link to comment
Share on other sites

Thanks for writing a new tuto.

If you want to have image pages without creating every page manually one by one, you can also use ImagesManager which has upload tool to directly create the pages. So the argument doesnt count ;-)

  • Like 1
Link to comment
Share on other sites

Hi everfreecreative,

you have done a very good and useful write up here. Thank you very much.

I want to drop two notes / suggestions / additions, - maybe.
 

everfreecreative, on 03 Jul 2013 - 23:53, said:
[...]
* I should mention that although it is possible to create galleries in Processwire where each image is represented by its own page (and, as Ryan has mentioned, is often preferable since it is ultimately more scalable), sometimes the ease of using a single image field (which can upload and decompress zip files of images in mass) simply outweighs any drawbacks. If I had to create this gallery with the 1-image-per-page method, it would have taken hours to upload all of the images one-by-one without some sort of additional programming to automate the process.

 
I also don't want to upload single images to single pages :) - but if you once have the need for a more scalable Gallery, you may use Somas ImagesManager to manage the creation of your gallery categories ( = albums) and to do the mass-upload by e.g. selecting up to 50 images at once and drag-drop them onto the upload field. (I don't know if IM supports upload via Zip's)
 

 

everfreecreative, on 03 Jul 2013 - 23:53, said:
[...]
The gallery will still work without FancyBox or with Javascript disabled; it will simply fall back to opening each image in a blank browser window.

 
Very good to support noscript, - but personally I don't like the opening in additional browser windows. You also can include a "single image view" to present the single images. With this, a visitor stays in a single window when browsing your galleries and doesn't get cluttered with mass _blank-windows. - But that's only _my_ preference. :)
 
Many Greets.

EDIT: hmm, - yeah, - I have had to do a phonecall during writing the post, - so now Soma has already pointed you to it :)

Edited by horst
Link to comment
Share on other sites

Thanks for writing a new tuto.

If you want to have image pages without creating every page manually one by one, you can also use ImagesManager which has upload tool to directly create the pages. So the argument doesnt count ;-)

@Soma,

Maybe it's time to put IM in the modules directory? ;)

Link to comment
Share on other sites

Hi everfreecreative,

you have done a very good and useful write up here. Thank you very much.

I want to drop two notes / suggestions / additions, - maybe.

I also don't want to upload single images to single pages :) - but if you once have the need for a more scalable Gallery, you may use Somas ImagesManager to manage the creation of your gallery categories ( = albums) and to do the mass-upload by e.g. selecting up to 50 images at once and drag-drop them onto the upload field. (I don't know if IM supports upload via Zip's)

Very good to support noscript, - but personally I don't like the opening in additional browser windows. You also can include a "single image view" to present the single images. With this, a visitor stays in a single window when browsing your galleries and doesn't get cluttered with mass _blank-windows. - But that's only _my_ preference. :)

Many Greets.

EDIT: hmm, - yeah, - I have had to do a phonecall during writing the post, - so now Soma has already pointed you to it :)

Oh yes, the images don't open in additional browser windows. They open in the current window in a blank page. But I was having a hard time coming up with a way to word that--Fixed.

Thanks to all who suggested ImagesManager. I didn't realize that was one of its features, so I'll have to check it out. But it is still an additional module, so I think my point is still at least partially valid :)

Link to comment
Share on other sites

I think the point "without additional" coding or a module is a bit strange seeing all the code you needed to make this gallery... :P In that time you can code an simple upload module twice ;)

Link to comment
Share on other sites

Ohh I just got an idea for a module. What if you have a gallery type page you upload the images as usual to an images field. Then when saving the page there would be children created for each image and the ones removed from the gallery page. This would be very simple few lines of code.

Sorry to hijack your thread. :)

Nothing against the method to have one images field you store a gallery. If theres no metadata needed with no multilang and so on it is a pretty good and simple way to a simple gallery. I use it myself too.

  • Like 7
Link to comment
Share on other sites

One issue I foresee with the "one-image-per-page" approach is editing. If I have hundreds of images and I wanted to delete some and I could only tell them apart by actually looking at the images, it could take quite some trawling to find and delete them in the admin....

Btw, @everfreecreative, your "one-page-per-album" could play nice with a recent tweak that Soma created for a forum member that allows multiple images on a page to be displayed in a multiple grid rather than in a single column/vertical grid. I can't find the post at the moment.

Another btw (sorry). There was a question recently about finding and displaying a limited number of images from various albums and displaying those in a gallery page. I'm not sure whether that was answered. I'm just thinking out loud here whether your approach could also solve that issue. Anyway, I digress... :)

Link to comment
Share on other sites

What I meant is this: You know when you view a page with images, they are normally displayed vertically on the page and if there's multiple images, it means lots of vertical scrolling. The solution I am talking about would arrange the images on a 3x3 grid on the page..Is that what you mean as well?

Edit:

Here's the post I refer to http://processwire.com/talk/topic/3919-individual-image-field-widths-float-display-inline/

Edited by kongondo
Link to comment
Share on other sites

  • 8 months later...
  • 3 weeks later...
  • 2 weeks later...

Ohh I just got an idea for a module. What if you have a gallery type page you upload the images as usual to an images field. Then when saving the page there would be children created for each image and the ones removed from the gallery page. This would be very simple few lines of code.

Sorry to hijack your thread. :)

Nothing against the method to have one images field you store a gallery. If theres no metadata needed with no multilang and so on it is a pretty good and simple way to a simple gallery. I use it myself too.

Go on then! :) Currently I'd use Batcher or CSV Import to do that. You way sounds much quicker.

  • Like 2
Link to comment
Share on other sites

  • 3 weeks later...

Sorry, I tried this but no images or thumbs show on my page...

I get this message:

Error: Call to a member function first() on a non-object (line 24 of /Applications/MAMP/htdocs/ProcessWire-SREP/site/templates/gallery-index.php) 

This error message was shown because you are logged in as a Superuser. Error has been logged.

Link to comment
Share on other sites

Hey PhotoWebMax, did you figure this out? It may be that you have your images field set to hold only one image. I think I've had this problem before. If you go into the admin, under the image field, click on details and change the maximum files allowed to 0 (if you want unlimited) or whatever number you want that's higher than 1. I think that should cause the "first()" function to kick in.

Link to comment
Share on other sites

No, sorry, I decided to back out of trying it this way. I had several templates and test gallery pages that were not working so I scrapped them all and started over from scratch. I created this thread of my journey to image gallery success here: https://processwire.com/talk/topic/6158-photography-galleries-best-solution/

*** I am quite a ways from reaching success though...

Link to comment
Share on other sites

Sorry, I tried this but no images or thumbs show on my page...

I get this message:

Error: Call to a member function first() on a non-object (line 24 of /Applications/MAMP/htdocs/ProcessWire-SREP/site/templates/gallery-index.php) 

This error message was shown because you are logged in as a Superuser. Error has been logged.

Hi PhotoWebMax. The error you're getting is where the first image from each album is grabbed to create an album thumbnail. Since I don't have any error checking here (oops) I think you might get this error if you have no albums, have empty albums, or your albums aren't using a template with the name gallery-album (as described in my setup instructions).

To be sure, I'd need to see the site you're working on.

Here is a site that uses this gallery system: http://www.maranathafamilyministries.org/photo-gallery/

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