タブ切り替えのjsについて（３パターン）

js 動作のタブ制作を調べていると、簡単に作れるものとして下記がよく見つかるような気がする。

下記では、jQueryを使って、ボックスエリアをタブと同じ順に並べた形で、表示・非表示を行う形式。

##■１つ目
```html
<ul class="l-tab-btns">
  <li class="tab1"><button class="js-button is-active">ボタン１</button></li>
  <li class="tab2"><button class="js-button">ボタン２</button></li>
</ul>
<div id="tab1" class="tab-box">
  タブ１の中身（ボックスエリア１）
</div>
<div id="tab1" class="tab-box is-hidden">
  タブ２の中身（ボックスエリア２）
</div>
```

```js
$(function () {
  $('.js-button').on('click', function () {

    //クリックしたタブのインデックス順を取得
    var index = $('.js-button').index(this);

    //タブ全てからアクティブクラスを排除。
    $('.js-button').removeClass('is-active');

    //クリックしたタブをアクティブに。
    $(this).addClass('is-active');
    
    //全てのタブエリアに非表示クラスを追加し、クリックしたタブと同じ順のタブエリアから非表示クラスを削除
    $('.tab-box').addClass('is-hidden').eq(index).removeClass('is-hidden');
    return false;
  });
});
```
クリックしたタブが何番目のタブなのかを数え、それと同じ順序に並んでいるボックスエリアのソースを表示させるというもの。

ただこの方法だと、タブの順とボックスエリアの順はそろえて置く必要がある。



##■２つ目
そこで下記では、タブの順に、ボックスエリアをの順を合わせる必要が無い形をとった。

ボックスエリアに各idを設置し、タブボタンのhrefに開きたいタブを指定してある。

```html
<div class="m-tab">
  <ul class="m-tab-btnList">
    <li class="m-tab-btn is-active"><a href="#tab1">ボタン１</a></li>
    <li class="m-tab-btn"><a href="#tab2">ボタン２</a></li>
  </ul>
  <div class="m-tab-box is-tab-open" id="tab1">
    タブ１の中身（ボックスエリア１）
  </div>
  <div class="m-tab-box" id="tab2">
    タブ２の中身（ボックスエリア２）
  </div>
</div>
```
```js
$(function () {
  $('.js-tab a').on('click', function () {

    //クリック自身にはクラス付加し、対象から親に上ってその兄弟にはクラス削除。
    $(this).parent().addClass('is-active').siblings('.is-active').removeClass('is-active');

    // クリックしたものからhref取得
    var id = $(this).attr('href');

    //対象クラスを全て破棄。
    $('.js-tab-box').siblings('.is-tab-open').removeClass('is-tab-open');

    //指定のクラスにクラス追加
    $(id).addClass('is-tab-open');
    return false;
  });
});
```




##■３つ目
また下記では、勉強のために内部処理をjQueryを禁止して、javascriptだけで記載してみた。

htmlでは、data属性に開きたいタブのidを記載し連携してある。

```html
<ul class="m-tab-lists">
  <li class="m-tab-list is-active"><button class="js-tab-btn" data-tab="tab1">ボタン１</button></li>
  <li class="m-tab-list"><button class="js-tab-btn" data-tab="tab2">ボタン２</button></li>
</ul>
<div class="m-tab-box js-tab-box is-open" id="tab1">
  タブ１の中身（ボックスエリア１）
</div>
<div class="m-tab-box js-tab-box" id="tab2">
  タブ２の中身（ボックスエリア２）
</div>
```

```js
$(function () {
  //-- タブ切り替え --------------------------------------------------------------------
  // 対象クラスのついているDOM全てを取得
  var btn = document.getElementsByClassName('js-tab-btn');

  // btn.length で 対象ボタンの個数全部を取得し、条件式が0になるまで回す。
  // 要素indexは0から割り振られているので-1することで、個数を、indexに合わせる。
  for (var i = btn.length - 1; i >= 0; i--) {
    // 各ボタン、イベントリスナーでクリックしたら発動
    btn[i].addEventListener('click', function () {

      // btn.length で 対象ボタンの個数全部を取得し、条件式が0になるまで回す。
      for (var x = btn.length - 1; x >= 0; x--) {
        // contains で対象クラス有無をチェックし、あれば削除
        if (btn[x].parentNode.classList.contains('is-active')) {
          btn[x].parentNode.classList.remove('is-active');
        }
      }

      // this はクリックされたオブジェクト。parentNode でその親。
      // classList でクラス操作。is-active クラスの追加と削除。
      this.parentNode.classList.add('is-active');

      // 対象クラスのついているDOM全てを取得
      var box = document.getElementsByClassName('js-tab-box');
      for (var y = box.length - 1; y >= 0; y--) {
        // contains で対象クラス有無をチェックし、あれば削除
        if (box[y].classList.contains('is-open')) {
          box[y].classList.remove('is-open');
        }
      }

      //data属性の値を取得して、同じidの要素にクラス付加。
      var tab_id = this.getAttribute('data-tab');
      document.getElementById(tab_id).classList.add('is-open');
    });
  }
});
```

上記のようにjavascriptでも対応できるが、jQueryで済むならそれに越したことはない。


##■参照
以下は参照。

https://blog-and-destroy.com/7389
https://www.flatflag.nir87.com/tab-1960

https://www.mdn.co.jp/di/contents/4047/54019/
https://www.mdn.co.jp/di/contents/4047/54084/