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

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

新規登録して質問してみよう
ただいま回答率
85.48%
ラジオボタン

ラジオボタンはフォームに使われる要素のひとつであり、ユーザに限られた選択肢からひとつの答えを選んでもらうというものです。

JavaScript

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

HTML

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

CSS

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

3回答

4867閲覧

【JavaScript】1回押す度に、直前に選択したラジオボタンのチェックを解除する「やり直し」ボタンを実装したい!

KentaroxKondo

総合スコア9

ラジオボタン

ラジオボタンはフォームに使われる要素のひとつであり、ユーザに限られた選択肢からひとつの答えを選んでもらうというものです。

JavaScript

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

HTML

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

CSS

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2021/05/30 14:23

実現したいこと:「戻る」ボタンを押すことで、直前に選択したラジオボタンの選択状態を解除し、ひとつずつ過去の状態にさかのぼれる機能を実装したい!

JavaScriptを独学し始めて1ヶ月ほどの超初心者ですm(_ _)m
現在、質問に回答するごとに正解の選択肢が絞られていく、**「アキネーター」**のようなプログラムを鋭意作成中です。

以下のスクリプトを活用し、「ZeroPossibility」クラスが付与された要素をCSSで非表示処理することによって、ユーザーが質問に答えるごとに正解となる選択肢が絞られていき、同時に尋ねる意義がなくなった質問も非表示になるプログラムが出来上がりました。

しかし、予期していなかった問題に気がつきました。それは、**「ユーザーが2個以上の選択を誤っていた場合に、一方をやり直すと結果が狂う」**ことです。

上記の回避策として、**「ひとつ前にいじったラジオボタンの選択状態を未選択状態に戻す」**ボタンの実装を思いついたのですが、どのようにコーディングすればよいのかわからずに困窮しております。

できれば、「一つ前に戻るボタン」を押す度に、何度でも直前にいじったラジオボタンの選択を解除できるようにしたいです。
なお、ユーザーが直前に、同じ質問の「はい」と「いいえ」を交互に切り替えていた場合は、「はい」や「いいえ」に戻す必要はないので、ただ選択を解除させたいです。

HTML

1<body> 2 3 <div id="Questions"><h1>質問</h1> 4 5 <div id="Q1"> 6 <p>Q. 動物ですか?</p> 7 <label><input type="radio" name="RadGrpA1" id="A1Yes">YES</label> 8 <label><input type="radio" name="RadGrpA1" id="A1No">No</label> 9 <label><input type="radio" name="RadGrpA1">わからない</label> 10 </div> 11 12 <div id="Q2"> 13 <p>Q. 首が長いですか?</p> 14 <label><input type="radio" name="RadGrpA2" id="A2Yes">YES</label> 15 <label><input type="radio" name="RadGrpA2" id="A2No">No</label> 16 <label><input type="radio" name="RadGrpA2">わからない</label> 17 </div> 18 19 <div id="Q3"> 20 <p>Q. 植物ですか?</p> 21 <label><input type="radio" name="RadGrpA3" id="A3Yes">YES</label> 22 <label><input type="radio" name="RadGrpA3" id="A3No">No</label> 23 <label><input type="radio" name="RadGrpA3">わからない</label> 24 </div> 25 26 <div id="Q4"> 27 <p>Q. トゲがありますか?</p> 28 <label><input type="radio" name="RadGrpA4" id="A4Yes">YES</label> 29 <label><input type="radio" name="RadGrpA4" id="A4No">No</label> 30 <label><input type="radio" name="RadGrpA4">わからない</label> 31 </div> 32 33 <div id="Q5"> 34 <p>Q. 人間ですか?</p> 35 <label><input type="radio" name="RadGrpA5" id="A5Yes">YES</label> 36 <label><input type="radio" name="RadGrpA5" id="A5No">No</label> 37 <label><input type="radio" name="RadGrpA5">わからない</label> 38 </div> 39 40 <div id="Q6"> 41 <p>Q. ミュージシャンですか?</p> 42 <label><input type="radio" name="RadGrpA6" id="A6Yes">YES</label> 43 <label><input type="radio" name="RadGrpA6" id="A6No">No</label> 44 <label><input type="radio" name="RadGrpA6">わからない</label> 45 </div> 46 47 </div> 48 49 <h1>可能性</h1> 50 <p id="Cabbage">キャベツ</p> 51 <p id="Cactus">サボテン</p> 52 <p id="Elephant">象</p> 53 <p id="Giraffe">キリン</p> 54 <p id="MichaelJackson">マイケルジャクソン</p> 55 <p id="NobunagaOda">織田信長</p> 56 57</body>

JavaScript

1document.getElementById("Questions").addEventListener("change", () => { 2 3 let Judge = {Cabbage:"", Cactus:"", Elephant:"", Giraffe:"", MichaelJackson:"", NobunagaOda:""}; 4 let JudgeArray = ["Cabbage", "Cactus", "Elephant", "Giraffe", "MichaelJackson", "NobunagaOda"]; 5 6 const ResponseAndProcess = [ 7 {Response:"A1Yes", Omit:["Cabbage","Cactus"]}, 8 {Response:"A1No", Omit:["Elephant","Giraffe","MichaelJackson","NobunagaOda"]}, 9 {Response:"A2Yes", Omit:["Cabbage","Cactus","Elephant","MichaelJackson","NobunagaOda"]}, 10 {Response:"A2No", Omit:["Giraffe"]}, 11 {Response:"A3Yes", Omit:["Elephant","Giraffe","MichaelJackson","NobunagaOda"]}, 12 {Response:"A3No", Omit:["Cabbage","Cactus"]}, 13 {Response:"A4Yes", Omit:["Cabbage","Elephant","Giraffe","MichaelJackson","NobunagaOda"]}, 14 {Response:"A4No", Omit:["Cactus"]}, 15 {Response:"A5Yes", Omit:["Cabbage","Cactus","Elephant","Giraffe"]}, 16 {Response:"A5No", Omit:["MichaelJackson","NobunagaOda"]}, 17 {Response:"A6Yes", Omit:["Cabbage","Cactus","Elephant","Giraffe","NobunagaOda"]}, 18 {Response:"A6No", Omit:["MichaelJackson"]}, 19 ]; 20 21 for (let i=0; i<ResponseAndProcess.length; i++) { 22 if (document.getElementById(ResponseAndProcess[i].Response).checked) { 23 for (let j=0; j<ResponseAndProcess[i].Omit.length; j++) { 24 Judge[ResponseAndProcess[i].Omit[j]] = "不正解"; 25 } 26 } 27 } 28 29 for (let i = 0; i < JudgeArray.length; i++) { 30 if (Judge[JudgeArray[i]] == "不正解") { 31 document.getElementById(JudgeArray[i]).classList.add("ZeroPossibility"); 32 } else { 33 document.getElementById(JudgeArray[i]).classList.remove("ZeroPossibility"); 34 } 35 } 36 37 document.querySelectorAll('#Questions > div').forEach(el => el.classList.remove("ZeroPossibility")) 38 const Possibilities = Object.entries(Judge).flatMap(e => e[1] === "不正解" ? [] : e[0]); 39 const ZeroPossibilityResponses = ResponseAndProcess.flatMap(e => Possibilities.every(x => !e.Omit.includes(x)) ? e.Response : []) 40 ZeroPossibilityResponses.forEach(opt => { 41 const $Options = document.getElementById(opt); 42 if(!$Options.checked){ 43 $Options.closest('div').classList.add('ZeroPossibility') 44 } 45 }); 46 47});

負んぶに抱っこですみませんが、皆様のお知恵を拝借できれば幸いです。どうぞよろしくお願いいたしますm(_ _)m

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

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

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

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

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

guest

回答3

0

javascript

1<script> 2window.addEventListener('DOMContentLoaded', ()=>{ 3 let data={}; 4 let url=""; 5 document.querySelectorAll('[type=radio]').forEach(x=>{ 6 x.addEventListener('change',e=>{ 7 let v=null; 8 ["a","b","c"].forEach(x=>{ 9 if(v=document.querySelector(`[name=${x}]:checked`)?.value) data[x]=v; 10 }); 11 url = Object.entries(data).map(arg=>arg.map(encodeURIComponent).join('=')).join("&"); 12 history.pushState(null,null,'?'+url); 13 }); 14 }); 15}); 16window.addEventListener('popstate', ()=>{ 17 url=location.search.substr(1); 18 data=Object.fromEntries(url.split("&").map(arg=>arg.split("=").map(decodeURIComponent))); 19 ["a","b","c"].forEach(x=>{ 20 let y; 21 if(typeof data[x]!=="undefined"){ 22 document.querySelector(`[name=${x}][value="${data[x]}"]`).checked=true; 23 }else if(y=document.querySelector(`[name=${x}]:checked`)){ 24 y.checked=false; 25 } 26 }); 27}); 28</script> 29a: 30<label><input type="radio" name="a" value="1">1</label> 31<label><input type="radio" name="a" value="2">2</label> 32<label><input type="radio" name="a" value="3">3</label><br> 33b: 34<label><input type="radio" name="b" value="1">1</label> 35<label><input type="radio" name="b" value="2">2</label> 36<label><input type="radio" name="b" value="3">3</label><br> 37c: 38<label><input type="radio" name="c" value="1">1</label> 39<label><input type="radio" name="c" value="2">2</label> 40<label><input type="radio" name="c" value="3">3</label><br> 41

投稿2021/05/31 01:36

yambejp

総合スコア114839

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

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

KentaroxKondo

2021/06/04 09:11

>yambejp様 ご親切にコードを教えていただきまして、心から感謝いたします! いただいたコードですが、初心者の私には理解が難しい部分があり、時間をかけて勉強させていただこうと思います。 今回は他にわかりやすく説明くださった方がおられたので、悩んだ結果他の方をベストアンサーとさせていただきました。 yambejp様にもいつも助けていただいているので感謝いたします!m(_ _)m 今後ともよろしくお願いいたします。
guest

0

考え方の一つとして参考にしてください。

  • クリックしたラジオボタンのnameを記録するグローバルな配列を用意する。仮にradioHistoryとする。
  • ラジオボタンをクリックしたら、クリックしたradioのnameをradioHistoryにpushするイベントハンドラを作成する。その際、一番最後にpushしたnameと一緒であればpushしないようにすれば連続で同じ設問を変更した際の対策になります。
  • 戻るボタンを用意し、ボタンを押したら、radioHistoryからデータをpopし、そのname属性と一致するinputのcheckedをfalseにするイベント関数を作成する。1つのnameに対しradioは3つあるので、3つともchecked=falseにすれば全て未選択状態になります。

配列からデータをpopすると配列から末尾のデータがなくなるので、連続でundoさせることが可能になります。

投稿2021/05/30 15:06

hope_mucci

総合スコア4447

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

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

KentaroxKondo

2021/06/04 09:08

>hope_mucci様 非常にわかりやすく解説いただきまして、ありがとうございます。 コードを考える上で、とても参考になる情報でしたので、今後も復習しようと思います! よろしければ今後も困った際に助けていただけると幸いです。 引き続きよろしくお願いいたします!m(_ _)m
guest

0

ベストアンサー

私も hope_mucci さんと同じ考え方ですが、質問の意図としては、A1Yes、A2Yes、A3No、A2No という操作をした時に、undo は Q2、Q3、(Q2をとばして)Q1 ということだと思うので、Set を使った方がいいかもしれない、と感じました。

js

1let responseHistory = new Set(); 2 3document.getElementById("Questions").addEventListener("change", (e) => { 4//... 5 responseHistory.delete(e.target.name) 6 responseHistory.add(e.target.name)

undoする時は、こんな感じでしょうか。

js

1 const targetResponce = [...responseHistory].pop() 2 responseHistory.delete(targetResponce) 3 document.getElementsByName(targetResponce).forEach(//...

投稿2021/05/31 07:50

Lhankor_Mhy

総合スコア36115

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

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

KentaroxKondo

2021/06/04 09:04

>Lhankor_Mhy様 いつも的確にご回答いただきまして、ありがとうございます。 Set() によって、重複を避けた配列を作成可能とのこと、非常に勉強になりました。 また、「…」の部分ですが、何かの省略かと思い調べましたが、そのまま活用できるのですね。 初めてみるコーディングで、びっくりしました! forEachの続きを考えるのが私には難しかったので、ひとまず以下のコーディングで理想を実現できました。(質問文の処理は「AutoJudgement」と名づけました。) ――――――――――――――――――――――――――― let RadbtnHistory = new Set(); document.getElementById("Questions").addEventListener("change", (e) => { AutoJudgement(); RadbtnHistory.add(e.target.name) }); document.getElementById("btnBack").addEventListener("click", () => { const LastItem = [...RadbtnHistory].pop() RadbtnHistory.delete(LastItem) const UncheckingTarget = document.getElementsByName(LastItem); for (let i = 0; i < UncheckingTarget.length; i++){ UncheckingTarget[i].checked = false; } AutoJudgement(); }); ――――――――――――――――――――――――――― また、先程投稿した質問にもご回答いただければと思いましたが、すでにご覧いただいたようで、ありがとうございます!今後ともよろしくお願いいたします。
Lhankor_Mhy

2021/06/04 09:07

それだと、undoする順番が想定と異なりませんか?
KentaroxKondo

2021/06/04 09:16

>Lhankor_Mhy 複数のラジオボタンをチェックして検証したところ、「btnBack」ボタンを押すたびに、直前に選択したボタンが順次解除され、AutoJudgement処理も走っていました。 特に問題は感じられなかったのですが、検証手順が不足しているのでしょうか・・・
Lhankor_Mhy

2021/06/04 09:28

回答に例示した、A1Yes、A2Yes、A3No、A2No とした時に、Q2ではなくてQ3から解除されそうなコードに見えたもので。 ご検証の結果、問題がないのであれば私の勘違いだと思いますので、お気になさらずに。
KentaroxKondo

2021/06/04 09:38

>Lhankor_Mhy すみません!おっしゃる通りでした・・・m(_ _)m 複数項目を選択後、何個か前につけたチェックを変更すると、戻るボタンの順序が直前の動作の解除ではなくなってしまうようでした・・・ この部分をforEachの続きで解消することができるのでしょうか? こんな細部にまですぐに気がつくなんて、本当にすごいです・・・
Lhankor_Mhy

2021/06/04 10:08

私の回答では responseHistory.delete(e.target.name) responseHistory.add(e.target.name) と削除→追加となっているところ、ご提示のコードは RadbtnHistory.add(e.target.name) と追加しかしていないのです。
KentaroxKondo

2021/06/04 10:21

>Lhankor_Mhy様 とても納得しました。いったん配列から消した後に、末尾に追加する処理を行っていたのですね! deleteする意味がわからずに、addのみにしていました。大変失礼いたしましたm(_ _)m 引き続き、よろしくお願いいたします!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問