Making a Flickr-powered Slideshow

Making a Flickr-powered Slideshow

Today we will be developing a jQuery plugin that will make it easy to create slideshows, product guides or presentations from your Flickr photo sets. The plugin will be using Flickr’s APIs and YQL to fetch the photos in the sets, after which it will create the markup of the slideshow and listen for events.

Updated on Oct 11th 2011: Due to a change in Flickr’s API, you are now required to provide an API key when requesting the photos in a set. The script and this tutorial were updated to reflect this change. If you have downloaded this script before, replace jqFlick.js and script.js. You will also need to generate a Flickr API key (as explained in the tutorial) and paste it in script.js.

The HTML

Before starting with jqFlick (the name of our plugin), lest first lay down the HTML structure of the underlying document. I am including the plugin’s CSS stylesheet – jqFlick.css, which we will be creating in the next step, and the plugin’s js file – jqFlick.js.

index.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jqFlick - Flickr Micro Slider Plugin | Tutorialzine Demo</title>

<link rel="stylesheet" type="text/css" href="assets/css/styles.css" />
<link rel="stylesheet" type="text/css" href="assets/jqFlick/jqFlick.css" />

</head>
<body>

<div id="page">

	<h1>Flickr Powered Micro Slider</h1>

	<div id="flickrSlider"></div>

	<p class="demos">More demos: <select>
    	<option value="1" selected>Presentation Example</option>
        <option value="2">Photo Slideshow</option>
        <option value="3">Product Shots (small)</option>
    </select></p>

</div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
<script src="assets/jqFlick/jqFlick.js"></script>
<script src="assets/js/script.js"></script>

</body>
</html>

Additionally, we have styles.css, which styles the page itself, and script.js, which calls the plugin. Also, we have a select element with demos of three different configurations of the plugin. We will come back to this in a moment.

The other important element in the fragment above is the #flickrSlider div, which is going to be populated with the slider’s HTML by the jqFlick plugin:

Generated Code

<div id="flickrSlider" class="flickrSliderHolder" style="width: 500px; height: 345px;">
	<span class="caption"></span>
	<ul style="width: 1000px; height: 320px; left: 0px;">
		<li style="background-image: url('example.jpg'); width: 500px;"></li>
		<li style="background-image: url('example2.jpg'); width: 500px;"></li>
	</ul>
	<div class="arrows">
		<a class="previous" href="#"></a>
		<a class="next" href="#"></a>
	</div>
</div>

The #flickrSlider div is assigned a class name – .flickrSliderHolder, a width and a height. Inside it we have an unordered list with the slides, an arrow div holder with previous and next arrows, and a span for the captions. The unordered list is set to be wide enough to accommodate the LIs side by side. The slide animation is achieved by animating the left property of the UL.

Flickr Slideshow jQuery Plugin

Flickr Slideshow jQuery Plugin

The CSS

We need to provide the plugin with its own stylesheet, so it is easier to include into a website. This stylesheet must only affect the markup generated by the plugin, and we have to make sure it does not corrupt any other elements on the page. To achieve this, we are going to prefix the styles with the .flickrSliderHolder class name, assigned to the slideshow holder by the plugin.

jqFlick.css

.flickrSliderHolder{
	position:relative;
	overflow:hidden;
}

.flickrSliderHolder ul{
	position:absolute;
	height:100%;
	list-style:none;
}

.flickrSliderHolder ul li{
	float:left;
	height:100%;
	background-repeat:no-repeat;
	background-position:center center;
}

.flickrSliderHolder .arrows{
	position:absolute;
	right:0;
	bottom:0;
}

.flickrSliderHolder .arrows a{
	width:22px;
	height:22px;
	float:left;
	background:url('arrows.png') no-repeat top left;
	text-decoration:none;
	outline:none;
	border:none;
}

.flickrSliderHolder a.previous:hover{
	background-position:left bottom;
}

.flickrSliderHolder a.next{
	margin-left:-1px;
	background-position:top right;
}

.flickrSliderHolder a.next:hover{
	background-position:bottom right;
}

.flickrSliderHolder .caption{
	font-size:13px;
	line-height: 22px;
	position:absolute;
	bottom:0;
	left:0;
}

Once called, jqFlick assigns the .flickrSliderHolder class to the slider holder div, and generates the markup that we saw in the previous step. The code above styles the arrows, caption, unordered list and the container.

Perfect for Slideshows, Product Guides and Presentations

Perfect for Slideshows, Product Guides and Presentations

The jQuery Code

Starting with the jQuery section, lets first see what a response from the Flickr API looks like:

Sample YQL Response

{
    "query": {
        "count": 3,
        "created": "2011-02-19T20:11:18Z",
        "lang": "en-US",
        "results": {
            "photo": [{
                "farm": "6",
                "id": "5456788328",
                "isprimary": "1",
                "secret": "e9eddccf8e",
                "server": "5213",
                "title": "The title of the image becomes an optional caption."
            }, {
                "farm": "6",
                "id": "5456179165",
                "isprimary": "0",
                "secret": "28bae85307",
                "server": "5216",
                "title": "There are no limits really."
            }, {
                "farm": "6",
                "id": "5456179233",
                "isprimary": "0",
                "secret": "e05287691f",
                "server": "5018",
                "title": "What more do you need.."
            }]
        }
    }
}

Here I’ve selected the photos that are contained in this photoset. The response contains useful information about the images. We are going to use the farm, id, secret, and server properties of these objects to put together the URL at which the photos are located, while the title properties are going to be used as captions.

You can find your photos at the following address, by replacing the keywords with the objects’ values:

http://farm{FARM}.static.flickr.com/{SERVER}/{ID}_{SECRET}.jpg

In our plugin, we will be using Flickr’s API method for listing photos in a photoset. However, to communicate with Flickr’s APIs, we will need to register for an API key.

API key registration

This step is actually quite simple. You need to have a valid Flickr registration and visit this page. After you choose the type of the registration (non commercial in our case), you fill in the application details. You now get your API key, which you will need in a second.

For more info on the various Flickr APIs you can go to their documentation page. If you would like to know more about the URL addresses of their photos (including info on how to fetch different image sizes) see here. You can also read more about YQL in our previous YQL tutorials.

Now we are ready to write the jQuery code. As you know, encapsulating jQuery functionality in a plugin has many benefits, as you can read from our jQuery plugin tutorial. Lets see what jqFlick.js, the main plugin file, looks like:

jqFlick.js

(function($){

	$.fn.jqFlick = function(options){

		// Default options:

		options = $.extend({
			width:500,
			height:500,
			maxFetch:50,
			captions:false,
			autoAdvance:false,
			advancePeriod:5000,
			apiKey:''
		},options);

		// Using YQL and the flickr.photosets.photos table to query the Flickr API.

		var YQL = 'http://query.yahooapis.com/v1/public/yql?q={QUERY}&format=json&callback=?',
			query = "SELECT * FROM flickr.photosets.photos({MAX}) WHERE photoset_id='{PHOTOSET}'"+
				" AND api_key='{KEY}'";

		// Replacing the "{EXAMPLE}" keywords from the strings:

		YQL = templateReplace(YQL,{
			"query": encodeURIComponent(
				templateReplace(query,{
					photoset : options.photosetID,
					max	: options.maxFetch,
					key	: options.apiKey
				}
			))
		});

		// Template for building Flickr's image URLs:

		var flickrSRC = 'http://farm{FARM}.static.flickr.com/{SERVER}/{ID}_{SECRET}.jpg',
			flickrSlider = this;

		flickrSlider.trigger('jqFlickRemove');

		// Fetching the images using Flickr's API:

		$.getJSON(YQL,function(r){
			if(!r || !r.query || !r.query.count){
				throw "There is no such photoset!";
			}

			var currentPos = 1,
				cnt = r.query.count;

			var caption = $('<span>',{
				className: 'caption'
			}).appendTo(flickrSlider);

			var ul = $('<ul>',{
				css:{
					width: options.width*r.query.count,
					height:options.height
				}
			});

			// Looping through the photo results:

			$.each(r.query.results.photo,function(){
				data = this;

				// Creating a new LI element with the photo as its
				// centered background image:

				$('<li>',{
					css : {
						backgroundImage: 'url('+templateReplace(flickrSRC,data)+')',
						width: options.width
					}
				}).appendTo(ul);
			});

			flickrSlider.addClass('flickrSliderHolder')
						.width(options.width)
						.height(options.height+25)
						.append(ul);

			// Binding a custom "slide" event.
			// You can then flickrSlider.trigger("slide",2)
			// to go to the second slide:

			flickrSlider.bind('slide',function(e,slide){
				if(slide < 1 || slide > cnt || ul.is(':animated')){
					return false;
				}

				ul.animate({
					left:-(slide-1)*options.width
				},{
					easing: 'easeInOutCirc',
					duration: 300
				});

				if(options.captions){

					// Animating the transition between
					// the captions (if enabled):

					caption.fadeOut(150,function(){
						caption.html(r.query.results.photo[slide-1].title);
					}).fadeIn(150);
				}

				currentPos = slide;
			});

			var arrows = $('<div>',{
				className: 'arrows'
			});

			// Creating the previous / next arrows, and
			// binding event listeners for the click events:

			var arrowPrev = $('<a>',{
				className: 'previous',
				href: '#',
				click : function(){
					var toShow = currentPos - 1;
					if(toShow < 1){
						toShow = cnt;
					}

					flickrSlider.trigger('slide',[toShow]);
					return false;
				}
			}).appendTo(arrows);

			var arrowNext = $('<a>',{
				className: 'next',
				href: '#',
				click : function(){
					var toShow = currentPos + 1;
					if(toShow > cnt){
						toShow = 1;
					}

					flickrSlider.trigger('slide',[toShow]);
					return false;
				}
			}).appendTo(arrows);

			arrows.appendTo(flickrSlider);

			// Showing the first slide by default:

			flickrSlider.trigger('slide',[1]);

			if(options.autoAdvance){

				// If auto advance is enabled, listen for
				// the load event and schedule a periodic slide change.
				//
				// Read more here:
				// http://tutorialzine.com/2011/01/how-to-make-auto-advancing-slideshows/

				$(window).load(function(){

					$.fn.jqFlick.timeOut = null;

					arrowPrev.add(arrowNext).click(function(e,simulated){
						if(!simulated){
							clearTimeout($.fn.jqFlick.timeOut);
						}
					});

					(function autoAdvance(){
						if($.fn.jqFlick.timeOut){
							arrowNext.trigger('click',[true]);
						}
						$.fn.jqFlick.timeOut = setTimeout(autoAdvance,options.advancePeriod);
					})();
				});
			}
		});

		// This custom event removes all event listeners,
		// and empties the slider holder:

		flickrSlider.bind('jqFlickRemove',function(){
			if($.fn.jqFlick.timeOut){
				clearTimeout($.fn.jqFlick.timeOut);
			}

			flickrSlider.empty().unbind('jqFlickRemove slide');

		});

		return flickrSlider;

	};

	// Helper function for replacing "{KEYWORD}" with
	// the respectful values of an object:

	function templateReplace(template,data){
		return template.replace(/{([^}]+)}/g,function(match,group){
			return data[group.toLowerCase()];
		});
	}

	// A custom easing functon. For more info visit:
	// http://gsgd.co.uk/sandbox/jquery/easing/

	$.easing.easeInOutCirc = function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	};

})(jQuery);

jqFlick takes an options object as its only parameter. You are required to specify the id of the photoset (the photosetID property), which you can easily copy from the address bar of your web browser while viewing the photoset. Only public photosets can be shown by the jqFlick.

Now lets see how the plugin is called. At the top of this file, you will need to paste your Flickr API key that we generated above:

js/script.js

$(document).ready(function(){

	// Paste your Flickr API key here
	var apiKey = '';

	// Creating a flickr slider. This is
	// how you would probably use the plugin.

	$('#flickrSlider').jqFlick({
		photosetID: '72157625956932639',
		width:500,
		height:320,
		autoAdvance:true,
		apiKey:apiKey
	});

	// Creating different flickr sliders,
	// depending on the select element value.

	$('select').change(function(){

		var options = {};

		switch(this.value){
			case '1':
				options = {
					photosetID: '72157625956932639',
					width:500,
					height:320,
					captions:true,
					autoAdvance:true,
					apiKey:apiKey
				};
				break;
			case '2':
				options = {
					photosetID:'42296',
					width:500,
					height:500,
					captions:true,
					autoAdvance:true,
					apiKey:apiKey
				};
				break;
			case '3':
				options = {
					photosetID:'72157625961099915',
					width:200,
					height:150,
					apiKey:apiKey
				}
		}

		$('#flickrSlider').jqFlick(options);
	});

});

In the switch statement above, I am listening for the change event of the select dropdown. There, depending on the value of the select, I assign different options objects, which are then passed to the plugin. This demonstrates the different options that are available without taking much screen space.

With this our Flickr-powered Slideshow is complete!

Conclusion

You can use this plugin to build slideshows, product guides or presentations. To use the plugin you just need to drop the jqFlickr folder to your website root and include jqFlick.css and jqFlick.js in your HTML documents.

by Martin Angelov

Martin is a web developer with an eye for design from Bulgaria. He founded Tutorialzine in 2009 and publishes new tutorials weekly.

Tutorials

26 Comments

  1. Kevin says:

    Very nice bit of jQuerying there, I'll have a play =) Thanks

  2. Alex Flueras says:

    Useful, simple and nice plugin. Thanks for sharing!

  3. Jireck says:

    Simple, useful and power plugin....
    Nice tut and thanks

  4. Tristan says:

    Simple, yet capable. This deserves the official awesomesauce label!

  5. e11world says:

    I love that you don't need an api key for this to work and it pulls more than 20 pix as well. Totally great plugin and I would love to be able to add thumbs to it but don't really know where to start!!

  6. Revell says:

    Thank you!

    Simple, clean and just the thing i was looking for, for about a week!

  7. Yes, e11world, nice that you don't need an api key. Maybe useful in the future, but I don't see myself using it now since no sites I've done recently really utilize Flickr. Thanks though for this tut.

  8. Lasse Jensen says:

    Anybody else having trouble with making the images bigger?
    I edited everywhere possible, but the images is still only 500 px wide...

  9. Lasse Jensen says:

    Any news on making the images bigger?

  10. Jared says:

    love it, but im also having some trouble making the photos bigger. for my site i would like to have 647x431px but everything i have tried still only places the images in a square that im pretty sure is 500px.

    I've gone through all the code several times except the jquery.min.js which im unable to edit...

  11. Cedric says:

    @ Lassee and @Jared

    The flickr feed itself sets the sizes of the images. I am not sure if you can use a pipe to change the feed and set the appropriate size, but its worth a shot. The feed specifies different sizes _s,_m,_l,_o,_z. You can check the flickr api for more information on this.

    But, you would need to have a script to resize the images as they are loaded onto the page -- specifically one that can resize proportionally. There is one jquery slidershow that does just this, "Supersized!", however, it wasn't meant as a typical slideshow, BUT, you can rework the css to place the slideshow within a container of whatever size you need (its originally meant as a background slideshow).

    The problem with flickr and slideshows....no one has created a slideshow/slider/plugin specifically for uh slideshows. There are plenty of plugins that pull from the api to display images, thumbs, or the original size of the image. There used to be a plugin called "Galleria" (and i think you can still download it), that uses the flickr api, and allows images to be resized, however, the developers of that project have stopped supporting it. blah blah blah

  12. Justin MacLeod says:

    I have been using this awesome plugin for a bit now and today I noticed it was returning the error "There is no such photoset!". The thing is I can see the photoset on the Flickr website and everything appears fine. I also see the exact same error happening on the demo. I wonder if Flickr/Yahoo have changed something?

    Justin

    1. Caleb says:

      Justin, my Flickr slider just recently stopped working. I'm wondering if something has changed too... The demo isn't even working.

  13. Luc says:

    I use this picture rotator on a nonprofit organization's site. One fundraiser is a golf scramble. Every year they take pictures. Before I started working on their site they simply had a stack of pictures on the past scramble pages. The pictures are now pulled from flicker and individually captioned (They were not before.) On flickers interface it is easy to caption, rearrange and categorize pictures into sets. I actually modified the script to parse the url for a phrase and a year. The phrase and year determines what set of pictures the script will pull. It's pretty helpful!
    I have found two other flicker picture rotator's but this one is the easiest to work with, along with being the best in my opinion!

    One more thing. Some of the past comments have been saying that the picture rotator is giving errors and is broken. Martin (the author of this code) has fixed this problem and it works great now.

  14. Joe Jag says:

    I've found this and thought it would be a great fit for a website I'm building. The only problem I'm having is that for some reason the autoAdvance option doesn't work in IE. Any ideas why? It works in other browsers...and your autoAdvance tutorial (http://demo.tutorialzine.com/2011/01/slideshow-autoadvance-jquery/) works in IE but the code built into this script doesn't. Any help would be greatly appreciated. Thanks!

  15. Kokoro says:

    I'm new to javascript would you please explain what to do with =
    http://farm{FARM}.static.flickr.com/{SERVER}/{ID}_{SECRET}.jpg

    I'm not sure what to replace or where to find the info.

    Thank you in advance.

  16. Kokoro says:

    any pointers on how to make the other two sliders autoadvance.

  17. For anyone that is looking for help on bringing in other image sizes, check out this URL: link.

    Basically, you'll want to find this line in jqFlick.js:

    var flickrSRC = 'http://farm{FARM}.static.flickr.com/{SERVER}/{ID}_{SECRET}.jpg',

    After the {SECRET} add a letter to represent the size you want the image imported as.

    Such as {SECRET}_z.jpg, {SECRET}_m.jpg

    s small square 75x75
    q large square 150x150
    t thumbnail, 100 on longest side
    m small, 240 on longest side
    n small, 320 on longest side
    - medium, 500 on longest side
    z medium 640, 640 on longest side
    b large, 1024 on longest side*
    o original image, either a jpg, gif or png, depending on source format

    1. Kerry Griggs says:

      I have everything working and can resize the images using the method Jon Bukiewicz described. That works great for everything except original images. Just putting in the _o does not work.

      I was able to obtain the values (ex. farm-id: 1, server-id: 2, photo-id:, 1418878, secret: 1e92283336, size: m) for my images but where does that information go?

  18. Stefan says:

    @ Kerry

    I think the _o images only work with an »pro« account due to the limited original images rights in the free account.

    But I haven’t tried.

  19. undsoft says:

    Your slideshow does not work correctly with the latest jquery.
    The problem is with:
    $('<span>',{
    className: 'caption'
    })

    In my browser it just creates the span with 'className' attribute, instead of 'class'.

  20. Love this slideshow, but had the same problem where it doesn't work properly with the latest version of Jquery, so had to go back to version 1.5 which isn't ideal.

    Any chance it could be updated please?

  21. Thor says:

    Hi, thanks for a great tutorial!
    I've implementet the slideshow on my page, and the images loads and slides perfectly. Only thing I can't figure out is the images seems a little off.

    I've taken a screenshot to try to illustrate it:

    http://tobba.org/bilder/screenshot.png

    In the screenshot there, I have drawn a red rectangle around the problem.
    The slideshow can be seen at my experimental page http://tobba.org/no/

    Hope someone can help me with this issue.

    Thanks
    -Thor

    1. Thor says:

      OK, not mutch response here.
      I've discovered that this problem occures when I use the _z parameter to get large photos from Flickr. Is there anyway to resolve this without removing the _z parameter?

      Thanks
      - Thor

  22. benz says:

    I like this plugin so much, thank you!

  23. dubbs says:

    Lovely slider - great work!

    Is it possible to get the autoadvance to be set to true after a user interaction on the next/prev button? By defualt it stops when the user presses next/prev - How can I fire the function to get autoplay to restart following the button press? Perhaps have a toggle button for autoadvance?

Add Comment

Add a Reply

HTML is escaped automatically. Surround code blocks with <pre></pre> for readability.
Perks:   **bold**   __italics__   [some text](http://example.com) for links