Thursday, January 9, 2014

Vertical Radio Button Groups

The jQuery UI buttonset widget, a group of buttons, can be used to group together form elements such as radio buttons. The label attached to the given radio control is used by the buttonset to display the button text. In other works, it'll format the labels with components from the theme framework while the radio is no longer visible, even though they're still used. The default layout for the buttonset widget is to stack the grouped buttons horizontally. With some style enhancements, we can make a vertical layout work with this widget.

This demonstration shows how it's done. Although the goal is a simple one, some of the gotchas with regard to state changes in the buttons are tricky to work out. But once you do, here's what the end result looks like.



The key to making these buttonset style adjustments is making the labels display as block. Also supplying the surrounding div container with a width. That gives us the basic change we're after in terms of alignment. The trick part is making this layout work with the hover and the active states. These state classes are added to the label elements by the buttonset widget.

Since these labels belong to a tightly-knit group, the top and bottom borders are pressed up against one another. That's easy enough to take care of by applying a transparent top or bottom border to certain elements, depending where they are in relation to other elements, and the state of those other elements. The part I couldn't figure out for the life of me was the hover state. My selector worked just fine, as I was hoping to handle all the border hacks using just CSS, but the property change just wouldn't take.

The workaround is the two JavaScript event handlers for the mouseenter and mouseleave events, which just adds, then removes, the ui-transparent-border-top class. Strange that this approach works and the CSS-based one did not.

The final task is an easy one — rearrange the border classes. While the original, horizontal layout was using left and right border classes from the CSS framework, we'll need to remove these, and add corners around the top and bottom instead. This done with a single line of JavaScript — while maintaining readability of course.