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

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

新規登録して質問してみよう
ただいま回答率
85.46%
メニュー

メニューは、UIにおける仕組みであり、ユーザに機能の表示と実行する手段を与えます。

JavaScript

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

コードレビュー

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

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

Q&A

解決済

2回答

1083閲覧

<アコーディオンメニュー>他要素の削除

ShojiroAbe

総合スコア31

メニュー

メニューは、UIにおける仕組みであり、ユーザに機能の表示と実行する手段を与えます。

JavaScript

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

コードレビュー

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

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

0グッド

0クリップ

投稿2021/09/15 18:15

前提・実現したいこと

アコーディオンメニューにて
他のメニューをクリックしたらすでに開いているメニューを閉じたいです。

該当のソースコード

html

1 <main> 2 <ul class="menu"> 3 <li> 4 <a>親メニュー1</a> 5 <ul> 6 <li><a>子リスト1</a></li> 7 <li><a>子リスト2</a></li> 8 <li><a>子リスト3</a></li> 9 </ul> 10 </li> 11 12 <li> 13 <a>親メニュー2</a> 14 <ul> 15 <li><a>子リスト1</a></li> 16 <li><a>子リスト2</a></li> 17 <li><a>子リスト3</a></li> 18 </ul> 19 </li> 20 21 <li> 22 <a >親メニュー3</a> 23 <ul> 24 <li><a>子リスト1</a></li> 25 <li><a>子リスト2</a></li> 26 <li><a>子リスト3</a></li> 27 </ul> 28 </li> 29 </ul> 30 </main> 31

css

1@charset "utf-8"; 2 3* { 4 margin: 0; 5 padding: 0; 6 font-size: 20px; 7 text-decoration: none; 8 list-style-type: none; 9} 10 11a { 12 color: #333; 13} 14 15main { 16 max-width: 1000px; 17 width: 100%; 18 margin: 50px auto; 19 background-color: #eee; 20 padding: 20px; 21 border-radius: 5px; 22} 23 24.menu ul { 25 display: none; 26} 27 28.menu ul.active { 29 display: block; 30} 31 32.menu a { 33 transition: .3s; 34} 35 36.menu a:hover { 37 opacity: 0.7; 38} 39 40.menu > li > a { 41 display: flex; 42 justify-content: space-between; 43 padding: 10px; 44 background-color: #ccc; 45} 46 47.menu > li > a::after { 48 content: ">"; 49 transform: rotate(90deg); 50} 51 52.menu > li > .active::after { 53 transform: rotate(-90deg) translateY(-3px); 54} 55 56.menu > li >ul a { 57 padding: 10px; 58 display: block; 59 background-color: #aaa; 60}

js

1const parentMenu = document.querySelectorAll(".menu > li > a"); 2 3for(let i = 0; i < parentMenu.length; i++) { 4 parentMenu[i].addEventListener("click", function(e) 5 this.classList.toggle("active"); 6 this.nextElementSibling.classList.toggle("active"); 7 }) 8}

試したこと

一度クラスactiveとついたものを取得して、toggleでクラスをつける前にクラスをリセットする形にしてみました

js

1const parentMenu = document.querySelectorAll(".menu > li > a"); 2 3const activeElement = document.getElementsByClassName("active") 4 5 6for(let i = 0; i < parentMenu.length; i++) { 7 parentMenu[i].addEventListener("click", function(e){ 8 e.preventDefault(); 9 activeElement.classList.remove("active") 10 this.classList.toggle("active"); 11 this.nextElementSibling.classList.toggle("active"); 12 }) 13}

そうすると今度はピクリとも動かず下記のエラーが出てしまいました。

発生している問題・エラーメッセージ

Uncaught TypeError: Cannot read properties of undefined (reading 'remove') at HTMLAnchorElement.<anonymous>

Javascriptへの理解が浅く、実現するために他にどういった考え方や挙動がいるのかわかりません…
どうかご教示お願いいたします。

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

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

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

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

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

guest

回答2

0

getElementsByClassName は、HTMLCollection を返します。Element を返しません。
ですので、document.getElementsByClassName("active").classListundefinedです。

js

1 var test = parentDOM.getElementsByClassName("test"); // 一致する要素のリストであり、要素自身では*ない* 2 console.log(test); //HTMLCollection[1] 3 4 var testTarget = parentDOM.getElementsByClassName("test")[0]; // 求める最初の要素 5 console.log(testTarget); //<p class="test">hello world 2</p>

クラスが 'test' である最初の要素を取得する | Document.getElementsByClassName() - Web API | MDN

parentMenu に対して行っているように、配列のように扱う必要があります。

投稿2021/09/16 02:22

Lhankor_Mhy

総合スコア36158

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

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

0

ベストアンサー

まず、
const activeElement = document.getElementsByClassName("active")

最初に記述すると読み込み時の該当要素を取得します。クリックしたときのものと一致するとは限りません。

clickイベント内に記述する必要があります。

また、他の方の指摘があるように getElementsByClassName は要素のコレクションを返します。
今回の場合は、開いているメニューは一つ以下なので、querySelectorメソッドを使うといいでしょう。
これだと見つかった最初の要素を返します。(見つからない場合はNull)


this.nextElementSibling.classList.toggle("active");

クリックした次の兄弟要素を操作してますが、これは CSSの隣接兄弟結合子(+)で指定できるのそちらを使った方かコードがシンプルになります。

css

1/* .menu ul.active { * 下記に修正/ 2.menu a.active + ul { 3 display: block; 4}

js

1const parentMenu = document.querySelectorAll(".menu > li > a"); 2for(let i = 0; i < parentMenu.length; i++) { 3 parentMenu[i].addEventListener("click", function(e){ 4 var active = document.querySelector(".menu > li > a.active"); 5 if(active) {active.classList.remove("active")} 6 7 if(!this.isEqualNode(active)){this.classList.add("active")} 8 }) 9}

投稿2021/09/16 04:48

hatena19

総合スコア33790

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

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

hatena19

2021/09/16 07:56

そうなんですね。誤解してました。 querySelectorAll() は静的なので同じだと思ってました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問