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.



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!



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…



Using spell checker for TinyMCE with .NET on IIS


Recently I’ve been working on a website which is built in C sharp using the .NET framework (version 2) and running on IIS. This is a fairly different experience to my usual linux/ apache/ php/ mysql and actionscript setup but it’s been interesting and rewarding. I’m planning a series of posts documenting things that I’ve found out and like or dislike about this environment but for now just a quick one about how to get the spell checker for TinyMCE working…

TinyMCE is “a platform independent web based Javascript HTML WYSIWYG editor control” which is very popular on the web (in fact I am using it to create this post in wordpress!). It comes with heaps of functionality and plugins including a spellchecker. As you’ll see at that link though, the spell checker requires PHP on the serverside… Or does it?

If you look on the TinyMCE download page you will see that there is a .NET package available. I was curious about what this was, especially when I looked through the zip and found that it contained a SpellChecker folder. Looking at the code it turns out that this is the alternative of the PHP code necessary for implementing the spell checker – it accepts the AJAX request from a TinyMCE instance, sends it off to Google’s spell checking web service and sends the relevant results back in the AJAX response. Yay! Now I needed to find out how to use it – for some unknown reason this all seems to be undocumented and google wasn’t bringing back any answers either.

Looking through the c# code, I found that the .NET package is implemented as an IHttpHandler. Once I knew that it was pretty easy to figure out how to configure IIS to use the code. Basically you need to drop the Moxiecode.TinyMCE.dll from the .NET package into the bin folder of your website. Then open your web.config file and find the httpHandlers node inside the system.web node and add the following line in:

<add verb="*" path="TinyMCEHandler.aspx" type="Moxiecode.TinyMCE.Web.HttpHandler, Moxiecode.TinyMCE" validate="false"></add>

This tells IIS that all calls to /TinyMCEHandler.aspx should infact be handled by the Moxiecode.TinyMCE.Web.HttpHandler class in the Moxiecode.TinyMCE assembly. The validate=”false” means that IIS won’t check if this dll and class can be found unless you actually request that page (this is useful if you have seperate applications mapped to virtual directories below this web.config as it will prevent those applications throwing errors because they can’t find the dll)

Now you just have to set up your TinyMCE instances to include a spell checker button and to know the correct place to look for the serverside script. Here is how we instantiate TinyMCE:

tinyMCE.init({
   mode : "textareas",
   theme : "advanced",
   plugins : "paste, spellchecker",
   theme_advanced_buttons1 : "bold,italic,underline,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,bullist,numlist,separator,undo,redo,separator,link,unlink,separator,cut,copy,paste,pastetext,pasteword,separator,forecolor,backcolor,separator,code,separator,spellchecker",
   spellchecker_rpc_url: "/TinyMCEHandler.aspx?module=SpellChecker"
});

The important things are:

  • Added “spellchecker” to the plugins list.
  • Added a “spellchecker” button to the buttons list.
  • Added the spellchecker_rpc_url which tells TinyMCE where to find the serverside script.
And that’s all there is to it. As you can see, it’s very easy as all the code is available but for some reason it seems to be undocumented and I couldn’t find any information out there about how to set it up. So hopefully this post will save someone else the time I spent figuring it out :)

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.


jScrollPane – Cross browser custom scrollbars


I’ve just released my latest plugin for jQuery – my favourite JavaScript library. It is a small (4KB) script which allows you to replace any vertical scrollbars on a div with overflow:auto with your own custom scroll bars. More info, demos and download here.



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