Skip to content
Christian Heilmann

Posts Tagged ‘php’

  • πŸ”™ Older Entries
  • Newer Entries πŸ”œ

How I built icant.co.uk – source code

Wednesday, June 3rd, 2009

After my talk at FOWA in Cambridge yesterday I showed off that http://icant.co.uk is fully driven by YUI and YQL and maintained elsewhere. I’ve recorded a screencast about this earlier which is also available for download as a M4V but hadn’t released the code yet.

So here goes – this is the PHP source of icant.co.uk (without the HTML which is more or less done with YUI grids builder


// get all the feeds to grab the data
$feeds = array(
‘http://feeds2.feedburner.com/wait-till-i/gwZf’,
‘http://feeds.delicious.com/v2/rss/codepo8/myvideos?count=15’,
‘http://feeds.delicious.com/v2/rss/codepo8/sandbox’,
‘http://feeds.delicious.com/v2/rss/codepo8/icantarticles’,
‘http://www.slideshare.net/rss/user/cheilmann’
);

// assemble the YQL statement
$yql = ‘select meta.views,content.thumbnail,content.description,title,’.
‘link,description from rss where url in ‘;
$yql .= “(‘” . join($feeds,”’,’”) . “’)”;

// assemble the request url
$root = ‘http://query.yahooapis.com/v1/public/yql?q=’;
$url = $root . urlencode($yql) . ‘&format=json’;

// get the feeds and populate the data to echo out in the HTML
$feeds = renderFeeds($url);
$blog = $feeds[‘blog’];
$videos = $feeds[‘videos’];
$articles = $feeds[‘articles’];
$presentations = $feeds[‘slides’];

// this function loads all the feeds and turns them into HTML
function renderFeeds($url){

// grab the content from YQL via cURL
$c = getStuff($url);

// as the content comes back as JSON, turn it into PHP objects
$x = json_decode($c);

// reset counter for videos and presentations
$count = 0;
$vidcount = 0;

// start new array to return
$out = array();

// loop over YQL results, if they exist.
if($x->query->results->item){
foreach($x->query->results->item as $i){

// if the link comes from the blog, add to the blog HTML
if(strstr($i->link,’wait-till-i’)){
$out[‘blog’] .= ‘

  • link . ‘”>’ . $i->title .
    ‘

    ’ . html_entity_decode($i->description) .
    ‘

  • ‘;
    $vidcount++;
    }

    // for interviews and articles, add to the articles section
    if(strstr($i->title,’Interview’) ||
    strstr($i->title,’Article:’)){
    $out[‘articles’].= ‘

  • link . ‘”>’ . $i->title .
    ‘

    YQL doesn’t send a diagnostics part

    // grab the books from my blog
    $yql = ‘select * from html where url=’.
    ‘”http://wait-till-i.com/books/”’.
    ’ and xpath=”//div[@class=’entry’]”’;
    $books = renderHTML($root.urlencode($yql).’&format=xml&diagnostics=false’);

    // this is a quick and dirty solution for the HTML output
    function renderHTML($url){
    // pull the information from YQL
    $c = getStuff($url);
    // check that something came back
    if(strstr($c,’<’)){
    // remove all the XML parts
    $c = preg_replace(“/.*|.*/”,’‘,$c);
    $c = preg_replace(“/ ” encoding=”UTF-8”?>/”,’‘,$c);
    // remove all comments
    $c = preg_replace(“//”,’‘,$c);
    }

    // send it back
    return $c;
    }

    // a simple cURL function to get information
    function getstuff($url){
    $curl_handle = curl_init();
    curl_setopt($curl_handle, CURLOPT_URL, $url);
    curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
    curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
    $buffer = curl_exec($curl_handle);
    curl_close($curl_handle);
    if (empty($buffer)){
    return ‘Error retrieving data, please try later.’;
    } else {
    return $buffer;
    }

    }

  • Tags: cambridge, fowa, howto, php, yql, YUI
    Posted in General | 2 Comments »

    Newsmap – using Placemaker to add geo location to a news feed

    Friday, May 22nd, 2009

    I am right now very excited about the new Placemaker beta – a location extraction web service released at Where2.0. Using Placemaker you can find all the geographical locations in a feed or a text or a web url and you get them back as an array of places.

    As a demo I took the Yahoo News feed and ran it through Placemaker. The resulting places are plotted on a map and the map moves from location to location when you hover over the news items.

    The result is online at http://isithackday.com/hacks/placemaker/map.php

    Yahoo News Map by  you.

    Getting the data from the data feed and running it through placemaker is very straight forward. I explained the basic principle in this blog post on the Yahoo Developer Network blog. The only thing to think about is to define the input and output types correctly:


    $key = ‘PASTE YOUR API KEY HERE’;
    $apiendpoint = ‘http://wherein.yahooapis.com/v1/document’;
    $url = ‘http://rss.news.yahoo.com/rss/topstories’;
    $inputType = ‘text/rss’;
    $outputType = ‘rss’;
    $post = ‘appid=’.$key.’&documentURL=’.$url.
    ‘&documentType=’.$inputType.’&outputType=’.$outputType;
    $ch = curl_init($apiendpoint);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $results = curl_exec($ch);
    ?>

    If you look at the source of this example you will find that Placemaker injected contentlocation elements in the feed itself:


    xmlns:georss=”http://www.georss.org/georss” xmlns:cl=”http://wherein.yahooapis.com/v1/cle”
    xmlns:xml=”http://www.w3.org/XML/1998/namespace” xml:lang=”en”>

    2514815

    38.8913
    -77.0337


    23424793

    21.511
    -77.8068


    23424977

    48.8907
    -116.982


    55843872
    Guantanamo, CU]]>
    19.9445
    -75.1541


    You’ll also notice that the elements are namespaced and the names of the locations in CDATA blocks, both things I hate with a passion. Not because they don’t make sense, but because simplexml can be drag to make understand them.

    What I wanted to do with this data was twofold: create a JSON array of geo locations to plot on a map and a display of the news content. This is the PHP that does that:


    $places = simplexml_load_string($results, ‘SimpleXMLElement’,
    LIBXML_NOCDATA);
    // if there are elements found
    if($places->channel->item){
    // start a JSON array
    $output .= ‘[‘;
    // start the HTML output
    $html = ‘
      ‘;
      // set the counter – this will be needed to link news
      // items and map markers
      $count = 0;
      // loop over RSS items
      foreach($places->channel->item as $p){
      // set inner counter (as there are more locations per news item)
      $innercount = 0;
      // start the HTML list item and give it an ID with the counter
      // value
      $html .= ‘
    • // all child elements with the defined namespace
      $locs = $p->children(‘http://wherein.yahooapis.com/v1/cle’);
      // check that there is a location sub-element in this item
      if($locs->contentlocation){
      // if there is one, add a class to the LI
      $html .= ’ class=”haslocation”’;
      // start an array for displaying of the locations under the
      // news items
      $dlocs = array();
      // loop over all the places found for this item
      foreach($locs->contentlocation->place as $pl){
      // append a new JS object with the location data
      // and a unique ID to the locations array
      $locations[] = ‘{name.’”,”title” title=”“>name“:”’.
      preg_replace(‘/n+/’,’‘,addslashes($p->title)).
      ‘”,latitude” title=”“>lat.
      ‘”,longitude.’”,”id”:”m” title=”“>lon‘.
      $count.’x’.$innercount.’”}’;
      // add the location name to the display locations array
      $dlocs[] = $pl->name;
      // increase the inner count to ensure that every marker has
      // a unique ID
      $innercount++;
      }

      }
      // append the HTML for the news item
      $html.=’>

      Locations: ‘.join(‘,’,$dlocs).’

      ‘;
      }

      // end the list item
      $html.=’

    • ‘;
      // increase the counter
      $count++;
      }

      // join the json object data with a comma and close the JSON array
      $output .= join(‘,’,$locations);
      $output .= ‘]’;
      // if there are no items simply return nothing
      } else {
      $output = ‘’;
      }

      // and this ends the HTML
      $html.= ‘

    ‘;
    ?>

    The result of this can be seen here http://isithackday.com/hacks/placemaker/map-2.php.

    The JavaScript to show the map is pretty straight forward and more or less the demo example of the maps API:


    // will be called with the array assembled in PHP
    function placeonmap(o){
    // if there are locations
    if(o.length > 0){
    // create a new geopoints array to hold all locations
    // this is needed to determine the original zoom
    // level of the map
    var geopoints = [];
    // add map with controls
    var map = new YMap(document.getElementById(‘map’));
    map.addZoomLong();
    map.addPanControl();
    // loop over locations
    for(var i=0;i // define a new geopoint and store it in the array
    var point = new YGeoPoint(o[i].lat,o[i].lon);
    geopoints.push(point);
    // create a new marker and give it the unique
    // id defined in the PHP. Pop up the title of
    // the news item and the name of the location when the
    // user hovers over the marker
    var newMarker = new YMarker(point,o[i].id);
    newMarker.addAutoExpand(o[i].title + ‘(‘+o[i].name+’)’);
    map.addOverlay(newMarker);
    }

    // define best zoom level and show map
    var zac = map.getBestZoomAndCenter(geopoints);
    map.drawZoomAndCenter(zac.YGeoPoint,zac.zoomLevel);
    }

    // add a mouseover handler to the list of results
    YAHOO.util.Event.on(‘news’,’mouseover’,function(e){
    // remove the “news” text of the ID of the current target
    // as we named the list items news0 to news19
    var id = YAHOO.util.Event.getTarget(e).id.replace(‘news’,’‘);
    // if there is still something left we have one of the news
    // items
    if(id!==’‘){
    // get the first marker with the ID we defined in the loop.
    var marker = map.getMarkerObject(‘m’+id+’x0’);
    // if there is one, pan the map there and show the message
    // attached to it.
    if(marker){
    map.panToLatLon(marker.YGeoPoint);
    marker.openAutoExpand();
    }

    }
    });
    }

    // call placeonmap with the JSON array
    placeonmap();

    That’s pretty much it. I am sure it can be refined, but it is amazing how easy it is to get geo information into any text with Placemaker.

    Tags: hack, javascript, maps, mashup, php, placemaker
    Posted in General | 1 Comment »

    Is it getting harder and harder to show very easy examples?

    Tuesday, April 7th, 2009

    I am right now teaching a four day class of DOM and Ajax in Sunnyvale, California and also do some tech editing for Scriptin with JavaScript and Ajax by Charles Wyke-Smith and I find one thing that is pretty worrying: easy examples of web development practices are dangerous to show these days.

    I’m talking about practices that make it easy to get quick results and give readers and attendees “I am getting this – this is easy” fuzzy warm feelings.

    One very obvious example is form validation and re-rendering of a form using PHP_SELF and displaying user data using $_GET or $_POST. Unfiltered they are a free invitation for any XSS attack and will turn your server into a spam-hub or bot-net drone. Explaining countermeasures of XSS normally is out of scope for an example that only shows how a form would work that you enhance progressively.

    The same applies to simply outdated ideas like onevent handlers. It is easy to show an example that uses a few onclick handlers, but explaining event handling really well takes a bit of time. Again, this is something that really does not fit in the scope of a DOM course.

    I do however think that it is important to get it in there, as there is no such thing as knowing one technology in the web development stack and being able to use it. There’s a lot of overlap with other areas and in order to be a good developer and play well with others you need to be aware of your effects and areas of overlap with your colleagues’ skill-sets.

    The other extreme I find myself doing is being too over-cautious. I went through the tough times of the first browser wars and got a deep-rooted mistrust towards anything some browser tells me is OK to do and use. However, I get the feeling that it doesn’t really matter any more if Internet Explorer has a problem with name vs. ID or whatever other shenanigans we have to be aware of when we build things from scratch.

    I do get the distinct feeling that not building on top of a good client-side library is simply a waste of time these days. Libraries allow us to write code, not to work around bugs and wonder what other safety measure we have to put in.

    That’s why I started asking people in my courses to use Firefox with Firebug and use a good text editor to code along. Today I managed to breeze through how to write HTML that is ready for internationalisation and works with assistive technology, over simple DOM access to the document and at the end writing a validation script for a form using generated DOM content. By concentrating on how things are meant to work instead of debugging random issues I managed to get the students to reach far into the matter in a day – even those who never touched JavaScript before.

    Maybe it is time to get beginners accustomed to a market that builds on working solutions and benefits from browser abstraction via libraries than teaching developing from total scratch – bad browsers and bad people taking advantage of any technology to gain access or spam us seem to have made this way of working redundant.

    Tags: examples, javascript, php, security, teaching, training, xss
    Posted in General | 5 Comments »

    TTMMHTM: Guardian getting enabled by design,interview,open hack day,bash magic,and XSS filters

    Wednesday, March 18th, 2009

    Things that made me happy this morning:

    • Denise Stephens, keynoter extraordinaire from Scripting Enabled is featured in the Guardian
    • SlideShare released the slideshare mobile version using Yahoo BluePrint – this was a hack on Open Hack Day Bangalore
    • The JavaScript Workshop released an interview with me
    • Open Hack Day is coming back to London! Sign up now
    • If you want to use the command line more, here’s a good list of most useful unix commands
    • Finally a nice introduction to PHP and cURL
    • The folks at flickr are doing strange and mental things again: fast client side search explained
    • If you ever wondered how addons.mozilla.org battles XSS attacks, here’s how

    Tags: accessibility, bash, curl, hackday, php, security
    Posted in General | Comments Off on TTMMHTM: Guardian getting enabled by design,interview,open hack day,bash magic,and XSS filters

    Building a hack using YQL, Flickr and the web – step by step

    Wednesday, March 11th, 2009

    As you probably know, I am spending a lot of time speaking and mentoring at hack days for Yahoo. I go to open hack days, university hack days and even organized my own hackday revolving around accessibility last year.

    One of the main questions I get is about technologies to use. People are happy to find content on the web, but getting it and mixing it with other sources is still a bit of an enigma.

    Following I will go through a hack I prepared at the Georgia Tech University hack day. I am using PHP to retrieve information of the web, YQL to filter it to what I need and YUI to do the CSS layout and add extra functionality.

    The main ingredient of a good hack – the idea

    I give a lot of presentations and every time I do people ask me where I get the pictures I use from. The answer is Flickr and some other resources on the internet. The next question is how much time I spend finding them and that made me think about building a small tool to make this easier for me.

    This is how Slidefodder started and following is a screenshot of the hack in action. If you want to play with it, you can download the Slidefodder source code.

    Slide Fodder - find CC licensed photos and funpics for your slides

    Step 1: retrieving the data

    The next thing I could have done is deep-dive into the Flick API to get photos that I am allowed to use. Instead I am happy to say that using YQL gives you a wonderful shortcut to do this without brooding over documentation for hours on end.

    Using YQL I can get photos from flickr with the right license and easily display them. The YQL statement to search photos with the correct license is the following:


    select id from flickr.photos.search(10) where text=’donkey’ and license=4

    Retrieving CC licensed photos from flickr in YQL

    You can try the flickr YQL query here and you’ll see that the result (once you’ve chosen JSON as the output format) is a JSON object with photo results:


    {

    “query”: {
    “count”: “10”,
    “created”: “2009-03-11T01:23:00Z”,
    “lang”: “en-US”,
    “updated”: “2009-03-11T01:23:00Z”,
    “uri”: “http://query.yahooapis.com/v1/yql?q=select+*+from+flickr.photos.search%2810%29+where+text%3D%27donkey%27+and+license%3D4”,
    “diagnostics”: {
    “publiclyCallable”: “true”,
    “url”: {
    “execution-time”: “375”,
    “content”: “http://api.flickr.com/services/rest/?method=flickr.photos.search&text=donkey&license=4&page=1&per_page=10”
    },
    “user-time”: “376”,
    “service-time”: “375”,
    “build-version”: “911”
    },
    “results”: {
    “photo”: [
    {

    “farm”: “4”,
    “id”: “3324618478”,
    “isfamily”: “0”,
    “isfriend”: “0”,
    “ispublic”: “1”,
    “owner”: “25596604@N04”,
    “secret”: “20babbca36”,
    “server”: “3601”,
    “title”: “donkey image”
    }

    [...]
    ]

    }
    }

    }

    The problem with this is that the user name is not provided anywhere, just their Flickr ID. As I wanted to get the user name, too, I needed to nest a YQL query for that:

    select farm,id,secret,server,owner.username,owner.nsid from flickr.photos.info where photo_id in (select id from flickr.photos.search(10) where text='donkey' and license=4)
    

    This gives me only the information I really need (try the nested flickr query here):


    {

    “query”: {
    “count”: “10”,
    “created”: “2009-03-11T01:24:45Z”,
    “lang”: “en-US”,
    “updated”: “2009-03-11T01:24:45Z”,
    “uri”: “http://query.yahooapis.com/v1/yql?q=select+farm%2Cid%2Csecret%2Cserver%2Cowner.username%2Cowner.nsid+from+flickr.photos.info+where+photo_id+in+%28select+id+from+flickr.photos.search%2810%29+where+text%3D%27donkey%27+and+license%3D4%29”,
    “diagnostics”: {
    “publiclyCallable”: “true”,
    “url”: [
    {

    “execution-time”: “394”,
    “content”: “http://api.flickr.com/services/rest/?method=flickr.photos.search&text=donkey&license=4&page=1&per_page=10”
    },
    [...]
    ],
    “user-time”: “1245”,
    “service-time”: “4072”,
    “build-version”: “911”
    },
    “results”: {
    “photo”: [
    {

    “farm”: “4”,
    “id”: “3344117208”,
    “secret”: “a583f1bb04”,
    “server”: “3355”,
    “owner”: {
    “nsid”: “64749744@N00”,
    “username”: “babasteve”
    }

    }
    [...]
    }

    ]
    }

    }
    }

    The next step was getting the data from the other resources I am normally tapping into: Fail blog and I can has cheezburger. As neither of them have an API I need to scrape the HTML data of the page. Luckily this is also possible with YQL, all you need to do is select the data from html and give it an XPATH. I found the XPATH by analysing the page source in Firebug:

    Using Firebug to find the right xpath to an image

    This gave me the following YQL statement to get images from both blogs. You can list several sources as an array inside the in() statement:


    select src from html where url in (‘http://icanhascheezburger.com/?s=donkey’,’http://failblog.org/?s=donkey’) and xpath=”//div[@class=’entry’]/div/div/p/img”

    Retrieving blog images using YQL

    The result of this query is again a JSON object with the src values of photos matching this search:


    {

    “query”: {
    “count”: “4”,
    “created”: “2009-03-11T01:28:35Z”,
    “lang”: “en-US”,
    “updated”: “2009-03-11T01:28:35Z”,
    “uri”: “http://query.yahooapis.com/v1/yql?q=select+src+from+html+where+url+in+%28%27http%3A%2F%2Ficanhascheezburger.com%2F%3Fs%3Ddonkey%27%2C%27http%3A%2F%2Ffailblog.org%2F%3Fs%3Ddonkey%27%29+and+xpath%3D%22%2F%2Fdiv%5B%40class%3D%27entry%27%5D%2Fdiv%2Fdiv%2Fp%2Fimg%22”,
    “diagnostics”: {
    “publiclyCallable”: “true”,
    “url”: [
    {

    “execution-time”: “1188”,
    “content”: “http://failblog.org/?s=donkey”
    },
    {

    “execution-time”: “1933”,
    “content”: “http://icanhascheezburger.com/?s=donkey”
    }

    ],
    “user-time”: “1939”,
    “service-time”: “3121”,
    “build-version”: “911”
    },
    “results”: {
    “img”: [
    {

    “src”: “http://icanhascheezburger.files.wordpress.com/2008/09/funny-pictures-you-are-making-a-care-package-very-correctly.jpg”
    },
    {

    “src”: “http://icanhascheezburger.files.wordpress.com/2008/01/funny-pictures-zebra-donkey-family.jpg”
    },
    {

    “src”: “http://failblog.files.wordpress.com/2008/11/fail-owned-donkey-head-intimidation-fail.jpg”
    },
    {

    “src”: “http://failblog.files.wordpress.com/2008/03/donkey.jpg”
    }

    ]
    }

    }
    }

    Writing the data retrieval API

    The next thing I wanted to do was writing a small script to get the data and give it back to me as HTML. I could have used the JSON output in JavaScript directly but wanted to be independent of scripting. The script (or API if you will) takes a search term, filters it and executes both of the YQL statements above before returning a list of HTML items with photos in them. You can try it out for yourself: search for the term donkey or search for the term donkey and give it back as a JavaScript call

    I use cURL to get the data as my server has external pulling of data via PHP disabled. This should work for most servers, actually.

    Here’s the full “API” code:

    
    ';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $flickurl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);
    $flickrphotos = json_decode($output);
    foreach($flickrphotos->query->results->photo as $a){
    $o = $a->owner;
    $out.= '
  • '. ''; $href = 'http://www.flickr.com/photos/'.$o->nsid.'/'.$a->id; $out.= ''.$href.' - '.$o->username.'
  • '; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $failurl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); curl_close($ch); $failphotos = json_decode($output); foreach($failphotos->query->results->img as $a){ $out.= '
  • '; if(strpos($a->src,'failblog') = 7){ $out.= ''; } else { $out.= ''; } $out.= ''.$a->alt.'
  • '; } $out.= ''; if($_GET['js']=’yes’){ $out.= ‘’})’; } echo $out; } else { echo ($_GET[‘js’]!==’yes’) ? ‘

    Invalid search term.

    ’ : ‘seed({html:”Invalid search Term!”})’; } } ?>

    Let’s go through it step by step:


    if($_GET[‘js’]===’yes’){
    header(‘Content-type:text/javascript’);
    $out = ‘seed({html:’‘;
    }

    I test if the js parameter is set and if it is I send a JavaScript header and start the JS object output.


    if(isset($_GET[’s’])){
    $s = $_GET[’s’];
    if(preg_match(“/^[0-9|a-z|A-Z|-| |+|.|_]+$/”,$s)){

    I get the search term and filter out invalid terms.

    
    $flickurl = 'http://query.yahooapis.com/v1/public/yql?q=select'.
    '%20farm%2Cid%2Csecret%2Cserver%2Cowner.username'.
    '%2Cowner.nsid%20from%20flickr.photos.info%20where%20'.
    'photo_id%20in%20(select%20id%20from%20'.
    'flickr.photos.search(10)%20where%20text%3D''.
    $s.''%20and%20license%3D4)&format=json';
    $failurl = 'http://query.yahooapis.com/v1/public/yql?q=select'.
    '%20*%20from%20html%20where%20url%20in'.
    '%20('http%3A%2F%2Ficanhascheezburger.com'.
    '%2F%3Fs%3D'.$s.''%2C'http%3A%2F%2Ffailblog.org'.
    '%2F%3Fs%3D'.$s.'')%20and%20xpath%3D%22%2F%2Fdiv'.
    '%5B%40class%3D'entry'%5D%2Fdiv%2Fdiv%2Fp%2Fimg%22%0A&'.
    'format=json';
    

    These are the YQL queries, you get them by clicking the “copy url” button in YQL.


    $out.= ‘
      ‘;

    I then start the output list of the results.


    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $flickurl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);
    $flickrphotos = json_decode($output);
    foreach($flickrphotos->query->results->photo as $a){
    $o = $a->owner;
    $out.= ‘
  • ‘.
    ‘‘.$href.’ – ‘.$o->username.’
  • ‘;
    }

    I call cURL to retrieve the data from the flickr yql query, do a json_decode and loop over the results. Notice the rather annoying way of having to assemble the flickr url and image source. I found this by clicking around flickr and checking the src attribute of images rendered on the page. The images with the “ico” class should tell me where the photo was from.


    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $failurl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);
    $failphotos = json_decode($output);
    foreach($failphotos->query->results->img as $a){
    $out.= ‘
  • ‘;
    if(strpos($a->src,’failblog’) = 7){
    $out.= '';
    } else {
    $out.= '';
    }

    $out.= ''.$a->alt.'

  • ';
    }

    Retrieving the blog data works the same way, all I had to do extra was check for which blog the resulting image came from.


    $out.= ‘‘;
    if($_GET[‘js’]=’yes’){
    $out.= ‘’})’;
    }

    echo $out;

    I close the list and – if JavaScript was desired – the JavaScript object and function call.


    } else {
    echo ($_GET[‘js’]!==’yes’) ?
    ‘

    Invalid search term.

    ’ :
    ‘seed({html:”Invalid search Term!”})’;
    }

    }
    ?>

    If there was an invalid term entered I return an error message.

    Setting up the display

    Next I went to the YUI grids builder and created a shell for my hack. Using the generated code, I added a form, my yql api, an extra stylesheet for some colouring and two IDs for easy access for my JavaScript:


    HTML PUBLIC “-//W3C//DTD HTML 4.01//EN”
    “http://www.w3.org/TR/html4/strict.dtd”>


    Slide Fodder – find CC licensed photos and funpics for your slides





    Slide Fodder


















    Slide Fodder by Christian Heilmann, hacked live at Georgia Tech University Hack day using YUI and YQL.

    Photo sources: Flickr, Failblog and I can has cheezburger.






    Rounding up the hack with a basket

    The last thing I wanted to add was a “basket” functionality which would allow me to do several searches and then copy and paste all the photos in one go once I am happy with the result. For this I’d either have to do a persistent storage somewhere (DB or cookies) or use JavaScript. I opted for the latter.

    The JavaScript uses YUI and is no rocket science whatsoever:


    function seed(o){
    YAHOO.util.Dom.get(‘content’).innerHTML = o.html;
    }

    YAHOO.util.Event.on(‘f’,’submit’,function(e){
    var s = document.createElement(‘script’);
    s.src = ‘yql.php?js=yes&s=’+ YAHOO.util.Dom.get(’s’).value;
    document.getElementsByTagName(‘head’)[0].appendChild(s);
    YAHOO.util.Dom.get(‘content’).innerHTML = ‘‘;

    YAHOO.util.Event.preventDefault(e);
    });

    YAHOO.util.Event.on(‘content’,’click’,function(e){
    var t = YAHOO.util.Event.getTarget(e);
    if(t.nodeName.toLowerCase()===’img’){
    var str = ‘

    ‘;
    if(t.src.indexOf(‘flickr’)!==-1){
    str+= ‘

    ‘+t.parentNode.getElementsByTagName(‘a’)[0].innerHTML+’

    ‘;
    }

    str+=’x

    ‘;
    YAHOO.util.Dom.get(‘basket’).innerHTML+=str;
    }

    YAHOO.util.Event.preventDefault(e);
    });
    YAHOO.util.Event.on(‘basket’,’click’,function(e){
    var t = YAHOO.util.Event.getTarget(e);
    if(t.nodeName.toLowerCase()===’a’){
    t.parentNode.parentNode.removeChild(t.parentNode);
    }

    YAHOO.util.Event.preventDefault(e);
    });

    Again, let’s check it bit by bit:


    function seed(o){
    YAHOO.util.Dom.get(‘content’).innerHTML = o.html;
    }

    This is the method called by the “API” when JavaScript was desired as the output format. All it does is change the HTML content of the DIV with the id “content” to the one returned by the “API”.


    YAHOO.util.Event.on(‘f’,’submit’,function(e){
    var s = document.createElement(‘script’);
    s.src = ‘yql.php?js=yes&s=’+ YAHOO.util.Dom.get(’s’).value;
    document.getElementsByTagName(‘head’)[0].appendChild(s);
    YAHOO.util.Dom.get(‘content’).innerHTML = ‘ ‘src=”http://tweeteffect.com/ajax-loader.gif”’+
    ‘style=”display:block;margin:2em auto”>‘;
    YAHOO.util.Event.preventDefault(e);
    });

    When the form (the element with th ID “f”) is submitted, I create a new script element,give it the right src attribute pointing to the API and getting the search term and append it to the head of the document. I add a loading image to the content section and stop the browser from submitting the form.


    YAHOO.util.Event.on(‘content’,’click’,function(e){
    var t = YAHOO.util.Event.getTarget(e);
    if(t.nodeName.toLowerCase()===’img’){
    var str = ‘
    ‘;
    if(t.src.indexOf(‘flickr’)!==-1){
    str+= ‘

    ‘+t.parentNode.getElementsByTagName(‘a’)[0].innerHTML+’

    ‘;
    }

    str+=’x

    ‘;
    YAHOO.util.Dom.get(‘basket’).innerHTML+=str;
    }

    YAHOO.util.Event.preventDefault(e);
    });

    I am using Event Delegation to check when a user has clicked on an image in the content section and create a new DIV with the image to add to the basket. When the image was from flickr (I am checking the src attribute) I also add the url of the image source and the user name to use in my slides later on. I add an “x” link to remove the image from the basket and again stop the browser from doing its default behaviour.


    YAHOO.util.Event.on(‘basket’,’click’,function(e){
    var t = YAHOO.util.Event.getTarget(e);
    if(t.nodeName.toLowerCase()===’a’){
    t.parentNode.parentNode.removeChild(t.parentNode);
    }

    YAHOO.util.Event.preventDefault(e);
    });

    In the basket I remove the DIV when the user clicks on the “x” link.

    That’s it

    This concludes the hack. It works, it helps me get photo material faster and it took me about half an hour to build all in all. Yes, it could be improved in terms of accessibility, but this is enough for me and my idea was to show how to quickly use YQL and YUI with a few lines of PHP to deliver something that does a job :)

    Tags: flickr, hack, HTML, javascript, php, scraping, yql
    Posted in General | 5 Comments »

    • < Older Entries
    • Newer Entries >
    Skip to search
    • Christian Heilmann Avatar
    • About this
    • Archives
    • Codepo8 on GitHub
    • Chris Heilmann on BlueSky
    • Chris Heilmann on Mastodon
    • Chris Heilmann on YouTube
    Christian Heilmann is the blog of Christian Heilmann chris@christianheilmann.com (Please do not contact me about guest posts, I don't do those!) a Principal Program Manager living and working in Berlin, Germany.

    Theme by Chris Heilmann. SVG Icons by Dan Klammer . Hosted by MediaTemple. Powered by Coffee and Spotify Radio.

    Get the feed, all the cool kids use RSS!