Custom checkboxes and radio buttons with jQuery

A recent project required checkboxes and radio buttons with a custom appearance, and searching around turned up numerous solutions to this need. There were a variety of approaches to solve the problem to varying degrees of completeness. The one I liked best was provided by Filament Group, the talented folks behind jQuery’s UI ThemeRoller. It was relatively lightweight, worked like a charm, and accessible to boot.

However, it didn’t support disabling the controls, something I needed. The developers say they will add this ability, but I needed it quickly, so I figured I’d just add it myself.

I encountered a couple other issues that required tweaks as well, which I’ll describe here for posterity. The first was integrating the jQuery UI dialog widget. I had a dialog with some radio buttons, and they looked great out of the box. Hovers and checked states worked fine, but clicking had no effect. It turns out that the modal div’s z-index was interfering. An odd problem, but easily fixed with some CSS to set the z-index higher than the theme’s modal z-index:
.ui-dialog .custom-radio label {
z-index: 1006;

The second issue was that my application generates markup fragments and binds their event handlers before inserting into the DOM. The original code grabs references to each input’s label and other radio buttons in a radio button set at the time the checkbox or radio is prepared. The problem is, if the markup fragment is not part of the document yet, those references are empty. For the radios, I modified the code so the other radios were not predetermined, but instead are located at the time they’re needed in the updateState() function:


Late-binding like this has the added benefit that if other radio buttons are added to the set after the page loads, they are still accounted for.

The reference to the label could also be solved in the same way, but I solved it by just grabbing the element following the input, which in my case, was guaranteed to be the label. Your mileage may vary.

I decided to make 2 other tweaks as long as I had my mind wrapped around this stuff. First, I eliminated the checkedHover and checkedFocus CSS classes because I don’t think they were necessary (But beware, I have not tested this assumption thoroughly yet). That allows deleting a small amount of JavaScript, but it requires some changes in the original CSS selectors, for example:
.custom-checkbox label.checkedHover
.custom-checkbox label.checked.hover

The final tweak was to replace the inputType variable with a reference to the wrapper div. I had a place where I needed to dynamically change a list of checkboxes to a list of radio buttons (or vice-versa). Having a reference to the wrapper div was much more helpful in this circumstance, and the inputType variable wasn’t doing anything except helping to build the wrapper div anyway, so no sense to keep it in the closure.

You can find the source files here.