Tutorial: Use the Flickr API, JavaScript (jQuery), AJAX and JSON to build a detailed 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:

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.

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.

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 its latitude and longitude on the Flickr 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.

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.

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.

Wrap up

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!