Flickr Code
Inspiration Tuesday

When I poke my head above my monitor at FlickrHQ, I can see a lot of headphones. Ever wonder what inspires us to write code (besides fried chicken sandwiches and cocktails)? Well I did a little snooping in the playlists of a few Flickreenos:

Zack

Zack in headphones

Top Tracks:

  • Fitz & The Tantrums - MoneyGrabber
  • Ear Infections mix - Goldenchyld
  • Live In San Diego - Goldenchyld
  • Little Birdy - Brother
  • Parliament - Red Hot Mama

Ross

Ross in headphones

Top Tracks:

  • David Gray – Flame Turns Blue
  • Kings of Convenience – Singing Softly to Me
  • Grizzly Bear – Southern Point
  • The Roots – The Next Movement
  • Iron & Wine – Jezebel

Trevor

Trevor in headphones

Top Tracks:

  • Crawler - Cosmic Tide
  • Quest for Fire - Next to the Fire
  • Bison BC - Die of Devotion
  • Radiohead - Little by Little
  • DMX Krew - Do It All Nite

Scott

Scott in headphones

Top Tracks:

  • Wax Tailor – No Pity
  • Ray Charles – Eleanor Rigby
  • Steve Martin – How to Meet a Girl
  • KRS-One – MC’s Act Like They Don’t Know
  • Quantic – Snakes in the Grass
Dubious friendship

Oh, and I suppose I should share mine too:

•  Blueprint Car Crash – Gun Moll
•  Little Dragon – Come Home
•  Angus & Julia Stone – Black Crow
•  Plants and Animals – Celebration
•  of Montreal – Coquet Coquette

Find even more of what inspires us on our FlickrHQ Last.Fm Group

Photos by waferbaby

A YUI3 Module for the Flickr API

Flickr API YUI3 ModuleDuring the redesign of our photo page, we created a YUI3 API  module, used for all Flickr API transactions. This module has been designed to load component modules as needed, which makes for a speedy initial load. For example, the YUI3 IO module, which handles XMLHttpRequests in the YUI3 library, is loaded only if writing to the Flickr API. Read requests are all handled by the Get Module, which is included in the core of YUI3. A byproduct of this approach is that read requests can be made cross domain, without a proxy.

Reading from Flickr

Simply include gallery-flickr-api in your requirement definition. Then use the Y.flickrAPI.callMethod function, passing the Flickr API method name and callback as arguments. Have a look at the YUI3 Gallery page for more information about using gallery modules. Read requests can be made cross-domain without a proxy, since the request and response will be loaded as a script resource instead of using XMLHttpRequest.

YUI().use('gallery-flickr-api', function(Y) {

Y.flickrAPI.callMethod('flickr.panda.getPhotos',
{
api_key: 'your_api_key',
panda_name: 'ling ling',
extras: 'license, date_taken, owner_name',
per_page: 50,
page:1
},
{
success : function(response_object) {
//Success Code
},
failure : function(response_object) {
//Failure Code
}
});

});

Writing to Flickr

Okay, writing to Flickr API (i.e. post requests) is a little trickier. You will need to make sure that your API key is enabled to read and write. As soon as you make the first API request to write, the YUI3 IO module will be loaded (if it is not already). It is important to note that write requests can only be done on the same domain, which is the standard security restriction of the XMLHttpRequest for browsers. POST requests to the Flickr API, will require some sort of proxy which will accept the post request on your domain and handle the cross-domain communication with api.flickr.com

YUI().use('gallery-flickr-api', function(Y) {

Y.flickrAPI.callMethod('flickr.favorites.add',
{
api_key: 'your_api_key',
photo_id: a_photo_id
},
{
success : function(response_object) {
//Success Code
},
failure : function(response_object) {
//Failure Code
}
});

});

We hope that you make use of this new module. It is a great way to get quick prototypes and full scale applications made using the Flickr API in a short amount of time. See you in the App Garden!

The Joy of Popup Windows

The Joy of Popup Windows As you’ve probably noticed, we’ve been working on the login process here at Flickr. In an effort to make this flow as painless as possible we’ve moved to a “contextual” login, which is to say, logging in doesn’t require you to leave the page you are looking at. We accomplished this by using a popup window. We initially considered using an in-page modal dialog box instead of a popup, but quickly dismissed this approach for two security reasons. Firstly, to prevent phishing and cross site attacks it’s very important that login forms are not posted cross domain (Yahoo!’s Membership Platform authentication happens on yahoo.com, not flickr.com). Secondly the URL of the login page should never be hidden from the user. An in-page modal fell foul of both of these concerns. A more suitable solution would be the popup browser window, once a favorite of advertisers.

Our initial approach

Revisiting our turn of the millennium Javascript for opening windows with the BOM, things looked simple enough: call window.open, make sure the window opened, then set a timeout to see if the window was closed:
function waitForWindowClose() {
	if (web1999Window && web1999Window.closed) {
		// the pop-up was closed, done with auth etc.
		window.location.reload();
	} else {
		// check again in a moment
		setTimeout(waitForWindowClose, 1000);
	}
}//cute function name by Scott Schiller
function webCirca1999(url) {
	try {
		web1999Window = window.open(url,'newWindow','width=640,height=650');
	} catch(e) {
		//handle blocked popup...
	}
	try {
		//this is to check if it really opened
		if (web1999Window.focus) {
			web1999Window.focus();
		}
	} catch(ee) {
		// also handle failure
	}
	waitForWindowClose();
	return false;
}
Unfortunately Yahoo!’s new user signup process closed our popup and opened a new one of their own. This triggered our waitForWindowClose{} function, web1999Window && web1999Window.closed evaluated to true, and the Flickr page refreshed, even though the user hadn’t logged in yet. The next thing we tried was watching window focus. When the window blurred after clicking on the login popup, we’d know the popup was open, and when focus came back we’d check the user’s login credentials. But focus tracking also had its problems. Some browsers didn’t always report the window blur event when a popup was open, resulting in inconsistent behavior. It was also possible for the user to accidentally focus back on the window and kill the flow. We tried several ways to track focus, and although behavior got better, it was never 100% reliable. For a feature like login that was obviously a problem.

The Cookie Solution

Ultimately we settled on a solution that forgot about popup tracking and window focus and instead concentrated on checking for the user’s login cookies. The code below polls to see if the login cookie is set, then makes an AJAX request to verify it, then refreshes the Flickr page:
function pollCookie(){

	if(document.cookie.match(sessionRegex)){
		authInProgress = false;
		checkAuth();
	}else{
		Y.later(20, this);
	}

}
This has the benefit of being very responsive, avoids the nightmare of focus tracking, and is low impact (as there’s no need for us to poll the server). So today we have a reliable contextual login. Our popup system also made it possible to add google and facebook login with less pain than usual.

Flickr Shapefiles Public Dataset 2.0

An embarrassingly long time ago we released the first public version of the Flickr Shapefiles. What does this have to do with Captain America and a cat? Nothing, really. Anyway, we haven’t completely forgotten about shapefiles and have finally gotten around to generating a new batch (read about Alpha Shapes to find out how it’s done). When Aaron did the first run we had somewhere around ninety million (90M) geotagged photos. Today we have over one hundred and ninety million (190M) and that number is growing rapidly. Of course lots of those will fall within the boundaries of the existing shapes and won’t give us any new information, but some of them will improve the boundaries of old shapes, and others will help create new shapes where there weren’t any before. Version 1 of the dataset had shapes for around one hundred and eighty thousand (180K) WOE IDs, and now we have shapes for roughly two hundred and seventy thousand (270K) WOE IDs. Woo. The dataset is available for download today, available for use under the Creative Commons Zero Waiver:

http://www.flickr.com/services/shapefiles/2.0/

Little Johnny JSON

Today I'm a Cop. Originally we provided the full dataset in our own home-grown XML format because, well, it seemed like a good idea. For version two we’re releasing the shapes in GeoJSON format. We think this is a Good Thing because unlike our  old XML format, at least one other person in the world already knows how to read and write GeoJSON. For example, Our friends over at Stamen Design and SimpleGeo have created a ridiculously easy-to-use JavaScript library called Polymaps which of course reads GeoJSON out of the box. With a few lines of JavaScript you can render the Flickr shapefiles and start using them without all that pesky XML parsing stuff: Statez Or if GeoJSON doesn’t suit you you can use a free tool like ogr2ogr to convert it to something that does.

Layers

1000 layers
(photo by doug88888)
The GeoJSON format allows grouping of features (and their related geometries) into FeatureCollection objects. A FeatureCollection seems to be roughly equivalent to a layer in a typical GIS, or a placetype in WhereOnEarth-speak. To make the dataset a little easier to manage we decided to break the shapes up into FeatureCollections based on placetype; one each for continents, countries, regions (states), counties, localities (cities), and neighbourhoods. Each of these is its own GeoJSON file in the dataset. Here’s an example of what one of our GeoJSON objects looks like:
{
  "type": "FeatureCollection",
  "name": "Flickr Shapes Public Dataset 2.0 - Regions",
  "features": [
    {
      "type": "Feature",
      "id": 2344541,
      "properties": {
      "woe_id": 2344541,
      "place_id": "Cxf0SmObApi9R9T8",
      "place_type": "region",
      "place_type_id": 8,
      "label": "Barbuda, AG, Antigua and Barbuda",
    },
    "geometry":
    {
      "type": "MultiPolygon",
      "created": 1292444482,
      "alpha": 0.03,
      "points": 118,
      "edges": 17,
      "is_donuthole": 0,
      "link": {
        "href": "http://farm6.static.flickr.com/5209/shapefiles/2344541_20101215_724c4cae47.tar.gz",
      },
      "bbox": [-62.314453125,17.086019515991,-61.690979003906,17.93692779541],
      "coordinates": [
        [
          [[-61.739044,17.587740], [-61.735268,17.546171], [-61.690979,17.426649], [-61.765137,17.413546]
... etc
A file is a single FeatureCollection object which holds an array of Features, which each hold a Geometry which is a MultiPolygon, which holds an array of Polygons which in turn each consist of an array of LinearRings. Got it?

You’ve Been Superseded

We’ve also included a separate file/layer called flickr_shapes_superseded.geojson. This is a FeatureCollection that consists of all the WOE IDs that have been “superseded”. Occasionally (too often?) a WOE ID needs to be retired and replaced with a new one. We keep up to date with these and are always reverse-geocoding against the latest WOE IDs. However, there are plenty of old photos (and Flickr shapes) that have been assigned to one of these old IDs, and we have shapes for them (currently a little more than nine thousand). A simple solution might be to just re-assign these photos to the new WOE IDs (when a WOE ID is retired its replacement is specified), or even just re-run the reverse-geocoding process. This may not be what the owner of the photo wants; it might come out with a different result than they had at first (which they may have been perfectly happy with), if the size and location of the WOE rectangle changed (which it probably did). So it’s a problem without a clear solution. And since we have data for these old WOE IDs we’ve included their associated shapes in the dataset. In most cases there will be shapes corresponding to the new WOE IDs that will over time become more and more accurate as more photos get uploaded and end up being assigned to the new WOE IDs. But you can have the old ones too.

WTF

Sometimes, Clustr just gets it wrong. As mentioned in previous posts many of the Flickr shapes are just plain weird. It may be due to a lack of data (i.e. source photos), a weakness of the algorithm, an inappropriate choice of the alpha parameter or (shame!) a plain old bug. One of the things that surprised us was that Clustr was not supposed to output inner rings, or polygons with holes. It turns out that it does. In the GeoJSON output this can cause some weirdness (depending on what you use to render the shapes) since the GeoJSON is formatted with the assumption that each ring is a distinct polygon, instead of possibly one part of a single polygon with holes in it. This and other weirdness are known issues and something we shall strive to fix in the future, however we felt it best to release the existing dataset now rather than spend forever trying to get it perfect, and end up not releasing anything at all. You may also notice that unlike version 1 of the dataset, there is only a single shape per WOE ID. All of the previous versions of the shapes are still available via the Flickr API, but in the interests of keeping the file size down we’ve limited this download to just the latest versions of each shape. And as always, there’s lots more to do.

The Flickr Developer Guide

We’re happy to announce today the launch of our Flickr API Developer Guide. Whether you’re just getting started or you have worked with our API for a long time, check it out for some tips on how to best (and respectfully) use the API. All feedback is welcome via the discussion board for the API Mailing List, and you can also check out the API Changelog for any updates, via @flickrAPI, the Flickr API Twitter feed.

The Not-So-New Image Size: Medium 640

Frank Whitney, fighting carpenter (LOC)In July 2010 we launched a new photo page that displays photos at up to 640 pixels on the largest side. In the months leading up to this launch we did a lot of work to support generating this new size, along with making our support of the Large image size more consistent.

Medium 640

We started adding support for the new Medium 640 size(_z suffix) on March 31st 2010. We generated a Medium 640 size for all photos uploaded after that date. Over the next couple months after that we found and corrected instances where we were not fully supporting this size. We display the Medium 640 size on the Photo, Photostream and All Sizes pages.

Dynamically Generated Images

If a photo was updated/uploaded before March 31st 2010 then we do not have a Medium 640 size on file and will try to dynamically generate it. We can do this if a large version of the photo exists, or if the original is a jpeg that has not been rotated(when you see an image URL that ends in _z.jpg?zz=1, the zz=1 indicates we can generate from an original). By doing this we make a lot of old photos display at 640 on the new Photo, All Sizes and Photostream pages. And every time we generate a Medium 640 image it gets cached, so we don’t have to generate it again for a while. If we can’t generate the image dynamically, we fall back to displaying the Medium 500. Generating photos dynamically needs to be happen fast, so we don’t try to generate a Medium 640 from the original if the photo has been rotated or needs to be converted from a non-jpeg format.

Larges For All

We wished we had generated a Large size in the past for all photos uploaded, it would have made it simpler to dynamically generate the Medium 640 size. Before May 25th 2010 we only generated Larges for photos uploaded greater than 1280 in size, now we generate a Large no matter what size is uploaded. This is great for certain types of photos, for example we can now display 800x600 photos(common to some camera phones) as a Large in Lightbox or on the All Sizes page. So, a Large photo will be 1024 pixels in size on the longest side, or the same size as the original if something smaller than 1024 pixels was uploaded(we never scale a photo larger, an original photo of 800x600 will have a Large that is 800x600). You can expect the Large to always exist for newly uploaded photos.

Using the API

The best way to get the URL for a Medium 640 is to include url_z in the extras field when calling the flickr API. When photo data is returned, it will also include the full Medium 640 URL in url_z, along with height_z and width_z. Constructing the URL from the photo data returned will also work, but less reliably for photos before March 31st 2010. http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_z.jpg See: http://www.flickr.com/services/api/misc.urls.html
A lil’ time with… Stephen

IMG_9625

Who are you, and what do you?

I’m Stephen Woods and I’m a frontend engineer at Flickr. Along with the rest of our team I am responsible for the bits that make the UI work, which mostly means html, css and javascript. So I write code, but I also make sure the design of the site looks and works the way the designers want it to.

What hardware are you using?

In terms of computers I have 15” MacBook Pro with a 24” monitor, as well as the standard ipad and iphone. I don’t have a desktop anymore and I do any hacking or side projects on a slicehost image. I used to have a pretty large collection of random computers and desktops, but over the years I have really cut back on hardware, it just doesn’t seem necessary anymore. Like a lot of people here I also enjoy photography. I have a digital rebel xsi and a someone worse for wear 4x5 view camera, neither of which I use as much as I would like.

And what software?

I use TextMate (and sometimes vim) for coding. My development browser is mostly Safari, with Firefox/firebox for some things. I use Charles proxy a lot for HTTP debugging. VMWare fusion is indispensable. I have a portable hard drive with a little collection of VM images to test all the various browsers out there. I am also completely dependent on Evernote. I use it for everything. Frequently I remember something I need to do or figure out a problem while lying in bed, so I just grab my ipad, write down my notes and they are on my laptop when I need them.

What would be your dream setup?

My dream setup would be the MacBook Pro with the good video so I could actually play games on it. Otherwise I am pretty much living the dream.
A lil’ time with… mroth

Mroth Hotdesks

Who are you, and what do you?

Ahoy! I’m Matthew Rothenberg. Most people here call me mroth. I’m the head of product strategy / management at Flickr, which means I’m ultimately responsible for figuring out what Flickr needs to build and why. I work with all of our teams during the development of Flickr features to help make sure they meet our goals and vision, as well as do boring manager-y things. In reality, that means I spend most of my life in meetings (formal or informal). In a broader sense, I’m responsible for trying to make Flickr the world’s best place to share your photos with the people who matter to you.

What hardware are you using?

I have a 15” MacBook Pro with 4GB of RAM (which I insist on still calling a PowerBook). I have a 24” Dell display both at work and at home, but I almost never bother to plug into them anymore. Mobile, oy—I have way too many phones. My primary phones that I carry every day are a BlackBerry 9650 (writing email, making phone calls I want to stay connected for more than 60 seconds), and an iPhone 4 (browsing the web and my primary camera). I also have a Palm Pre (used to be my main phone, now I use it mostly for development), HTC Evo 4G (development and testing) and a Nokia N95-3 (which I use as the world’s most expensive alarm clock). With all those phones, I’m a heavy Google Voice user for bouncing calls back and forth. For running all my side projects and home backup, I have a homebuilt Linux (Ubuntu Server 10.04.1 LTS) server with an Atom chipset sitting in a MSI Wind enclosure, and a Seagate “Green” hard drive that spins down to lower speeds to conserve power. My loft’s stereo is wired up for network play via AirTunes and Airport Express, but unfortunately the software for it is so terrible (no streaming from iOS) it doesn’t get much use currently — I’m hoping AirPlay in iOS 4.2 will finally resolve this. More successfully I do stream video via the 802.11n network from the Linux server to my Sony PS3 which is hooked up to the television (Sony 40” flatscreen of some sort, if anyone actually cares). The most transformative tech hardware I’ve purchased in years has been the Kindle (2nd gen), which completely changed my relationship with books. It perfectly embodies the design principle of doing one thing exceptionally well, and has resulted in me reading approximately 350% more books since I purchased it. Finally, and most importantly, the best productivity-enhancing hardware I own is a La Marzocco GS/3 espresso machine.

And what software?

I live in email — I currently use Mail.app for its live search folders but I’m not entirely satisfied with it. There is a definite market for a real “power user” email app that hasn’t quite been filled yet. Skitch is another “couldn’t live without it” application for me, since I spend a lot of time reviewing not-quite-ready-for-primetime features, it lets me super quickly capture and annotate notes for the team. I’ve been a UNIX nerd for a long long time, so I spend a lot of time in Terminal.app, and sadly even do most of my basic navigation file system operations in there. For actually hacking on code, I use TextMate. Most of my side projects are coded in Python, but lately I’ve been dabbling in Ruby/Rails. Github completely changed the way I hack on side projects. If you haven’t read Anil Dash’s recent blog post on it, you should. If you ever develop software for fun and you aren’t using it, you’re sorely missing out. I occasionally have to build presentations for my job, so when I do, I insist on using Keynote.

What would be your dream setup?

A mythical iPhone with a physical QWERTY keyboard (jailbroken, of course).
A lil’ time with… Chris

CJ Martin

Who are you, and what do you?

Hello, I’m Chris Martin, one of the resident nerds here at Flickr who keep everything running smoothly. I’m from Atlanta, Georgia but I don’t have a southern accent and this seems to disappoint people pretty regularly, I apologize for that. My focus at Flickr is on mobile engineering and making sure people can get their lovely photos out of their pockets and on to Flickr; and vice versa. In real life I’m a professional travel writer/photographer. I’ve never written anything and my photos are sub-par, but I have to justify traveling around the world somehow.

What hardware are you using?

At work I use a 15” MacBook Pro hooked up to two 24” Dell displays, one for code and one for browser windows etc., they are both quite useful for creating a barrier to hide behind during the regular FlickrHQ foam dart wars. I also have a variety of mobile devices that we use to test our own code, 3rd party integrations, and API apps. My Flickr Moleskine and stack of post-it notes are also integral parts of my work hardware setup. At home I have a pretty assorted collection of hardware, the most interesting of which is probably a 450MHz G4 Cube that sits quietly on my desk and still does a great job as a file server. Rounding out my fanboy worthy collection of Apple products are a unibody 15” MacBook Pro, an iPad, and an iPhone 4 that replaced my 1st gen iPhone which I’ve used for the past 3 years (and still do for testing). I have two “hackintosh” machines; one desktop with a couple terabyte drives hooked up to my Samsung TV as a media center, and a 12” ASUS 1201n which I find myself using more than my MacBook Pro because I like it’s small size when I’m out, and I hook up to a 24” display when I’m at my desk at home. In my “retired” collection are a linux PC that used to be a MythTV media center, an original eepc 701 that served me well on a 5 month backpacking trip, an ancient original iMac, and an assorted collection of iPods. I have a problem saying goodbye. It’s probably appropriate to include camera gear as well… I have a Canon 350D which usually wears a 50mm f1.4 lens; it’s starting to show it’s age but has seen and faithfully captured many great trips over the years, a Kodak M1033 which isn’t the greatest camera in the world but it’s built like a tank and was the least obscenely expensive thing I could find in India after leaving a Canon on a train, and a Panasonic Lumix ZS3 that takes excellent video. However, I still take most of my photos with my iPhone.

And what software?

Obviously I’m an OSX guy, ever since I moved from Gentoo linux to a powerbook in college. I love the polish of the Mac GUI, and the raw power of Unix that’s just below the pretty surface. I use the assortment of standard apps (Safari, Mail.app, iCal, and address book) as my primary browser, mail, and calendar applications. I’ve moved around a bunch in the past in this area, but the apple tools have finally started playing nicely with the google suite of services and they work well enough to keep me happy and in sync with my iPhone. For development I primarily use TextMate (web-dev) and xCode (Cocoa), with the occasional trip over to Coda when I need to quickly touch something I’m doing any front end development on. I don’t have any special tools I use for source control or file transfer, that’s all svn, git, scp, etc. in terminal. A few other apps like Linkinus, Adium, and Echofon live in my dock all the time, and of course I pull out photoshop when I need to mock something up. As for utilities, I absolutely can’t live without Visor, a SIMBL plugin that makes my terminal appear on command from the top of the screen, teleport is a nifty tool for sharing one keyboard and mouse between multiple computers, DeskLickr keeps my desktop beautiful with photos from Flickr, and MenuMeters gives me a quick view of how the computer is doing from the menu bar. On my phone, I use Echofon for twitter, Reeder is my absolute favorite RSS reader of all time (I wish there were a desktop version), Instapaper, AutoStitch to make panorama photos, iTimelapse for time-lapse video, and of course m.flickr.com and the Flickr app for browsing Flickr.

What would be your dream setup?

As much as I love laptop computers and the amazing mobile devices we have today, I can’t wait until our computing experiences are more thoroughly integrated into all of the other objects we use in daily life. I don’t just mean “connected things”, but more along the lines of augmented reality. I guess my dream setup would be a pair of contact lenses that I could put in in the morning and immediately start seeing extra information in every day life. I’m sure it will be done, but it will be a fine balance between adding to reality, and completely removing ourselves from it; I hope we do it well.
Creating a dashboard for the help team

When creating a tool for the help team, one of the main things we wanted to do was find a good way to give them updates on new features and site issues. For any of you that have ever been on a help team you know that no matter how much your boss tells you it’s very important that you check your email or look at X web page for updates before each case, that’s probably not going to happen. When you are trying to get through help cases every click and keystroke counts.

So if you are supposed to check some page that only changes 1 out of 100 times you check it, it naturally falls into the list of things that you probably don’t 100% have to check. You don’t have time for that, you’ve got people to help and the queue keeps growing!

So how do you get people to look at those updates? Make it useful!

To make the page useful we tried to solve one of the other frustrations common to most help teams, the tools you need are all on different pages (maybe even managed by different teams). Go here to search for accounts, over there to search for a photo, another place to look up an ID, etc. Any search that might be needed to research a question we put all on one page. The actual tools may still reside somewhere else, but a search box is also included here so you can get to any tool you need, even the flickr.com searches for pictures and people.

Here is an example of what it looks like with a few parts and dates changed for security reasons.

T1Screen

Directly below the searches is “Current Issues” and new FAQs. Now that this is the page you will start at for every case, you’ll always see these updates.

But is that enough? At each stage we tried to think of our audience. If you are trying to get through cases, when you go to a page over and over you start to tune out what you don’t use. To combat that tunnel vision we rotate the color of the issue title and FAQs so it’s easier to notice that something changed. (I actually usually think of that T-Rex in Jurassic park that only sees you if you move. But don’t tell the help team that’s what I was thinking. They’re actually very nice.)

When we released it to the help team, everyone made it their homepage without the boss man having to go around and make them. Success!