How do I add a menu subtitle to field sets displayed as vertical tabs? I have formatted my field sets in a form builder function to display as vertical tabs. Here's a snippet of my code. It works fine:

$form['vertical_tabs'] = array(
    '#type' =&gt; 'vertical_tabs',
);

// * Form elements: fieldset tree.
$form['episode'] = array(
    '#title' =&gt; t('Episode details'),
    '#type' =&gt; 'fieldset',
    '#tree' =&gt; TRUE,
    '#collapsible' =&gt; TRUE,
    '#group' =&gt; 'vertical_tabs',
);


I see a lot of vertical tabs with, let's call it, a menu subtitle just below the menu title. It's the grey text under the blue anchor text in this pic from the vertical_tabs module page - the top one reads 'Create new revision':



I guessed, wrongly, that adding a #description attribute with my menu subtitle would add it in, but is just appears at the top the field sets' tab contents. Does anyone know how this is done?

Thanks

SOLUTION

Some may consider this not to be the 'correct' Drupal way, but this is simple, requires hardly any code, resides in the Sites folder (so it won't be over written on update), and does not require editing any core files. Just a bit of CSS. This is what I did:

.vertical-tabs ul.vertical-tabs-list li:nth-child(1) .summary:after {
  content: 'Menu subtitle 1';
}
.vertical-tabs ul.vertical-tabs-list li:nth-child(2) .summary:after {
  content: 'Menu subtitle 2';
}


Clive's answer (see below) may be a better option if you're handy with JavaScipt.

ANOTHER SOLUTION

Here, is a jQuery solution I've developed:

Add this jQuery file to your module directory, call it jquery.YOURFILE.js:

/**
 * Vertical tabs summary setters.
 */
(function( $ ) {
  $(function() {
    $( ".summary:gt(0)" ).html( "Foo" );
    $( ".summary:gt(2)" ).html( "Bar" );
  });
})( jQuery );


Here I used the .gt method, but you could target tabs individually with the .eq method. In your form element definition, where you define your fieldsets, add:

'#attached' =&gt; array(
  'js' =&gt; array(drupal_get_path('module', 'YOURMODULE') . '/jquery.YOURFILE.js'),
),


MORE SOURCES OF INFORMATION

See the vertical_tabs examples module for another way to do this.

Look in content_types.inc and content_types.js in the node module too.

This is an update of the jQuery file above. It uses Drupal.behaviors and the eq method. Probably more 'correct' than the one above.

(function ($) {

Drupal.behaviors.yourModule = {
  attach: function (context) {
    $( ".summary:eq(0)" ).html( "Foo" );
    $( ".summary:eq(1)" ).html( "Bar" );
    $( ".summary:eq(2)" ).html( "Baz" );
  }
};

})(jQuery);
The tab summary is set by JavaScript (I don't think you can do it in PHP), per the comments in misc/vertical-tabs.js:


  Each tab may have a summary which can be updated by another script. For that to work, each fieldset has an associated 'verticalTabCallback' (with jQuery.data() attached to the fieldset), which is called every time the user performs an update to a form element inside the tab pane.


The node module has a good example of how to do this, the code in node.js should be pretty easy to adapt for your own module:

Drupal.behaviors.nodeFieldsetSummaries = {
  attach: function (context) {
    $('fieldset.node-form-revision-information', context).drupalSetSummary(function (context) {
      var revisionCheckbox = $('.form-item-revision input', context);

      // Return 'New revision' if the 'Create new revision' checkbox is checked,
      // or if the checkbox doesn't exist, but the revision log does. For users
      // without the "Administer content" permission the checkbox won't appear,
      // but the revision log will if the content type is set to auto-revision.
      if (revisionCheckbox.is(':checked') || (!revisionCheckbox.length &amp;&amp; $('.form-item-log textarea', context).length)) {
        return Drupal.t('New revision');
      }

      return Drupal.t('No revision');
    });

    ...


I think the only PHP change you'll need to make is to add a specific class to the fieldset so the JS can target it:

$form['episode'] = array(
  '#title' =&gt; t('Episode details'),
  '#type' =&gt; 'fieldset',
  '#tree' =&gt; TRUE,
  '#collapsible' =&gt; TRUE,
  '#group' =&gt; 'vertical_tabs',
  '#attributes' =&gt; array('class' =&gt; array('mymodule-node-options')),
);