Message
back to the journal

Archive for the ‘tips’ Category

Using Quicksilver to control Last.fm

August 7th, 2009

Quicksilver & Last.fm

For a while, I’ve been using handy Quicksilver triggers to control iTunes. I like not needing to switch my attention from what I’m working on, in order to skip a track, pause the playback, set a rating or whatever. You can find out how to create a trigger from one of the many great Quicksilver tutorials out on the Web.

At the moment though, I find myself listening to Last.fm more and more, and have been looking for a similar way to control the Last.fm application. I couldn’t find a plugin for Quicksilver to achieve this so I set about writing an Applescript which I could trigger with Quicksilver.

I’m not much of an Applescript whizz, but I managed to put the following script together to skip the track currently playing in the Last.fm application:

tell application "Last.fm" to activate
tell application "System Events"
	tell process "Last.fm"
		click menu item "Skip" of menu "Controls" of menu bar 1
	end tell
end tell

After saving this in a suitable location (I have a Utils folder where I keep lots of scripts and utilities), I set a Quicksilver trigger to run the script. Simple!

Happy with the result, I created similar scripts for some other controls like love, ban, play and stop and assigned them all keyboard triggers.

My only wish was that I could do this without giving Last.fm focus. Generally this is fine for my because I have it running in a second display, so it doesn’t steal my attention, but it would be nice if I could get Applescript to execute the command without activating the application. I’d welcome suggestions from anyone with more Applescript fu than me.

Leveraging jQuery and jQuery plugins in TiddlyWiki

March 13th, 2009

jQuery

The recent release of TiddlyWiki v2.5 included something rather exciting for me: JQuery, the popular Javascript library is now part of the TiddlyWiki core.

This is exciting for a number of reasons.

  1. The TiddlyWiki core functions can now use jQuery to perform all manner of DOM inspection and DOM manipulation. We can refactor a ton of code to benefit from jQuery’s blistering Sizzle engine and pass the burden of maintaining lots of utility functions over to those clever jQuery bods. All of which will simplify the TiddlyWiki codebase and ultimately make it easier to read and easier to maintain.
  2. TiddlyWiki plugin developers will now be able to make use of jQuery in their plugins. That’s great news for both hardcore plugin developers and people dabbling for the first time. jQuery is elegantly expressive, powerful, and superbly documented. All of this lowers the barriers to entry for a would be developer and smooths the way for exisiting developers.
  3. There is a huge wealth of jQuery plugins which can now be utilised by TiddlyWiki. The quality of many of these plugins is tremendously high. Bring ‘em on!

But how does a TiddlyWiki plugin developer get started? How can we bring a jQuery plugin into TiddlyWiki and make it available via a Macro? Let’s take a look at an example.

Fred, my colleague at Osmosoft stumbled upon a plugin which creates a nice navigation structure from an HTML List element. The plugin has lots of examples and documentation and seemed like a good contender for bringing something useful into TiddlyWiki.

To include the plugin, all we need to do is copy it into a tiddler and then tag the tiddler with systemConfig. After saving the file and reloading, the plugin is available for us to use.

Plugin inclusion

With the jQuery plugin availble, we can use it to provide a snazzy UI for any UL or LI elements on the page. The Javascirpt syntax for that is nice and simple:

// Turn the list element with an ID of 'myList' into a funky ListNav
$('#myList').listnav();

This is great, but we want people to be able to call this from TiddlyWiki without having to write Javascript. If we create a TiddlyWiki macro to call this for us, people can easily make a nice NavList anywhere. Let’s make a macro which turns the contents of a tiddler into a NavList like this:

<<listnav TiddlerTitle>>

To make that available, we should create a TiddlyWiki plugin which delivers this macro. We do this in a new tiddler. I created a tiddler called ‘ListNavPlugin’ and once again tagged it with systemConfig so that it becomes code that TiddlyWiki knows to interpret. To start with, let’s just create the macro and ensure that we can invoke it.

 
// create macro object
config.macros.listnav = { 
 
  // Add a handler function to be invoked by <<listnav TiddlerTitle>> 
  handler: function(place, macroName, params, wikifier, paramString, tiddler) {
 
    // do some magic...
    alert("I'm gonna make a funky listnav!");
 
  }
};

To see it working, I created two more new tiddlers. MyFruityList holds a list of items, and ExampleListNav holds a call to the new macro.

MyFruityList and ExampleListNav

Saving the TiddlyWiki file and reloading will make the macro available to call. If we open the ExampleListNav tiddler, we should see our macro called like this:

Macro called

All good, but not exciting yet. Let’s flesh out our TiddlyWiki macro a bit. We’ll use a TiddlyWiki function to get the text from our desired tiddler and then make a list from it. Where we might once have used some TiddlyWiki utility functions to help us create the HTML elements (like createTiddlyElement), we can now use jQuery’s helper functions to append elements to the document.

 
// create macro object
config.macros.listnav = {
 
  // Add a handler function to be invoked by <<listnav TiddlerTitle>> 
  handler: function(place, macroName, params, wikifier, paramString, tiddler) {
 
    // target tiddler passed in as macro parameter
    var title = params[0];
 
    // read list items from tiddler contents
    var text = store.getTiddlerText(title);
    if(text) {
 
      // generate list
      var items = text.split("\n");
      var list = jQuery("<ul />").attr("id", "listnav").appendTo(place);
      jQuery.each(items, function(i, itm) {
        jQuery("<li />").text(itm).appendTo(list);
      });
 
    }
  }
};

Now we’re getting somewhere. We’ve grabbed each line from our MyFruityList tiddler and used jQuery to turn them into an unordered list.

List created from tiddler text

We can now call the jQuery plugin to render our list as a NavList. The plugin requires a little extra HTML so we can create that, and then call the listnav plugin.

 
// create macro object
config.macros.listnav = {
 
  // Add a handler function to be invoked by <<listnav TiddlerTitle>> 
  handler: function(place, macroName, params, wikifier, paramString, tiddler) {
 
    // target tiddler passed in as macro parameter
    var title = params[0];
 
    // read list items from tiddler contents
    var text = store.getTiddlerText(title);
    if(text) {
 
      // generate nav bar
      jQuery("<div />").attr("id", "listnav-nav").appendTo(place);
 
      // generate list
      var items = text.split("\n");
      var list = jQuery("<ul />").attr("id", "listnav").appendTo(place);
      jQuery.each(items, function(i, itm) {
        jQuery("<li />").text(itm).appendTo(list);
      });
 
      // apply listnav
      list.listnav();
    }
  }
};

When we save our plugin, reload the page and open up our ExampleListNav tiddler, we see the navlist. Cool! Hang on though, it looks a bit rubbish. Not like the examples we saw earlier. We have to include the CSS to style our new navlist. Easy enough, let’s use our TiddlyWiki plugin to create a sylesheet for our new HTML by adding this:

 
// add default styles (adapted from http://www.ihwy.com/labs/downloads/jquery-listnav/2.0/listnav.css)
config.shadowTiddlers.StyleSheetListNav = "/*{{{*/\n" +
  "#listnav-nav { margin: 20px 0 10px; }\n" +
  ".ln-letters { overflow: hidden; }\n" +
  ".ln-letters a { font-size: 0.9em; display: block; float: left; padding: 2px 6px; border: 1px solid #eee; border-right: none; text-decoration: none; }\n"+
  ".ln-letters a.ln-last { border-right: 1px solid #eee; }\n" +
  ".ln-letters a:hover, .ln-letters a.ln-selected { background-color: #eaeaea; }\n" +
  ".ln-letters a.ln-disabled { color: #ccc; }\n" +
  ".ln-letter-count { text-align: center; font-size: 0.8em; line-height: 1; margin-bottom: 3px; color: #336699; }\n" +
  "/*}}}*/";
store.addNotification("StyleSheetListNav", refreshStyles);

And we’re done. The jQuery plugin is turning our boring old list into a dynamic indexed list with navigation. Cool! For extra credit, we can make our jQuery a little more concise. Notice that we call jQuery by name rather than with the common idiom of $. We could simply replace each jQuery with $ in our code and that would work, but beware! There are other Javascript libraries that use the $ shortcut. we don’t want to introduce the possibility of a clash. Luckily, there is a simple way to get around that. All we need to do is wrap our TiddlyWiki plugin in a closure and pass jQuery in as an argument (as explained on the jQuery documentation site). Then we can use whatever shortcut for jQuery in our code that we like. The final code looks like this:

 
(function($) { // set up alias
 
  // create macro object
  config.macros.listnav = {
 
  // Add a handler function to be invoked by <<listnav TiddlerTitle>> 
  handler: function(place, macroName, params, wikifier, paramString, tiddler) {
 
    // target tiddler passed in as macro parameter
    var title = params[0];
 
    // read list items from tiddler contents
    var text = store.getTiddlerText(title);
    if(text) {
 
     // generate nav bar
     $("<div />").attr("id", "listnav-nav").appendTo(place);
 
     // generate list
     var items = text.split("\n");
     var list = $("<ul />").attr("id", "listnav").appendTo(place);
     $.each(items, function(i, itm) {
       $("<li />").text(itm).appendTo(list);
     });
 
     // apply listnav
     list.listnav();
    }
  }
};
 
  // add default styles (adapted from http://www.ihwy.com/labs/downloads/jquery-listnav/2.0/listnav.css)
  config.shadowTiddlers.StyleSheetListNav = "/*{{{*/\n" +
  "#listnav-nav { margin: 20px 0 10px; }\n" +
  ".ln-letters { overflow: hidden; }\n" +
  ".ln-letters a { font-size: 0.9em; display: block; float: left; padding: 2px 6px; border: 1px solid #eee; border-right: none; text-decoration: none; }\n"+
  ".ln-letters a.ln-last { border-right: 1px solid #eee; }\n" +
  ".ln-letters a:hover, .ln-letters a.ln-selected { background-color: #eaeaea; }\n" +
  ".ln-letters a.ln-disabled { color: #ccc; }\n" +
  ".ln-letter-count { text-align: center; font-size: 0.8em; line-height: 1; margin-bottom: 3px; color: #336699; }\n" +
  "/*}}}*/";
  store.addNotification("StyleSheetListNav", refreshStyles);	
 
})(jQuery);

You can explore the finished example in a TiddlyWiki.

How to create and distribute lovely screencasts

March 28th, 2008

For a while I have been meaning to start posting screencasts of some of my work to spread the word, and to explain some of the details that are difficult to describe in text.

After much tinkering, I think that I have arrived at a nice setup and have found a good way to distribute the screencasts, making them available to stream over the web or to download for consumption in your own sweet time.

In this post, I’ll share my findings so that you can set yourself up with a similar environment. I use a Mac, and so these tips are leveled squarely at the Mac users out there. Sorry to everyone else, but I’m just writing about what I know.

Read the rest of this entry »