We will be creating a fairly nice javascript view of photos fed in from a flickr group feed, using only
the new feeds module and views.
There is no need in this tutorial to have a flickr api key.
feeds is the successor to feedAPI and is very powerful. With it you can set a feed, automatically update on cron runs, and map xml fields to cck elements. For this tutorial, we will just make use of the images.
flickr images come in four flavours - the standard image, say dogs.jpg, the thumbnail dogs_t.jpg version, a small version dogs_m.jpg, square version dogs_s.jpg and a large version dogs_b.jpg. Note the somewhat confusing suffixes for small (m), square (s) and medium (no suffix).
As a Montreal Canadiens fan, for this example I will use the group the Montreal Canadiens (HABS) Fans group icon
Montreal Canadiens (HABS) Fans and click on the link beside 'Group Pool', which currently lists 330 Items.
On this page, there is an rss feed which I can click on and save the url to.
http://api.flickr.com/services/feeds/groups_pool.gne?id=461503@N25&lang=en-us&format=rss_200
Step 1 - install new modules.
Download The feeds module,
ctools (feeds depends on it) and
views. Make sure to enable views ui, feeds admin UI and feeds defaults, in addition
to the module cores. You might also need CCK installed (but really if you had views installed, you probably already do).
Step 2 - setup a feed importer
Go to Administer >> Site Building >> Feed Importers, or directly to /admin/build/feeds. Check the 'enabled' box on the 'Feed' line. The status will change to 'Overridden'. You will have 'feed' and 'feed item' types created.
Create a new CCK type - call it 'montreal_feed_item'. Click 'New Importer' name this feed importer 'Montreal Canadiens flickr'.
When we are brought back to the feed listing, we see that this feed is attached to a 'Page' and status is 'normal'. We
will change this by clicking on the 'edit' link. Click on 'Settings' under 'Basic Settings'. Change the 'Attach to content type' select box to
'Montreal Feed Item' and then click the save button.
Next click on the 'Change' link beside 'Fetcher'. The current fetch method is by url download - so this is ok. Parser 'Change' reveals that we are parsing with the 'Common syndication parser'. This is also what we want. Processor 'Change' reveals that we are creating nodes from parsed content, which is again what we want.
However, the 'Settings' link reveals that the content type is set to 'Story'.
Let's change this to 'Feed Item' and click save. Finally, by clicking 'Mapping', we see that no mapping currently exists. Let's map 'Description' to 'Body',
'Title' to 'Title', 'Item URL (link)', to 'URL', and 'Published Date' to 'Published Date'.
Step 3 - create a feed
Go to Create Content >> Feed or directly to /node/add/feed. Give your feed a title and url. I called mine 'canadiens feed' and set the url to
http://api.flickr.com/services/feeds/groups_pool.gne?id=461503@N25&lang=en-us&format=rss_200
You should get a green success message similar to 'Created 20 Feed item nodes.'
Once imported, you should be able to view the new raw feed items at '/node'. So all the feed items are there, only problem is that they are ugly as sin.
We need to create a view. Also note how easy it is to delete and import the feed items if need be.
Step 4 - create a view
At Adminster >> Site Building >> Views or directly at '/admin/build/views'. Click 'Add' and create a new view. I called mine 'flickr_images'.
This view is quite simple to create.
Step 5 - override and format the views templates
Without theming the templates, the view is visually pretty awful.
So we will create a couple files to overwrite the defaults. Click on the 'information'
link beside theme. Depending on whether you are creating a view for a block or a page, and using an unformatted, table or grid, the filenames and default content will differ. I am creating an unformatted page view for this example.
We will create a file views-view--flickr-images.tpl.php to override the default 'Display output' one. Click on the display output link to display the default html and php template and cut/paste that into your new file. This file should be saved in the theme directory that you are using. Repeat this for views-view-unformatted--flickr-images.tpl.php to override the default 'Style output'.
Click the 'rescan template files' submit button and the newly created files should be bolded, to reflect the changes. Check that your cache is cleared
if changes to the new files are not being seen.
The first file, 'views-view--flickr-images.tpl.php' is the wrapper for each individual photo in the view. Here, I've set a placeholder element to display a large image and changed the <div> to float image elements instead of putting them on new lines.
<div id='large_image' style='margin-bottom: 10px; border: 1px dashed black; height: 333px; width: 500px;'>
<div style='margin: 30px;'>
<h2>large image</h2>
</div>
</div>
<?php
foreach ($rows as $id => $row): ?>
<div style="float: left; padding-right: 5px;" class="flickr_photo_<?php print $id.' '; print $classes[$id]; ?>">
<?php print $row; ?>
</div>
<?php endforeach; ?>
<div style='clear: both;'> </div>
For the second file, 'views-view-unformatted--flickr-images.tpl.php' and 'Style output', this controls the details of each
element. Each element has stored the description into the body similarly to
<p><a href="http://www.flickr.com/people/65579825@N00/">aynos01</a> has added a photo to the pool:</p>
<p><a href="http://www.flickr.com/photos/65579825@N00/4025250257/" title="Carey Price (17 oct 09)"><img src="http://farm4.static.flickr.com/3489/4025250257_23a2994159_m.jpg" width="240" height="180" alt="Carey Price (17 oct 09)" /></a></p>
</p>"
But all I am really interested in is the img src and alt values, so I have used regex to parse them out.
<?php
$image_source = preg_replace('%(.*)<img src="(.*)_[a-z].jpg"(.*)%is', '\2', $fields['body']->content);
$image_alt = preg_replace('%(.*)<img(.*)alt="(.*)"(.*)%is', '\3', $fields['body']->content);
print "<a href='$image_source.jpg' ><img alt='".$image_alt."' src='".$image_source."_t.jpg'/></a>";
?>
Note, for performance, you can use a single preg_match statement instead of two preg_replace calls.
preg_match('%(.*)<img src="(.*)_[a-z].jpg"(.*)alt="(.*)"(.*)%is', $fields['body']->content, $image_details);
$image_source = $image_details[2];
$image_alt = $image_details[4];
Depending on how regular the photos, you may have further work. If all images are the same size that is great. If not, you will need to do some css and jquery fiddling around. With this feed, the images are vertical and horizontal, so the square thumbnail images, _sm.jpg, works best. As well the large image is not going to be a fixed width, so the number of thumbnails will not fill it up nicely unless appropriately padding is added. The large image div will also need to find the appropriate height and width to resize to.
As I do not want to focus on this right now, consider this alternative rss feed
http://api.flickr.com/services/feeds/groups_pool.gne?id=698658@N21&lang=en-us&format=rss_200
Which has only vertical files of identical size and so is perfect. Go to your feed page /content/canadiens-feed if you named it the same
as me (replace your name with '-' for spaces). If you can not remember, you can find it through admin/content/node.
Click 'delete items', click edit, modify the url and save. Then click 'Import'.
I will comment on how to modify the css and jquery for the previous, more complex RSS feed later.
Step 6 - add jquery
Now all images are 320px by 480px. So we will modify the large image dimensions and revert the thumbnail to the _t.jpg images.
Let's add some jquery to load the first image in our view into the large_image div on page load, and switch the images onclick.
In the details template:
<?php
$image_source = preg_replace('%(.*)<img src="(.*)_[a-z].jpg"(.*)%is', '\2', $fields['body']->content);
$image_alt = preg_replace('%(.*)<img(.*)alt="(.*)"(.*)%is', '\3', $fields['body']->content);
print "<a href='#' onclick='change_large_image(\"".$image_source."\");' ><img alt='".$image_alt."' src='".$image_source."_t.jpg'/></a>";
?>
and in the wrapper template
<?php
drupal_add_js(
"
$(document).ready(function(){
var src = $('.flickr_photo_0 a img').attr('src');
src = src.substring(0, src.length -6);
change_large_image(src);
});
function change_large_image(src){
var image = '<img src=\"' + src + '.jpg\">';
var large_image = document.getElementById('large_image').innerHTML = image
}",
"inline"
);
?>
<div id='large_image' style='margin-bottom: 10px; border: 1px dashed black; height: 480px; width: 320px;'>
<div style='margin: 30px;'>
<h2>large image</h2>
</div>
</div>
<?php
foreach ($rows as $id => $row): ?>
<div style="float: left; padding-right: 5px;" class="flickr_photo_<?php print $id.' '; print $classes[$id]; ?>">
<?php print $row; ?>
</div>
<?php endforeach; ?>
<div style='clear: both;'> </div>
Further steps:
I hope that this tutorial has been helpful and welcome comments or suggestions for improvement.
back to drupal tips...