Wednesday, April 23, 2014

jQuery UI: Disabled Tabs Are Better

If you're using the jQuery UI tabs widget, the beforeActivate event gives you the opportunity to "cancel" the activation of the tab. This works by having your handler function for this event return false. The widget knows that a false value returned by any of the beforeActivate handlers means that the whole show is off. In practice, however, this isn't necessarily the best way to go about handling tabs that shouldn't be activated.

For example, let's say that there's currently some condition in my UI that should prevent the second tab from being activated. In other words, should the user decide to click on it, nothing should happen because, well, the condition. Here's what that code looks like.

$( "#tabs" ).tabs({
    beforeActivate: function( e, ui ) {
        if ( condition &&
             $( this ).find( ".ui-tabs-nav > li" )
                 .index( ui.newTab ) === 1 ) {
            return false;
        }
    }
});

The condition variable represents the logic of your application says "don't let the user activate this tab" — it could be anything. The rest of the condition is just checking the index of the clicked tab. If it's the tab the condition forbids from being activated, we return false, and nothing happens. Everybody's happy. Except the user, because the tab looks like it's clickable.

The second tab looks like it's supposed to be clicked, or at least, that if I click it, something's going to happen. Which isn't the case, given the way we've coded things. The better approach is to use the disabled option. This takes care of ensuring that the tab cannot be activated, and it takes care of informing the user that it can't be activated by visually disabling it. For example, disabling the second tab is done like so.

$( "#tabs" ).tabs( "option", "disabled", [ 1 ] );

The result is a much better user experience.

It's just as easy to re-enable the tab, once the conditions of our UI permit doing so.

$( "#tabs" ).tabs( "option", "disabled", [] );