cms/drupal/misc/vertical-tabs.js
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     1 
       
     2 (function ($) {
       
     3 
       
     4 /**
       
     5  * This script transforms a set of fieldsets into a stack of vertical
       
     6  * tabs. Another tab pane can be selected by clicking on the respective
       
     7  * tab.
       
     8  *
       
     9  * Each tab may have a summary which can be updated by another
       
    10  * script. For that to work, each fieldset has an associated
       
    11  * 'verticalTabCallback' (with jQuery.data() attached to the fieldset),
       
    12  * which is called every time the user performs an update to a form
       
    13  * element inside the tab pane.
       
    14  */
       
    15 Drupal.behaviors.verticalTabs = {
       
    16   attach: function (context) {
       
    17     $('.vertical-tabs-panes', context).once('vertical-tabs', function () {
       
    18       var focusID = $(':hidden.vertical-tabs-active-tab', this).val();
       
    19       var tab_focus;
       
    20 
       
    21       // Check if there are some fieldsets that can be converted to vertical-tabs
       
    22       var $fieldsets = $('> fieldset', this);
       
    23       if ($fieldsets.length == 0) {
       
    24         return;
       
    25       }
       
    26 
       
    27       // Create the tab column.
       
    28       var tab_list = $('<ul class="vertical-tabs-list"></ul>');
       
    29       $(this).wrap('<div class="vertical-tabs clearfix"></div>').before(tab_list);
       
    30 
       
    31       // Transform each fieldset into a tab.
       
    32       $fieldsets.each(function () {
       
    33         var vertical_tab = new Drupal.verticalTab({
       
    34           title: $('> legend', this).text(),
       
    35           fieldset: $(this)
       
    36         });
       
    37         tab_list.append(vertical_tab.item);
       
    38         $(this)
       
    39           .removeClass('collapsible collapsed')
       
    40           .addClass('vertical-tabs-pane')
       
    41           .data('verticalTab', vertical_tab);
       
    42         if (this.id == focusID) {
       
    43           tab_focus = $(this);
       
    44         }
       
    45       });
       
    46 
       
    47       $('> li:first', tab_list).addClass('first');
       
    48       $('> li:last', tab_list).addClass('last');
       
    49 
       
    50       if (!tab_focus) {
       
    51         // If the current URL has a fragment and one of the tabs contains an
       
    52         // element that matches the URL fragment, activate that tab.
       
    53         if (window.location.hash && $(this).find(window.location.hash).length) {
       
    54           tab_focus = $(this).find(window.location.hash).closest('.vertical-tabs-pane');
       
    55         }
       
    56         else {
       
    57           tab_focus = $('> .vertical-tabs-pane:first', this);
       
    58         }
       
    59       }
       
    60       if (tab_focus.length) {
       
    61         tab_focus.data('verticalTab').focus();
       
    62       }
       
    63     });
       
    64   }
       
    65 };
       
    66 
       
    67 /**
       
    68  * The vertical tab object represents a single tab within a tab group.
       
    69  *
       
    70  * @param settings
       
    71  *   An object with the following keys:
       
    72  *   - title: The name of the tab.
       
    73  *   - fieldset: The jQuery object of the fieldset that is the tab pane.
       
    74  */
       
    75 Drupal.verticalTab = function (settings) {
       
    76   var self = this;
       
    77   $.extend(this, settings, Drupal.theme('verticalTab', settings));
       
    78 
       
    79   this.link.click(function () {
       
    80     self.focus();
       
    81     return false;
       
    82   });
       
    83 
       
    84   // Keyboard events added:
       
    85   // Pressing the Enter key will open the tab pane.
       
    86   this.link.keydown(function(event) {
       
    87     if (event.keyCode == 13) {
       
    88       self.focus();
       
    89       // Set focus on the first input field of the visible fieldset/tab pane.
       
    90       $("fieldset.vertical-tabs-pane :input:visible:enabled:first").focus();
       
    91       return false;
       
    92     }
       
    93   });
       
    94 
       
    95   this.fieldset
       
    96     .bind('summaryUpdated', function () {
       
    97       self.updateSummary();
       
    98     })
       
    99     .trigger('summaryUpdated');
       
   100 };
       
   101 
       
   102 Drupal.verticalTab.prototype = {
       
   103   /**
       
   104    * Displays the tab's content pane.
       
   105    */
       
   106   focus: function () {
       
   107     this.fieldset
       
   108       .siblings('fieldset.vertical-tabs-pane')
       
   109         .each(function () {
       
   110           var tab = $(this).data('verticalTab');
       
   111           tab.fieldset.hide();
       
   112           tab.item.removeClass('selected');
       
   113         })
       
   114         .end()
       
   115       .show()
       
   116       .siblings(':hidden.vertical-tabs-active-tab')
       
   117         .val(this.fieldset.attr('id'));
       
   118     this.item.addClass('selected');
       
   119     // Mark the active tab for screen readers.
       
   120     $('#active-vertical-tab').remove();
       
   121     this.link.append('<span id="active-vertical-tab" class="element-invisible">' + Drupal.t('(active tab)') + '</span>');
       
   122   },
       
   123 
       
   124   /**
       
   125    * Updates the tab's summary.
       
   126    */
       
   127   updateSummary: function () {
       
   128     this.summary.html(this.fieldset.drupalGetSummary());
       
   129   },
       
   130 
       
   131   /**
       
   132    * Shows a vertical tab pane.
       
   133    */
       
   134   tabShow: function () {
       
   135     // Display the tab.
       
   136     this.item.show();
       
   137     // Show the vertical tabs.
       
   138     this.item.closest('.vertical-tabs').show();
       
   139     // Update .first marker for items. We need recurse from parent to retain the
       
   140     // actual DOM element order as jQuery implements sortOrder, but not as public
       
   141     // method.
       
   142     this.item.parent().children('.vertical-tab-button').removeClass('first')
       
   143       .filter(':visible:first').addClass('first');
       
   144     // Display the fieldset.
       
   145     this.fieldset.removeClass('vertical-tab-hidden').show();
       
   146     // Focus this tab.
       
   147     this.focus();
       
   148     return this;
       
   149   },
       
   150 
       
   151   /**
       
   152    * Hides a vertical tab pane.
       
   153    */
       
   154   tabHide: function () {
       
   155     // Hide this tab.
       
   156     this.item.hide();
       
   157     // Update .first marker for items. We need recurse from parent to retain the
       
   158     // actual DOM element order as jQuery implements sortOrder, but not as public
       
   159     // method.
       
   160     this.item.parent().children('.vertical-tab-button').removeClass('first')
       
   161       .filter(':visible:first').addClass('first');
       
   162     // Hide the fieldset.
       
   163     this.fieldset.addClass('vertical-tab-hidden').hide();
       
   164     // Focus the first visible tab (if there is one).
       
   165     var $firstTab = this.fieldset.siblings('.vertical-tabs-pane:not(.vertical-tab-hidden):first');
       
   166     if ($firstTab.length) {
       
   167       $firstTab.data('verticalTab').focus();
       
   168     }
       
   169     // Hide the vertical tabs (if no tabs remain).
       
   170     else {
       
   171       this.item.closest('.vertical-tabs').hide();
       
   172     }
       
   173     return this;
       
   174   }
       
   175 };
       
   176 
       
   177 /**
       
   178  * Theme function for a vertical tab.
       
   179  *
       
   180  * @param settings
       
   181  *   An object with the following keys:
       
   182  *   - title: The name of the tab.
       
   183  * @return
       
   184  *   This function has to return an object with at least these keys:
       
   185  *   - item: The root tab jQuery element
       
   186  *   - link: The anchor tag that acts as the clickable area of the tab
       
   187  *       (jQuery version)
       
   188  *   - summary: The jQuery element that contains the tab summary
       
   189  */
       
   190 Drupal.theme.prototype.verticalTab = function (settings) {
       
   191   var tab = {};
       
   192   tab.item = $('<li class="vertical-tab-button" tabindex="-1"></li>')
       
   193     .append(tab.link = $('<a href="#"></a>')
       
   194       .append(tab.title = $('<strong></strong>').text(settings.title))
       
   195       .append(tab.summary = $('<span class="summary"></span>')
       
   196     )
       
   197   );
       
   198   return tab;
       
   199 };
       
   200 
       
   201 })(jQuery);