PageSourceSearch

https://www.izumi.jp/themes/custom/izumi/js/common/tab.js?tm8ss1

js izumi.jp collected 2026-10-02 05:44:59 UTC 2,225 bytes, 72 lines download raw bytes

1// タブの処理を行うクラス
2export class Tab {
3  constructor(option = { locationChange: false }, cb) {
4    this.option = option;
5    this.callback = cb;
6    this.selectors = document.querySelectorAll('[data-tab]');
7
8    if (this.selectors.length > 0) {
9      this.selectors.forEach(wrapper => {
10        this.tabs = wrapper.querySelectorAll('[role="tab"]');
11        this.panels = wrapper.querySelectorAll('[role="tabpanel"]');
12        this._bindEvents();
13      });
14    }
15  }
16
17  // イベントのバインド
18  _bindEvents() {
19    this._applyHashState();
20    window.addEventListener('hashchange', () => this._applyHashState());
21
22    if (this.tabs) {
23      this.tabs.forEach(tab => {
24        tab.addEventListener('click', ev => this._onClick(ev));
25      });
26    }
27  }
28
29  // ハッシュ部分に応じてタブとパネルの状態を更新
30  _applyHashState() {
31    const hash = location.hash;
32    if (!hash || !document.querySelector(hash)) return;
33
34    const targetId = hash.slice(1);
35    this.tabs.forEach(tab => {
36      const controls = tab.getAttribute('aria-controls');
37      tab.setAttribute('aria-expanded', String(controls == targetId));
38    });
39
40    this.panels.forEach(panel => {
41      panel.setAttribute('aria-hidden', String(panel.id != targetId));
42    });
43  }
44
45  /** タブクリック時の処理 */
46  _onClick(event) {
47    event.preventDefault();
48    const clicked = event.currentTarget;
49    const targetId = clicked.getAttribute('aria-controls');
50    const targetPanel = document.getElementById(targetId);
51
52    // すべてのタブとパネルを閉じる
53    this.tabs.forEach(tab => tab.setAttribute('aria-expanded', 'false'));
54    this.panels.forEach(panel => panel.setAttribute('aria-hidden', 'true'));
55
56    // クリックしたタブと対応パネルを開く
57    clicked.setAttribute('aria-expanded', 'true');
58    if (targetPanel) {
59      targetPanel.setAttribute('aria-hidden', 'false');
60    }
61
62    // オプションでハッシュ付与
63    if (this.option.locationChange) {
64      window.history.pushState(null, '', `${location.pathname}#${targetId}`);
65    }
66
67    // コールバック呼び出し
68    if (typeof this.callback === 'function') {
69      this.callback(targetId);
70    }
71  }
72}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.