Flickr doesn't give us a URL for each photo since it stores many different formats of posted images. Instead, when we search, Flickr provides us with all the bits we need to create the URL of the image we want, using a set of predefined rules. This allows us to choose from a number of image formats, depending on the context.
To display each image, we therefore need to calculate the URLs and then make use of the URL to create an image in the form. We'll now show how to do that.
The first thing we need to do is create the full URL for each image. The URL consists of the Flickr domain name, a number for a server to retrieve the image from, an ID, a 'secret number', and a size:
http://static.flickr.com/{server}/{id}_{secret}_{size}.jpg
The following mark-up creates a URL like this for each photo in the search results:
<xf:repeat nodeset="instance('inst-rs')/photos/photo">
<xf:output
value="concat('
'http://static.flickr.com/',
@server, '/',
@id, '_',
@secret, '_s.jpg'
)"
/>
</xf:repeat>
The main new feature to note is that we're using the attribute value on our output control, rather than the ref attribute. The distinction is that ref refers to an item in an instance, whilst value can be any calculated expression.
In the value attribute we have an XPath expression that is making use of the concat function. All this function does is to join together all of its arguments to produce a string:
concat( 'http://static.flickr.com/', @server, '/', @id, '_', @secret, '_s.jpg' )
This is an XPath function that combines each of its parameters together to create a string. If any of the parameters are themselves XPath expressions then they are evaluated first, so in this case the values for the attributes server, id and secret are obtained from each photo and placed into the result.
Now that the output control has access to the calculated URL, we can make use of it to load the desired image. To do this, all we need to do is add the mediatype attribute which indicates that the data in the output is not just to be used as plain text for display, but is a reference to some other kind of object. The values of @mediatype will usually be MIME types, so to indicate that we want an image we simply use image/jpeg or image/*.
<xf:repeat nodeset="instance('inst-rs')/photos/photo">
<xf:output
value="concat('
'http://static.flickr.com/',
@server, '/',
@id, '_',
@secret, '_s.jpg'
)"
mediatype="image/*"
class="image"
/>
</xf:repeat>
You'll see that we also added a @class whilst we're here; this is so that we can make the images a little neater by adding the following style rule to the end of flickr.css:
xf\:output.image
{
border : 1px solid black;
width : 75px;
height : 75px;
margin : 5px;
}
Note the use of the class "image" that we set on the output; this is so that other uses of output don't get displayed as 75x75 squares.
Now, save, refresh and search, and you should have results that look something like this: