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

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

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

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

Q&A

解決済

3回答

484閲覧

JavaScript for文からbreakでうまく抜けられていない事案を解決したいです

pecoro0321

総合スコア10

JavaScript

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

0グッド

0クリップ

投稿2019/05/14 17:52

編集2019/05/15 09:32

JavaScript / for文からbreakでうまく抜けられていない事案を解決したい

※※1回目の回答をいただいたあと、kei344さんに作成いただいたサンプルを元に質問を編集させていただきました。
最初の質問では必要な範囲が記載しきれていませんでした。


Javascript初級者です。
Javascriptでモーダルウィンドウを実装しています。(#iconOpenをクリックすると#worksDetailWebを表示します)

「work-web」というクラスが付与されたdivをdisplay:noneで非表示にし、
「current」というクラスがついたdivのみdisplay:blockで表示しています。
「#iconRight」ボタンを押すとひとつ次のdivに「current」クラスを付与して内容を切り替える動きを実装しようとしたところ、for文が意図どおりに動作しませんでした。

該当のソースコード

HTML

1<div id="iconOpen">iconOpen</div> 2 3<div id="worksDetailWeb" class="dispnone"> 4 <div id="iconClose">iconClose</div> 5 <div id="iconRight">iconRight</div> 6 7 <div id="wrapper"> 8 <div class="work-web current" id="div01">div01</div> 9 <div class="work-web" id="div02">div02</div> 10 <div class="work-web" id="div03">div03</div> 11 <div class="work-web" id="div04">div04</div> 12 <div class="work-web" id="div05">div05</div> 13 </div> 14</div>

CSS

1#worksDetailWeb { 2 border: 1px solid #000; 3} 4.current { 5 color: red; 6} 7.dispnone { 8 display: none; 9}

Javascript

1 2const worksDetailWeb = document.getElementById('worksDetailWeb'); 3const eachWebWorks = document.getElementsByClassName('work-web'); 4const iconRight = document.getElementById('iconRight'); 5const iconClose = document.getElementById('iconClose'); 6const iconOpen = document.getElementById('iconOpen'); 7 8function worksDetail(){ 9 //#iconRightをクリック→currentクラスを削除して1つ次のdivにcurrentクラスを付与する。 10 iconRight.addEventListener('click', function (e) { 11 for (i = 0; i < eachWebWorks.length-1; i++) { 12 let self = eachWebWorks[i]; 13 if (self.classList.contains('current')) { 14 self.classList.remove('current'); 15 eachWebWorks[i + 1].classList.add('current'); 16 break; 17 } 18 } 19 }); 20 21 //#iconCloseをクリック→currentクラスを#div01に付与し直す。 22 iconClose.addEventListener('click', function (e) { 23 for (let eachWebWork of eachWebWorks) { 24 if (eachWebWork.classList.contains('current')) { 25 eachWebWork.classList.remove('current'); 26 eachWebWorks[0].classList.add('current'); 27 break; 28 } 29 } 30 worksDetailWeb.classList.add('dispnone'); 31 }); 32} 33 34//#iconOpenを開いたらモーダル部分を表示する 35iconOpen.addEventListener('click', function (e) { 36 e.preventDefault(); 37 if (worksDetailWeb.classList.contains('dispnone')) { 38 worksDetailWeb.classList.remove('dispnone'); 39 worksDetail(); 40 } 41}) 42 43

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

1回目は#div01→#div02→#div03→#div04→#div05
と期待した通り動いたのですが、一度#iconCloseボタンでモーダルを閉じ、再度開くと

2回目は#div01→#div03→#div05
3回目は#div01→#div04→#div05
4回目以降は#div01→#div05

という動きになってしまいました。

breakの前の行にconsole.logを入れて確認したところ、
表示されなかったdivの部分はbreakせずに次の処理に進んでしまっていました。

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

初めて質問させていただきます。質問の仕方に不備などありましたら申し訳ありません。
何卒よろしくお願いします。

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

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

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

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

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

x_x

2019/05/15 02:24

モーダルウィンドウというのはどの部分のことを指していますか?
miyabi_takatsuk

2019/05/15 02:37

質問に関係ない、コードのツッコミですが、 JavaScriptには、ASIがありますが、明示的に自分でセミコロン記述するようにした方がいいですよ。 (他の言語では全く通用しない) さすがに全行のステートメントにセミコロンついてないのはちょっと・・・。Swiftじゃないんだから。
pecoro0321

2019/05/15 09:34

恐れ入ります、ご指摘を受けて質問を編集させていただきました。 また、セミコロンについても「省略可能」というふんわりした認識だったのですが「ASI」という言葉を検索して記事など拝読しまして、必ずつけるようにしたほうがいいと認識いたしました。ご指摘ありがとうございました。
guest

回答3

0

ベストアンサー

動くサンプル:https://jsfiddle.net/f9c2vw48/


特に問題が無く動いているようなので、他のコードがあってそれが邪魔しているのではないでしょうか。

投稿2019/05/14 18:15

kei344

総合スコア69400

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

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

pecoro0321

2019/05/15 08:51

サンプルを作っていただきありがとうございます!!質問に書き出した部分は動いているのですね。。質問のためのコードの切り出し範囲に問題がありそうなので、コードを見直しつつ質問を編集するか検討したいと思います。 コードが動くかどうかの確認にどうサンプル化すればいいかわからなかったので勉強になりました。ありがとうございました!
kei344

2019/05/15 09:40

(追記に対して)moredeepさんの回答にあるように、addEventListenerが複数回実行されています。 addEventListenerは同じイベントに複数の関数を割り当てられるため、開閉するたび同じ関数が複数回実行されるのでそのような問題が起きています。 表示を消すたびに関数の登録を解除するか、クリックイベントの中でクリックイベントを登録するような設計をやめましょう。 https://jsfiddle.net/rwj6dh91/
pecoro0321

2019/05/15 10:01

早速のご対応ありがとうございます!! クリックイベントの中にクリックイベントがあるのがおかしかったのですね。。。 深く理解できていない部分をなんとなく書いてしまっていることを痛感いたしました。 今後気をつけたいと思います。ありがとうございました。 ※コメントでいただいているworksDetail()の関数化については、「works-graphic」というdivをもつモーダルが別でありまして、引数を加えてあとで使いまわそうかと思っていました。そのような場合に関数化するという考えは合っていますでしょうか…?
kei344

2019/05/15 10:18

> そのような場合に関数化するという考えは合っていますでしょうか…? 現在提示されている関数/変数の構成では、関数化する必要がありませんね。そもそも複数のものが別々にあるのに[getElementsByClassName]で一気に取得するのでしょうか。 あとから読み込むデータがあり、読み込むたびにイベントをつける等の処理のために関数化することは設計として考えられますが、その場合要素の取得も含めて関数の中に入れることになると思います。
pecoro0321

2019/05/15 10:37

ご返答ありがとうございます! ご指摘を元に他の部分も実装を進めてみたいと思います。 大変お世話になりました。ありがとうございました。
guest

0

addEventListenerが複数回実行されているだけではないでしょうか?

投稿2019/05/15 00:47

moredeep

総合スコア1507

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

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

pecoro0321

2019/05/15 09:38

回答ありがとうございます!ご指摘部分を意識しつつ周りのコードも読んでみようと思います。
guest

0

こんな感じでは?

javascript

1<style> 2.work-web{display:none;} 3.work-web.current{display:block;} 4</style> 5<script> 6window.addEventListener('DOMContentLoaded', function(e){ 7 var w=document.querySelectorAll('.work-web'); 8 var l=w.length; 9 ['#iconRight','#iconClose'].forEach((x,y)=>{ 10 document.querySelector(x).addEventListener('click',()=>{ 11 var c=[].indexOf.call(w,document.querySelector('.work-web.current')); 12 var n=(y==1||c==(l-1))?0:c+1; 13 w[c].classList.remove('current'); 14 w[n].classList.add('current'); 15 }); 16 }); 17}); 18</script> 19<div id="worksDetailWeb"> 20 <div id="iconClose">close</div> 21 <div id="iconRight">right</div> 22 <div id="wrapper"> 23 <div class="work-web current" id="div01">1</div> 24 <div class="work-web" id="div02">2</div> 25 <div class="work-web" id="div03">3</div> 26 <div class="work-web" id="div04">4</div> 27 <div class="work-web" id="div05">5</div> 28 </div> 29</div>

投稿2019/05/15 00:35

yambejp

総合スコア114784

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

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

yambejp

2019/05/15 02:08

つまりforで回す意味がないということです
pecoro0321

2019/05/15 09:41

ご回答ありがとうございます!初級者のため時間がかかってしまうのですが、いただいたコードを読んでまずは理解してみようと思います。
pecoro0321

2019/05/15 11:51

拝読しました。 配列の中で特定の要素が何番目にあるかというのを var index = Array.indexOf.call(配列, 特定の要素); という形で取得できるのですね。。勉強になりました。ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問