質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

1回答

2197閲覧

javascript 複数階層 タブ切り替えメニューの切替時の表示を解決したい

RyoYamane

総合スコア2

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

0クリップ

投稿2021/03/31 10:43

前提・実現したいこと

JavaScriptを使用して、複数階層(第3階層まで)のタグメニュー実装を行いたいです。

発生している問題

下記、Gifのように第1階層の選択時の色は、選択エリアごとに変わるものの、
選択したことによって出現した第2階層のメニューは、選択エリアごとに消えない。
https://gyazo.com/383699c4017be9011999dd60554c615d

第1階層選択時の色のように、第2階層のメニューも選択外のところは消したい。

何卒よろしくお願いいたします。

該当のソースコード

Js

1(()=>{ 2 3window.addEventListener('load', () => { 4 const tabMenu = document.getElementById("js-tab") 5 const menuDetail = tabMenu.querySelectorAll("[data-id]") 6 const menuMoreDetail = tabMenu.querySelectorAll("[data-menu]") 7 console.log(menuMoreDetail) 8 for(let i = 0; i < menuDetail.length; i++) { 9 //タブメニュークリック時 10 11 menuDetail[i].addEventListener('click', (e) => { 12 const init = () => { 13 menuMoreDetail[i].style.display = 'block'; 14 }; 15 init(); 16 17 //クリックされた要素(メニュー要素)を取得 18 let currentMenu = e.currentTarget; 19 //ターゲットとなる要素(タブメニューdata属性ちと等しいid値を持つコンテンツ要素を取得 20 let currentContent = document.getElementById(currentMenu.dataset.id); 21 console.log(currentContent) 22 23 // すべてのタブメニューの'is-active'クラスを削除 24 for(let i = 0; i < menuDetail.length; i++) { 25 menuDetail[i].classList.remove('is-active'); 26 } 27 // クリックしたタブメニューに'is-active'クラスを追加 28 currentMenu.classList.add('is-active'); 29 30 // タブコンテンツを非アクティブにする 31 for(let i = 0; i < menuMoreDetail.length; i++) { 32 menuMoreDetail[i].classList.remove('is-active'); 33 } 34 // 対象コンテンツ(指定したIDの要素があったら)を表示させる 35 if(currentContent !== null) { 36 currentContent.classList.add('is-active'); 37 } else { 38 currentContent.classList.remove('is-active'); 39 } 40 41 }) 42 } 43}) 44})();

css

1/* タブメニュー */ 2.tab-menu { 3 display: flex; 4 margin: 0 -5px; 5} 6 7.tab-menu__item { 8 box-sizing: border-box; 9 width: -webkit-fill-available; 10} 11 12 13.tab-trigger { /* label */ 14 text-align: left; 15 cursor: pointer; 16 display: block; 17 padding: 10px; 18 border: 1px solid #ccc; 19 border-bottom: 0; 20 border-radius: 5px 5px 0 0; 21 overflow: hidden; 22 background-color: lightgray; 23 position: relative; 24} 25 26.tab-trigger.is-active { 27 background-color: darkgoldenrod; 28 29} 30 31/* 2段目たぶ */ 32.tab-menu-detail{ 33 display: none; 34} 35 36.tab-menu-detail.is-active { 37 display: flex; 38} 39 40.second-menu { 41 width: 100%; 42 text-align: left; 43 cursor: pointer; 44 padding: 6px; 45 border: 2px solid dimgray; 46 border-radius: 5px 5px 0 0; 47 overflow: hidden; 48 background-color: lightslategrey; 49 position: relative; 50 51}

html

1<div id="js-tab"> 2<ul class="tab-menu" > 3 <li class="tab-menu__item"><span class="tab-trigger js-tab-trigger is-active" data-id="tab01">予約管理</span> 4 <ul class="tab-menu-detail" id="tab01"> 5 <li class="second-menu js-tab-target " data-menu="1">スケジュール確認</li> 6 <li class="second-menu js-tab-target " data-menu="2">定休日選択</li> 7 </ul> 8 </li> 9 10 <li class="tab-menu__item"><span class="tab-trigger js-tab-trigger" data-id="tab02">メニュー作成</span> 11 <ul class="tab-menu-detail" id="tab02"> 12 <li class="second-menu js-tab-target is-active" data-menu="3">新規メニュー作成</li> 13 <li class="second-menu js-tab-target " data-menu="4">既存メニュー編集・削除</li> 14 </ul> 15 </li> 16 17 <li class="tab-menu__item"><span class="tab-trigger js-tab-trigger" data-id="tab03">クーポン作成</span> 18 <ul class="tab-menu-detail" id="tab03"> 19 <li class="second-menu js-tab-target " data-menu="5">新規クーポン作成</li> 20 <li class="second-menu js-tab-target " data-menu="6">既存クーポン編集・削除</li> 21 </ul> 22 </li> 23 24 <li class="tab-menu__item"><span class="tab-trigger js-tab-trigger" data-id="tab04">レビュー確認</span> 25 <ul class="tab-menu-detail" id="tab04"> 26 <li class="second-menu js-tab-target " data-menu="7">新規メニュー作成</li> 27 <li class="second-menu js-tab-target " data-menu="8">既存メニュー編集・削除</li> 28 </ul> 29 </li> 30</ul> 31<!-- .tab-menu --> 32 33<!-- .2段目めにゅ --> 34 35 36<!-- .2段目めにゅ --> 37<div class="tab-content"> 38 <div class="tab-content__item js-tab-target is-active" id="tab01"> 39 <p>タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。タブ1のコンテンツが入ります。</p> 40 </div><!-- .tab-content__item --> 41 <div class="tab-content__item js-tab-target" id="tab02"> 42 <p>タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。タブ2のコンテンツが入ります。</p> 43 </div><!-- .tab-content__item --> 44 <div class="tab-content__item js-tab-target" id="tab03"> 45 <p>タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。</p> 46 </div><!-- .tab-content__item --> 47 <div class="tab-content__item js-tab-target" id="tab04"> 48 <p>タブ4のコンテンツが入ります。タブ4のコンテンツが入ります。タブ4のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。タブ3のコンテンツが入ります。</p> 49 </div><!-- .tab-content__item --> 50</div><!-- .tab-content --> 51</div> 52

試したこと

jsファイルにif文でelse以下を追加し、removeする記述を追加してみたが、特に変化なし。

// 対象コンテンツ(指定したIDの要素があったら)を表示させる if(currentContent !== null) { currentContent.classList.add('is-active'); } else { currentContent.classList.remove('is-active'); }

参考にしたページ

https://blog.pranktone.net/web/javascript/20200304150200.html

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

menuMoreDetail[data-menu]なのでulです。
currentContentdocument.getElementById(currentMenu.dataset.id)なのでliです。

上の二つが違うものなので、

js

1 // タブコンテンツを非アクティブにする 2 for(let i = 0; i < menuMoreDetail.length; i++) { 3 menuMoreDetail[i].classList.remove('is-active'); //←これと 4 } 5 // 対象コンテンツ(指定したIDの要素があったら)を表示させる 6 if(currentContent !== null) { 7 currentContent.classList.add('is-active'); //←これが違うもの

というのが原因です。


解決方法ですが、いろいろあると思いますが、手っ取り早いのは、

css

1/* .tab-menu-detail.is-active { */ 2.is-active+.tab-menu-detail { 3 display: flex; 4}

とCSSで解決する方法でしょうか。

ただ、多段メニューにするなら少し考えないといけないと思います。

投稿2021/04/01 03:33

Lhankor_Mhy

総合スコア36115

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RyoYamane

2021/04/01 17:20

お忙しいところご回答ありがとうございます。 ご指摘いただきましたのCSS追加とJsのfori以下を削除したことで、 下記Gifの通り挙動確認できました。 ``` https://gyazo.com/fe468d92b30dc2cbd8a2015682c4b47a ``` また今回うまく動作しなかった原因は ulとliが別物にもかかわらず指定していたため、動作が思ったようにいかなかったということですね! 理解しました。 このあと第2階層のクリックしたらコンテンツ表示されるというところは、 これからチャレンジしてみたいと思います! ちなみに、コメントいただいた内容で、 >ただ、多段メニューにするなら少し考えないといけないと思います とありますが、 私の作業イメージだと、『liのidを取得→イベント発火→紐付けたdata属性のコンテンツを表示→他の要素はremoveする』 上記イメージしておりますが、こちらだと実装は難しいイメージでしょうか? ご回答いただけましたら、幸いでございます。 よろしくお願いいたします。
Lhankor_Mhy

2021/04/02 00:37

いえ、そのイメージでいいと思うのですが、この回答のようにCSSで対処する場合には構造を考え直さないといけないかな、と感じています。 というのも、RyoYamane さんの JavaScript は data-id などを使ってHTML構造に依存しない形になっていますが、私が回答で提示した .is-active+.tab-menu-detail のようなセレクタはHTML構造に依存しているので、複雑化すると矛盾してしまうような気がするのです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問