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.