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

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

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

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

Q&A

解決済

1回答

1158閲覧

JavaScript「クイズアプリ」2問目を表示する際に、1問目を消したい

halu_0366

総合スコア1

JavaScript

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

0グッド

0クリップ

投稿2021/05/25 06:45

前提・実現したいこと

Youtubeの”セイト先生のWeb・IT塾”さんの【JavaScript超入門講座】基礎文法だけでクイズゲームのアプリを開発!を改良してみようと思い、制作中です。
動画では4択と決められていますが、**「選択肢の数に応じてボタンの数も変化させてみよう」**をやってみたくて、予めbuttonは書かずに__createElement("button")__で書いていて、それを__answersBox.appendChild($button)__で表示しています。

想定している動きは
選択肢をボタンに1つずつ表示、クリックで正誤判定(alert)、次の問題へ移る__(再びsetupQuiz)__時に1問目を消し、2問目を表示したいと考えていて、問題数分繰り返して、残りの問題が無くなったら最後に正解数を表示します。

ソースコードの状態では2問目→3問目と表示できますが、前の問題が消えずに残ってしまいますし、2問目と3問目はクリックの対象からも外れています。この点を解決するためのコードまたヒントだけでも教えていただけると助かります。
お時間ある方回答よろしくお願いいたします。

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

貼り付けたソースコードでエラーは起きていないのですが、setQuiz関数の$button.textContent を$button[quizIndex].textContentや$button[i].textContentにすると「undefinedにtextContentはsetできない」とエラー

index3.html:118 Uncaught TypeError: Cannot set property 'textContent' of undefined at setupQuiz (index3.html:118) at index3.html:172

該当のソースコード

html,javascript

1<!DOCTYPE html> 2<html class="no-js" lang=""> 3 <head> 4 <meta charset="utf-8" /> 5 <title></title> 6 <meta name="description" content="" /> 7 <meta name="viewport" content="width=device-width, initial-scale=1" /> 8 9 <meta property="og:title" content="" /> 10 <meta property="og:type" content="" /> 11 <meta property="og:url" content="" /> 12 <meta property="og:image" content="" /> 13 14 <link rel="manifest" href="site.webmanifest" /> 15 <link rel="apple-touch-icon" href="icon.png" /> 16 <!-- Place favicon.ico in the root directory --> 17 18 <!-- CSS only --> 19 <link 20 href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" 21 rel="stylesheet" 22 integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" 23 crossorigin="anonymous" 24 /> 25 26 <meta name="theme-color" content="#fafafa" /> 27 </head> 28 29 <body> 30 <div class="container"> 31 <div id="js-question" class="alert alert-primary mt-4" role="alert"> 32 A simple primary alert—check it out! 33 </div> 34 35 <div id="answers-box" class="d-flex justify-content-center"> 36 <!-- <button type="button" class="btn btn-primary">Primary</button> 37 <button type="button" class="btn btn-primary ms-2">Primary</button> 38 <button type="button" class="btn btn-primary ms-2">Primary</button> 39 <button type="button" class="btn btn-primary ms-2">Primary</button> --> 40 </div> 41 </div> 42 43 <script> 44 const quiz = [ 45 { 46 question: "ハリソン・フォードが大好きなのは日本の何?", 47 answers: ["忍者", "酒", "祭り", "相撲", "城"], 48 correct: "忍者", 49 }, 50 { 51 question: "トム・クルーズは学生時代、何回転校した?", 52 answers: ["4", "7", "11", "14"], 53 correct: "14", 54 }, 55 { 56 question: "「シュワちゃん」のシュワルツェネッガー、正しいスペルは?", 57 answers: [ 58 "Schwalzeneger", 59 "Schwarzenegger", 60 "Shwarzeneger", 61 "Schwalzenegger", 62 "Schwarzeneger", 63 "Shwarzenegger", 64 ], 65 correct: "Schwarzenegger", 66 }, 67 ]; 68 69 const quizLength = quiz.length; 70 let quizIndex = 0; 71 let score = 0; 72 73 const answersBox = document.querySelector("#answers-box"); 74 75 76 // クイズの問題文、選択肢を定義 77 const setupQuiz = () => { 78 // 問題 79 document.querySelector("#js-question").textContent = 80 quiz[quizIndex].question; 81 82 // 選択肢 83 let buttonIndex = 0; 84 const buttonLength = quiz[quizIndex].answers.length; 85 86 87 for (i = 0; i < buttonLength; i++) { 88 const $button = document.createElement("button"); 89 90 $button.classList.add("btn", "btn-primary", "ms-2"); 91 $button.type = "button"; 92 93 console.log($button); 94 95 $button.textContent = quiz[quizIndex].answers[i]; 96 answersBox.appendChild($button); 97 } 98 }; 99 100 // const clearQuiz = () => { 101 // answersBox.removeChild(); 102 // } 103 104 const clickHandler = (e) => { 105 if (quiz[quizIndex].correct === e.target.textContent) { 106 window.alert("正解!!おめでとう"); 107 score++; 108 } else { 109 window.alert("不正解...残念"); 110 } 111 112 quizIndex++; 113 if (quizIndex < quizLength) { 114 // clearQuiz(); 115 setupQuiz(); 116 } else { 117 if (score === quizLength) { 118 window.alert( 119 "終了です。あなたの正解数は" + 120 score + 121 "/" + 122 quizLength + 123 "です! \n 全問正解!!素晴らしい!!" 124 ); 125 } else { 126 window.alert( 127 "終了です。あなたの正解数は" + 128 score + 129 "/" + 130 quizLength + 131 "です! \n 答えが知りたい方はまた遊んでください。" 132 ); 133 } 134 } 135 }; 136 137 // buttonをclickしたら正誤判定 138 const judge = () => { 139 const btn = document.querySelectorAll("button"); 140 let handlerIndex = 0; 141 while (handlerIndex < btn.length) { 142 btn[handlerIndex].addEventListener("click", (e) => { 143 clickHandler(e); 144 }); 145 handlerIndex++; 146 } 147 }; 148 149 setupQuiz(); 150 judge(); 151 </script> 152 </body> 153</html> 154

試したこと

コメントアウトで残しておきましたが、clearQuiz()関数として__answersBox
の中身を空にしようともしましたが、「removeChildはNodeが1つは必要、今はゼロ」とエラーになるため、なにか入れようと__answersBox.removeChild($button);にしたところ、関数が違うため「$button is not defined
」とエラーでした。

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

windows,Chromeブラウザ,VSCodeエディタ使用

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

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

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

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

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

m.ts10806

2021/05/25 07:15

自身で書いたコードはどの程度説明できるのでしょうか
halu_0366

2021/05/25 12:12

返信ありがとうございます。張り付けたソースコードに関しては全て説明出来る状態でした。 answersBox.innerHTML = ''; と judge()を1つ追加で解決しました。
m.ts10806

2021/05/25 12:28

なるほど。「説明できる程度に理解できてるならなぜこの質問は出たのだろう」という疑問は残りました。
guest

回答1

0

ベストアンサー

前の問題のボタンが消えない

clearQuiz()に関しては、以下のようにすることで子要素すべてを削除することが出来ます。

javascript

1const clearQuiz = () => { 2 answersBox.innerHTML = ''; 3}

この関数が用意出来たら、実際に次の問題に移るタイミングで、関数を実行することで前の問題のボタンが消えた状態で、次の問題を表示することが出来ます。

次の問題のボタンイベントが発火しない

こちらは、judge()が初回の描画時の一回のみしか実行されていない為です。
こちらも上の件と同様に、次の問題が作成されるタイミングで、judge()を実行してイベントを設定する必要があります。

※実行箇所は、考えてみてください。

投稿2021/05/25 07:34

yoshihiko555

総合スコア84

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

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

halu_0366

2021/05/25 12:06

回答ありがとうございます。返信が遅くなり申し訳ありません answersBox.innerHTML = '';で「answersBoxのHTMLを空にする」なんですね。 if (quizIndex < quizLength) { clearQuiz(); setupQuiz(); judge(); } で期待通りの動きになりました。quizの配列をさらに4個5個と増やしても問題なく動作しています。 解決です、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問