The evolution of the Internet from a document-sharing environment to a programmable platform has enabled developers to use familiar programming paradigms to create applications that take advantage of this distributed execution medium; such applications would have been impossible on a large scale only a few years ago. This evolution was made possible by the emergence of trusted Web services: vendors such as Yahoo, Google, and Amazon made their Application Programming Interfaces (APIs) available to developers using simple, text-based protocols, with no regard for the language/IDE platform used.
Get the code: FLICKR2.ZIP
In this article I will discuss three of these simple text-based protocols and their usage in a variety of languages. For the Web service I will use Yahoo's Flickr.
My main purpose is to show you how to start using public Web services in the most efficient way, using existing open source API wrappers. I will use Flash's Actionscript as the language of choice, but later in the article I will translate relevant sections in the examples into C# and Java. Finally, I will show you how to integrate two Web services: Flickr and GoogleMaps. This is not a detailed article on how to program Flickr, but rather a programmer's introduction to Web service client development.
Flickr
To get started with Flickr development, once you have signed in (assuming you have an account; if not, get one at www.flickr.com), navigate to Explore > Flickr Services on the Flickr homepage. You will need to get an API key (a link on the page will allow you to apply for one), and in the process you will also receive a user id and a 'secret' string. These are needed for authentication (which is probably the most complex feature of Flickr); after all you would not want everyone to be able to tamper with your photos!
You can connect to Flickr from a desktop, mobile, or web application. In this article I will discuss the latter case, but most of the code should be relevant to the others as well.
You should read the online API documentation, terse as it may be. The web site also has links to a wealth of applications from different developers. Who would have thought that there are so many things that can be done with photographs?
The beauty of Web services (Flickr included) is that the communication is in 'clear': you send XML-encoded text requests formatted for the protocol you want to use, and you receive XML-encoded strings in return from the service. In order to communicate with the service you need to be able to authenticate to it and you need to know the endpoints (the Web address to which requests can be sent) and the proper XML encoding for the request/response pair for each protocol. The choice of tool/language is yours, as long as it supports bidirectional communications over HTTP: you can use Actionscript, C#, Java, PHP, Ruby, Javascript (with some limitations that will be discussed at the end of the article), or even Applescript.
So what can you do with Flickr as a developer? Take a look at the API methods listed on the site and you will find various methods grouped in several categories. You can:
- get a list of the photos uploaded by a user
- get information about photos, users, groups, blogs (Flickr has a blogging feature)
- query the comments and tags associated with the photos (one of Flickr's major selling points initially was its ability to let users 'tag' their photos)
- get location information about a photo, if this information is recorded (something I will discuss later in the article)
- upload and modify existing photos.
I wanted to build a simple 'photo of the day' feature for my personal site; since I already use Flash extensively, I decided to build this small application using Actionscript. You can see the end result on my web page at
http://razvan.petrescu.googlepages.com/ActionPhoto.html ; the code is in the ActionPhoto.as file attached to this article. When you open the page, Flash queries Flickr and returns the number of photos I have available (it builds a list of the photos' URLs at the same time). Clicking on the button will load a random photo from the list. Because this action does not require a special authorization (other than the API key, which is embedded in the Actionscript code), you do not have to authenticate to Flickr.
It is important to realize that the Flickr API is entirely text-based and does not return binaries such as images back to you. When you want to get a photo, for example, Flickr will return the address of the image file, and it is up to you to download it, using the features of your language.
I mentioned protocols—the Flickr documentation calls them request formats and this may be a better term. Flickr supports three request formats: REST, XML-RPC, and SOAP. I will discuss these next, but they are not that different: which one you choose is a matter of preference, and also possibly of tool support (for example, .NET has classes that implement SOAP, which makes that a natural choice if you are using a .NET language).
REST
REST (Representational State Transfer) is a design pattern for architecting distributed systems. You can find a good introduction to the philosophy underpinning REST on Wikipedia.
Flickr's compliance with REST's principles is disputed by some. I will let you decide the REST-worthiness of Flickr; what you really care about, as a developer, is the address that you need to send your message to and how to encode your message.
At the code level, REST for Flickr is just a HTTP GET operation. The address (endpoint) is http://api.flickr.com/services/rest/and the message is encoded in XML. SOAP and XML-RPC use HTTP POST, which differs from GET in that it uses both a request and a response stream; GET uses only a response stream; the request is appended to the URL using ?method.
To address some security issues, the endpoints (for Flash applications) were recently changed; for example, the REST endpoint used to be http://www.flickr.com/services/rest/. This caused me a fair amount grief because the Actionscript code on my web page stopped working, while the same code worked just fine from my desktop. You can find this issue discussed in more detail here. Now, all the endpoints listed on the Flickr site start with api.flickr.com, so I assume that is the URL that should be used regardless of programming language.
You can see how this works very easily, just paste this line into your web browser (replace your_API_key with your actual Flickr API key):
http://api.flickr.com/services/rest/?method=flickr.test.echo&api_key=your_API_key
This is the Flickr echo service. The response ('payload') is an XML block that will be displayed in your browser, in this case:
<rsp stat="ok">
<method>flickr.test.echo</method>
<api_key>your API key</api_key>
</rsp>
The stat attribute's value is 'ok' for a successful call and 'fail' for an unsuccessful one (in which case the contents of the message will provide details about the error).
This is really all there is to Flickr. To use the API you need to construct the HTTP request for each method you need and parse the response.
For example, to invoke the findByEmail method (part of the People category; it takes two parameters, the API key and the e-mail you are looking for, and it returns a user id and a user name). In Actionscript you would use the following code:
var url = “http://api.flickr.com/services/rest?/method=flickr.people.findByEmail&api_key=" + your_api_key
+ "&find_email="+find_argument
var response:XML;
response.XML.onLoad=function(){ ...function to parse the XML response ...}
response.load( url );
In .NET, there is a variety of classes you can use: WebClient, WebRequest, or HttpWebRequest. To send a GET request (suitable for REST), you would use something similar to the following:
string URL = "http://api.flickr.com/services/rest/?method=flickr.people.findByEmail&api_key=" + your_api_key
+ "&find_email="+find_argument;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create (URL);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream() );
string str = reader.ReadLine();
while(str != null)
{
Console.WriteLine(str);
str = reader.ReadLine();
}
As expected, the Java code is very similar:
String sRestRequest = "http://api.flickr.com/services/rest/?method=flickr.people.findByEmail&api_key=" + your_api_key
+ "&find_email="+find_argument;
int rawData;
String output = "";
try{
URL u1 = new URL(sRestRequest);
InputStream is1 = u1.openStream();
while((rawData = is1.read()) != -1 )
{
output += ((char)rawData);
}
is1.close();
}
You could build this request manually, but you do not have to. On the Flickr API page you will find links to API kits, which are wrappers written by different developers that provide classes or modules that will abstract the API for you and that you can just use in your own code.
For Actionscript, my favorite API kit is the REST-based one developed by Fabricio Zuardi (if you speak Portuguese, be sure to check out Fabricio's blog). He grouped the different categories of Flickr methods into classes that conveniently wrap the API calls. Because I used his API kit in my project, I will talk about it in more detail later in the article. For .NET developers, I recommend this excellent presentation of an API kit for .NET. .
XML-RPC
XML-RPC is the second request format supported by Flickr. XML-RPC uses HTTP as the transport and XML for encoding. In XML-RPC, the method parameters are wrapped in a XML document and POST-ed to the XML-RPC endpoint, in this case http://api.flickr.com/services/xmlrpc/.
A XML-RPC request will have this format:
<methodCall>
<methodName>flickr.test.echo</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>api_key</name>
<value><string>..your API key..</string></value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>
If the method takes more than one parameter, you will have to repeat the <member> structure for each parameter; you can find detailed instructions regarding the packaging of complex datatypes at www.xmlrpc.com.
Here is how to implement this call in Actionscript:
var request:XML;
var response:XML;
request=new XML();
response = new XML();
response.onLoad=function(success:Boolean){
trace(success);
trace(this.toString());
}
request.xmlDecl = '<?xml version="1.0"?>';
request.parseXML("<methodCall><methodName>flickr.test.echo</methodName><params>
<param><value><struct><member><name>api_key</name><value>..your API
key..</value></member></struct></value></param></params></methodCall>");
request.sendAndLoad("http://api.flickr.com/services/xmlrpc/", response);
Since this is a HTTP POST operation, I have to use the sendAndLoad method of the XML object.
Developer Matt Shaw is behind an open source project that provides a XML-RPC library for Actionscript; an introduction can be found at http://xmlrpcflash.mattism.com/, or you can
download the library (more details can be found
here). Using this library, the call to the echo function shown above would look like this:
import com.mattism.http.xmlrpc.Connection;
import com.mattism.http.xmlrpc.ConnectionImpl;
onLoadListing = function( response:Array ){
trace("Found the following objects:");
var i:Number;
for (i=0; i<response.length; i++){
trace(i+". "+url+response[i]);
}
};
var url:String = "http://api.flickr.com/services/xmlrpc/";
var c:Connection = new ConnectionImpl();
c.setUrl(url);
c.onLoad = onLoadListing;
c.addParam( { api_key:'...your API key...' }, "struct");
c.call("flickr.test.echo");
The addParam method is the only item in this snippet that is somewhat tricky—XML-RPC parameters are structures and this is the proper way of passing a structure parameter in Actionscript.
In .NET:
string req = "<?xml version=\"1.0\"?><methodCall><methodName>flickr.test.echo</methodName>
<params><param><value><struct><member><name>api_key</name><value>
<string>...your API key...</string></value></member></struct></value></param>
</params></methodCall>";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
"http://api.flickr.com/services/xmlrpc/");
request.Credentials = CredentialCache.DefaultCredentials;
request.Method = "POST";
request.ContentType = "text/xml";
request.ContentLength = req4.Length;
Stream requestStream = request.GetRequestStream();
ASCIIEncoding ascii_encoding = new ASCIIEncoding();
byte[] send_data = ascii_encoding.GetBytes(req);
requestStream.Write(send_data, 0, send_data.Length );
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string str = reader.ReadLine();
while(str != null){
Console.WriteLine(str);
str = reader.ReadLine();
}
requestStream.Close();
In Java:
String sxmlRpcRequest = "<?xml version=\"1.0\"?><methodCall><methodName>flickr.test.echo
</methodName><params><param><value><struct><member><name>api_key
</name><value><string>...your API key...</string></value></member>
</struct></value></param></params></methodCall>\r\n";
URL u2 = new URL("http://api.flickr.com/services/xmlrpc/");
HttpURLConnection connection2 = (HttpURLConnection)u2.openConnection();
connection2.setDoOutput(true);
connection2.setDoInput(true);
connection2.setRequestMethod("POST");
OutputStream out2 = connection2.getOutputStream();
Writer wout2 = new OutputStreamWriter(out2);
wout2.write(sxmlRpcRequest);
wout2.flush();
wout2.close();
InputStream in2 = connection2.getInputStream();
while((rawData = in2.read()) != -1 )
{
output += ((char)rawData);
}
in2.close();
connection2.disconnect();
SOAP
SOAP is the most complex request format among those discussed here; it provides a basic framework for sending messages over a network. SOAP is just another way of formatting the request to the Flickr service. The SOAP endpoint is http://api.flickr.com/services/SOAP/ and to this address you will POST the HTTP request. The SOAP request looks like this:
<s:Envelope
xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
>
<s:Body>
<x:FlickrRequest xmlns:x="urn:flickr">
<method>flickr.test.echo</method>
<name>value</name>
</x:FlickrRequest>
</s:Body>
</s:Envelope>
</code></pre>
To format the request appropriately, you would use something like the following:
<p>
In Actionscript:
<pre><code>
var request:XML;
var response:XML;
request=new XML();
response = new XML();
response.onLoad=function(success:Boolean){
trace(success);
trace(this.toString());
}
request.parseXML('<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema" >
<s:Body>
<x:FlickrRequest xmlns:x="urn:flickr">
<method>flickr.test.echo</method><api_key>..your API key..</api_key></x:FlickrRequest></s:Body></s:Envelope>');
request.sendAndLoad("http://api.flickr.com/services/soap/", response);
Since this is a POST operation, I am using the sendAndLoad Actionscript method—the code is identical to the XML-RPC code, only—of course—the endpoint and the payload are different.
In .NET:
string req_soap = "<s:Envelope xmlns:s=\"http://api.w3.org/2003/05/soap-envelope\"
xmlns:xsi=\"http://api.w3.org/1999/XMLSchema-instance\" xmlns:xsd=\"http://api.w3.org/1999/XMLSchema\">
<s:Body><x:FlickrRequest xmlns:x=\"urn:flickr\"><method>flickr.test.echo</method>
<api_key>...your API key...</api_key></x:FlickrRequest></s:Body></s:Envelope>";
HttpWebRequest request_soap = (HttpWebRequest)WebRequest.Create(
"http://api.flickr.com/services/soap/");
request_soap.Credentials = CredentialCache.DefaultCredentials;
request_soap.Method = "POST";
request_soap.ContentType = "text/xml";
request_soap.ContentLength = req_soap.Length;
Stream requestStream_soap = request_soap.GetRequestStream();
ASCIIEncoding ascii_enc = new ASCIIEncoding();
byte[] send_data_soap = ascii_enc.GetBytes(req_soap);
requestStream_soap.Write(send_data_soap, 0, send_data_soap.Length );
HttpWebResponse response_soap = (HttpWebResponse) request_soap.GetResponse();
StreamReader reader_soap = new StreamReader(response_soap.GetResponseStream());
string str_resp = reader_soap.ReadLine();
while(str_resp != null)
{
Console.WriteLine(str_resp);
str_resp = reader_soap.ReadLine();
}
requestStream_soap.Close();
In Java:
String sSoapRequest = "<s:Envelope xmlns:s=\"http://api.w3.org/2003/05/soap-envelope\" xmlns:xsi=\
"http://api.w3.org/1999/XMLSchema-instance\" xmlns:xsd=\"http://api.w3.org/1999/XMLSchema\">
<s:Body><x:FlickrRequest xmlns:x=\"urn:flickr\"><method>flickr.test.echo</method>
<api_key>...your API key...</api_key></x:FlickrRequest></s:Body></s:Envelope>\r\n";
URL u3 = new URL("http://api.flickr.com/services/soap/");
HttpURLConnection connection3 = (HttpURLConnection)u3.openConnection();
connection3.setDoOutput(true);
connection3.setDoInput(true);
connection3.setRequestMethod("POST");
OutputStream out3 = connection3.getOutputStream();
Writer wout3 = new OutputStreamWriter(out3);
wout3.write(sSoapRequest);
wout3.flush();
wout3.close();
InputStream in3 = connection3.getInputStream();
while((rawData = in3.read()) != -1 )
{
output += ((char)rawData);
}
in3.close();
connection3.disconnect();
}catch(Exception e){
output = (e.getMessage());
}
finally{
System.out.print(output);
}
}
So far I have discussed in some detail the request formats. Of course every request format has a corresponding
response format. Your code will have to interpret this response, which will be XML-encoded. In my project, which I discuss next, you will see an example of how to interpret a REST response in Actionscript. Flickr added one more response format, JSON (JavaScript Object Notation—for details see http://www.json.org). Requesting this type or response is only a matter of sending an additional parameter in the request, format='json'.
My Project—ActionPhoto
It's time to combine all this information and look at a finished project. ActionPhoto.as, which is included in the code download, contains the code used in my application. When running, the code will instantiate three objects: a Loader, a TextArea, and a Button; it will connect to my photo repository at Flickr using my API key and build a list of photos. The TextArea is used to display information to the user ("Loading file...y% done", "Today I have x photos"). When you click the Button, a photo is chosen randomly from the list and loaded using the Loader. This is all there is to it.
If you look at the code, two variables are worthy of attention:
private var _buttonListener:ButtonListener;
private var _fp:FlickrPeopleExt;
ButtonListener is implemented in the ButtonListener.as file and is the click event handler for the button; it effectively chooses (by setting numPhoto to a random value less than the total number of photos in my collection) a random photo from the list and calls the ButtonClickedCallback function in the ActionPhoto class, which performs the actual loading of the photo, as follows:
url = "http://static.flickr.com/" + _photosArray[numPhoto] + ".jpg";
_loader.load(url);
The _photosArray variable stores the list of Flickr URLs (as returned by the getPublicPhotos method). You can locate a photo using the URL constructed in the statement above.
_fp is where things get interesting. I mentioned before that I am using Zuardi's Actionscript API kit in my project, and the import com.zuardi.flickr.* statement at the beginning of the ActionPhoto.as file hints at that. _fp is a subclass of Zuardi's FlickrPeople class (implemented in FlickrPeopleExt.as) that calls back into my ActionPhoto class when the photo list is generated by the call to the getPublicPhotos function (which is documented here):
_fp.getPublicPhotos("66489324@N00", 500);
66489324@N00 is my internal Flickr user id. When completed (asynchronously; the reasons are obvious: it may take some time for this operation to complete and you do not want your code to hang while waiting for the result), getPublicPhotos will call my GotPhotosCallback function, which parses the XML-encoded list of photos returned by Flickr and populates the _photosArray variable. The XML message also includes the number of photos in my collection, which I display on screen as soon as my code is loaded.
getPublicPhotos has a slight kink in that it returns the results in pages. '500' tells it to return 500 photos per page, the largest allowed number. I have less than 500 photos in my collection, but if I had more than 500 I would have to call this function repeatedly, with a page number parameter, to generate the entire photo list.
I encourage you to download Zuardi's kit and examine the source code (if you are an Actionscript developer). To use his kit with my source code, you will need to create a project in Flash, place my starter.as, ActionPhoto.as and ButtonListener.as files in the root; on the first frame of the fla file created by Flash paste this action: #include "starter.as", which will instantiate a new ActionPhoto class and cause the code in its constructor to execute. Then create a directory tree in the root with the structure: com, which has a zuardi subdirectory, which in turn has subdirectory named flickr. Copy the framework (FlickrUrls.as, FlickrTest.as, etc) in the flickr subdirectory.
Zuardi's coding style is somewhat different than mine, however I have found his code not difficult to understand, and I think he has done a great service to the Flash (and Flickr) community by making it available as open source. However, there is one problem—which you may encounter with other API kits as well: he did not implement the entire Flickr API. One of the functions he did not implement is getUserPhotos, which returns the URL address of a user's photos, is part of the 'Urls' method category and is documented at http://www.flickr.com/services/api/flickr.urls.getUserPhotos.html. I am listing my own implementation here, which makes use of Zuardi's coding structures and variables; you can paste it somewhere in FlickrUrls.as.
public function getUserPhotos(api_key:String, user_id:String):Void{
var method_url:String = _rest_endpoint +
"?method=flickr.urls.getUserPhotos&api_key=";
var flickrUrlsObjPointer:FlickrUrls = this;
if(!api_key){
throw new Error("api_key is required");
}
else
this._api_key = api_key;
method_url += this._api_key;
if( user_id )
method_url += "&user id=" + user_id;
else
method_url += "&user_id=" + this._user_id;
this._response.onLoad = function(success:Boolean){
var error:String = "";
var isRsp:Boolean = false;
if( success )
{
if( this.firstChild.nodeName == "rsp" ) /* received valid REST response */
{
isRsp = true;
if( this.firstChild.firstChild.nodeName == "user")
{
flickrUrlsObjPointer._user_photos_url =
this.firstChild.firstChild.attributes['url'];
else
if(this.firstChild.firstChild.nodeName == "err")
{
error ="ERROR CODE:" +
this.firstChild.firstChild.attributes['code'] +
"msg:" + this.firstChild.firstChild.attribute
['msg'];
}
}
else /* received an error */
error = this.firstChild.attributes['code'] +
" msg: " + this.firstChild.attributes['msg'];
}
else
error = "Cannot load user photos: " +
method_url;
flickrUrlsObjPointer.onGetUserPhotos
(error,flickrUrlsObjPointer);
}
this._response.load( method_url );
}
This function is quite simple—it returns the link to a user id's photos; in my case the URL is www.flickr.com/photos/zzkj. While its usefulness may be limited, it is an example of how to parse a REST response, and, more generally, of how you can extend (or complete) an existing API kit to fit your needs.
Security
So far all the Flickr operations performed in the sample code only needed the simple authentication provided by the API key. Other operations (for example, uploading photos) will need authentication with more rights—'write' authentication for example. Authentication is discussed in detail here. Also the .NET API article (mentioned previously) has a good discussion of authentication.
For Flash developers, authentication involves the use of the crossdomain.xml file. When you apply for the API key, you have to tell Flickr if you plan on using Flash to connect to it; this way your calling domain is registered. At least, this is how things used to be until the recent change of endpoints for Flash. A quick peek at the file, located at http://api.flickr.com/crossdomain.xml, reveals that access is allowed from any (*) domain.
Mashups with Flickr and Google Maps
I think a discussion of Flickr is incomplete without talking about how it can be integrated with other online services to create mashups. Mashups are Web 2.0 applications that use content from more than one source (web service). One of the more popular mashup-type of applications involves mapping services from Google, Yahoo, or Microsoft. I decided to test Google Maps; I was not aware at the time that Flickr offered its own geotagging/mapping application (http://www.flickr.com/map/), allowing users to place their photos on a map to record the location where the photos were taken. This very recent Flickr feature is based on Yahoo Maps.
Google Maps is a large subject and discussing it in detail is beyond the scope of this article. You will need a good understanding of it before you can tackle the next code samples, so if you are interested in it I suggest you read the documentation at http://www.google.com/apis/maps/ .
My mapping application, written in Javascript, can be found at http://razvan.petrescu.googlepages.com/MyTravels.html. It loads an XML file containing the names of different cities I have traveled to and my favorite spots there, geocodes them using Google Maps' geocoding service (geocoding is the process of assigning identifiers, usually latitude and longitude, to geographical locations identified, for example, by name), and plots them on a global Google Map. Geocoding is necessary because in order to plot a location on the map, Google Maps needs the latitude/longitude coordinates of the place, and I did not want to have to keep track of those manually, especially since a geocoding service was already available free of charge.
The Javascript code loads the locations' XML file asynchronously via XMLHttpRequest, parses it, calls the Google geocoder for each node in the file, and plots the coordinates on screen when the geocoder returns them. It is quite easy to integrate this functionality with Flickr and build something similar to Flickr Maps, whereby a set of Flickr photos are connected with a certain location, and, for example, clicking on a location on the map (Google Maps offers a fair amount of interactivity) loads the photos in Flickr taken at that location. This would be even a bit more technically snazzy than Flickr Maps since the user would not have to define the location on the map of each photo set – that information would be stored as a user-readable location in a file. Or, the photos could be named in such a fashion that a part of the file name would include the location, or the photo set name would include the location, etc.
While developing the complete application is beyond the scope of this article, I will present the pieces needed to complete it next.
In this article so far I discussed various means of accessing the Flickr API other than Javascript; Javascript is the language of Google Maps. There is a good reason why Flickr shies away from Javascript, and that is the security restrictions in the language, where calls to a different domain than the one the script originates from are forbidden. If your Javascript resides at http://mypage.com, you cannot load contents (using Javascript's XMLHttpRequest) from http://www.google.com. (Read the details here.)
There are a number of ways of dealing with this restriction, using proxies (for example, having your Javascript code call PHP code which is not subject to the location restriction and which can send the request across domains and return the response to Javascript), signing your code, etc. The easiest work around (and the one I ultimately used) is only supported by Firefox browsers. It gives a list of photos from my Flickr account (basically, by XMLHttpRequest-ing to the REST endpoint of Flickr); I did not have a PHP app server handy to test a more portable solution. I want to emphasize this is just a non-portable solution to demonstrate how to quickly connect Javascript to a REST endpoint; a ‘production'-level solution will demand the use of PHP proxies.
You can see how this was done at http://razvan.petrescu.googlepages.com/Glickr.html (remember it only works in Firefox, and you will have to click 'Accept' when you get the security message; you will also need to add an entry to the prefs.js file on your hard drive (while Firefox is not running), which stores some Firefox settings:
user_pref("signed.applets.codebase_principal_support", true);
The entire Javascript is in the Glickr.js attachment (in the code download), but an abbreviated version is shown after this paragraph. This is exactly what the first part of the Actionscript code (from the beginning of the article) does: I'm getting the list of photos from Flickr as an XML document. At this point I can parse the document, and if I have a way of assigning a location name to a photo name as discussed above, I can quite easily use my existing Google Maps code to implement Flickr Maps-like functionality.
var Glickr =
{
req: false,
processDOM: function( doc ){
netscape.security.PrivilegeManager.
enablePrivilege('UniversalBrowserRead');
var dom = doc.responseXML;
var nodes = dom.getElementsByTagName('photo');
var i;
for( i = 0; i < nodes.length; i++ ){
//your data is here:
//nodes[i].attributes['title'].value
}
},
processReqChange: function(){
if (req.readyState == 4){
req.ContentType = "text/xml";
Glickr.processDOM( req );
}
},
/* entry point, called from HTML */
load: function(url)
{
req = false;
req = new XMLHttpRequest();
req.onreadystatechange = Glickr.processReqChange;
req.overrideMimeType('text/xml');
netscape.security.PrivilegeManager.
enablePrivilege('UniversalBrowserRead');
req.open("GET", url, true);
req.send(null);
}
};
The entry point to the application is the load function, which is called from the HTML page with the URL set to
http://api.flickr.com/services/rest/?method=flickr.people.getPublicPhotos&api_key=your_key&user_id=your_user_id&per_page=500. XMLHttpRequest then sends the request to the Flickr REST endpoint, and when the response (in the form of a REST-formatted XML file) is received, the processReqChange function (which is the onreadystatechange event handler for XMLHttpRequest) transfers control to the processDOM function. The processDOM function can access the individual photo URLs through the ‘photo' tag name set.
At this point, the same functionality that was implemented in the ActionPhoto.as Actionscript class is implemented in Javascript. One note: you will have to set the Mime type to ‘text/xml' repeatedly because the response from Flickr can confuse the Javascript engine in your browser, which will trigger an error when you try to parse the XML response.
As a final note, if you are interested in developing Flickr applications, you will want to subscribe to the Flickr developers mail list at http://tech.groups.yahoo.com/group/yws-flickr/ . If you get stuck, the Flickr support staff is very responsive.
Web services are exciting. Let's see how creative can you get!
Get the code: FLICKR2.ZIP