AccessjQuery Masonry & phpFlickr

Introduction

A demonstration of the jQuery Masonry plugin dynamically organising thumbnails based on browser size. Here the thumbnails are provided by an API call to a Flickr group using phpFlickr.

For more information and to leave a comment see the original Think Access post.

 
Demo   Source code   Leave a comment

Demo

Code

Markup

Provide a container to wrap the thumbnails:

<div id="photos" class="loading">
  <?php PHP SCRIPT TO LOAD IMAGE THUMBNAILS ?>
</div>  

PHP

Include the phpFlickr library in your web app. Obtain a free Flickr API key and create a connection object (here referred to as $f):

<?php
  require_once("phpFlickr/phpFlickr.php");
  $f = new phpFlickr('YOUR_API_KEY_HERE');
?>

You can cache the Flickr requests on your server to improve response times. All you need to do is specify a cache lifetime and a path to a folder your web app has write access to. phpFlickr will create text files containing information about the requested images. It won't store local copies of the Flickr images.

<?php
  // Cache the Flickr requests for one hour
  $lifetime = 60 * 60; // One hour
  $f->enableCache("fs", "path/to/cache/folder", $lifetime);
?>

Using the ID of your chosen Flickr group request the latest 50 images:

<?php
  // Access Featured Photos Group - http://www.flickr.com/groups/1632855@N24/pool/
  $group = $f->groups_pools_getPhotos('1632855@N24', NULL, NULL, NULL, 'url_s, url_l', 50);
  $photos = (array) $group['photos']['photo'];
?>

Note that the maximum number of images you can request is 500.

The 'url_s, url_l' attribute specifies that I want Flickr to return URLs to the small and large images. If you don't specify this then the returned array wont contain any URLs. Various size options are available, just play: url_sq, url_t, url_s, url_q, url_m, url_n, url_z, url_c, url_l, url_o.

This code can easily be modified to request images from a particular set or user's photo-stream. Refer to the phpFlickr docs.

Now we can iterate through the images and print out the thumbnail and title with a link to the larger image:

<?php
  foreach ($photos as $photo) {
    print '<a class="photo fancybox" rel="flickr" title="'.$photo['title'].'" href="'.$photo['url_l'].'">'.
            '<img src="'.$photo['url_s'].'" alt="'.$photo['title'].'" />'.
            '<span class="title">'.$photo['title'].'</span>'.
          '</a>';
  }
?>

I've added the class fancybox and rel="flickr" to utilise the fancyBox lightbox plugin but this is optional.

Javascript

This example uses jQuery (of course), jQuery Masonry, imagesLoaded and fancyBox.

The aim is to layout the thumbnails as if they were bricks in a wall, taking in to account their different aspect ratios. imagesLoaded helps us to hide the individual thumbnails until everything is loaded and laid out correctly. If we skip this element then everything jumps around the page whilst the images load in. It all looks a little ugly. fancyBox provides the lightbox modals for viewing larger images.

Include the libraries:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="js/jquery.masonry.min.js"></script>
<script src="js/jquery.imagesloaded.min.js"></script>
<script src="fancybox/jquery.fancybox.pack.js"></script>

On document ready perform these steps:

<script type="text/javascript">
  $(document).ready(function() {
    
    $('#photos .photo').hide();    // Use jQuery to hide all photos temporarily
    
    var $container = $('#photos'); // Create a reference to the image container
    
    // Use the imagesLoaded callback function to activate the Masonry plugin
 		$container.imagesLoaded(function(){
 		  $container.masonry({
 		    itemSelector : '.photo', // The selector of the thumbnail divs
 		    isAnimated : true,       // Animate (with javascript) the layout when changing window size
 		                             // Set to false if you'd rather animate with CSS3 transitions
 		                             // Or toggle with Modernizr like this: isAnimated : !Modernizr.csstransitions
 		    columnWidth: 260,        // Width of the thumbnail including any padding and borders
 		    gutterWidth: 20          // The gap between thumbnails
 		  });
 		  $container.find('.photo').fadeIn('fast'); // Fade back in the thumbnails when the layout is complete
 		  $container.removeClass('loading');        // Remove the loading class from the container
 		});

    // Optionally use your favourite fancyBox configuration
    $(".fancybox").fancybox({
 	  	openEffect	: 'elastic',
 			closeEffect	: 'elastic',
 			padding : 10,
 		  helpers : {
 			  title : {
 			    type : 'outside'
 			  }
 			}
    });    

  });
</script>

CSS

#photos.loading {
  min-height: 500px;
  background: transparent url(images/loader.gif) no-repeat center center;
}
#photos .photo {
  padding: 10px;
  box-shadow: #222 3px 3px 3px;
  width: 240px;
  font-size: 87%;
  background: #F5F5F5;
  display: block;
  text-decoration: none;
  float: left;
  margin-bottom: 20px;
  display: none;
}
#photos .photo:hover {
  box-shadow: #000 3px 3px 3px;
  background: #FFFFFF;
}
#photos .photo img {
  max-width: 100%;
}
#photos .photo .title {
  padding: 8px 8px 0 0;
  font-style: italic;
  font-weight: bold;
  display: block;
  color: #333333;
}