A Huffduffer Widget

March 22nd, 2009

When Jeremy talked about Huffduffer at March’s £5app he revealed that pretty much every page in Huffduffer had a RSS/JSON/XML version. A couple of weeks back, I asked whether Huffduffer supported JSONP. After a quick reply back from Jeremy that it wasn’t, there was another reply within an hour or two saying Jeremy had added JSONP support. At that point I felt my curiosity had got the better of me and I felt duty bound to a least do something with the newly added JSONP support…

So here I present a very simple embed-able Javascript widget for Huffduffer:



Both the page used to generate the widget HTML and the widget code itself are 100% client-side. There’s no server-side code involved at all. For the widget itself this seemed pretty key. Such widgets may be embedded in pages that get a lot of hits, so doing anything beyond serving up a static file seemed best to avoid.

I’d not really written a widget like this before, but planned to create something similar for chrss at some point, so it seemed like a good thing to have a go at. Most of the techniques are based on code from Dr Nic’s DIY widgets – How to embed your site on another site article. However I tried to add a few more features/constraints into the mix:

  • Allow more than one widget with different data on the same page
  • Don’t pollute the global namespace
  • Don’t require special html embedded with the widget (just a single script tag)
    • The first point involved allowing a static javascript file to server different data. The easy way would be to have some server side code serve up some slightly different Javascript depending on the parameters given, but I decided there’s no reason why the Javascript can’t do that itself.

      When the widget script runs it looks at the last known script element – which should be the element used to load the script itself to parse the parameters. In this case I just want a single parameter. So if the script tag used to embed the widget looks like this:

      <script src="http://psychicorigami.com/huffduffer/build/huffduffer.js?lilspikey" type="text/javascript"></script>
      

      I can extract everything after the ? thus:

          function findURL() {
              // assume that last script in page is this script
              var scripts = document.getElementsByTagName('script');
              var script = scripts[scripts.length-1];
              var scriptURL = script.getAttribute('src');
              var m = scriptURL.match('^.*\\?(.*)');
              if ( m ) {
                  return m[1];
              }
              return ''
          }
      

      So that solves the first problem.

      The next problem is not polluting the global namespace. First I make sure that everything is wrapped inside an anonymous function that is called immediately. This reduces the scope of the functions declared in there. However we do need at least one global function to act as a callback for the JSONP data. In addition this function must be unique to each widget embedded in the page, so that the correct data gets given to the correct widget.

      So first I generate a relatively unique id:

          function uuid() {
              var id = "_"+(new Date()).getTime();
              for ( var i = 0; i < 8; i++ ) {
                  id += "0123456789".charAt(Math.floor(Math.random()*10));
              }
              return id;
          }
          var id = uuid();
          var div_id = 'huffduffer'+id;
      

      Then we use that id as a name for the function and create a callback that embeds the id of the div the widget will appear in via a closure:

          function createCallback(div_id) {
              // return a function with the div_id in a closure
              return function(data) {
                  // real callback code here
              }
          }
          
          // create a function with a generated name, to ensure 
          // we get the right div
          window[id] = createCallback(div_id);
          document.write("<div id='"+div_id+"'></div>");
      

      This means that we can have multiple widgets on the page all showing different data and the global namespace pollution is limited to one randomly named function per widget.

      In addition by creating this unique id we can tie the callback function to the relevant div in the page without needing any more magic. Which means we've also dealt with the third problem.

      The "real" widget has been minimized using YUICompressor, but you can see the regular version of the code here:

      I've tested everything in most of the major browsers, but can't guaranteed it'll work perfectly everywhere.

5K Morse Code App Using Capslock LED

March 1st, 2009

This is probably my first attempt at “literary programming”, though using that phrase may be taking liberties a little. In this case by “literary programming” I mean – programming inspired by literature. The literature in question is Cryptonomicon by Neal Stephenson. Cryptonomicon already features a Perl script in it’s pages, but that’s not what I’m talking about here. Instead there’s a chapter later in the book when Randy Waterhouse has been incarcerated. However he’s been given the use of his laptop so that – his captors hope – he will decrypt a key piece of data whilst they are monitoring his screen via Van Eck Phreaking. Randy cottons onto this, so he creates an app that will convert text to morse code and have that morse code emitted via the LEDs on his laptop’s keyboard.

I suddenly decided to have a go at creating such a morse code script for my Macbook and here’s the result in action:


You can test the script out by running this at the command line (from the directory with the script in):

echo 'sos' | python morse.py -led

It depends on libraries that are only found in OS X 10.5 Leopard for controlling the capslock LED.

With a bit of compression it all fits well under 5K of code, so makes a worthy example of a 5K app. The morse part of the app is very simple – apart from the lookup table, it could probably fit into 2-3 lines of code! The bulk of the code is simply concerned with driving the capslock key’s LED via the HID. For this I cribbed heavily from some of Apple’s sample code and converted it to run in Python using ctypes.

The only problem I found was that for some reason they internal keyboard on my Macbook stops responding to the request to change the LED state after several seconds. However using this script with an external USB keyboard worked fine. I guess the internal keyboard has some sort of abuse-prevention built-in.