Christian Heilmann

Posts Tagged ‘hack’

Pitching a hack (or a product) do’s and dont’s

Saturday, May 16th, 2009

Disclaimer: Dearie me, some of this is very subjective and may completely disagree with what worked for you. This is great and please leave a comment about what worked and what tips you can give rather than shooting one of the points here down in flames. I simply listed what I was looking for and what worked well for me in the past.

We just came back from the University hack day in Sunderland, England where students pitched hacks they built in a few weeks to judges that were meant as mock clients. As students asked us for feedback on what went well in the presentations and what didn’t here are some tips and tricks.

Pitches are not sex – you don’t need foreplay

The first mistake almost every group made was to introduce who they are and what they used to make the hack. This was partly a requirement of the assessment but it is also a sure-fire way to bore judges or VCs. There are two ways you can go:

  • Show your hack and what it does and then go into the details or
  • Explain the one problem that your hack solves and show the hack immediately afterwards as the solution.

Either approach has to answer some questions right off the bat:

  • What does the hack do?
  • Why should I use it?
  • Who is it for?
  • What does it do better/different than other solutions?

On being a team

The hack teams were 6-7 people each. Introducing each and every one of them costs a lot of precious time that you cannot use to make the audience interested in your product. Introduce only the needed people – those who will give the pitch and tell after the presentation who else did what in case there are specialist questions that need answering.

Anybody who is not part of the immediate pitch should not be standing around – all they do is distract from the presentation. Absolute suicide is to have people standing on the side scratching various body parts or looking at the ceiling or out of the window. If you pitch as a team, everybody should be awake and damn excited about the product – else you’re doing a better job sitting on the bench.

Your main spokesperson should be the most excited about the product. There were a few presentation wheres the first pitcher was amazing and had us going and when handing over to the tech guy to explain the product snoozing kicked in. If you hand over from presenter to presenter keep the energy flowing, otherwise don’t hand over.

If you have different experts delivering different parts of the pitch have them introduce each other and have their expertise be a natural part of the flow of the presentation. Some teams did a great job at that, with simple sentences like “in the future this will be extended to become important for more audiences and my colleague XY will show you what we have planned on the business side of things.”

On running your presentation

You are the presenter which means that you define the pace of the presentation and which slides are shown. You cannot have somebody else as your slide-jockey – it is terribly unprofessional to have to tell somebody to change the slide or even worse go back some slides. Presenter remotes are not expensive and most places will have some for installed equipment so use these instead. Your focus as the presenter is on the audience or jury and eye-contact is terribly important.

This applies to longer presentations, too. You can find out a lot from the audience reactions. When I present to a big crowd, one trick is to pick out a new single person in the audience I talk directly to every few slides. This is especially good to do if you pick people that seem to drift away and ask yourself what is the “what is in it for me” for that person.

Slides are an aid – not your pitch

One of the rookie mistakes is to have slides that tell and spell out everything you want to say. Less is more – much more. One word could be enough if it is backed up by your presentation. You can and should have a handout that explains details but this should not be your slide deck. Screenshots are good in case the wireless forsakes you – which it always does. Random clipart is bad as the 80ies are definitely over. Humour works – I loved for example typical English self-deprecation when one of the presentations introduced students as a target audience with a student wearing a traffic-cone hat as the example photo.

See your slides as the table of contents of your presentation – not the transcript and definitely not a different story. When your talk deviates from what is written on the wall you’ve lost us.

Bullet points are effective but also have become almost a cliche for presentations. If you feel comfortable with them, by all means use them but never have more than 3-5 on a slide with one short sentence for each.

You learn presentation writing by looking at successful presentation decks. A great resource is SlideShare where people upload their decks and the comments and views show you which ones are successful. My own slides there are all licensed with Creative Commons, which means that I am happy for you to re-use them.

Basic, really very basic typography

This applies to both the slides and the product itself. Legibility and professional type layout is very important. This is not because we are anal about this (and believe me there are a lot of people on the web that are) but there is a subconscious unease when we read things as humans and get lost because there is something not right with it.

Comic Sans Serif was lately added to the Geneva convention as a forbidden weapon when dealing with audiences that are above 3 years of age or don’t suffer from learning disabilities (this is not an evil jib – Comic Sans really proved to be very effective for these groups). Other than that pick a friendly, easy to read font that shows you mean business.

Bullet points should never be center aligned on the screen, unless they are a centered block.

Basic Bullet point etiquette

Use a large enough font size and good contrast of background and foreground to keep your slides and products readable even on a terrible projector. Don’t rely on colours to be shown the way you expect them to be.

On web applications, nothing spells “we are unprofessional” more than not defining a font for your text. Out of the box browsers render in Times New Roman, so you just look sloppy if you don’t change that.

If you have no clue about HTML and CSS and you don’t want to bother with it but show something that is readable and works across all browsers, use the YUI grids in your document:


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



My awesome App







I rock! I really do






This adds a very basic level of typography for free and with the CSS hosted (and, if needed, fixed) by Yahoo for you.

Explain the unique – not the very obvious

What you want to achieve with a pitch is to get us excited and interested about what you did. The only real way to do that is to tell us what your system does differently than others – “what is it that makes it unique?” is the question you need to answer.

Get the one thing that makes your product great and shine the world’s biggest light on it.

Do not tell us that you have a delete, update and edit button. Do under no circumstances show us what happens when you click the delete button and – oh wonder of wonders – it deletes something. Then please do not continue to tell and show us the other – as predictable – functionality. Do tell us when one of these functionalities deviate from the normal patterns and do a better job though.

Do not tell us what colours you used in the background, we can see that and the colour is a means to an end, not the main reason to build the hack. Time is precious, do not waste it on things that we can find out for ourselves.

Cover the big concerns

Two things drive people nuts on the web: lacking security and hard to use products. If you ask for data show that you protect that data (some teams did a great job doing that, thanks). If you claim your interface is easy to use, don’t get lost trying to show it and under no circumstance tell other people who show the product for you what to do. “No, click the other button, no the other above this one” does not spell “millions of users will have a great time using this”.

People get annoyed very quickly if things take too long on the web. We use computers and online systems to make our lives easier, not to wait for your system or go through a five step process that could be one. Some teams did a great job with this. Sentences like “you don’t need to sign up, only when you want extra functionality explained here” are a real winner!

Tell the human story

What you build is there for humans. It is great if it makes their lives easier, it is good when it allows them to learn something and it is even OK when it just amuses them for a short while. Don’t get stuck with the technology but find the human aspect of your product instead.

Tell the story of the mother who hasn’t got enough time to juggle the day to day caring for her kids and the hard to use school enrollment and booking system. Tell the story that you got lost and tried hard to find the nearest bus stop and would have loved to get your mobile out and find it. Tell the story that you were not able to enjoy a party as you had no clue when the last train ran so you couldn’t relax as you didn’t want to get marooned there.

Computers are bastards

Things will go wrong in your presentation and you should swiftly deal with that and move on. Most presenters did that. Immediately say what happens normally and move on to the next integral part that works. Even better is when your product shows a great, well worded and easy to understand error message. Failure is as normal as success in software – both cases need a good user interface and not leave the user puzzled what is going on.

Do not try to gloss over

If you get caught out not having thought of something – own up and thank people for the great suggestions. Do not try to skirt around the issue and say that this is in there but you can’t show it now or something like that. Do not make something look as if it is more than it is – with web products it is far too easy to catch you out. Explain why things got omitted and there is no problem with that.

Don’t pad, build one thing well and sell this one

One thing that goes down terribly bad is adding gadgets gizmos and features to make a product look cooler. If a map display does not really aid the main task you try to make people achieve – don’t add it. News show that the site is up to date but can also distract from the real reason the site is there. Photos are fun but are they really needed for a time table application? Don’t think about what can be added but what can be removed. If you can’t remove any more and still make it easy to do what people come for to do you have a winner.

In summary

These are the main problems we found. Overall we had a great time and we were very impressed with both the presentations and the products. I remembered my own school time and I know how scared the presenters must have been. In that regard I have to say great job, guys.

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



























    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 :)

    Searching Flickr photos by license and text and returning defined sizes made easy with YQL

    Saturday, February 14th, 2009

    We (Nagesh Susarla and moi) are just sitting here at Open Hack Day in Bangalore, India and geek out on YQL trying to find how far we can push it to make the life of a hacker easier.

    One of the things was using Flickr photos and making sure we can only get photos of a certain license for a certain text. Here’s the magic we YQL statement we came up with:

    select * from flickr.photos.sizes where photo_id in (select id from flickr.photos.search(20,20) where text=@text and license=@license)  and label=@label

    The (20,20) means “get me 20 photos starting at the 20th” and to make it easier say we do the first 50 results instead. The @parameter are placeholders which will be replaced by URL parameters.

    As a URL you can use this and send the right parameters, for example find cats with an attribution license and only square photos (75×75pixels):

    http://query.yahooapis.com/v1/public/yql?q=select%20*%20from flickr.photos.sizes%20where%20photo_id%20in%20(select%20id%20from%20flickr.photos.search(50)%20where%20text%3D%40text%20and%20license%3D%40license)%20and%20label%3D%40label&format=xml&text=cats&license=4&label=Square

    Possible licenses are:

    1 Attribution-NonCommercial-ShareAlike License
    2 Attribution-NonCommercial License
    3 Attribution-NonCommercial-NoDerivs License
    4 Attribution License
    5 Attribution-ShareAlike License
    6 Attribution-NoDerivs License
    7 No known copyright restrictions

    Possible labels are Square,Thumbnail,Small,Medium and Original

    To make it easier, you can also wrap the whole thing in a method:

    function display(o){
    var out = ‘’;
    for(var i=0;i var cur = o.query.results.size[i];
    out+=’‘;
    }

    var d = document.createElement(‘div’);
    d.innerHTML = out;
    document.body.appendChild(d);
    }

    /*
    leechFlickr() by Christian Heilmann
    Gets an object as the parameter. Object properties:
    query (mandatory) – term to search flickr for
    amount – amount of photos (defaults to 20)
    license – 1 to 7
    label – Square,Thumbnail,Small,Medium and Original
    callback – callback function name as string

    */
    function leechFlickr(o){
    if(o.query){
    var amount = o.amount || 20;
    var license = o.license || 4;
    var url = ‘http://query.yahooapis.com/v1/public/yql?’ +
    ‘q=select%20*%20from flickr.photos.sizes’ +
    ‘%20where%20photo_id%20in%20(select’ +
    ‘%20id%20from%20flickr.photos.search(’ +
    amount + ‘)%20where%20text%3D%40text%20and’ +
    ‘%20license%3D%40license)’;
    if(o.label){
    url += ‘%20and%20label%3D%40label’;
    }

    url += ‘&format=json&callback=’ + o.callback +
    ‘&text=’ + o.query + ‘&license=’ + license;
    if(o.label){
    url += ‘&label=’ + o.label;
    }

    var s = document.createElement(‘script’);
    s.src = url;
    document.getElementsByTagName(‘head’)[0].appendChild(s);
    }

    }

    leechFlickr(
    {

    query:’cats’,
    label:’Square’,
    callback:’display’
    }

    );
    leechFlickr(
    {

    query:’parrots’,
    amount:10,
    license:3,
    label:’Square’,
    callback:’display’
    }

    );

    See the code in action and download the script.

    Does YQL rock or what? No messy user IDs, no mixing and matching all kind of API methods, just plain yummy data.

    How long is yours and how happy are you with it (twitter style)?

    Tuesday, January 13th, 2009

    One of the “useful” services of the web made the rounds on Twitter today: Twicksize allows you to show the world the size of your twick in gradient and round goodness (incidently, mine is 11 inch).

    Whilst being stunned by the usefulness of the service and the aesthetic perfection I felt a little prick of annoyance that there was no API for it. Surely showing off your twicksize to the world on your blog would be useful. Well, this can be fixed.

    Using the net tab of Firebug, it is pretty easy to detect the API driving the site and you find out that http://twicksize.com/ajax.measureme.php?twittername={user_name} gets you the HTML to show your twember in all its glory.

    Using YQL and the correct XPATH you can easily turn this into a data set to work with.

    The size is one thing, but as a lot of well-intentioned email keeps telling me it is all about how happy you are with your size. Luckily there is another service called Happy Tweets that uses science, magic and an obviously stunningly clever algorithm to determine the happiness of a twitter user. Again using Firebug we can easily determine that http://happytweets.com/TweetAnalysis.aspx?u={user_name} is the magic URL to get the data and using YQL gives us this information

    Putting both together, it is easy to write a simple script to tell the world all about the size of your twick and how happy you are with it:



    I am codepo8


    I’ve whipped it out for you here. If you want to know about your size and happiness, just use your username as the hash at http://icant.co.uk/sandbox/are-you-twick-happy.html#techcrunch, for example techcrunch or icaaq.

    The options are endless, we could for example use Google charts to create a nice image :)

    Adding transcripts to presentations embedded from SlideShare using YQL

    Sunday, January 11th, 2009

    I like SlideShare a lot (yeah, repetition, I know). It is a great way of spreading your presentations as it allows others to embed them into their blogs and web sites and it also allows people to download and re-use what you’ve done.

    One thing I really like about SlideShare is that it creates HTML transcripts of your presentation displayed far down the page as shown in the following screenshot:

    Screenshot of slideshare showing transcripts

    Now, the annoying thing is that the SlideShare API - full of goodness as it is – does not provide a way to get to these transcripts in case you want to display them alongside your presentation. You also need to authenticate for detailed information which is very needed but also bad if you just want to offer a JavaScript solution.

    Good thing that there is an easy way to retrieve information from any web site out there now and get it back as JSON to use in JavaScript: YQL. Using the YQL console and some XPATH I can for example extract the transcription information and get it back as XML (the slideshare URL is http://www.slideshare.net/cheilmann/shifting-gears-presentation and the XPATH //ol/li):


    http://query.yahooapis.com/v1/public/yql?q=select * from html where url%3D”http%3A%2F%2Fwww.slideshare.net%2Fcheilmann%2Fshifting-gears-presentation” and xpath%3D’%2F%2Fol%2Fli’&format=xml

    If you define the format as JSON and provide a callback parameter you can easily use this to write a small script to inject transcripts into SlideShare embeds:

    slideshareTranscripts = function(){
    var div = document.getElementsByTagName(‘div’);
    var containers = {};
    for(var i=0;div[i];i++){
    if(div[i].id.indexOf(‘__ss’)!==-1){
    var slideurl = div[i].getElementsByTagName(‘a’)[0].href.split(‘?’)[0];
    containers[slideurl]={c:div[i],id};
    get(slideurl);
    }

    }
    function get(url){
    var url = ‘http://query.yahooapis.com/v1/public/yql?’ +
    ‘format=json&callback=slideshareTranscripts.doit&q=’ +
    ‘select%20strong,p%20from%20html%20where%20url%3D%22’ +
    encodeURIComponent(slideurl) +
    ‘%22%20and%20xpath%3D%27%2F%2Fol%2Fli%27&’;
    var s = document.createElement(‘script’);
    s.src = url;
    s.type = ‘text/javascript’;
    document.getElementsByTagName(‘head’)[0].appendChild(s);
    }

    function doit(o){
    var url = decodeURIComponent(o.query.uri).split(‘”’);
    var out = document.createElement(‘ol’);
    var lis = o.query.results.li;
    for(var i=0,j=lis.length;i var li = document.createElement(‘li’);
    var strong = document.createElement(‘strong’);
    var p = document.createElement(‘p’);
    strong.appendChild(document.createTextNode(lis[i].strong));
    p.appendChild(document.createTextNode(lis[i].p));
    li.appendChild(strong);
    li.appendChild(p);
    out.appendChild(li);
    }

    containers[url[1]].c.appendChild(out);
    }

    return{doit:doit}
    }();

    You can see the script in action and download it for your own use. All you need to do is add it to the bottom of any document with one or several SlideShare embed codes in it. Here’s what the script does:

    slideshareTranscripts = function(){
    var div = document.getElementsByTagName(‘div’);

    We get all the DIV elements in the page (there is probably a faster way using CSSQuery these days, but let’s be bullet-proof).

    In order to find out which one of the DIVs is a SlideShare embed, we check for an ID that contains __ss as the embed codes have a generated ID starting with this.

    What we will do with each of these is to find out what the url of the slideshow is. This is needed because of two reasons: first of all we want to retrieve the transcript and secondly we need a way of matching the returned data from YQL with the right DIV container.

    As generated script nodes are not safe to load one after the other this makes sure that the right transcript gets added to the right slides.

    So, what we do is check the ID of the DIV, get the first link, retrieve the url from it, store the DIV in an object called containers and use the url as the property name. This property gets a shortcut to the correct DIV as its value. All we need to do then is to get the transcript data via get():


    var containers = {};
    for(var i=0;div[i];i++){
    if(div[i].id.indexOf(‘__ss’)!==-1){
    var slideurl = div[i].getElementsByTagName(‘a’)[0].href.split(‘?’)[0];
    containers[slideurl]={c:div[i],id};
    get(slideurl);
    }

    }

    The get() method is your garden variety script node generation function that calls the YQL API and defines slideshareTranscripts.doit() as the callback parameter. This means that the script will generate a script node, point it to YQL, YQL then gets the transcript information from SlideShare, turns it into JSON and calls doit() with the transcript information as a parameter.


    function get(url){
    var url = ‘http://query.yahooapis.com/v1/public/yql?’ +
    ‘format=json&callback=slideshareTranscripts.doit&q=’ +
    ‘select%20strong,p%20from%20html%20where%20url%3D%22’ +
    encodeURIComponent(slideurl) +
    ‘%22%20and%20xpath%3D%27%2F%2Fol%2Fli%27&’;
    var s = document.createElement(‘script’);
    s.src = url;
    s.type = ‘text/javascript’;
    document.getElementsByTagName(‘head’)[0].appendChild(s);
    }

    The job of doit() is to generate the right markup and inject it into the embed codes. We create an ordered list and loop over all the li elements. We create the fitting HTML code for each of the list items and add the content as text nodes (innerHTML would try to render markup used in the slides – not a good idea).

    We then retrieve the URL from the uri property and add the list as a new child node to the container div stored previously in the container object.

    nt
    function doit(o){
    var out = document.createElement(‘ol’);
    var lis = o.query.results.li;
    for(var i=0,j=lis.length;i var li = document.createElement(‘li’);
    var strong = document.createElement(‘strong’);
    var p = document.createElement(‘p’);
    strong.appendChild(document.createTextNode(lis[i].strong));
    p.appendChild(document.createTextNode(lis[i].p));
    li.appendChild(strong);
    li.appendChild(p);
    out.appendChild(li);
    }

    var url = decodeURIComponent(o.query.uri).split(‘”’);
    containers[url[1]].c.appendChild(out);
    }

    return{doit:doit}
    }();

    That’s it. Of course you can simplify this by matching only the OL and using innerHTML to write out the list in one go, but this solutions also allows you to alter the HTML output of the list to – for example – make every http://example.com a link.

    Happy transcribing!