Tutorial: Use the Flickr API, Javascript (jQuery), AJAX and JSON to Build a Detailed Photo Wall
by: Kyle Rush
Categories: AJAX, Flickr, JavaScript, jQuery, JSON
Jun
17
09

Tutorial: How to Use the Flickr API, JavaScript, jQuery, Ajax and JSON to Build a Photo Wall
Introduction
In this tutorial, I’ll show you, line by line, how to build a photo wall by pulling your pictures from Flickr using the Flickr API, jQuery, Ajax and JSON. The script I wrote places the following information over the image to which it relates: title, author, comment count, tag listing, location with a link to a map of those coordinates and the description. If any of this information doesn’t exist for a given photo, the script will just not include it. If you haven’t used the Flickr API before, you should read my post on How to Use the Flickr API first. I won’t provide much explanation here on the Flickr API. This is more a tutorial of interacting with Flickr using JavaScript, jQuery, Ajax, and JSON. You do not need an advanced or intermediate understanding of JavaScript or jQuery because I’ll explain almost everything. Let’s get started.
Getting Started: the HTML/CSS
Because the HTML and CSS to achieve this layout is fairly simple and because this isn’t an HTML/CSS tutorial, comments on this section will be short. Whenever you are using JavaScript to manipulate the DOM, you have to take into account accessibility. Since we’ll be adding our Flickr photo to the document after it is loaded, we’ll need to provide an alternative way to get to the content (your Flickr photos) for visitors without JavaScript enabled. This needs to be handwritten in the HTML. Take note of the element with an ID of a-link. I’ve written this into the HTML so that anyone without JavaScript enabled can still get to my photos, however, later on I’ll use JavaScript to remove it immediately so that visitors with JavaScript won’t see it. That aside, you have to place a container for your images and make sure you give it a unique ID so that later jQuery can quickly find it in the document. Next, create some markup for each of your images. This is completely dependent on how you want your Photo Wall to look. Mine looks like this:
The CSS is fairly self explanatory. I floated the ‘image-container’ class to the left since I want all the photos to display in rows of three. I’m letting the browser wrap them within the container. Next, I just applied some styling to suit my taste:
body, html {background: #000; font-size: 12px;}
#container {width: 810px; margin: 0 auto 0 auto;}
#notice {color: #fff; font-weight: bold; font-size: 15px; font-style: italic;}
h1 {font-size: 38px; line-height: 45px;}
h1 span {font-size: 16px; color: #ff0084;}
h1 a:hover span {color: #fff;}
#tut-info {width: 810px; margin: 0 0 20px 0;}
#tut-info a {float: left; display: block; background: #fff; font-size: 20px; padding: 20px 20px; font-weight: bold; margin: 0 15px 0 0;}
#tut-info a:hover {background: #ff0084;}
#loader {margin: 20px 0 40px 350px;}
.image-container {height: 180px; width: 240px; position: relative; float: left; margin: 0 20px 20px 0; background-color: #666; border: 5px solid #fff; overflow: hidden;}
.image-info {display: none;}
.image-info-active {height: 180px; width: 240px; background: rgba(255,255,255,.85);}
a {cursor: pointer; text-decoration: none; color: #0063dc;}
a:hover {color: #fff; background: #0063dc;}
a.title {color: #ff0084;}
a.title:hover {color: #fff; background: #ff0084;}
.bottom {padding: 5px;}
.bottom p {margin: 0 0 5px 0; }
p.top {background: #fff; width: 240px; padding: 0 0 5px 0; margin: 0;}
a.title {font-size: 20px; font-weight: bold; display: block; line-height: 20px;}
span.author {font-size: 10px;}
.infoTitle {font-weight: bold;}
.clearfix:after { content:"."; display:block; height:0; clear:both; visibility:hidden; }
.clearfix {display:inline-block;}
.clearfix {display:block;}
Starting the jQuery and the Initial Ajax Request
In the code below, line 1 starts the doc ready function of jQuery. This is the same as using document.ready. Immediately after, I remove the accessibility link (#a-link). Then, I append a ‘loading’ image into the #image-container element so that if the user has a slow connection or Flickr is taking a while to respond, he/she will know that the JavaScript is actually running. Ajaxload is a very easy to use online app that will generate an animated loading gif images. On line seven, I set my Flickr API key equal to the variable apiKey. Since I’ll be using my API key in several parts of this script, it’s easier to have it stored in one place in case I need to change it. Line 11 starts the Ajax request to Flickr. To send the request, I’ve used jQuery’s getJSON method. This method allows for cross-domain Ajax calls, meaning that you can request data from a different domain than that of which the script is running. Ajax is not inherently cross-domain and takes some hacking to do so, but jQuery makes it easy for us.
Notice the URL for the Ajax request. Instead of providing my API key, I have just referenced the variable that holds my API key that I created earlier. I do this by using the + operator to concatenate the variable into the string. So the ‘ (apostrophe) character at the beginning of the URL starts the string and it then ends after &apiKey=. The plus sign concatenates the variable into the string and then we add another string after the apiKey variable. After JavaScript processes that statement, it will look like http://api.flickr.com/services/rest/?&method=flickr.people.getPublicPhotos&api_key=[YOUR API KEY]&user_id=29096781@N02&per_page=12&page=4&format=json&jsoncallback=? where [YOUR API KEY] is the value of the apiKey variable/your Flickr API key.
$(function(){
jQuery('#a-link').remove();
jQuery('
').attr('id', 'loader').attr('src', 'ajax-loader.gif').appendTo('#image-container');
//assign your api key equal to a variable
var apiKey = '[YOUR API KEY]';
//the initial json request to flickr
//to get your latest public photos, use this request: http://api.flickr.com/services/rest/?&method=flickr.people.getPublicPhotos&api_key=' + apiKey + '&user_id=29096781@N02&per_page=15&page=2&format=json&jsoncallback=?
$.getJSON('http://api.flickr.com/services/rest/?&method=flickr.photosets.getPhotos&api_key=' + apiKey + '&photoset_id=72157619415192530&format=json&jsoncallback=?',
Understanding JSON
Flickr responses in JSON format are not very readable in order to save space. So a typical response of the flickr.people.getPublicPhotos method is: jsonFlickrApi({“photos”:{“page”:4, “pages”:52, “perpage”:3, “total”:”154″, “photo”:[{"id":"3606437738", "owner":"29096781@N02", "secret":"7a02f95b14", "server":"2480", "farm":3, "title":"Water Fountain Closeup", "ispublic":1, "isfriend":0, "isfamily":0}, {"id":"3605617857", "owner":"29096781@N02", "secret":"2f9da1d270", "server":"3385", "farm":4, "title":"Water Fountain Closeup", "ispublic":1, "isfriend":0, "isfamily":0}, {"id":"3605617773", "owner":"29096781@N02", "secret":"bf1c89212e", "server":"2463", "farm":3, "title":"Water Fountain Closeup", "ispublic":1, "isfriend":0, "isfamily":0}]}, “stat”:”ok”}). I have limited this request to three photos for brevity using the &per_page=3 argument. For something more readable, I copied that code and pasted it into the online JavaScript Beautifier. The result is below.
jsonFlickrApi({
"photos": {
"page": 4,
"pages": 52,
"perpage": 3,
"total": "154",
"photo": [{
"id": "3606437738",
"owner": "29096781@N02",
"secret": "7a02f95b14",
"server": "2480",
"farm": 3,
"title": "Water Fountain Closeup",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
},
{
"id": "3605617857",
"owner": "29096781@N02",
"secret": "2f9da1d270",
"server": "3385",
"farm": 4,
"title": "Water Fountain Closeup",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
},
{
"id": "3605617773",
"owner": "29096781@N02",
"secret": "bf1c89212e",
"server": "2463",
"farm": 3,
"title": "Water Fountain Closeup",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
}]
},
"stat": "ok"
})
To access data in the array, we just follow the simple structure. If you imagine that the entire array is called, say ‘data’, then data.photos.pages would return the value 52. In this tutorial, we’re not interested in how many pages of images are available, so data.photos.photo.title[0] (JavaScript starts its numbers at 0 instead of 1) would return “Water Fountain Closeup” for the first image. Since we know we’ll have more than one image, but we don’t necessarily know how many, we can create a loop that will pull the data we need for each photo that exists. That will be covered next.
Getting Basic Information and the Geo Location of Each Photo
Line 1 continues the jQuery JSON request and instructs jQuery to run the code within the function when the data is received. Line 4 in the following code starts jQuery’s .each() method, which is arguably an easier way to write a for loop. This loop will carry out a function through each of the items (photos) that Flickr sent. On line 7 I created a string variable that contains a URL for the image on which the loop is currently on (information on how the URL is build can be found here or on the Flickr API URL info page). Notice how and where I place the data from Flickr’s JSON response. I will later use this variable as the value of the href parameter of the anchor linking back to the image. After that, on line 10, I turn the photo’s ID into a variable as I will be using this several times.
We have pretty much all the basic information on the photo from our first Ajax request, but if you look carefully you can see that the geo location is not provided. To get this, we start another Ajax request on line 13 using the Flickr API’s flickr.photos.geo.getLocation method. We already have required arguments, so look carefully how I placed them into the URL. On line 14 I tell jQuery to run a function as soon as the data is received. On line 13 I use a conditional statement to see if my request was a failure. I do this because not all photos on Flickr have a geo location and if they don’t, Flickr will respond with failed request details. Here is the response Flickr will give if one of the pictures I request has no geo location: jsonFlickrApi({“stat”:”fail”, “code”:2, “message”:”Photo has no location information.”}). If data.stat is ever in the response then the request has failed. So, the conditional statement on line 17 tells JavaScript that if data.stat does not exist, continue with the following code. In the following code on line 18, I create a variable called pLocation (the keyword location is reserved in JavaScript) that contains a string of HTML combined with the latitude and longitude from the request. In the HTML of this, I have included a link to the Flickr map where the image was taken because we have latitude/longitude data. You may have noticed that earlier I use the var keyword to declare the apiKey variable while this time I did not. In JavaScript, variables declared with the var keyword are local variables that live inside the function in which they were created. Variables declared without var are global and can be accessed outside the function in which they were created. I decided to make pLocation a global variable because I will need to access it outside of the function I created it later on in the code. When possible, you should always use local variables as global variables can interfere with each other and cause you some headaches. At the end of first the loop I will delete this global variable so that it doesn’t cause problems when the loop moves to the next image.

Each Image Will Link to It's Latitude and Longitude on the Flickr Map
function(data){
//loop through the results with the following function
$.each(data.photoset.photo, function(i,item){
//build the url of the photo in order to link to it
var photoURL = 'http://farm' + item.farm + '.static.flickr.com/' + item.server + '/' + item.id + '_' + item.secret + '_m.jpg'
//turn the photo id into a variable
var photoID = item.id;
//use another ajax request to get the geo location data for the image
$.getJSON('http://api.flickr.com/services/rest/?&method=flickr.photos.geo.getLocation&api_key=' + apiKey + '&photo_id=' + photoID + '&format=json&jsoncallback=?',
function(data){
//if the image has a location, build an html snippet containing the data
if(data.stat != 'fail') {
pLocation = '' + data.photo.location.locality._content + ', ' + data.photo.location.region._content + ' (Click for Map)';
}
});
Getting the Flickr Tags of the Images
Line 2 in the following code starts another Ajax request similar to the one that I used to get the geo location. The only difference is the URL. When the request is complete, I used a conditional statement on line 6 that searches the response data to see if there are any tags. In JavaScript, this is known != as an is not operator. It is the opposite of ==. So, if data.photo.tags.tag is not empty (specified by empty apostrophes: ”), then run the following code.
I chose to hold each tag in an Array. To do this, I set the variable tagsArr equal to a new array. On line 12 I start a new for each loop to loop through each tag since they are grouped separately. The only thing different on this loop is that I use j instead of i so as to not have any confusion with the geo code loop which uses the variable i. Next, on line 15, I add some HTML that contains the tag data to the tagsArr array using JavaScript’s .push() method. When that loop is finished going through the tags, I use the .join() method on line 20 to combine all the tags in the array into a string that will be easier to use later. I created a new variable tags and set it to a value of the tags.
//use another ajax request to get the tags of the image
$.getJSON('http://api.flickr.com/services/rest/?&method=flickr.photos.getInfo&api_key=' + apiKey + '&photo_id=' + photoID + '&format=json&jsoncallback=?',
function(data){
//if the image has tags
if(data.photo.tags.tag != '') {
//create an empty array to contain all the tags
var tagsArr = new Array();
//for each tag, run this function
$.each(data.photo.tags.tag, function(j, item){
//push each tag into the empty 'tagsArr' created above
tagsArr.push('' + item.raw + '');
});
//turn the tags array into a string variable
var tags = tagsArr.join(', ');
}
Preparing the Variable to Append to the Document
Now that we have prepared all of our data in nice little variables that we can use, we need to combine it all into one variable that we can easily insert into the DOM. On line 2 I create this variable and give it a value of some HTML interlaced with some of the data from the request received. On line 5, I use a conditional statement to see if the tags variable exists. It will only exist if there were tags in our data because if there weren’t, our previous conditional statement wouldn’t have run the code that created the variable in the first place. Returning the typeof of a variable will tell you what kind of variable it is. If the typeof is undefined, then the variable doesn’t exist. On line 8, I use the += operator to concatenate a string onto the previously created imgCont variable.
On line 12, I do the exact same thing with the geo location data as I did with the tags on line 5. I add the description of the image to the imgCont variable on line 19. Now that the imgCont variable contains all the data I want it to, I use jQuery’s appendTo() method to insert the picture and all its data into the #image-container div in the HTML. Directly after that I delete the global variable pLocation so that it doesn’t repeat in the next loop because that will be a different image.
//create an imgCont string variable which will hold all the link location, title, author link, and author name into a text string var imgCont = '' + data.photo.title._content + ''; //append the 'imgCont' variable to the document $(imgCont).appendTo('#image-container'); //delete the pLocation global variable so that it does not repeat delete pLocation; }); }); });Comments: ' + data.photo.comments._content + ' '; //if there are tags associated with the image if (typeof(tags) != 'undefined') { //combine the tags with an html snippet and add them to the end of the 'imgCont' variable imgCont += ' Tags: ' + tags + ' '; } //if the image has geo location information associate with it if(typeof(pLocation) != 'undefined'){ //combine the geo location data into an html snippet and at that to the end fo the 'imgCont' variable imgCont += ' Location: ' + pLocation + ' '; } //add the description & html snippet to the end of the 'imgCont' variable imgCont += ' Decription: ' + data.photo.description._content + '
Adding the Rollover Effect and Removing the Loading Image

An Image which Reveals Information on Mouseover
In the following code, I use jQuery’s .live() method to apply a function when our images are either rolled over or rolled off of. In this situation I have to use .live() instead of .hover() because I need the rollover to apply to elements inserted into the DOM after the DOM was loaded. .live() is an awesome method that will apply a function to all elements that match the selector no matter when they are added to the DOM. To create the rollover, I just change the class of the image container to a class that’s display property is not none. Line 5 just reverses this previous function when the mouse hovers off the image. The last thing is to remove the loader image since everything is done. Although all images may not have been loaded, everything has been added to the document. We could create a function that checks to see if the last image was loaded and then to remove the loader image, but this tutorial is already quite long.
//assign hover actions to each image
$('.image-container').live('mouseover', function(){
$(this).children('div').attr('class', 'image-info-active');
});
$('.image-container').live('mouseout', function(){
$(this).children('div').attr('class', 'image-info');
});
jQuery('#loader').remove();
});
Conclusion
Congratulations on building a dynamic Flickr photo wall. I know it was a long tutorial, but I wanted to provide as much information as possible. Was the tutorial helpful for you? See anything that should be changed? Want to see more tutorials like this? Let me know in the comments!
[...] … uso de la Flickr API Aprende a usar la Flickr API y a sacar ventaja de ella para tu sitio … una muralla de fotos haciendo uso de la Flickr API Aprende a hacer una muralla con fotos de flick usando la Flickr API, js, AJAX y [...]
here is an example of how to place the images in an unordered list: http://kylerush.net/tutorials/flickr-photo-wall/f…
the parts of the source that i changed on that page are lines 80, 145-147, 131 and 132.
as for using different sized thumbnails, flickr makes that easy with size suffixes. if you take a look at line 25 of the source of the original demo, you see this line:
var photoURL = 'http://farm' + item.farm + '.static.flickr.com/' + item.server + '/' + item.id + '_' + item.secret + '_m.jpg'
for a smaller thumbnail you would just change the last part of that line to '_s.jpg' or '_t.jpg' instead of '_m.jpg'
full documentation on flckr size suffixes can be found here: http://www.flickr.com/services/api/misc.urls.html
Howdy, I know this blog post is a little old, but your tutorial is very high on the google search results! I hope you still read the comments/questions.
I, like the above other user, am trying to use TAGS instead of photosets. Your response & example response all link back to this post.
I know i have to alter the "photosets.getPhotos" and "photoset_id" in the script, but i cannot find any example of what to change http://api.flickr.com/services/rest/?&method=… + apiKey + '&photoset_id=
is there a way of opening up the images via lightbox ?
yep, this is certainly possible. how you would do it depends on which lightbox script you would be using.
[...] to look through my sites and see if anything had changed without my knowledge. I found that the most popular post on this blog had been changed. The title was erased so that only “…” showed up as [...]
If using the getPublicPhotos request, rather than the photoset request, you'll also need to replace the $.each with:
$.each(data.photos.photo, function(i,item){
rather than
$.each(data.photoset.photo, function(i,item){
Great tutorial though, thanks a lot!
is there any way to have the photos from the "flickr favorite" rather than a set?
yes there is. see my post on how to use the flickr api to customize this script: http://kylerush.net/flickr/flickr-api/
Kyle;
Concerning [ Your API Key ] – I noticed your code doesn't include "YOUR" api key and I can see why. Can you do this in a browser, as oppsed to the server, without exposing your apikey? Javascript running in a browser isn't private so someone could grab and abuse your apikey.
Nice, instructive example though.
Bill
thanks bill.
to my knowledge it isn't really possible to not expose your api key with javascript. if that is a concern of yours then you may have to do some of the work on the server side to hide your key.
Awesome tutorial ! Help me a lot to understanding Flickr API and how to work with that.
Thanks a lot
Saulo Padilha
London – UK
http://api.flickr.com/services/rest/?method=flickr.people.getPublicPhotos&api_key=‘ + apiKey + ‘&user_id=30248130@N05&per_page=15&page=2&format=json&jsoncallback=?
this not work for me.. i tried many way.. but not work.. is it need to set anything in flickr or else..
help me please
Very very informative tutorial. I am still quite a noob but it would’ve helped if you could give some more description from the 5000ft level like I can see how you have a CSS file, HTML file to create the website. But for the ajax request/jquery, am I supposed to have a separate file for each? Also is this python or something in which you are coding it?
Is this sample downloadable and customizable somehow? Thanks again for putting this together!
Hi, I just thought I’d mention that the getPublicPhotos method with its extras, say ‘description’ and ‘url_o’ etc will allow you to get a bunch of extra info for each photo with only one API call. So, rather than looping through your images, and calling new API queries for each (which might be useful for very specific info, but is inefficient) you might just be able to get it in one shot. Its worth a look. As for placing your API key in a publicly available JS I’d also like to know how to get around this. Obviously, you can just make the call server side and render your own response, but I’d like to know if anyone else has their own solution?
I have the same issue as above, although I copied yr source almost exactly.
Although changing the background to 'no-repeat' is easy enough (in var imgCont), I'm still left with small photos, rather than large ones, like in the sample.
you can see what I mean athttp://nationalheadquarters.org/c-list-pics/flcik…
also, it is worth noting that I am posting this comment as Kyle Rush hisself, as did the person above!
Is the a mediatemple problem?
Is there no way to pull the description of a flickr image? only the titles and tags?
your api key must have been disabled. try requesting a new one. make sure that you are not requesting a commercial api key.
the problem is a failed flickr request. in firebug, go to the 'net' tab and look at the response of the last flickr request. in this case, yours is: jsonp1246994848456({"stat":"fail", "code":100, "message":"Invalid API Key (Key not found)"})
flickr will send this on all unsuccessful requests. it's telling you that the api key you have submitted is not valid. since flickr responded with the 'stat' object and error details there is not 'photoset' object in the response, so firebug throws the following error in the console:
data.photoset is undefined
$.each(data.photoset.photo, function(i,item){n
i looked at your code and the problem is that you are submitting an invalid flickr api key. you have set the value of the apiKey variable to your flickr api key wrapped in brackets. the brackets are not necessary. it should look like this:
var apiKey = '123456789123456789';
and not:
var apiKey = '[123456789123456789]';
note: that is a fake api key i just made up.
i hope that helps.
what are you trying to pull? images from one of your sets? you need to adjust my code if you want to pull different images than the ones i pulled. you need to adjust the first ajax request to flickr:
$.getJSON('http://api.flickr.com/services/rest/?&method=flickr.photosets.getPhotos&api_key=' + apiKey + '&photoset_id=72157619415192530&format=json&jsoncallback=?',
if you want to pull images from one of your sets, then you need change the '&photoset_id' variable to the id of the photo set you'd like to pull.
i'm not sure what you want each photo to link to, but you want your photo to link to something, you need to edit line 68 of your code:
var imgCont = '<li class="thumb"><img class="resize" src="' + photoURL + '" /></div>';
to add a link to your image, simple html will do the trick:
var imgCont = '<li class="thumb"><img class="resize" src="' + photoURL + '" /></div>';
if you want the photo to link to the photo's flickr page, change line 68 of your code to this:
var imgCont = '<li class="thumb"><img class="resize" src="' + photoURL + '" /></div>';
i built that url after looking at the url of one of my flickr photos, say:
http://www.flickr.com/photos/kylerush/3606436456/…
if you notice from the value of the href parameter in the new code for line 68, i'm using information from the flickr json response to fill in the 3rd, 4th, and 6th segments in the url to the image's flickr page.
is there a way to pull based on the tags assigned to images so that if I have a pool of images and I only want the ones with a "younger" tag to show?
there is. see my post on using the flickr api: http://kylerush.net/flickr/flickr-api/
if you're struggling with the code, let me know.