summaryrefslogtreecommitdiffstatshomepage
path: root/core/misc/vertical-tabs.js
blob: 369fbfac0e1c11bdc5070ac4c4138b4ab83a47d0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
* DO NOT EDIT THIS FILE.
* See the following change record for more information,
* https://www.drupal.org/node/2815083
* @preserve
**/

(function ($, Drupal, drupalSettings) {
  const handleFragmentLinkClickOrHashChange = (e, $target) => {
    $target.parents('.vertical-tabs__pane').each((index, pane) => {
      $(pane).data('verticalTab').focus();
    });
  };

  Drupal.behaviors.verticalTabs = {
    attach(context) {
      const width = drupalSettings.widthBreakpoint || 640;
      const mq = `(max-width: ${width}px)`;

      if (window.matchMedia(mq).matches) {
        return;
      }

      $(once('vertical-tabs-fragments', 'body')).on('formFragmentLinkClickOrHashChange.verticalTabs', handleFragmentLinkClickOrHashChange);
      once('vertical-tabs', '[data-vertical-tabs-panes]', context).forEach(verticalTab => {
        const $this = $(verticalTab).addClass('vertical-tabs__panes');
        const focusID = $this.find(':hidden.vertical-tabs__active-tab')[0].value;
        let tabFocus;
        const $details = $this.find('> details');

        if ($details.length === 0) {
          return;
        }

        const tabList = $('<ul class="vertical-tabs__menu"></ul>');
        $this.wrap('<div class="vertical-tabs clearfix"></div>').before(tabList);
        $details.each(function () {
          const $that = $(this);
          const $summary = $that.find('> summary');
          const verticalTab = new Drupal.verticalTab({
            title: $summary.length ? $summary[0].textContent : '',
            details: $that
          });
          tabList.append(verticalTab.item);
          $that.removeClass('collapsed').removeAttr('open').addClass('vertical-tabs__pane').data('verticalTab', verticalTab);

          if (this.id === focusID) {
            tabFocus = $that;
          }
        });
        $(tabList).find('> li').eq(0).addClass('first');
        $(tabList).find('> li').eq(-1).addClass('last');

        if (!tabFocus) {
          const $locationHash = $this.find(window.location.hash);

          if (window.location.hash && $locationHash.length) {
            tabFocus = $locationHash.closest('.vertical-tabs__pane');
          } else {
            tabFocus = $this.find('> .vertical-tabs__pane').eq(0);
          }
        }

        if (tabFocus.length) {
          tabFocus.data('verticalTab').focus();
        }
      });
    }

  };

  Drupal.verticalTab = function (settings) {
    const self = this;
    $.extend(this, settings, Drupal.theme('verticalTab', settings));
    this.link.attr('href', `#${settings.details.attr('id')}`);
    this.link.on('click', e => {
      e.preventDefault();
      self.focus();
    });
    this.link.on('keydown', event => {
      if (event.keyCode === 13) {
        event.preventDefault();
        self.focus();
        $('.vertical-tabs__pane :input:visible:enabled').eq(0).trigger('focus');
      }
    });
    this.details.on('summaryUpdated', () => {
      self.updateSummary();
    }).trigger('summaryUpdated');
  };

  Drupal.verticalTab.prototype = {
    focus() {
      this.details.siblings('.vertical-tabs__pane').each(function () {
        const tab = $(this).data('verticalTab');
        tab.details.hide();
        tab.details.removeAttr('open');
        tab.item.removeClass('is-selected');
      }).end().show().siblings(':hidden.vertical-tabs__active-tab')[0].value = this.details.attr('id');
      this.details.attr('open', true);
      this.item.addClass('is-selected');
      $('#active-vertical-tab').remove();
      this.link.append(`<span id="active-vertical-tab" class="visually-hidden">${Drupal.t('(active tab)')}</span>`);
    },

    updateSummary() {
      this.summary.html(this.details.drupalGetSummary());
    },

    tabShow() {
      this.item.show();
      this.item.closest('.js-form-type-vertical-tabs').show();
      this.item.parent().children('.vertical-tabs__menu-item').removeClass('first').filter(':visible').eq(0).addClass('first');
      this.details.removeClass('vertical-tab--hidden').show();
      this.focus();
      return this;
    },

    tabHide() {
      this.item.hide();
      this.item.parent().children('.vertical-tabs__menu-item').removeClass('first').filter(':visible').eq(0).addClass('first');
      this.details.addClass('vertical-tab--hidden').hide().removeAttr('open');
      const $firstTab = this.details.siblings('.vertical-tabs__pane:not(.vertical-tab--hidden)').eq(0);

      if ($firstTab.length) {
        $firstTab.data('verticalTab').focus();
      } else {
        this.item.closest('.js-form-type-vertical-tabs').hide();
      }

      return this;
    }

  };

  Drupal.theme.verticalTab = function (settings) {
    const tab = {};
    tab.title = $('<strong class="vertical-tabs__menu-item-title"></strong>');
    tab.title[0].textContent = settings.title;
    tab.item = $('<li class="vertical-tabs__menu-item" tabindex="-1"></li>').append(tab.link = $('<a href="#"></a>').append(tab.title).append(tab.summary = $('<span class="vertical-tabs__menu-item-summary"></span>')));
    return tab;
  };
})(jQuery, Drupal, drupalSettings);