HTML5, CSS3, jQuery, JSON, Responsive Design...

Faster mobile JavaScript click responses with fastclick.js

Michael Brown  April 10 2014 04:39:07 AM
As I pointed out in my post Speedier responses for iPhone web apps a couple of years ago, it's a little known fact is that iOS devices, and older Android devices too, are slow at responding to JavaScript click events.  This is because they have a built-in 300ms delay, due to them needing to respond to other types of tap, such as double tap (to zoom), drag and pinch to zoom.

That 300ms might not sound like a long time, but it is noticeable when you're clicking web page controls that triggers hides and shows etc with JavaScript.  I'd say it's one of the main reasons why so many web apps seem so sluggish when compared to native iOS apps.

Here's a sample page to demonstrate the issue:
http://www.users.on.net/~mikeandgeminoz/mobileclick/index.html

Open it on an iPhone or iPad and start tapping on the radio buttons.  Notice the short delay before the box colour changes?  Perhaps not.  Okay, so try this page instead:
http://www.users.on.net/~mikeandgeminoz/mobileclick/index2.html

Much faster to respond to the radio buttons than the first page, yes?

If you don't have an iOS device to test with, then I've done a video capture of my accessing the two pages with my own iPhone.  (The white circles that you see, correspond to my finger tapping on the screen.)



There's only one difference between the two pages: the second page has the fastclick.js library loaded.  This library does some behind the scenes re-mapping of click events, so you can get that speedier response time without having to rewrite your click events to touchstart or touchend events, as I'd recommended in my original post.  (Using the touchstart event has the disadvantage of disabling drag for the element on which you have it set.)

When, hopefully, the whole 300ms problem is fixed in a later version of iOS - as it already appears in more recent versions of Android - then all you have to do is remove the fastclick library from your apps.

Serving HTML5 Video from Domino

Michael Brown  February 14 2014 01:00:25 PM

I'm looking at rolling out HTML5 video for a site that I'm working on.  The site is made up of Notes documents, and I would be storing the video files on Rich Text fields within those documents.  I last looked at this about six months ago, and well, things in the HTML5 Video world were something of mess.


Six Months Ago

There are three HTML5 formats:
  • H264 (.mp4 file), favoured by Microsoft and Apple
  • Theora (.ogv file), favoured by Mozilla
  • VP8 (.webm file) favoured by Google
If you looked at the W3 Schools' HTML5 Video page, you would seen the major problem with the whole thing:  there wasn't a single one of those file formats that was supported by all 3 of the major browsers!  Furthermore, Internet Explorer requires at least version 9 to support any kind of HTML5 video, and my site needed to support IE7 and IE8.  So, we would have been forced to keep at least two versions of our video files converted to cover the big three browsers, plus a JavaScript/Flash fallback for IE8 and earlier.  I decided to keep using our Flash/JavaScript video solution, which has the major problem that it won't play on iPads or iPhones.

Today

Look at that W3 Schools' HTML5 Video page now though, and you'll see that there's been some major movement: Firefox now supports H264 .mp4!!  Only on Windows, and then only Windows Visa or higher at the moment, although Mac and Linux is supposed to be coming (maybe XP as well?)

The second major change is an internal one: my site no longer needs to support IE8 or earlier.  So, yes, that means we can use only one file format!! .mp4 saves the day!

That's when I ran into problems.  The videos would play on some browsers but not others.  


MIME Type

If you have such problems, then you need to check your MIME types are set up correctly for HTML5 video on the Domino server.   If the MIME type is missing on your Domino server, then you'll likely see the video as something like "application/octet-stream" in Chrome:
MP4 with missing MIME type


For .mp4, the browser should show a MIME type of "video/mp4" as shown below (in Chrome):
MP4 with correct MIME type

To fix this, you need to have your friendly Domino admin edit the httpd.cnf file, which should be somewhere in your server's Domino folder.  For .mp4, you need to add the following line to the that file:

AddType .mp4 video/mp4


Your admin will need to restart the HTTP task after saving the file.  (I don't think a refresh is enough.)


Apple iDevices

That fixed things on the desktop browsers, but there was still one major problem.  My .mp4 files wouldn't play on iPhones or iPads.  It worked fine on desktop, and most annoyingly, on a test Android phone!  On the iPhone though, it just showed with a line through it, and refused to play:
MP4 video won't play on iPhone

As iDevice compatibility was one of the big pay-offs for doing this project in the first place, so I had to simply get it working.


At first, I thought it must be something to do with the video file encoding.  Apple's devices are very fussy about the .mp4 encoding for HTML5 web video.  It has to be H264 encoded for video, with AAC for audio.  But I couldn't get that to work on our internal network.  Oddly enough though, the same video file was served up fine to me iPhone by my own, personal Domino server.  Was it the company network messing things up then?

Nope, it was something far more dumb than that.  It was Domino compression.


Don't Compress Video in Notes!

When I was adding the .mp4 files to my Notes Rich Text fields, I was doing it dragging and dropping them from the Windows File Manager.  But if you do that, the files are always compressed.   This was pointless because these kind of files are already compressed up to the eyeballs before they reach Domino.

I knew all this, but didn't think it could possibly be the problem.  Almost out of desperation, I deleted the video from the Rich Text field, then reattached it using the paperclip icon, remembering to untick the Compress checkbox as I did it.  Bingo!   My .mp4 file now plays fine on my iPhone:
MP4 video ready to play on iPhone

Why this should be the case, and for iDevices only, I'm not really sure.  My guess is that when Domino serves up a compressed file, there's a short delay while the server decompresses it, and the iPhone is being over sensitive to that delay.


 

"Google’s Threat To MIcrosoft, Chromebooks Are Now ... 10% Of All Computers"

Michael Brown  December 29 2013 05:32:02 PM
This is from Forbes, and the full quote is:

"Google's Threat To MIcrosoft, Chromebooks Are Now 21% Of All Notebooks And 10% Of All Computers"

As Shaggy used to say, "like wow!!!"

There have been signs that this was coming for quite a while: the Samsung Chromebook sat at the top of Amazon's PC sales charts for months on end, yet Amazon refused to release any actual sales figures.  Yet here it is, and not from some nerdy, IT blogger either. Nope, this is from Forbes, the darling of Wall Street.

Suddenly, Microsoft's anti-Chromebook "Scroogled" adverts make some sense: I mean, would the company spend time and money trying to dismiss something that they weren't afraid of?

There's zinger after zinger quotes for Microsoft in here.  Here's just one:

Sales [of Windows] were driven forward in the past by those network effects: everyone else had Windows, everyone was writing for Windows, therefore I must have Windows too. But if those things are no longer true then we’re going to get, pretty rapidly, to a state where Windows isn’t even the default OS for a laptop or notebook: and I can see that following to the desktop soon enough.

Here in Australia, I've seen figures that show Windows usage is down 10% from calendar year 2012 to calendar year 2013.  10%!!!!  And sorry, but Windows 8.1 isn't going to stop that rot.  Once the tipping point is reached, and people stop thinking of Windows as that default thing that you have to have with every PC, then that will be the end for Microsoft in this space; maybe in every space.

Notes Calendar invitees - hidden web service!

Michael Brown  November 14 2013 02:51:13 PM
I've been working on a Web-based calendar that has an ordinary Notes calendar as its source at the back-end.

I was struggling on how to get the invitee status for a Notes calendar entry.  Digging through the Notes mail file design, there's a lot of undocumented LotusScript classes and methods at use for that purpose.  I managed to lift some of that stuff and got it half-working, but not quite there.  Then I came across a way to get it all put on a plate for me!

First, here's a direct link to my calendar entry itself:

http://184.73.169.93:8080/mail/testmail.nsf/0/09ADB82D7590879300257C22006E7CA6/?OpenDocument

Now, see what happens when I append the "&Form=s_ReadPartStatus" parameter:

http://184.73.169.93:8080/mail/testmail.nsf/0/09ADB82D7590879300257C22006E7CA6/?OpenDocument&Form=s_ReadPartStatus

Wow!  There's the participant statuses served up for me as XML.  Too easy!

I couldn't find a way to get it to produce JSON, so I used the xml2json library to do that, then ran the following jQuery function to map the relevant data to a smaller JSON object:

var jsonObj = $.xml2json(xml);
var mappedObj = $.map(jsonObj.viewentries.viewentry, function(value, index) {
       lineObj = {};
       if (value.entrydata[1].text.value) {
               lineObj.primaryName = value.entrydata[1].text.value;
       }
       if (value.entrydata[2].text.value) {
               lineObj.alternateName = value.entrydata[2].text.value;
       }
       if (value.entrydata[5].text.value) {
               lineObj.roleName = value.entrydata[5].text.value;
       }
       if (value.entrydata[7].text.value) {
               lineObj.statusName = value.entrydata[7].text.value;
       }
       if (value.entrydata[16].text.value) {
               lineObj.delegee = value.entrydata[16].text.value;
       }
       return lineObj;
});



If you're looking for the s_ReadPartStatus form in your mail file design, you won't find it.  It's actually in iNotes Forms database (iNotes\forms85.nsf).

Taskbar on every monitor!

Michael Brown  November 7 2013 04:01:28 AM
Some time ago, I inherited a widescreen monitor from a friend who as about to leave the country (thanks, George!)  I have it set up as my main monitor, right in front of me, in a dual monitor config with my old 4:3 Acer monitor, which I've positioned to my right.

In the last few months though, it's developed a serious glitch. (Really, can't you get eff all for eff all money any more?)  The glitch is that it flickers so badly that it's unusable for about 10 minutes.  After that, it seems to "warm up" and start behaving itself again- perhaps with few sharp slaps from my hand to help it along.  

No problem, you might think: I can still use my 4:3 monitor while the widescreen one is warming up, right?  Which brings us to the taskbar.  I want the taskbar on my main, widscreen monitor, rather than the 4:3 monitor.  But that means that for the warming up period, the taskbar can't be used while my widescreen monitor is warming up.  And with no taskbar, I have no program switching, no program launching for that matter.  Sure, I can move the taskbar to my secondary monitor, but I don't want it stil there after my main, widescreen monitor finally comes online.  And moving it back and forth between monitors is a pain. (When I shutdown my PC, I have to remember to move the taskbar back to the secondary monitor, otherwise it will be unavailable when I start my PC up the next day.)

What I need then is a way of puting the taskbar on both of my monitors.  In KDE/Linux, it's a piece of cake; I simply add a new panel on the second monitor!  Windows 7, however, doesn't seem to have any built-in way of doing this.

Enter Actual Tools Multiple Monitors, which (according to their blurb) allows "you will get a fully functional taskbar onto each display".  It's $25, but they do offer a free 30-day trial.  I'm running the latter at the moment, and it seems to work quite well (see screenshot below):

Actual Multiple Monitors

My first Chrome extension: Forum Troll Blocker!

Michael Brown  August 31 2013 10:39:15 PM
A couple of weeks back, I wrote a post called Dealing with trolls on ZDNet comments, which showed how to block trolls in the ZDnet.com technical forums by using the Tampermonkey Chrome extension.  Although I was pretty pleased with it at the time, it was rather obviously a "geeks only" exercise.  You had to edit JavaScript by hand to define your own list of trolls; not exactly a layman's task.  So I thought, why not make it a Chrome extension in its own right?  I could then give users an basic GUI to define their trolls rather than having to mess with JavaScript.  So that's what I did.

And here it is; the Forum Troll Stomper extension for Google Chrome!

Forum Troll Stomper extension in the Chrome Web Store

It's basically the same JavaScript code that I was running under the Tampermonkey extension, only with some extra HTML and CSS to make it an extension in its own right.  It took a bit of time to acquaint myself with the basic ins and outs of developing Chrome Extensions, but  it's nothing too difficult for anybody who's done any kind of web development.  There's a one-off Developer Fee of $5 - yes, five whole USD - to pay in order to load Chrome Extensions and apps on the Chrome Web Store.  In fact, when I went to pay even this modest fee, I discovered that I'd already done so over a year ago!  (Which makes me either far-sighted or just bone idle.)

As it says in my blurb on the Chrome Store, the Forum Troll Stomper extension is only for the ZDNet.com forums at the moment, just because it's a forum that I happen to frequent that has a real troll problem, IMHO.  But it shouldn't be any real problem to adapt to other forums if there's a need.






Dealing with trolls on ZDNet comments

Michael Brown  August 14 2013 04:35:26 PM
Comments on ZDNet tech articles these says, invariably descend into an ill-mannered slanging match.

Actually, a good many IT sites are prone to this problem, but on ZDNet it's particularly bad.  The worst offenders, IMHO, are a small group of Microsoft trolls, who go by names such as Owllllnet, Loverock-Davidson and toddbottom.  You know they're bad because their names turn up under different spellings (because they got banned from the forums under the previous spelling).  So Owllnet, might be Owlllnet, Owlllllnet or Owllllllnet and so on; each new spelling was a forum ban, causing him to go register under a new name.  Likewise toddbottom might be toddbottom2 or toddbottom3.  And so on.

What each of these trolls has in common is a religiously pro-Microsoft agenda.  This goes far beyond legitimate opinion: anybody making points even mildly against Microsoft, or in favour of Microsoft competitors, is relentlessly attacked and ridiculed.  They like to turn up on posts from Steven J Vaughan-Nichols, since he's a Linux aficionado.  Here's a prime example: a Vaughan-Nichols article describing a windows powered botnet.  See how toddbottom (he's up to "3"  here) wades in, in full attack mode.

Trolls on ZDNet

Wouldn't it be nice to have a kill file for idiots like this, like you do for email?  I thought so too.  So I wrote one!  I've called it Filter ZDnet Troll Comments (catchy, eh?) and it takes the form of a user script.

User Scripts

User scripts are JavaScripts that you, the user, can insert into sites, even where you don't control that site's code.  You insert them at the browser level, in effect.  The easiest way to install them is a via an extension or plug-in.  I used one called for Tampermonkey for Google Chorme to install my script, although it should also work with Greasemonkey for Firefox, although I haven't tested the latter.

Adding the Script to Tampermonkey

To find my script, once you've installed the Tampermonkey, you need to:
  1. Click on the Tampermonkey icon on your Chrome toolbar and choose "Get new scripts..." from the pop-up menu.
  2. That will open the userscripts.org site.  Type in "zdnet" as your search term, and my Filter ZDnet Troll Comments script should be the top listed one (because it's the most recent updated one as I write this!)
  3. Click the script's URL to open it.
  4. Click the Install button at the top right.

If you now visit the that Vaughan-Nichols article again, it should look like this:

Trolls not on ZDNet

Yep, Mr Bottom is no longer present in the comments!  The Chrome console confirms the blocking of his comments.

Editing the Script

That's all fine for my personal bugbears, but I'm sure you have your own.  So, here's how to edit the script to block out your own, personal trolls:
  1. Click on the Tampermonkey icon on your Chrome toolbar and choose "Dashboard" from the pop-up menu.
  2. The Filter ZDnet Troll Comments script should be the listed in your Dashboard.  Click on it to Edit.
  3. Click the script's URL to open it.
  4. Click on the Save button when you're done editing


The Script Itself

If you're familiar with JavaScript, you'll see that there's not really a lot to it.  There's some jQuery that finds all elements (divs, actually) that have the class of "author" to get the authors of the comments on that page.  It then compares those authors against master array of troll names.  If the author is in the troll array, then the author's parent comment div (class = "commentWrapper") is hidden.

Here's the troll array, which you'll need to customise to your own (dis)tastes:
myFilter.globals.filterList = [
  ["william farrel"],
  ["owl", "net"],
  ["toddbottom"],
  ["loverock", "davidson"]
];


As you can see, each name in the array is an array itself.  The code will fail the author as a troll if each member of that inner array is contained somewhere in the author's name.  So "owl" and "net" are both contained in Owlnet, Owlllnet, Owlllllnet and so on, so he can't escape, unless he changes his name completely.  "toddbottom", on the other hands, is contained by "toddbottom", "toddbottom2", "toddbottom3" etc, so I only needed to specify his name as a single-member array.


Dealing with trolls on ZDNet comments

Michael Brown  August 14 2013 04:35:26 PM
Comments on ZDNet tech articles these says, invariably descend into an ill-mannered slanging match.

Actually, a good many IT sites are prone to this problem, but on ZDNet it's particularly bad.  The worst offenders, IMHO, are a small group of Microsoft trolls, who go by names such as Owllllnet, Loverock-Davidson and toddbottom.  You know they're bad because their names turn up under different spellings (because they got banned from the forums under the previous spelling).  So Owllnet, might be Owlllnet, Owlllllnet or Owllllllnet and so on; each new spelling was a forum ban, causing him to go register under a new name.  Likewise toddbottom might be toddbottom2 or toddbottom3.  And so on.

What each of these trolls has in common is a religiously pro-Microsoft agenda.  This goes far beyond legitimate opinion: anybody making points even mildly against Microsoft, or in favour of Microsoft competitors, is relentlessly attacked and ridiculed.  They like to turn up on posts from Steven J Vaughan-Nichols, since he's a Linux aficionado.  Here's a prime example: a Vaughan-Nichols article describing a windows powered botnet.  See how toddbottom (he's up to "3"  here) wades in, in full attack mode.

Trolls on ZDNet

Would it be nice to have a kill file for idiots like this, like you do for email?  I thought so too.  So I wrote one!  I've called it Filter ZDnet Troll Comments (catchy, eh?) and it takes the form of a user script.

User Scripts

User scripts are JavaScripts that you, the user, can insert into sites, even where you don't control that site's code.  You insert them at the browser level, in effect.  The easiest way to install them is a via an extension or plug-in.  I used one called for Tampermonkey for Google Chorme to install my script, although it should also work with Greasemonkey for Firefox, although I haven't tested the latter.

Adding the Script to Tampermonkey

To find my script, once you've installed the Tampermonkey, you need to:
  1. Click on the Tampermonkey icon on your Chrome toolbar and choose "Get new scripts..." from the pop-up menu.
  2. That will open the userscripts.org site.  Type in "zdnet" as your search term, and my Filter ZDnet Troll Comments script should be the top listed one (because it's the most recent updated one as I write this!)
  3. Click the script's URL to open it.
  4. Click the Install button at the top right.


Here's a direct link to the script if you don't want to go through all those steps.  Assuming you've installed the script, if you now visit the that Vaughan-Nichols article again, it should look like this:

Trolls not on ZDNet

Yep, Mr Bottom is no longer present in the comments!  The Chrome console confirms the blocking of his comments.

Editing the Script

That's all fine for my personal bugbears, but I'm sure you have your own.  So, here's how to edit the script to block out your own, personal trolls:
  1. Click on the Tampermonkey icon on your Chrome toolbar and choose "Dashboard" from the pop-up menu.
  2. The Filter ZDnet Troll Comments script should be the listed in your Dashboard.  Click on it to Edit.
  3. Click the script's URL to open it.
  4. Click on the Save button when you're done editing


The Script Itself

If you're familiar with JavaScript, you'll see that there's not really a lot to it.  There's some jQuery that finds all elements (divs, actually) that have the class of "author" to get the authors of the comments on that page.  It then compares those authors against master troll array of names.  If the author is in the troll array, then the author's parent comment div (class = "commentWrapper") is hidden.

Here's the troll array, which you'll need to customise to your own (dis)tastes:
myFilter.globals.filterList = [
   ["william farrel"],
   ["owl", "net"],
   ["toddbottom"],
   ["loverock", "davidson"]
];


As you can see, each name in the array is an array itself.  The code will fail the author as a troll if each member of that inner array is contained somewhere in the author's name.  So "owl" and "net" are both contained in Owlnet, Owlllnet, Owlllllnet and so on, so he can't escape, unless he changes his name completely.  "toddbottom", on the other hands, is contained by "toddbottom", "toddbottom2", "toddbottom3" etc, so I only needed to specify his name as a single-member array.

Xmarks is synching... and synching....

Michael Brown  August 3 2013 09:58:04 PM
Xmarks synching...

I've been using the Xmarks browser extension for a number of years now.  It synchs your bookmarks between your installed browsers.  Yes, Chrome and Firefox (and IE?) have their own, free, built-in bookmarks synching tools, and they'll synch across platform (apart from IE).  But none of them will synch across brand - i.e. Chrome only synchs to Chrome, and Firefox only synchs to Firefox, and so on.  Xmarks synchs bookmarks between Chrome, Firefox, Safari and yes, even IE.

Recently though, I've been having some problems with it.  Namely, it gets stuck on the synching dialog and never seems to finish; I'm talking 15-20 minutes here.  Worse still, if it ever does eventually finish, it will end up wiping most of my bookmarks!

I've noticed this mainly on Chrome, which is the browser I most use for ... errmmm... browsing!  FYI, I mainly use Firefox for its development tools (Firebug rocks!) and IE, well, only when I need to test whether something works on IE.  Otherwise, I avoid IE like the proverbial plague.  I tried all sorts of fixes from the Xmarks extension itself: e.g. "Repair Bookmarks", and the download bookmarks feature, all to no avail.  Either they didn't finish again, or wiped most of my bookmarks.

Here's what fixed it for me.

First, I logged into the https://my.xmarks.com site, and checked my bookmarks that were stored there.  Wow, what a mess!   I had bazilliions of bookmarks there, most of them repeats of repeats of duplicates, repeated in sub-folders of sub-folders ad nauseam.  So, I obviously needed to sort that out, but before I did, I backed up what was there.  To do that, go to Tools->Export Bookmarks to HTML from the myxmarks site.  If you're following my procedure, then you should backup your bookmarks after each step, so that you've got something to go back to.  Back them up to your hard drive, and than back that file up to Google Drive, Dropbox, a USB stick, whatever.  You want in at least two backup locations to be safe.

Okay, having backed up the best, I went into the myxmarks site and starting tidying up.  This was mostly deleting redundant bookmarks and merging duplicate folders; it's all drag and drop, so not too difficult.

Once I had my bookmarks in decent shape on the myxmarks site, I exported them to HTML again.  My plan was to delete my local bookmarks in Chrome, and then import the HTML file into Chrome to replace them.  Small problem: Chrome doesn't have an import bookmarks from HTML feature!  Or if it does, I couldn't find it.  So instead, I loaded up Firefox and did it from there.  Namely:
  1. I opened the Bookmarks Manager (Bookmarks->Show all Bookmarks) in Firefox and deleted all my bookmarks there.
  2. Still in the Firefox Bookmarks Manager, I clicked on Import and Backup->Import Bookmarks from HTML and selected the last HTML backup that I'd saved from the myxmarks site.  When done, I checked that my bookmarks in Firefox looked okay.
  3. Still in Firefox, I launched the Xmarks Advanced setting (click on the Xmarks icon on your toolbar and pick the Advanced tab - note that in Firefox, the Xmarks icon maybe on your Add-on bar, at the bottom, so you'll need to be displaying that).  Under the Advanced tab hit the Upload button.  Warning, this wipes your bookmarks on the myxmarks site and replace them with what's now in Firefox, so double-check that you took all those backups!
  4. That sorted me out for Firefox and also my bookmarks stored on the myxmarks site.  I now needed to switch to Chrome and do the reverse process: call up the Xmarks Advanced tab and click on the Download Bookmarks button.  This wiped my current Chrome bookmarks, but those were a mess (which is where I started).




Dynamic form validation with jQuery

Michael Brown  July 19 2013 04:20:00 AM
I've been using the superb jQuery Validation Plugin for a number of years now, and really, I don't know how I got by without it before.

Basically, it allows you to (relatively) easily set up form validation notifications that appear on the form itself - e.g. if a field needs a value, then some (usually red coloured) text will appear next to the that field, telling you so.  Here's some examples of how the plugin works.

I see so much old code - and not so old code, for that matter - where the programmer seems to think that users like nothing better than dismissing alert() dialogs when filling forms.  And when they've dismissed the first one, they click on the Submit button again, only to run into the next dialog, telling them that they've failed in their duty (missed another field) yet again.  Repeat and rinse, ad infinitum.

A project that I've been working on recently has caused me to stretch the plugin even further, and thankfully, it was well up to the job.  The requirement for this new project was that the form fields required would change, according to what options the user had selected further up the form.  Dynamic rules, in other words.  Here's a jsfiddle demo of what I mean.

On this simple form, I've set up three text fields that might require validation.  Above them is a radio option field.  If the first radio button option is checked, then one of the three text fields is required for validation.  If the second radio button option is selected, then two of three of those fields are required.  Click on the Submit button, and the validation messages, to the right of the fields, will change according to which radio button you have checked.  Not only that, but those validation messages should then disappear when you've entered something into the requisite number of fields: one or two, as the case may be.

This post on stackoverflow helped me approach this problem.  In particular, Ryley's answer gave me the require_from_group2 add-on method for the jQuery Validate plug-in, and also the addRules() and removeRules() functions.

The key to how it works is the rulesConfigObj object.  Within this object I've set up what I call "rule groups" - "oneOfTwo" and "twoOfThree" - each of which contains the jQuery Validation parameters that I want set at a particular time.  When the radio button is clicked, its jQuery.change() event does two things.  First, it removes any existing rule groups from the jQuery Validation plugin - via the removeRulesGroup() function, which is my own contribution (although it's really just a wrapper around removeRules()).  Second, it adds the appropriate rule group, "oneOfTwo" or "twoOfThree", depending on what the user picked on the radio button.

Read through the code on the JSFiddle and you should be able to follow the rest.

About