Friday, March 28, 2014

jQuery UI: Icon Radio Buttons

If you have a group of radio buttons, you can use the buttonset widget to make them look like a jQuery UI widget. That is, you call the buttonset() plugin on a container element, usually a div, and the widget groups the radio button labels together, and applies styles from the theme framework. For example, here's what a radio buttonset widget looks like by default.

The markup to produce this widget uses two input elements, and two label elements. The labels are how the buttonset widget knows what text to display for each radio. Text is a good default, but it's often more space-efficient to get your point across using icons only. We should be able to modify the buttonset widget to support this since it's just a collection of regular buttons widgets — and they have an icon option.

Here's the example buttonset extension that makes this possible. Essentially, we're looking for a way to specify, in the markup, which icon should be displayed instead of the text label. Data attributes on the radio input elements themselves are a good starting point.

$.widget( "app.buttonset", $.ui.buttonset, {
    
    refresh: function() {
        
        this._super();
        
        this.buttons.each(function() {
            
            var $this = $( this ),
                icon = $this.data( "icon" );

            if ( !icon ) {
                return;    
            }
            
            $this.button( "option", {
                icons: { primary: icon },
                text: false
            });
            
        });
        
    }
    
});

In this extension of the buttonset widget, we have only one method to override — the refresh() method. The default implementation finds all the elements that make up the set and instantiates the button widget for each. We invoke this default behavior using _super(). Then, we iterate over each button in the buttons property and look for a data-icon attribute. If we find one, we simply take the value found in that attribute, the icon class, and apply it to the button. We also hide the text using the text option if an icon is found.