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

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

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

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

リファクタリング

リファクタリングとはコードの本体を再構築するための手法であり、外見を変更せずに内部構造を変更/改善させることを指します。

Q&A

解決済

2回答

2741閲覧

【JavaScript】同じクラス名を持つ複数の要素にクリックイベントを適用させたい

s-ueshi

総合スコア6

JavaScript

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

リファクタリング

リファクタリングとはコードの本体を再構築するための手法であり、外見を変更せずに内部構造を変更/改善させることを指します。

0グッド

0クリップ

投稿2022/07/15 04:09

前提

JavaScriptでモーダルウィンドウを実装したいと考えています。

実現したいこと

HTML上のclass名は同一の、モーダルウィンドウを複数用意し、
個別にクリックイベントの処理を行いたいです。

class名を個別につけて、その都度JSを書いて実装することはできるのですが、
同じソースコードの羅列になり後から見にくいので
まとめてしまいたいです。

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

3つのモーダルウィンドウを用意して試したところ、
現在のコードではクリックした際、3つすべての要素を取得してしまい
すべてが重なって表示されてしまいます。
(結果最後の要素で指定した画像が最上面となり表示されます)

該当のソースコード

HTML

1 <body> 2 <div class="second-area"> 3 <!-- 1つめ --> 4 <div class="modalOpen other-img"> 5 <img src="image/column1.jpg"> 6 </div> 7 <!-- 1つめのモーダルウィンドウ --> 8 <div class="easyModal modal"> 9 <div class="modalScale modal-scale"> 10 <div class="modal-content"> 11 <div class="modal-header"> 12 <span class="modalClose toggle"></span> 13 </div> 14 <div class="modal-body"> 15 <img src="image/column1.jpg"> 16 </div> 17 <p>Lorem ipsum dolor sit amet.</p> 18 </div> 19 </div> 20 </div> 21 <!-- 2つめ --> 22 <div class="modalOpen other-img"> 23 <img src="image/column2.jpg"> 24 </div> 25 <!-- 2つめのモーダルウィンドウ --> 26 <div class="easyModal modal"> 27 <div class="modalScale modal-scale"> 28 <div class="modal-content"> 29 <div class="modal-header"> 30 <span class="modalClose toggle"></span> 31 </div> 32 <div class="modal-body"> 33 <img src="image/column2.jpg"> 34 </div> 35 <p>Lorem ipsum dolor sit amet.</p> 36 </div> 37 </div> 38 </div> 39 <!-- 3つめ --> 40 <div class="modalOpen other-img"> 41 <img src="image/column3.jpg"> 42 </div> 43 <!-- 3つめのモーダルウィンドウ --> 44 <div class="easyModal modal"> 45 <div class="modalScale modal-scale"> 46 <div class="modal-content"> 47 <div class="modal-header"> 48 <span class="modalClose toggle"></span> 49 </div> 50 <div class="modal-body"> 51 <img src="image/column3.jpg"> 52 </div> 53 <p>Lorem ipsum dolor sit amet.</p> 54 </div> 55 </div> 56 </div> 57 </div> 58</body>

SCSS

1@charset "utf-8"; 2// 共通スタイル 3* { 4 margin: 0; 5 padding: 0; 6 -webkit-box-sizing: border-box; 7 box-sizing: border-box; 8 &::before, 9 &::after { 10 -webkit-box-sizing: border-box; 11 box-sizing: border-box; 12 } 13} 14html { 15 font-size: 62.5%; 16 overflow: auto; 17} 18img { 19 max-width: 100%; 20} 21body { 22 overflow: hidden; 23 width: 100%; 24 height: 100vh; 25 display: flex; 26 justify-content: center; 27 align-items: center; 28} 29 30 31// スタイル 32.second-area { 33 width: 80%; 34 display: flex; 35 gap: 20px; 36 .other-img { 37 flex-grow: 1; 38 cursor: pointer; 39 } 40 .easyModal { 41 display: none; 42 } 43 .modal { 44 z-index: 20; 45 width: 100vw; 46 height: 100vh; 47 position: fixed; 48 top: 0; 49 left: 0; 50 overflow: auto; 51 .modal-scale { 52 width: 100%; 53 height: 100%; 54 background: rgba(0, 0, 0, 0.6); 55 display: flex; 56 justify-content: center; 57 align-items: center; 58 .modal-content { 59 background: #f4f4f4; 60 width: 40vw; 61 height: 40vw; 62 display: flex; 63 justify-content: center; 64 align-items: center; 65 flex-direction: column; 66 gap: 10px; 67 position: relative; 68 box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.2), 69 5px 5px 10px rgba(0, 0, 0, 0.17); 70 animation-name: modalopen; 71 animation-duration: 1s; 72 @keyframes modalopen { 73 from { 74 opacity: 0; 75 } 76 to { 77 opacity: 1; 78 } 79 } 80 .modal-header { 81 position: absolute; 82 top: 10px; right: 10px; 83 cursor: pointer; 84 .toggle { 85 display: block; 86 position: relative; 87 width: 30px; 88 height: 30px; 89 border: 2px solid #333; 90 border-radius: 50%; 91 background: #fff; 92 &::before, 93 &::after { 94 content: ""; 95 position: absolute; 96 top: 50%; 97 left: 50%; 98 width: 3px; 99 height: 22px; 100 background: #333; 101 } 102 &::before { 103 transform: translate(-50%, -50%) rotate(45deg); 104 } 105 &::after { 106 transform: translate(-50%, -50%) rotate(-45deg); 107 } 108 } 109 } 110 .modal-body { 111 width: 80%; 112 img { 113 border-radius: 4px; 114 } 115 } 116 p { 117 font-size: 1.5rem; 118 letter-spacing: 2px; 119 } 120 } 121 } 122 } 123}

JavaScript

1window.addEventListener('DOMContentLoaded', function() { 2 3 window.onload = function() { 4 5 let buttonOpen = document.querySelectorAll('.modalOpen'); 6 let modal = document.querySelectorAll('.easyModal'); 7 let buttonClose = document.querySelectorAll('.modalClose'); 8 let modalScale = document.querySelectorAll('.modalScale'); 9 10 // ボタンがクリックされた時 11 buttonOpen.forEach(x => { 12 x.addEventListener('click', modalOpen); 13 function modalOpen() { 14 modal.forEach(y => { 15 y.style.display = "block"; 16 }); 17 } 18 }); 19 20 // トグルがクリックされた時 21 buttonClose.forEach(x => { 22 x.addEventListener('click', modalClose); 23 function modalClose() { 24 modal.forEach(y => { 25 y.style.display = "none"; 26 }); 27 } 28 }); 29 30 // モーダルコンテンツ以外がクリックされた時 31 modalScale.forEach(x => { 32 x.addEventListener('click', outsideClose); 33 function outsideClose(e) { 34 modalScale.forEach(y => { 35 if(e.target == y) { 36 modal.forEach(z => { 37 z.style.display = "none"; 38 }); 39 } 40 }); 41 } 42 }); 43 } 44});

試したこと

for文での記述も試したのですが、上記のコードと
同じ結果になってしまいました。

JavaScript

1window.addEventListener('DOMContentLoaded', function() { 2 3 // ボタンがクリックされた時 4 for( let i=0; i<buttonOpen.length; i++ ) { 5 buttonOpen[i].addEventListener('click', modalOpen); 6 function modalOpen() { 7 for( let i=0; i<modal.length; i++ ) { 8 modal[i].style.display = "block"; 9 } 10 } 11 } 12 13 // トグルがクリックされた時 14 for( let i=0; i<buttonClose.length; i++ ) { 15 buttonClose[i].addEventListener('click', modalClose); 16 function modalClose() { 17 for( let i=0; i<modal.length; i++ ) { 18 modal[i].style.display = "none"; 19 } 20 } 21 } 22 23 // モーダルコンテンツ以外がクリックされた時 24 for( let i=0; i<modalScale.length; i++ ) { 25 modalScale[i].addEventListener('click', outsideClose); 26 function outsideClose(event) { 27 if(event.target == modalScale[i]) { 28 for( let i=0; i<modal.length; i++ ) { 29 modal[i].style.display = "none"; 30 } 31 } 32 } 33 } 34 35});

何卒宜しくお願い致します。

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

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

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

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

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

guest

回答2

0

処理的にはこう

javascript

1<script> 2document.addEventListener('click',e=>{ 3 const t=e.target; 4 if(t.matches('.modalOpen')){ 5 t.nextElementSibling.showModal(); 6 } 7 if(t.matches('dialog .close')){ 8 t.closest('dialog').close(); 9 } 10}); 11</script> 12<div class="second-area"> 13<div class="modalOpen">open 1</div> 14<dialog>modal 1 15<input type="button" value="close" class="close"> 16</dialog> 17<div class="modalOpen">open 2</div> 18<dialog>modal 2 19<input type="button" value="close" class="close"> 20</dialog> 21<div class="modalOpen">open 3</div> 22<dialog>modal 3 23<input type="button" value="close" class="close"> 24</dialog> 25</div>

投稿2022/07/15 06:51

yambejp

総合スコア114814

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

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

s-ueshi

2022/07/15 07:55

yambejpさん 具体的な記述法をありがとうございます。 参考にしつつ書き換えたところ無事に実装できました!
guest

0

ベストアンサー

.modalOpen が複数あって .modal も複数ある場合は、何らかの方法で押されたボタンから表示するモーダルを決める必要があります。たとえば「押されたボタンの次の要素の中にある .modal」が対象だとすると、イベントリスナをそのように書き換えましょう。

js

1x.addEventListener('click', modalOpen); 2function modalOpen(event) { 3 event.currentTarget.nextElementSibling.querySelector('.modal').stye.display = "block"; 4}

buttonClosemodalScale に関しては、対象はクリックした要素の先祖の .modal でしょうから、event.target.closest('.modal') を対象にしましょう。

投稿2022/07/15 04:34

編集2022/07/15 07:00
int32_t

総合スコア20856

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

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

s-ueshi

2022/07/15 07:50

int32_tさん お陰様で無事実装することができました! 要素ノードの取得によって特異的にイベント発火することができるのですね、、、 実装できない理由とその対策についての わかりやすい説明によって、スムーズな理解に繋がりました。 本当にありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問