タブ切り替え

Javascript

こんにちはkazutoです今回は、タブ切り替え機能を実装していきます。

事前準備

まず初めに事前準備をしていきます。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="tab.css">
  <script src="tab.js"defer></script>
</head>
<body>
  <h1>Tab Switching</h1>
  <main>
    <ul class="tabs">
      <li class="tabList">1ー1</li>
      <li class="tabList">1ー2</li>
      <li class="tabList">1ー3</li>
    </ul>
    <div class="contents">
      <div class="content "> 
        <table border="5">
          <tr>
          <th>firstname</th>
          <th>lastname</th>
          <th>number</th>
          <th>gender</th>
          </tr>
          <tr>
          <td>kaito</td>
          <td>aida</td>
          <td>1</td>
          <th>boy</th>
         </tr>
         <tr>
          <td>junya</td>
          <td>ikeda</td>
          <td>2</td>
          <th>boy</th>
         </tr>
         <tr>
          <td>aoi</td>
          <td>saitama</td>
          <td>3</td>
          <th>girl</th>
         </tr>
         <tr>
          <td>mika</td>
          <td>takei</td>
          <td>4</td>
          <th>girl</th>
         </tr>
         <tr>
          <td>jun</td>
          <td>nakata</td>
          <td>5</td>
          <th>boy</th>
         </tr>


        </table>
      </div>

      <div class="content">
        <table border="5">
          <tr>
            <th>firstname</th>
            <th>lastname</th>
            <th>number</th>
            <th>gender</th>
            </tr>

            <tr>
              <td>yui</td>
              <td>akita</td>
              <td>1</td>
              <th>girl</th>
             </tr>
             <tr>
              <td>ryou</td>
              <td>ikuta</td>
              <td>2</td>
              <th>boy</th>
             </tr>
             <tr>
              <td>yuki</td>
              <td>satou</td>
              <td>3</td>
              <th>girl</th>
             </tr>
             <tr>
              <td>kazuki</td>
              <td>yosida</td>
              <td>4</td>
              <th>boy</th>
             </tr>
             <tr>
              <td>riku</td>
              <td>watanabe</td>
              <td>5</td>
              <th>boy</th>
             </tr>

        </table>
      </div>
      <div class="content">
        <table border="5">
          <tr>
            <th>firstname</th>
            <th>lastname</th>
            <th>number</th>
            <th>gender</th>
            </tr>
            <tr>
              <td>ryouta</td>
              <td>itikawa</td>
              <td>1</td>
              <th>boy</th>
             </tr>
             <tr>
              <td>tarou</td>
              <td>utida</td>
              <td>2</td>
              <th>boy</th>
             </tr>
             <tr>
              <td>kenta</td>
              <td>suzuki</td>
              <td>3</td>
              <th>boy</th>
             </tr>
             <tr>
              <td>kento</td>
              <td>nisida</td>
              <td>4</td>
              <th>boy</th>
             </tr>
             <tr>
              <td>asuka</td>
              <td>watabe</td>
              <td>5</td>
              <th>girl</th>
             </tr>

        </table>
      </div>
      </div>
      </div>
    </div>
  </main>
</body>
</html>
ul, li
{
    margin:0;
    padding:0;
    border:0;
    font-size:100%;
    vertical-align:baseline;
    background:transparent;
}



*, *:before, *:after {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    -o-box-sizing: border-box;
    -ms-box-sizing: border-box;
    box-sizing: border-box;
}
body{
  background-color: #222222;
  color: white;
  font-family: cursive;
}

.contents{
  height: 600px;
  width: 800px;
}
h1{
  text-align: center;
  font-size: 50px;
}
ul{
  list-style: none;
  color: white;
}
main{
  text-align: center;
  height: 600px;
  width: 800px;
  margin: auto;
  margin-top: 30px;
}
.tabs{
    display: flex;
    justify-content: space-around;
    font-size: 30px;
}
.tabList{
  height: 50%;
  width: 100%;
  background-color: black;
  border-top:4px solid gray ;
  border-left:4px solid gray ;
  border-right:4px solid gray ;
  padding:0,1000px ;
}

.content{
  margin: auto;
  height: 90%;
  width:100%;
  display: none;
  font-size: 30px;
}


table{
  width: 100%;
  height: 400px;
  text-align: center;
  background-color: black;
  color: white;
}

.tansprarent{
 opacity: 0.4;
}
.block{
 display: block;
}

※必ず漏れのない様、コピペをしてください。正常に動かない恐れがあります。

今回、作成するタブ切り替え機能は、ページを移動せずにテーブル内の内容を変更をしていきます。

タブ切り替え機能

では、実際にタブ切り替え機能を実装していきましょう。タブ切り替え機能を実現をするために今回は、clickイベントを用います。

  • ノードの取得
  • イベント登録
  • イベント発火後の処理を実装

ノードの取得

まずは実装に必要なノードを取得しましょう。

const tabLists  = document.querySelectorAll(".tabList")
const contents   = document.querySelectorAll(".content")

今回の実装の肝は、タブと内容を紐づける点です。一つのタブには、一つの内容が紐づきます。なので互いに、querySelectorAllメソッドを用いて、NodeListを取得し、ノードを配列で管理をして、内容にインデックス番号を振り分ける事でタグと内容のリレーションを表す必要があります。

少し概念的な部分の解説で、難しいと感じる方とは思いますが、実装していく中で頭の中に入ってくると思うので大丈夫です。

ノードの取得する意図を把握した所で、正しくノードを取得できているかを確認をするためにデバックをしていきましょう。

function forLogs(elments){
  elments.forEach(elment=>console.log(elment));
}
forLogs([tabLists,contents])

ノードを取得できたのが確認できてたら次のステップに進みましょう。

イベント登録

実装に必要なノードを取得できた所で、イベントを登録をしていきます。タブ切り替え機能は、タブをクリックして、タブに紐づいた内容を表示(切り替え)をします。したがって、定数tabListsの各ノードにclickイベントを登録をしていきます。

tabLists.forEach((tabList,index)=>{
  tabList.addEventListener("click",function(){
  })
})

定数tabListsの各ノードにclickイベントを登録をしたいので、定数tabListsに対してforEachメソッドを用いています。実際に、イベントが登録ができたか、デバックしてみましょう。

tabLists.forEach((tabList,index)=>{
  tabList.addEventListener("click",function(){
  console.log("test")
  })
})

testという文字列が出力されていれば、無事にイベントが登録できた事になるので次のステップに進みましょう。

イベント発火後の処理を実装

先ほどのトピックでイベントが登録できたので、こちらのトピックでは、イベントが発火した際の処理を実装していきます。


function classChange(element,behavior,className){
  switch (behavior) {
    case "add":
      element.classList.add(className)
      break;
   case "remove":
    element.classList.remove(className)
      break;
  }
}
tabLists.forEach((tabList,index)=>{
  tabList.addEventListener("click",function(){
    if( document.querySelector(".tansprarent")==tabList){
      classChange(document.querySelector(".tansprarent"),"remove","tansprarent")
      classChange(document.querySelector(".block"),"remove","block")
      return
    }else if(document.querySelector(".tansprarent")){
        classChange(document.querySelector(".tansprarent"),"remove","tansprarent")
        classChange(document.querySelector(".block"),"remove","block")
    }
        classChange(tabList,"add","tansprarent")
        classChange(contents[index],"add","block")
  })
})

今回、挙動として大きく2つに分ける事ができます。

  • クラスtansprarentが存在した場合
    →該当のクラスを削除する
  • クラスtansprarentが存在しない場合
    →何もしない

となります。

 if( document.querySelector(".tansprarent")==tabList){
      classChange(document.querySelector(".tansprarent"),"remove","tansprarent")
      classChange(document.querySelector(".block"),"remove","block")
      return
    }else if(document.querySelector(".tansprarent")){
        classChange(document.querySelector(".tansprarent"),"remove","tansprarent")
        classChange(document.querySelector(".block"),"remove","block")
    }

更に「クラスtansprarentが存在する場合」のif文のブロック内でも挙動を分けています。

  • クラスtansprarentとクリックした要素が等しい場合
  • クラスtansprarentが存在する場合

となります。

if( document.querySelector(".tansprarent")==tabList){
        classChange(document.querySelector(".tansprarent"),"remove","tansprarent")
        classChange(document.querySelector(".block"),"remove","block")
        return
      }
  

上記のソースコードは、if文を用いてクラスtansprarentとクリックした要素が等しい場合と条件分岐をしています。処理内容自体は、特に変わらないのですがreturnメソッドを用いて、プログラムを強制終了しています。

プログラムを強制終了する理由として、returnメソッドの先の処理が読み込まれてしまうとエラーが出てしまうためです。

else if(document.querySelector(".tansprarent")){
        classChange(document.querySelector(".tansprarent"),"remove","tansprarent")
        classChange(document.querySelector(".block"),"remove","block")
    }

クラスtansprarentとクリックした要素が等しい場合に該当しない場合は、クラスtansprarentが存在する場合が次の条件として上がってきます。

処理内容は、同じです。しかし、returnメソッドの記述がありませんので、以降の処理も実行されます。なので少し挙動が違います。

classChange(tabList,"add","tansprarent")
classChange(contents[index],"add","block")

こちらのソースコードでは、クラスを追加をしています。returnメソッドが発火しない限り、クラスを追加します。

ここまでの一連の流れを繰り返す事によりタブ切り替え機能を実現をしています。以上で、「タブ切り替え機能」の実装を終了します。完成したソースコードは下記に貼り付けて起きます

const tabLists  = document.querySelectorAll(".tabList")
const contents   = document.querySelectorAll(".content")
function classChange(element,behavior,className){
  switch (behavior) {
    case "add":
      element.classList.add(className)
      break;
   case "remove":
    element.classList.remove(className)
      break;
  }
}

tabLists.forEach((tabList,index)=>{
  tabList.addEventListener("click",function(){
    if( document.querySelector(".tansprarent")==tabList){
      classChange(document.querySelector(".tansprarent"),"remove","tansprarent")
      classChange(document.querySelector(".block"),"remove","block")
      return
    }else if(document.querySelector(".tansprarent")){
      classChange(document.querySelector(".tansprarent"),"remove","tansprarent")
      classChange(document.querySelector(".block"),"remove","block")
    }
      classChange(tabList,"add","tansprarent")
      classChange(contents[index],"add","block")
  })
})

まとめ:タブ切り替え

今回はタブ切り替え機能を実装しました。タブ切り替え機能自体は、色々なwebアプリケーションで用いられている機能の一つです。タブ切り替え機能を実装できたという事は、また一つwebアプリケーションの知見が、広がったという見方もできます。これからも一つ一つ徐々にwebアプリケーションの知見を広げっていきましょう。

以上、kazutoでした。

関連記事