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

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

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

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

1回答

951閲覧

jQueryのクリックイベントで、とんでもないジレンマに陥りました

ka2ga2

総合スコア19

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2019/02/12 15:19

編集2019/02/12 15:51

セレクトボックスを自作するにあたり、jQueryを使っています。

後述するように色々調べて3パターン作ってみたのですが、どれも「開くと閉じる」という状態です!!

その箇所は、下記コードの

/* * ラベルクリックで選択肢を開く * どのパターンでもできない! */

という部分です。
3パターンどれも「開くと閉じる」になってしまいます。

サンプルを作りました。操作して頂くと早いと思います。
https://jsfiddle.net/tf0vu1pd/

コードはこちらです。

html

1<div> 2 <label class="open"> 3 <input type="radio" id="submit" checked="" value="a"> 4 <span id="now">りんご</span> 5 </label> 6 <ul> 7 <li data-submit="0"><span>りんご</span></li> 8 <li data-submit="1"><span>ごりら</span></li> 9 <li data-submit="2"><span>らっぱ</span></li> 10 </ul> 11</div>
<style> /* 選択中のものを表示 */ label { background: #efefef; width: 100px; padding: 5px 10px; display: block; cursor: pointer; } input { display: none; } /* 選択肢を表示 */ ul { list-style: none; margin: 0; padding: 0; display: none; } li { background: #efefef; border-bottom: 1px solid #ddd; padding: 5px 10px; margin: 0; width: 100px; cursor: pointer; } li:hover { background: #aaa; color: #fff; } </style>
<script> /* * ラベルクリックで選択肢を開く * どのパターンでもできない! */ //パターン1 $(document).on("click","label", function(){ if( $(this).hasClass('open') ){ $(this).closest('div').find('ul').slideDown(); $(this).removeClass('open'); }else{ $(this).closest('div').find('ul').slideUp(); $(this).addClass('opan'); } }); //パターン2 $(document).on("click","label.open", function(){ $(this).closest('div').find('ul').slideDown(); $(this).removeClass('open').addClass('close'); }); $(document).on("click","label.close", function(){ $(this).closest('div').find('ul').slideUp(); $(this).removeClass('close').addClass('opan'); }); //パターン3 $(document).on("click","label", function(){ if( $(this).closest('div').find('ul').css('display') == 'block' ){ $(this).closest('div').find('ul').slideUp(); }else{ $(this).closest('div').find('ul').slideDown(); } }); /* * 選択するとinputを変更 * 問題なくできた */ $(document).on("click","li", function(){ var selected_txt = $(this).text(); $('#now').text(selected_txt); var selected_data = $(this).attr('data-submit'); $('#submit').val(selected_data); $(this).closest('div').find('ul').slideUp(); }); </script>

かなり頑張ったのですが、どのパターンでも玉砕しまして、どうしても「開くと閉じる」のジレンマが解決できません。

閉じるのは選択してからでいいのですが…、

このようなジレンマはどうすれば解決できるものでしょうか?
具体的なコードで教えて頂けますと大変助かります。
どうか助けてください!宜しくお願いします!

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

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

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

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

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

kei344

2019/02/12 15:26

(質問文は編集できます)質問文のコードはそれぞれ(HTML/JavaScript/CSS)コードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「<code>」ボタンを押すとコードブロックになります。
guest

回答1

0

ベストアンサー

labelのなかにinput(チェックボックス)があることで、labelにイベントを設定すると二重にclickイベントが発生します。
inputtype="hidden"に変更

opanopen

以上の二点でとりあえず問題となるところは解決するかと

追記

インタラクティブ・コンテンツの中にインタラクティブ・コンテンツがあって、jQueryでclickイベント設定するとか、普通は設定しないので、
予期しない動作だから二度イベントが呼ばれるとかじゃないかなと思います。
インタラクティブ・コンテンツについて

下記のように、preventDefault()を使うことで、3パターンどれでも解決はするんですが

js

1$(document).on("click","label", function(e){ 2 e.preventDefault();

そもそもこの処理なら、buttonで実装するのが良いと思います。

html

1 <button class="open" id="submit" value="a"> 2 <span id="now">りんご</span> 3 </button>

js

1$(document).on("click","button", function(e){ 2 if( $(this).hasClass('open') ){ 3 $(this).closest('div').find('ul').slideDown(); 4 $(this).removeClass('open'); 5 }else{ 6 $(this).closest('div').find('ul').slideUp(); 7 $(this).addClass('open'); 8 } 9});

on()イベントよりはclick()イベントで良いと思いますが、そこは触れないでおきます。

コメントに対する回答

<div><p><span></span></p></div>は、どれもインタラクティブコンテンツではないので、JSで設置したイベントを処理しているだけです。
そのため、一回しか処理されません。

投稿2019/02/12 15:41

編集2019/02/12 16:17
kszk311

総合スコア3404

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

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

ka2ga2

2019/02/12 15:50

ありがとうございます。openすみませんw あとよくわからないのですが、クリックイベントの対象は、クリックした要素の子要素にまで及ぶのですか? では<div><p><span></span></p></div>とあってdivにクリックイベントをつけたら、3回クリックイベントが発生するといこと、では、ないですよね?(試したら違いました→https://jsfiddle.net/u06qebt4/)
ka2ga2

2019/02/12 16:27 編集

追記とコメントに対するご回答、ありがとうございます。 でもlabelの中にinputってよくある書き方ですよね。それはよくあるけど、クリックイベントを設定することがあまりないということでしょうか。 あとpreventDefault()もいいですね。 そしてbuttonにしておきます。 大変勉強になりました。感謝です。
kszk311

2019/02/12 16:37

>labelの中にinputってよくある書き方ですよね。 よくありますね。 ただ、そこにクリックイベントを設定することは、見かけたことがありません。(主観ですが、6年の経験上の話です) なので、その構成で進めるなら「e.preventDefault()」つけておけば良いと思います。
ka2ga2

2019/02/12 16:39

6年......恐れ入ります。貴重なご意見をどうもありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問