Christian Heilmann

Author Archive

Is it time to take mashups and use them to solve real issues?

Monday, June 2nd, 2008

This is my presentation given at the BarCamp4 at Gcap in London, talking about my recent move to start doing more mashups again and what lead to it.

My mashup and accessibility fatigue

In a nutshell I have to say that I was getting tired of ethical hacking and mashups. Far too many people just create mashups for the sake of putting some information together or prove a technical concept but I just couldn’t see the use of what was produced. We create a lot of ideas, prototypes, proofs of concept, celebrate them as being cool and then never re-visit or turn them into projects.

I was also bored with the accessibility movement on the web. Instead of concentrating on solutions for people we ran in circles demanding technical solutions or implementation of standards that don’t make much sense in the real world. It was much more important to be compliant with something than to really deliver for the people who needed us to remove barriers for them. It is all about demanding things to be done rather than doing them. And I felt that I wasted my time trying to get something done in this surrounding.

Boost : The social innovation camp

That changed drastically when I was a judge at the Social Innovation Camp. The concept of the camp was brilliant: allow people who have real world problems to draft up an idea how modern technology like web sites and social networks could help solving or at least making these problems smaller. The entries were massive and ranged from simple things like sharing sites (rent a drill instead of buying one and let it collect dust) to personal growth/learning monitoring systems.

Boost : Enabled by design

The project that stood out the most for me was Enabled by design which is a showcase site for people with disabilities showing the world what problems they have fulfilling certain day to day tasks (say cutting food) and what tools are available to overcome these problems.

The second idea of enabled by design is that it should become a place where product designers and production companies could get information about what products are needed and then can start designing and producing those in more appealing ways. Most assistive technology and products are ugly, and they don’t have to be – actually that makes the person who just had to start to use them to fulfill tasks previously easy for them feel even worse. People get as excited about product design as we get about APIs and mashing things up – both of these great amounts of energies could be targeted to solve real-life needs of real people.

Boost – Ability 2.0 conference and accessihacking YouTube

With my mindset of giving the accessibility world a swift kick up the backside I gave my talk Fencing-in the habitat at the Accessibility2.0 conference pointing out the useless energy we waste on technical solutions built to satisfy ourselves rather than making a difference for the end user.

One of the other talks that day was Antonia Hyde talking about the issues users with learning disabilities are facing on the web, especially in regards to online video. Well, I thought to myself, as YouTube has an API, and I’ve been playing around with it already, why not have a go at an accessible YouTube player. I’ve created a prototype and sent that out to Antonia and some other accessibility contacts and the feedback was awesome.

What confused me most was that I got feedback from schools and blind people thanking me for the player and finally being able to use YouTube. I liked that a lot – realizing that I helped far more people than I thought by tackling something I hadn’t tried before – thinking in detail about the needs of people with learning disabilities!

The player is going strong and I am now writing documentation for the 2.0 version which will feature a search, playlists created by bookmarking in del.icio.us and more features like zoom.

Question: What about the future?

Am I weird (don’t answer that out of context) or is there something in there? Are there more developers out there who are stuck in a rut mashing up data without ever really making a difference with it, or do I care to go there just because I have so much exposure to this world?

I am imagining (and already started) planning an event for exactly that – social and accessible hacking of currently used internet services. We could have a hackday weekend with spokespeople from different agencies explaining the issues that people with disabilities have to use for example flickr, youtube, last FM and so on and a bunch of hackers to have a go at building alternative interfaces based on the APIs of these companies. I would also like to get people from these companies there to learn about the hacks and maybe take on some of the learnings and put them in the live systems.

The question is: would that be something you want?

[tags]mashups,accessibility,barcamp,barcamp4london,hacking,event,youtube,api[/tags]

@media2008 report live on YDN

Friday, May 30th, 2008

It is 1.14am after the first day of @media2008 and I just finished my report over on the YDN blog:

See you there tomorrow morning for day two, I am off to bed.

Providing script configuration in-line and programatically

Friday, May 23rd, 2008

One of the things I’ve been quite consistent and pushy about when writing code is to separate out all the things that should be customizable into an own configuration object.

A normal script I write these days would look like this:

var module = function(){
  // configuration, change things here
  var config = {
    CSS:{
     classes:{
       hover:'hover',
       active:'current',
       jsEnabled:'js'
     },
     ids:{
       container:'maincontainer'
     } 
    },
    timeout:2000,
    userID:'chrisheilmann'
  };
 
  // start of main code 
  function init(){
 
  };
  // ... more methods and other code ...
 
  // make init a public method
  return {
    init:init
  };
}();
module.init();

The benefits should be quite obvious:

  • Implementers don’t need to hunt through the whole script to find what they need to change
  • There’s a clear separation of “change what you need to change here” and “only touch this if you know what you are doing” – allowing more developers to use your code.
  • You show implementers in a single location where you overlap with other development layers, for example by defining IDs of HTML elements you use and CSS class names you apply to generated elements.
  • Having all the strings in one place makes for easier localisation and also speeds up the script (IE6 creates a string object for every string – even in conditions inside loops for example!)

I was quite OK with that until Ara Pehlivanian asked for an option to programatically override the configuration files, much like the YUI allows you to do with the YAHOO.util.Config utility. He is right of course, sometimes you’d want to change the config and re-initiate the script (the other way of course is to write a module with instantiation).

The easiest way to approach that is to make the config object public:

var module = function(){
  // configuration, change things here
  var config = {
    CSS:{
     classes:{
       hover:'hover',
       active:'current',
       jsEnabled:'js'
     },
     ids:{
       container:'maincontainer'
     } 
    },
    timeout:2000,
    userID:'chrisheilmann'
  };
 
  // start of main code 
  function init(){
 
  };
  // ... more methods and other code ...
 
  // make init and config a public method
  return {
    init:init,
    config:config
  };
}();

That way you can override the properties you need before you call init():

module.config.CSS.ids.container = 'header';
module.config.userID = 'alanwhite';  
module.init();

However, Ara thought it more convenient to be able to provide an object as a parameter to init() that overrides certain properties. You can do that by checking for this object, looping through its properties and recursively trying to find and match a property of the config object:

var module = function(){
  // configuration, change things here
  var config = {
    CSS:{
     classes:{
       hover:'hover',
       active:'current',
       jsEnabled:'js'
     },
     ids:{
       container:'maincontainer'
     } 
    },
    timeout:2000,
    userID:'chrisheilmann'
  };
 
  // start of main code 
  function init(){
    // check if the first argument is an object
    var a = arguments;
    if(isObj(a[ 0 ])){
      var cfg = a[ 0 ];
 
      // loop through arguments and alter the configuration
      for(var i in cfg){
        setConfig(config,i,cfg[i]);
      }
    }
  };
 
  function setConfig(o,p,v){
    // loop through all the properties of he object
    for(var i in o){
      // when the value is an object call this function recursively
      if(isObj(o[i])){
        setConfig(o[i],p,v);
 
      // otherwise compare properties and set their value accordingly
      } else {
        if(i === p){o[p] = v;};
      }
    }
  };
 
  // tests if a parameter is an object (and not an array)
  function isObj(o){
    return (typeof o === 'object' && typeof o.splice !== 'function');
  }
  // ... more methods and other code ...
  // make init a public method
  return {
    init:init
  };
}();
module.init({
  container:'header',
  'timeout':1000
});

This works swimmingly when all the configuration properties are unique. It fails though when a property in a nested object has the same name as another one on a higher level. In order to allow for this, we can offer the option to send a string with the path to the property as the property name. Then it gets messy as we need to eval() that string and make sure we return the value in the right format. All in all it could look like this:

var module = function(){
  // configuration, change things here
  var config = {
    CSS:{
     classes:{
       hover:'hover',
       active:'current',
       jsEnabled:'js'
     },
     ids:{
       container:'maincontainer'
     } 
    },
    timeout:2000,
    userID:'chrisheilmann'
  };
 
  // start of main code 
  function init(){
    if(isObj(arguments[ 0 ])){
      var cfg = arguments[ 0 ];
      for(var i in cfg){
        if(i.indexOf('.')!== -1){
          var str = '["' + i.replace(/\./g,'"]["') + '"]';
          var val = getValue(cfg[i]);
          eval('config' + str + '=' + val);
        } else {
          setConfig(config,i,cfg[i]);
        }
      }
    }
  };
  function setConfig(o,p,v){
    for(var i in o){
      if(isObj(o[i])){
        setConfig(o[i],p,v);
      } else {
        if(i === p){o[p] = v;};
      }
    }
  };
  function isObj(o){
    return (typeof o === 'object' && typeof o.splice !== 'function');
  };
  function getValue(v){
    switch(typeof v){
      case 'string':
        return "'" + v + "'";
      break;
      case 'number':
        return v;
      break;
      case 'object':
        if(typeof v.splice === 'function'){
          return '[' + v + ']';
        } else {
          return '{' + v + '}';
        }
      break;
      case NaN:
      break;
    };
  };
 
  // ... more methods and other code ...
  // make init a public method
  return {
    init:init
  };
}();
module.init({
  'container':'header',
  'CSS.classes.active':'now',
  'timeout':1000
});

In order to make that readable, let’s encapsulate all the configuration alteration code in an own module:

var module = function(){
  // configuration, change things here
  var config = {
    CSS:{
     classes:{
       hover:'hover',
       active:'current',
       jsEnabled:'js'
     },
     ids:{
       container:'maincontainer'
     } 
    },
    timeout:2000,
    userID:'chrisheilmann'
  };
 
  // start of main code 
  function init(){
    console.log(config);
  };
 
  // ... more methods and other code ...
 
  // Configuration changes 
  var changeConfig = function(){
    function set(o){
      var reg = /\./g;
      if(isObj(o)){
        for(var i in o){
          if(i.indexOf('.')!== -1){
            var str = '["' + i.replace(reg,'"]["') + '"]';
            var val = getValue(o[i]);
            eval('config' + str + '=' + val);
          } else {
            findProperty(config,i,o[i]);
          }
        }
      }
    };
    function findProperty(o,p,v){
      for(var i in o){
        if(isObj(o[i])){
          findProperty(o[i],p,v);
        } else {
          if(i === p){o[p] = v;};
        }
      }
    };
    function isObj(o){
      return (typeof o === 'object' && typeof o.splice !== 'function');
    };
    function getValue(v){
      switch(typeof v){
        case 'string': return "'"+v+"'"; break;
        case 'number': return v; break;
        case 'object':
          if(typeof v.splice === 'function'){
            return '['+v+']';
          } else {
            return '{'+v+'}';
          }
        break;
        case NaN: break;
      };
    };
    return{set:set};
  }();
  // make init a public method
  return {
    init:init
  };
}();
module.init({
    'container':'header',
    'CSS.classes.active':'now',
    'timeout':1000
});

And that is one way to provide a configuration object and make it possible to change it programatically in the init() method. Can you think of a better one?

An unobtrusive badge for Google Reader’s shared items

Wednesday, May 21st, 2008

I am a user of Google Reader to get through the vast amounts of RSS feeds I subscribed to. I think it is safe to say that reading RSS and twittering has replaced most of my web surfing.

Like most big RSS readers, Google reader also allows you to share great finds you had with people who want to and are in your social neighbourhood. You can either get these finds as a feed or as a little badge (called a clip in Google lingo) to include in your blog or other sites.

The out-of-the-box version of this badge can be customized and results in two JavaScript includes which write out the badge.

That is nice, but I don’t quite care for things that could offer functionality without JavaScript but don’t bother, which is why I checked more closely what the Google badge does.

If you look at the generated script includes you’ll find for example the following URL ( added spaces to avoid breaking my blog :) )

http://www.google.com/ reader/public/javascript/ user/07479231772993841072/ state/com.google/broadcast? n=5&callback=GRC_p%28%7Bc%3A%22green%22%2Ct %3A%22Christian%20Heilmann%27s %20shared%20items%22%2Cs%3A%22false%22%7D%29%3Bnew%20GRC

Clicking this will get you a JSON object with a wrapper function (and for some reason a comment that this is a JavaScript file), which means you can use this for your own purposes.

All you need is your user ID, which you can get this one easily from your shared items homepage that Google Reader offers. In my case this is http://www.google.com/reader/shared/07479231772993841072.

The other interesting parameters of the JSON API are the n parameter defining the amount of items and the callback parameter defining the name of the function call wrapped around the JSON data.

Putting all of this together it was easy to create a badge that uses the following HTML to show off my shared items on Google Reader.


Visitors without JavaScript will still be able to click through to the page of my shared items. Those with JavaScript will get the latest five.

You can see the badge in action and download it for yourself on the demo page (using tutorialbuilder):

How SearchMonkey can lead to a cleaner, more data-rich web

Friday, May 16th, 2008

I normally don’t write about products of my company here, but I want to quickly talk about SearchMonkey, a new service by Yahoo available for developers right now.

I spent some time with journalists from several magazines yesterday explaining the technicalities of SearchMonkey following a presentation about the business and end user benefits explained by a colleague who knows more about that area. This opened my eyes as to what a massive impact SearchMonkey will have if we use it the right way.

What is SearchMonkey and what is the business or user benefit?

On the surface, SearchMonkey means that Yahoo! opens their search result pages to write plugins for them. You can individually style search results and provide “a much richer user experience”. In other words you can actually write “monkeys” that allow people to deep-dive into your site from the search results provided by Yahoo.

Say for example you are netflix or any other DVD rental company and you want people to rent the movie. You could write a monkey that styles search results by imdb.com or other film review sites to show the cover of the DVD, a synopsis and a link to netflix to rent the movie.

The benefits are that the end user does not need to load the IMDB page if she’s happy with the information in the synopsis and you as netflix get a lot of traffic you hadn’t had before.

Splendid, that gets the end users and business people happy, but how does it lead to a cleaner web?

How can you use this to make the web a cleaner place?

Well, this is a strong business case to show to people. Search result pages are boring and people tried to game them with SEO techniques (and abominations) for years – people love to be found. Yahoo! opening their SERPs (Search Engine Result Pages) to the world means first of all you can offer a monkey as a service if you are a developer or small agency.

Monkeys are built upon data available about the document. In its most basic form that is the information Yahoo is keeping in its index – titles, descriptions and other meta information. You can use this information to add more HTML to the SERP showing it, but the harvest is on the meager side of things.

To battle that problem, SearchMonkey allows you to offer “Custom Data Services” to get more information to display. These services could be an XSLT that grabs information from the document, an API that returns an XML in a certain DataRSS format or – and here is where it gets really interesting – RDF or microformats information in the document.

Scraping a document with XSLT always feels wrong to me as the HTML structure is impacted by so many factors – the other issue of course is that it is very memory and computation hungry.

Providing an own API returning XML is of course the optimal way of offering data, but you may not have the resources or drive to do so.

Which leaves microformats and RDF. Right now we support hAtom, hCalendar, hCard, hReview and XFN in terms of microformats and embedded RDF and that makes it a lot easier to retrieve information.

There is a leveraging the Data Web section in the SearchMonkey documentation that explains this in detail (and I am sorry someone considered “leveraging” good language).

So, all in all SearchMonkey is not only a massive step in opening the web for developers (you can style search results without paying for that – something that would have given marketing people seizures not too long ago), it also means that we finally have a channel to display the data we add in microformatic or RDF format that is not a Firefox extension or a specialized search engine. With information in the page developers (either in-house or external) can create customized search results in one step without having to rely on the structure on your document and without having to set up both a monkey app and a data service.

On the flipside, even the idea that someone can use SearchMonkey to enhance search results with data provided by you (and link back to you) if it is easy to write an XSLT to get to the data is a mighty argument to show to people when you want to promote clean HTML structure (no, I won’t call it POSH, as there is nothing plain and old about good, semantic HTML - it is not common practice, sadly enough).

Check out the SearchMonkey information page to get started or just dive into developing your first monkey – the options are endless.

[tags]searchmonkey,rdf,microformats,api,xml,dataweb[/tags]