kelvinluck.com

a stroke of luck

jQuery styleswitch – now with toggle!


About three years ago I posted my stylesheet switcher switcher here. It was the first bit of programming I ever did using jQuery. Surprisingly enough it is still one of the most popular posts on my blog and I still get quite frequent questions about it.

One of the most popular questions is “how can you make the styleswitcher toggle between available stylesheets?”. So I just put together a little example of how to do this. While doing it I noticed that the original code wasn’t really that extensible which is probably why people were always asking that question! So I ended up rewriting the code a bit as well as putting together the new example. You can find it all here.



Progressive enhancement with jQuery example


Update: shAIR is now called Sharify so I’ve updated the links below to point to the new website.

As I previously wrote, we just launched a new product called shAIRSharify. The website was a great chance to implement some progressive enhancement using my favourite javascript library, jQuery. So I thought I’d take the chance here to explain some of the things I did and how they continue to work without javascript enabled. None of this is rocket science by any stretch of the imagination but I thought is was worthy of a quick description.

Since much of the functionality discussed below is behind a login in the admin panel I put together a little example sandbox page which demonstrates the points below.

Styled submit buttons

The beautiful site design from hoppermagic called for submit buttons which don’t really look like buttons at all. Styling a normal submit button is fairly limited and hard to do cross browser so instead I decided to use javascript to swap out the submit button for a normal link which has an event listener which submits the form. If js is disabled the user gets a normal, accessible submit button. If js is available then we know that we will be able to use javascript to submit the form.

The code in question looks like this:

$(':submit').each(
   function()
   {
      var $this = $(this);
      var f = this.form;
      var link = $('<a href="#">' + $this.val() + '</a>')
         .bind(
            'click',
            function()
            {
               $(f).trigger('submit');
               return false;
            }
         )
      $this.after(link).css({position:'absolute', top:'-2000px'});
   }
)

Note that rather than hiding the real submit button with visibility:hidden or display:none we instead just move it way off the screen. This means that you can still submit the form by pressing return in one of the form fields (IE doesn’t allow this if there is no visible submit field in the form).

Form validation

Using the validation plugin made it very quick and easy to add clientside validation to my forms. This doesn’t replace serverside validation but it means that you can inform your users of their errors and give them meaningful feedback quickly. One thing that I would love to see added to the validation plugin is some sort of hooks for when the error message is shown and hidden. I wanted my errors to animate nicely into and out of existence. I managed to hack in a slideDown on the appear by abusing the errorPlacement callback but I wasn’t able to animate the disappearance of the element.

The code related to the validation plugin looks like this:

$forms = $('.validated-form');
if ($forms.length) {
 
   $forms.validate(
      {
         errorPlacement: function(error, element)
            {
               element.after(error);
               error.hide().slideDown();
            }
      }
   );  
}

Note that I only try and call the validate method where I find forms with a class of validated-form. This is because I use the same javascript throughout my site but I only include the validate plugin (and add the validated-form class to forms) on pages where it is required. I would get errors complaining that the validate method couldn’t be found if I didn’t have the check.

Tooltips

Another easy one thanks to the jquery.simpletip plugin. None of the examples on that page seem to use the tooltip in a particularly gracefully degrading way though. In my case I decided to use the title element of the items I was creating a tooltip for to hold the text of the tooltip. This means that without javascript enabled people will still see (less pretty) tooltips. The code is very simple, it grabs the value of the title and passes it into the simpletip initialiser. We also need to remember to empty the title attribute so that the browser doesn’t display it’s tooltip as well as ours.

$('.tt').each(
   function()
   {
      var $tt = $(this);
      $tt.simpletip(
         $tt.attr('title'),
         {
            hook: {
               tooltip: 'topLeft',
               target: 'bottomLeft'
            },
            offset: [20, -5],
            stem: {
               corner: 'topLeft',
               color: '#000',
               size: 15
            }
         }
      ).attr('title', '');
   }
);

FAQs accordian

For the FAQs page I wanted to make it easy for people to scan the questions and then click on the one they wanted the answer for. And jquery made it really easy to add a bit of animation to this too. As an added extra I also add a CSS class to the relevant question heading which changes the direction of the arrow besides it. The answers are hidden by javascript on document ready so users without javascript will just see a normal list of questions followed by answers.

var $h2;
var $answer;
$('.answer').hide();
$('#faq h2').bind(
   'click',
   function()
   {
      if ($h2 && $h2[0] != this) {
         $answer.slideUp();
         $h2.removeClass('open');
      }
      $h2 = $(this);
      $answer = $h2.next();
      $answer.slideDown();
      $h2.addClass('open');
   }
)

Message for IE6 users

I spent a little bit of time making sure that the site was at least usable in IE6. But I didn’t want to waste too much time making sure everything looked perfect. So I decided to add a little message to the top of every page which encourages IE6 users to upgrade their browser. This way they are at least aware why things don’t look quite right and they can’t complain. Luckily, IE6 is a (slowly) dying beast and will be used by a very small proportion of the site’s target audience (developers who are using Adobe AIR).

Summary

So that’s a quick description of some of the simple steps we took to make the website as beautiful and easy to use as possible for people on modern browsers while making sure it is still accessible and available to people using older browsers or who have javascript disabled (for whatever reason).

With the tools and information web developers have at their disposal these days it is so easy to build a site in this manner that there really is no excuse for sites which are completely broken with javascript disabled. Hopefully these simple examples illustrate the some of the concepts behind progressive enhancement.



Data scraping with YQL and jQuery


For a project that I’m currently working on I need a list of all the US National Parks in XML format. Google didn’t come up with anything so I decided that I would need to somehow grab the data from this list on Wikipedia. The problem is that the list is in messy HTML but I want some nice clean XML ready for parsing with E4X in Flash.

There are a number of ways I could parse the data. If I knew Ruby and had an environment set up I’d probably use hpricot. Or I could get my hands dirty again with PHP and DOMDocument. Or if the Wikipedia page was XML or could be converted into XML easily then I could use an XSL transform. Or I’m sure there are hundreds of other approaches… But in this case I just wanted to very quickly and easily write a script which would grab and translate the data so I could get on with the rest of the project.

That’s when I thought of using jQuery to parse the data – it is the perfect tool for navigating a HTML DOM and extracting information from it. So I wrote a script which would use AJAX to load the page from Wikipedia. And that’s where I hit the first hurdle: “Access to restricted URI denied” – you can’t make crossdomain AJAX calls because of security restrictions in the browser :(

At this point I had at least a couple of ways to proceed with my jQuery approach:
  • Copy the HTML file from Wikipedia to my server thus avoiding the cross domain issues.
  • Write a quick serverside redirect script to live on my server and grab the page from Wikipedia and echo it back out.
I didn’t like the idea of either of those options but luckily at this point I remembered reading about YQL:
The YQL platform provides a single endpoint service that enables developers to query, filter and combine data across Yahoo! and beyond.
After a quick flick through the documentation and some testing in the YQL Console I put together a script which would grab the relevant page from Wikipedia and convert it into a JSONP call which allows us to get around the cross-domain AJAX issues. As an added extra it’s really easy to add some XPath to your YQL so I’m grabbing only the relevant table from the Wikipedia document which cuts down on the complexity of my javascript. Here’s what I ended up with:
SELECT * FROM html WHERE url="http://en.wikipedia.org/wiki/List_of_United_States_National_Parks_by_state" AND xpath="//table[@class='wikitable sortable']"

If you run this code in the console you’ll see that it grabs the relevant table from wikipedia and returns it as XML or JSON. From here it’s easy to make the AJAX call from jQuery and then loop over the JSON returned creating an XML document. If you are interested in the details of that you can check out the complete example.

I was really impressed with how easy it was to quickly figure out YQL and I think it’s a really useful service. Even if you just use it to convert a HTML page to a valid XML document then it is still invaluable for all sorts of screen scraping purposes (it’s always much easier to parse XML than HTML tag soup). One improvement I’d love to see the addition of a CSS style selection engine as well as the XPath one. And the documentation could maybe be clearer (I figured out the above script by checking examples on other blogs rather than by reading the docs). But overall I give Yahoo! a big thumbs up for YQL and look forward to using it again soon…



jQuery date picker


My jQuery datepicker is a jQuery plugin which allows you to easily add “date picker” calendars to you HTML forms. These calendars make it much quicker, easier and less error prone for people to input certain types of dates.

Examples

There are full examples of many different use-cases for jQuery date picker all available from the datePicker homepage.

Version

The jQuery datepicker plugin is currently at version 2.1.1.

You can keep up with all changes to the date picker using the project feeds from the plugin’s googlecode page.

Download

The date picker plugin has it’s own googlecode site – this is where the latest sourcecode and releases can be downloaded from. The latest release will always be a featured download and the cutting edge code will be found in the svn trunk:

http://jquery-datepicker.googlecode.com/svn/trunk/

Previous releases will be tagged in the Subversion tags directory:

http://jquery-datepicker.googlecode.com/svn/tags/

Bug reporting and feature requests

Please submit any bug reports or feature requests through the issues list on googlecode. Please remember to include all information necessary to replicate the bug, including effected browser and operating system and a URL to a test page displaying the problem. Please also first search through the issues list to see if there are any existing related issues.

Donate

The date picker plugin is completely free and open source. However, if you find it useful and you would like to make a donation towards my beer fund then please use the paypal button below to donate any amount. Thanks!



Switch stylesheets with jQuery


Update: I’ve released an updated version of this code which is more flexible. Please check it out.

I’ve just discovered jQuery which is an awesome JavaScript library. From the horse’s mouth:
jQuery is a Javascript library that takes this motto to heart: Writing Javascript code should be fun. jQuery acheives this goal by taking common, repetitive, tasks, stripping out all the unnecessary markup, and leaving them short, smart and understandable.
As an example of how succinct and easy code written with jQuery can be I put together a little example that allows you to add a stylesheet switcher to your site. Check out the example in action.

The stylesheet switcher allows your visitors to choose which stylesheet they would like to view your site with. It uses cookies so that when they return to the site or visit a different page they still get their chosen stylesheet.

The JavaScript code that powers the example looks like this:

/**
* Styleswitch stylesheet switcher built on jQuery
* Under an Attribution, Share Alike License
* By Kelvin Luck ( http://www.kelvinluck.com/ )
**/


(function($)
{
   $(document).ready(function() {
      $('.styleswitch').click(function()
      {
         switchStylestyle(this.getAttribute("rel"));
         return false;
      });
      var c = readCookie('style');
      if (c) switchStylestyle(c);
   });

   function switchStylestyle(styleName)
   {
      $('link[@rel*=style][title]').each(function(i)
      {
         this.disabled = true;
         if (this.getAttribute('title') == styleName) this.disabled = false;
      });
      createCookie('style', styleName, 365);
   }
})(jQuery);

Then all you need to do is to add a class of “styleswitch” to any links that you want to activate the stylesheet switcher and a “rel” attribute which corresponds to the “title” attribute of the link tag embedding the stylesheet you want to switch to. Just view the source of the example and all should become clear…

I’d appreciate any feedback on the effectiveness of this technique. I think it should work fine on any browser that jQuery supports (I’ve tested on IE5.5, IE6 and FF1.5 on XP and Safari on OSX). It should degrade gracefully by going to the href of the link when jQuery isn’t supported or JavaScript is disabled. I have linked to a page which suggests possible ways to deal with this situation (disable JavaScript and try and switch stylesheets on the example to see the page).

If you would like to use this code then please feel free to download the zip



Hello Adobe feeds!


I’ve just found out that my blog is now aggregated on Adobe Feeds. So I thought I would do a quick post to say hello (hello!) and to link to some of my popular or interesting old content:

  • The launch of Sharify – a service to allow developers to easily add shareware features to their AIR applications so that they can sell them
  • jScrollPane - my plugin to allow you to create cross browser custom scrollbars on any HTML element.
  • Some audio programming experiments in Flash Player 10.
  • Some experimental javascript – playing with jQuery and Raphael JS to use javascript for fun and experimentation rather than serious “work”.
  • My jQuery datepicker plugin.
  • My experiments with tweetcoding – seeing what can be made in 140 characters of actionscript.
  • Some experiments with Papervision.
  • Flashr – my old as2 wrapper for the Flickr API.

I hope some of that is interesting to people. Moving forwards, I hope to be making many more posts about Flash, Flex, Javascript, AIR and more. Recently I’ve been programming quite a lot of c sharp .net too and I’ll to write up some of my thoughts about that from the point of view of someone coming from languages like actionscript and javascript. Plus I want to finish the bunch of half done papervision and audio experiments I have sitting around!



Not my mother’s javascript!


Last week Google launched Chrome Experiments – a set of javascript experiments – to spread the word about their browser, Chrome. One of the major selling points of Chrome (can something free have selling points?) is V8 – it’s new and optimised javascript engine. I guess the idea is that by sponsoring a site of cool experimental stuff they can virally drive people to download and play with their product. And it worked on me! When some of the experiments ran a bit jerkily on my Firefox I decided to download it and give it a go.

Most of the javascript I write is fairly serious with a strong requirement for cross browser compatibility and graceful degradation, but the experiments inspired me. Having recently had some fun with tweetcoding (where you ignore every type of best practise to squeeze “something cool” out of 140 characters of actionscript 3) I felt like trying the same sort of thing with javascript.

For my first attempt I ported my first ever as3 experiment. Click on the image below to try “boingPic” which will split an image of your choice into 100 squares each of which is scared of the mouse (or view it in it’s own window if you want to boing larger images).

boingpic

Then I was reading an interview with Toxi about the creation of Social Collider (one of the chrome experiments). In it he mentioned Raphaël – a javascript library which uses the SVG W3C Recommendation and VML as a base for generating vector graphics.

I decided to check it out and found out that it’s a really great library which gave me the freedom to easily experiment with graphical stuff in javascript. I had loads of fun playing around with it – you can see some of my experiments below. They do appear to run best in Chrome so I’d recommend using that (looks like google’s ploy is working!) or at least Safari (FF doesn’t seem to render the width of paths but webkit does). [Thanks to Dmitri for pointing out the error in my code, it now works in FF too]

  • test3
  • test6
  • test7
  • test8
  • test12
  • test13
  • test17
  • test18
  • test19
  • test20

Most of my experiments were inspired by my previous tweetcoding entries. Feel free to view source on any of them to see how they are done – there is nothing at all complex going on. Big thanks to all of the chrome experiments for getting me to start playing with this and to Raphaël for the vector js goodness – I’m hoping to find more time to do some more complex experiments in the future!



Tweetcoding – 140 characters of actionscript 3


Just over a week ago, Grant Skinner started a competition on Twitter called Tweetcoding. It’s very simple:
#tweetcoding: code something cool in <=140 characters of AS3
By happy coincidence this was just after I’d decided to give Twitter another chance and so I heard about the competition and decided to get involved. The first thing I did was to put together a quick tweetcoding minifier using jQuery – it lets you paste in your (slightly) readable AS3 code and it strips unnecessary whitespace and tells you how many characters you’ve used. Definitely much easier than the find and replace gymnastics I was doing in my text editor to start with!

Next I had big plans for creating a website to allow you to compile your own tweetcodes online. But all three of my approaches failed – I couldn’t trigger Java (and therefore mxmlc) from PHP on my shared host, I couldn’t piggyback on the wonderfl API (they use mxmlc behind the scenes too) and screaming donkey couldn’t handle the DisplayList. Luckily, Robert Cadena had the same idea and managed to execute it wonderfully and produce the tweetcoding compiling robot (I’m not sure what it’s really called!). You can visit that page and check out all of the great entries without compiling yourself.

The next step was to find a way to compile my tweetcoding from FDT – my preferred editor. I tried using Flash but it’s little code window annoyed me quickly and I don’t have CS4 yet so I couldn’t access any of the flash player 10 features. So I set up a project in FDT and created the following class:

package
{
   import flash.filters.*;
   import flash.text.TextField;  
   import flash.media.Microphone;  
   import flash.ui.Mouse;  
   import flash.events.*;        
   import flash.display.*;

   dynamic public class Tweetcode extends MovieClip
   {

      public var g:Graphics;
      public var mt:Function;
      public var lt:Function;
      public var ls:Function;
      public var m:Class;
      public var r:Function;
      public var s:Function;
      public var o:Object;
      public var i:Number = 0;

      public function Tweetcode():void
      {
         stage.scaleMode='noScale';
         stage.align='top';
         g = graphics;
         mt = g.moveTo;
         lt = g.lineTo;
         ls = g.lineStyle;
         m = Math;
         r = m.random;
         s = m.sin;
         o = {};

         addEventListener("enterFrame", f);
      }

      public function f(e:Event):void
      {
         // 140 characters here!
      }
   }
}

As you can see, it includes Grant’s gimmie code and space for me to add my code. I’ve added extra imports as I’ve needed them but I’m sure there are more that could be included. And I added some static typing to the variables even though this isn’t necessary – it does means I get a little help from FDT’s code hinting. Then I added ” –strict=false” to the mxmlc command line in my launch target and I was good to go :)

Below are some of my tweetcoding attempts in reverse chronological order (that doesn’t necessarily mean that they get better though!). Make sure you check out all of the other entries as well though – there is some incredible stuff. It is amazing what you can cram into so few characters!

Flickering Flame

A simple flame-like effect. View

g.clear(),o[++i]={x:mouseX,y:mouseY,b:9},filters=[new BlurFilter(4,4)];for each(p in o)a=p.b-=.2,ls(a,3e9,a),mt(p.x,p.y),lt(p.x+a,p.y--+a);

Windmill

Blow into your microphone to make it spin around!. View

if(i&lt;6.5) q=Microphone.getMicrophone(),q.setLoopBack(),ls(2),x=y=99,mt(0,0),lt(90*s(i),90*m.cos(i)),i+=m.PI/18;rotation+=q.activityLevel/9;

Colourful bondage

The coloured lines want to keep your mouse prisoner. View

g.clear(),Mouse.hide(),o[++i]={x:mouseX,y:mouseY,b:7,c:i< &lt;16+i<&lt;32};for each(p in o)a=p.b-=.3,ls(a,p.c,a),mt(p.x,p.y),lt(mouseX,mouseY);

Stripy wallpaper

Just some nice animating blue stripes. View

g.clear();t=stage,o[++i]={x:300+s(i)*300,b:9,c:9*i};for each(p in o)a=p.b-=.3,ls(a,p.c,a),l=p.a,mt(p.x,0),lt(p.x,t.stageHeight);

Mouse bubbles

Little bubble like particles escaping from the mouse. View

g.clear(),o[++i]={x:mouseX,y:mouseY,a:r()*9-5,b:r()*9};for each(p in o)a=p.b--,ls(2),p.a*=.9,p.b*=.9,mt(p.x+=p.a,p.y+=p.b),lt(p.x+1,p.y+1);

Ninja the mouse killing line

Weird title (I guess the tweetcoding had gone to my head) but probably my favourite of my entries. View

g.clear();o[++i]={x:mouseX,y:mouseY,a:o[i-1],b:9};for each(p in o)!p.a||(ls(p.b--),l=p.a,mt(p.x-=(p.x-l.x)/6,p.y-=(p.y-l.y)/6),lt(l.x,l.y));

Heartbeat

Short and simple. View

g.clear();o[++i]={x:i,y:99+s(i)*99,a:o[i-1]||{x:0,y:99}};for each(p in o)ls(1,p.x*0x020101),mt(p.x,p.y-=(p.y-p.a.y)/6),lt(p.x,p.y+2);

Marching ants

They follow the mouse and slowly straighten out over time. View

g.clear();ls(2);o[++i]={x:mouseX,y:mouseY,a:o[i-1]||{x:250,y:250}};for each(p in o)mt(p.x-=(p.x-p.a.x)/6,p.y-=(p.y-p.a.y)/6),lt(p.x+1,p.y);

Silly String

Stringy stuff falls from your mouse. View

g.clear();ls(2);o[++i]={x:mouseX,y:mouseY,a:o[i-1]||{x:9,y:9}};for each(p in o)mt(p.x-=(p.x-p.a.x)/6,p.y-=(p.y-p.a.y)/6),lt(p.a.x,p.a.y);

Random Silly String

Stringy stuff gets spread around the screen. View

g.clear();ls(1);o[++i]={x:500*r(),y:500*r(),a:o[i-1]||{x:9,y:9}};for each(p in o)mt(p.x-=(p.x-p.a.x)/6,p.y-=(p.y-p.a.y)/6),lt(p.a.x,p.a.y);

First try

This one is from before there was any gimmie code so it's 140 characters that run by themselves. Unsurprisingly, they do very little! View

var w=x=y=200,b,g=graphics,m=Math,l=g.lineTo,c=m.cos,s=m.sin,i=361;while(i--){g.lineStyle(1,m.random()*0xfff);l(w*c(i),w*s(i));l(0,0);}

Tweetcoding is great fun and seems to be part of a trend to impose constraints to trigger creativity. I've been a close follower of the 25 lines competition and been blown away by what people have achieved there. I'm also really interested in the 4k flash game competition and would love to find the time to put an entry together. It's incredible the amazing results you can get by abandoning anything like best practises and trying to squeeze something interesting out of a constrained situation. Good clean geek fun :D



jScrollPane 1.2 released


I’ve just released a new version of jScrollPane – my jQuery plugin for cross-browser customisable scrollbars. It’s been a long time since the plugin has been updated and this release contains a number of significant improvements:
  • a jScrollPane now correctly scrolls when you tab to a focusable element within it [example]
  • a jScrollPane can now automatically re-initialise itself when images inside it load [example]
  • external (and internal) links to an anchor within a jScrollPane now correctly scroll the jScrollPane [example]
  • defaults settings are now user-settable [example]
In addition to these changes, jScrollPane now has a new home on googlecode. This makes it easier for people to keep up to date with the latest version and more importantly it makes it easier for me to track bug reports and issues with jScrollPane (something that was basically impossible on the jQuery plugins site). As you can see, there is already a number of issues raised (one of which has high priority) so there may well be a bug fix release soon. In the meantime, it would be good to get people testing the new release and seeing if I broke anything else while implementing these changes…

Update:

jScrollPane 1.2.1 was released very shortly after 1.2 to fix a fairly serious bug which prevented links within the scroll pane from working correctly. As always, the googlecode site has the latest version.


Projects


In this section of the site you will find any of my random experiments which have progressed far enough to earn the title “project”. That probably means that they are somewhat generic and may be useful to other people.