Flickr Photo Gallery Extension

Mathias Biilmann

This is a guest post by Viv, one of our clients running Lumina Web Solutions. He recently wrote a smooth extension using the Flickr API and we asked him to share.

For me, one of the great things about Webpop is how relatively simple it is to create some quite powerful extensions. On some previous projects I had been using jQuery on the client side to pull in photos from Flickr. However, I thought it would be nice to try to do the same from the server side (and learn some more about javascript and Webpop extensions in doing so).

Flickr provides an API that returns the response in JSON format (it can also return XML but I opted for JSON). This extension pulls in an album (photoset) from Flickr using the Flickr JSON API.

The Javascript Extension File

The getData function builds the a URL to connect with the Flickr API. Flickr will return a JSON object with information about the photos in that particular photoset. The URL needs to supply an API Key as well as a photoset ID (explained below).

The exports.entries function maps the returned JSON object to an array. This array is passed to the front-end template providing the image information required to build URLs for the individual images. The code checks that Flickr hasn't returned an error code in which case the template will display an error message.

Pagination

The exports.pagination function provides a way to paginate the photos if there is a lot of photos in the set. The number of photos per page is set within the getData function.

Caching of the JSON Object

The photosetCache variable is there so that each page load will only require a single call to Flickr. Otherwise the exports.entries and exports.pagination functions would make the same call to Flickr twice in a single page load.

API Key

You need to obtain a Flickr API Key. More information about this can be found here: https://www.flickr.com/services/api/misc.api_keys.html

Put flickr.js into your extensions folder, adding the API Key to the variable declaration at the top.

Flickr.js

var http          = require("http"),
    photosetCache = {};

// Fetch the Data as JSON
function getData(flickr_photoset_id) {
  var api_key           = "YOUR API KEY",
      per_page          = 28,
      query_page_number = request.params.page,
      cached            = null;

  // Get the first page if there is no 'page' query string specified
  if (typeof query_page_number == 'undefined') {
    query_page_number = 1;
  }
  var flickr_url = "https://api.flickr.com/services/rest/?method=flickr.photosets.getPhotos" + 
                    "&api_key=" + api_key + "&photoset_id=" + flickr_photoset_id +
                    "&per_page=" + per_page + "&page=" + query_page_number +
                    "&format=json&nojsoncallback=1";
  
  cached = photosetCache[flickr_url];
  if (cached) { return cached; }

  var body = http.get(flickr_url);
  photosetCache[flickr_url] = body;
  return body;
}

exports.entries = function(options) {
  var body = getData(options.flickr_photoset);
  // Response can return 'stat' as 'ok or 'fail'
  //https://www.flickr.com/services/api/response.json.html
  if (body.stat != "ok"){
    return {
      error: "Sorry, there was an error retrieving photos from Flickr." + 
             "Try refreshing the page in a moment or come back later."
    };
  }
  return body.photoset.photo.map(function(post) {
    return {
      id: post.id,
      title: post.title,
      secret: post.secret,
      server: post.server,
      farm: post.farm
    }
  });
};

exports.pagination = function(options) {
  var body = getData(options.flickr_photoset);
  
  // Response can return 'stat' as 'ok or 'fail'
  //https://www.flickr.com/services/api/response.json.html
  if (body.stat != "ok"){
    return null;
  }
  
  var flickr_page_number = body.photoset.page,
      flickr_total_pages = body.photoset.pages,
      next_page          = parseInt(flickr_page_number) + parseInt(1),
      previous_page      = parseInt(flickr_page_number) - parseInt(1),
      current_url        = options.current_url,
      html               = "";

  if (flickr_total_pages == 1){
    return "<li></li>";
  }
  
  // Create the PREVIOUS button
  if (flickr_page_number > 1) {
    // ACTIVE previous button
    html += "<li class='arrow'>" +
              "<a href='" + current_url + "?page=" + previous_page + "'>&laquo;</a>" +
            "</li>";
  }
  
  // Create the PAGE LINK button
  for (var i=1; i <= flickr_total_pages; i++) {
    if ( i == flickr_page_number ) {
      html += "<li class='current'>";
    } else {
      html += "<li>";
    }
    html += "<a href='" + current_url + "?page=" + i + "'>" + i + "</a></li>";
  }
    
  if (flickr_page_number < (flickr_total_pages)) {
    // ACTIVE next button
    html += "<li class='arrow'>" +
              "<a href='" + current_url + "?page=" + next_page + "'>&raquo;</a>" +
            "</li>";
  }

  return html;
};

The Template Include File

Modify _flickr_gallery.tpl however you want and use it as an include in a main template. I'm using the Foundation 5 as the CSS framework hence the class names used in the snippet.

<p class="my-image-click">Click on image below to enlarge:</p>

<pop:tag name="photoset_id"><pop:content><pop:flickr_photoset/></pop:content></pop:tag>

<pop:flickr:entries wrap="ul"
                    class="gallery flickr small-block-grid-3 medium-block-grid-4 largeblock-grid-4"
                    flickr_photoset="<pop:photoset_id/>">
  <pop:error><h4><pop:value /></h4></pop:error>
  <li>
    <a href="https://farm<pop:farm/>.staticflickr.com/<pop:server/>/<pop:id/>_<pop:secret/>_b.jpg"
    rel="gallery-1" class="swipebox" title="<pop:title/>"><img
    src="https://farm<pop:farm/>.staticflickr.com/<pop:server/>/<pop:id/>_<pop:secret/>_m.jpg"
    alt="<pop:title/>" title="<pop:title/>" /></a>
  </li>
</pop:flickr:entries>

<div class="pagination-centered">
  <ul class="pagination">
    <pop:flickr:pagination flickr_photoset="<pop:photoset_id/>"
                           current_url="<pop:permalink/>"
                           escape="false"/>
  </ul>
</div>
<p>
  <a class="button" href="https://www.flickr.com/photos/<pop:flickr_id/>/sets/<pop:flickr_photoset/>/">
    View this photoset at Flickr
  </a>
</p>

Content Section

You will need to create a single line text field within Webpop admin on your gallery page called 'Photoset ID'. This field provides the ID of the specific photoset to pull in from Flickr.

How do I get the Flickr photoset ID?

You can find the ID When you are viewing a specific album in Flickr - it's the long number at the end of the URL.

Modifications

It shouldn't take too much to modify this code to use pull in images from other photo sharing services – eg. using the Picasa Web Albums API.

« Back to Blog Index

Sign up now

30 days free trial. Sign up in 60 seconds. Upgrade, downgrade, cancel at any time.
×
blog comments powered by Disqus