Advertisement

How to Create an Image Gallery Powered by Picasa

by

In this tutorial we are going to create a simple image gallery powered by Google's Picasa Web Albums. In order to enhance the user's experience, we'll throw some jQuery into the mix and create a scrollable album carousel.

Final Product

Overview

We are going to use PHP's SimpleXML extension to sort and access the data inside the XML feed provided by Picasa Web Albums. jQuery will be responsible for the DOM manipulation and AJAX request. We are also going to use the Scrollable library, which is part of jQuery Tools to create the carousel. Next, we'll use jQuery's MouseWheel plug-in to allow for cross-browser mouse wheel support. Finally, we'll use the Fancybox plug-in to each image in a "lightbox."

What We Need

Getting Started

We'll begin by downloading the files and putting them into the same folder. I also combined all of the Fancybox images with jQuery Tools ones, and placed them inside the img folder.

PHP files

For our project, we are going to use following PHP files:

  • index.php
  • _ajax.php
  • _conf.php
  • index.php will be responsible for displaying albums, images, and sending requests to _ajax.php.
  • _ajax.php will be handling dynamic request and returning formatted thumbnails
  • _conf.php, as you may have guessed, will contain some configuration information that will be used by both files.

_code.php

This file is very simple and short.

// First we need to set some defaults
$gTitle=""; // title of your gallary, if empty it will show: "your nickname' Photo Gallary"
$uName= "kozlov.m.a"; // your picasaweb user name
$tSize="72c"; // thumbnail size can be 32, 48, 64, 72, 144, 160. cropt (c) and uncropt (u)
$maxSize="720u"; // max image size can be 200, 288, 320, 400, 512, 576, 640, 720, 800. These images are available as only uncropped(u) sizes.

Basically, in this file we set the username (Picasa Web Album ID), thumbnail size, and max image size that we are going to show in our gallery.

index.php

This file requires a bit more to make the gallery work. We begin with referencing our configuration file (_conf.php):

<?php
include './_conf.php'; // getting constants

Next we need to load the album feed. We are only retrieving publicly available albums, so our request will look something like: "http://picasaweb.google.com/data/feed/api/user/user_name?kind=album&access=public".

<code>
$file = file_get_contents("http://picasaweb.google.com/data/feed/api/user/".$uName."?kind=album&access=public&thumbsize=".$tSize);
</code>

file_get_contents will load content from the XML feed into $file variable. As you can see, we used the $uName variable defined in _conf.php to get the right feed. We also passed the additional parameter "thumbsize;" so that the returned feed will contain thumbnails of our chosen size.

Now, let's convert the contents of the feed into a SimpleXml object and define the namespaces we are going to use:

$xml = new SimpleXMLElement($file);
$xml->registerXPathNamespace('gphoto', 'http://schemas.google.com/photos/2007');
$xml->registerXPathNamespace('media', 'http://search.yahoo.com/mrss/');

You can find all namespaces used in the API feeds by visiting http://code.google.com/apis/..., but we'll only be using "media" and "gphoto" in our tutorial; you do not have to worry about the rest of them.

Next, we'll get the web album's name in case we did not already set one in __conf.php file:

if($gTitle == null){ // if empty Gallery title will be "user id's  Photo Gallery"
$nickname = $xml->xpath('//gphoto:nickname'); // Mikhail
$gTitle =$nickname[0]."'s Photo Gallery";
}
?>

Finally, it is time for some simple HTML. We'll set our header and reference a few CSS files.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title><?php echo $gTitle; ?></title>
<link rel="stylesheet" href="reset.css" type="text/css" />
<link rel="stylesheet" href="960.css" type="text/css" />
<link rel="stylesheet" href="style.css" type="text/css" />
<link rel="stylesheet" href="fancybox.css" type="text/css" />
</head>
<body>
<div class="container_16">
<div class="grid_16">
<?php echo "<h1>". $gTitle ."</h1>";?>

As you can see, we've set the page title to $gTitle and have added some CSS to make things pretty.

Style Files

I do not think that reset.css needs any additional explanation, so let's skip over it and take a closer look at the other stylesheet.

  • 960.css allows for a more grid-like layout.
  • style.css comes from the provided stylesheet from jQuery Tools.
  • And fancybox.css is part of the FancyBox plug-in.

Note: Please make sure that you change image path in both fancybox.css and style.css, so all background images point to img folder.

Album Holder and Navigational Elements

It is time to create our album holder and navigational elements. This is where jQuery Tools is a huge help. For the album navigation, we'll be using the Scrollable library. If you visit the Scrollable reference page and take a look at some of the examples, you'll see that we're using it almost without any modifications.

<div>
<a id="prev">&nbsp;</a> <!-- Prev controll-->
</div>
<div id="albums">
<div>
<!-- php code will go here -->
</div>
</div>
<div>
<a id="next">&nbsp;</a><!-- Next controll-->
</div>
<div>&nbsp;</div>
<div id="navi"></div> <!-- Pagination holder-->
<div>&nbsp;</div>

We'll also need a holder for the album picture thumbnails, and the album title that will be loaded via AJAX:

<h2 id="a_title"></h3>
<div id="pic_holder">
</div>
</div>
</div>

JavaScript

Let's finish our page by referencing the JavaScripts we'll be using.

<script type="text/javascript" language="JavaScript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
<script type="text/javascript" language="JavaScript" src="jquery.tools.min.js"></script>
<script type="text/javascript" language="JavaScript" src="jquery.easing.1.3.js"></script>
<script type="text/javascript" language="JavaScript" src="jquery.fancybox-1.2.1.pack.js"></script>
</body>
</html>

PHP

Now it is time to go through the XML file and sift the album thumbnails out. Place the following PHP code inside the </div class="items"> element.

<?php
foreach($xml->entry as $feed){
$group = $feed->xpath('./media:group/media:thumbnail');
$a = $group[0]->attributes(); // we need thumbnail path
$id = $feed->xpath('./gphoto:id'); // and album id for our thumbnail
echo '<img src="'.$a[0].'" alt="'.$feed->title.'" title="'.$feed->title.'" ref="'.$id[0].'" />';
?>
}

Our plan was to load album pictures once visitors click on a specific thumbnail, therefore we have to create some kind of reference to connect the two. For this purpose, we are putting a ref attribute into each album's img tag; so it will look something like this when compiled:

	<img ref="5364767538132778657" title="2009-07-31 - Beach Ocean City, MD" alt="2009-07-31 - Beach Ocean City, MD" src="http://lh4.ggpht.com/_X7imT2xUAEM/SnN7pvTzfqE/AAAAAAAAHmg/DNWeIS7JGzg/s72-c/20090731BeachOceanCityMD.jpg" />

AJAX

Finally, we'll spice it all up with some jQuery. Firstly, we need to initialize the jQuery Tools plug-in with some additional parameters:

$("div.scrollable").scrollable({
	size: 10, // number of pictures per "page"
	next: '#next', // id of next control element
	prev: '#prev', // id of prev control element
	navi:'#navi' // id of navigation control holder
});

The code above will automatically add scrollable controls.

Note: It is better to set the scrollable size to an odd number. This way, selected images will appear right in the middle.

Next we'll create on click event for the album thumbnail:

$("#albums img").bind("click", function(){
	$("#a_title").text($(this).attr('title'));
	$("#pic_holder").html('<div><img src="/images/loading.gif" alt="Loading..."></div>').load("_ajax.php",{"aID":$(this).attr("ref")},function(){
	$("#pic_holder").find("a").fancybox();
	});
});

Let's take close look at what we are doing here. First we define our click event trigger:

$("#albums img").bind("click", function(){

We use bind instead of the simple click because we do not want to interrupt the work of the scrollable plug-in that we just initiated above.

Next, we'll apply the album title into the h2 tag with id "a_title" from the title attribute of the anchor tag:

	$("#a_title").text($(this).attr('title'));

Finally, we send an AJAX request to _ajax.php and let Fancybox re-index the freshly loaded images:

$("#pic_holder").html('<div><img src="/images/loading.gif" alt="Loading..."></div>').load("_ajax.php",{"aID":$(this).attr("ref")},function(){
 	$("#pic_holder").find("a").fancybox();
});

As you probably noticed, we are inserting a "loading image" inside "pic_holder" before sending the AJAX request. This will provide the user with some feedback to let them know that their request is currently being processed. Once we receive a response from the server, jQuery will replace the contents of the "pic_holder" with data that came from _ajax.php.

_ajax.php

Now it is time to serve the contents of the album to our visitors. Our plan is to show thumbnails linked to originals on the Picasa server. Once a thumbnail is clicked, Fancybox will take over and create a lightbox-like image gallery. We'll start with the entire contents of the file, and then go over each line:

<?php
	include './_conf.php'; // getting constants
	if(isset($_POST['aID'])){
		$aID = $_POST['aID']; // let's put album id here so it is easie to use later
		$file = file_get_contents('http://picasaweb.google.com/data/feed/api/user/'.$uName.'/albumid/'.$aID.'?kind=photo&access=public&thumbsize=72c&imgmax='.$maxSize); // get the contents of the album
		$xml = new SimpleXMLElement($file); // convert feed into SimpleXML object
		$xml->registerXPathNamespace('media', 'http://search.yahoo.com/mrss/'); // define namespace media
		foreach($xml->entry as $feed){ // go over the pictures
		$group = $feed->xpath('./media:group/media:thumbnail'); // let's find thumbnail tag
		$description = $feed->xpath('./media:group/media:description'); // file name appended by image captioning
		if(str_word_count($description[0]) > 0){ // if picture has description, we'll use it as title
			$description = $feed->title. ": ". $description[0];
		}else{
			$description =$feed->title; // if not will use file name as title
		}
		$a = $group[0]->attributes(); // now we need to get attributes of thumbnail tag, so we can extract the thumb link
		$b = $feed->content->attributes(); // now we convert "content" attributes into array
		echo '<a rel="'.$aID.'" href="'.$b['src'].'" title="'.$description.'"><img src="'.$a['url'].'" alt="'.$feed->title.'" width="'.$a['width'].'" height="'.$a['height'].'"/></a>';
		}
	}else{
		echo 'Error! Please provide album id.';
	}
?>

First, we are going to reference our configuration file, so we can have access to the constant parameters: Picasa ID and thumbnail size.

include './_conf.php'; // getting constants

Then we'll check if the album ID was sent via POST request:

if(isset($_POST['aID'])){

If we did not find an album ID, we're simply going to print an error message:

}else{
   echo 'Error! Please provide album ID.';
}

If _ajax.php received the album ID, we'll get an XML feed and start working on it, so let's create a link to the correct XML feed:

 $aID = $_POST['aID']; // let's put the album id here so it is easier to use later
 $file = file_get_contents('http://picasaweb.google.com/data/feed/api/user/'.$uName.'/albumid/'.$aID.'?kind=photo&access=public&thumbsize=72c&imgmax='.$maxSize); // get the contents of the album

As you can see, we use the album ID that came via the POST request as well as constants from _conf.php file. Again, we are using file_get_contents to load the XML feed and store it in the $file variable. Next we convert it to a SimpleXMLElement object cycle through each entry nodes that contain information about each picture. To do so, we'll use a simple foreach() loop.

foreach($xml->entry as $feed){ // go over the pictures

Next, we are ready to extract data needed for our link and thumbnail. I've commented every line and hopefully it is enough to understand what is going on:

$group = $feed->xpath('./media:group/media:thumbnail'); // let's find the thumbnail tag
$description = $feed->xpath('./media:group/media:description');  // let's find the description tag
if(str_word_count($description[0]) > 0){ // if the picture has description, we'll use it as the title
	$description = $feed->title. ": ". $description[0]; // file name appended by image captioning
}else{
	$description =$feed->title; // if not, will use file name as title
}
$a = $group[0]->attributes(); // now we need to get attributes of thumbnail tag, so we can extract the thumb link
$b = $feed->content->attributes(); // now we convert "content" attributes into array

Finally, we are putting it all into HTML context. We'll echo a link to the original image and thumbnail image:

echo '<a rel="'.$aID.'" href="'.$b['src'].'" title="'.$description.'"><img src="'.$a['url'].'" alt="'.$feed->title.'" width="'.$a['width'].'" height="'.$a['height'].'"/></a>';

To force Fancybox to organize all of the images into a gallery, we are adding the rel attribute to each link. You can simply put same number or string as value, but I'm going to use the album ID.

Styling

As I mentioned before, most of the styling was taken straight from examples at the jQuery Tools website. All you must do here is simply adjust the height and width to suit the design of your website.

Mouse Wheel Scroll

Mouse Wheel Scroll is another beauty that you can easily use. As some may have noticed, we never initiated this plug-in; yet, if you hover over the album carousel and try to scroll with your mouse wheel, it will work thanks to jQuery Tools.

Conclusion

We've learned how to combine PHP's SimpleXML extension with a handful of plugins and Picasa to create a beautiful and dynamic image gallery. I hope you enjoyed and learned from it!