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

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

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

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

jQuery

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

Q&A

解決済

4回答

435閲覧

対象のボタン以外をクリックしたことを判定する方法

narutona

総合スコア23

JavaScript

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

jQuery

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

1グッド

0クリップ

投稿2019/06/18 00:31

編集2019/06/18 23:52

JavaScript、jQueryで、対象のボタン以外をクリックしたことを判定したいです。
宜しくお願い致します。

###前提・実現したいこと
下記3つの機能を実現したいです。(文末に補足して4つにしました)

➀ボタンクリックでメニュー表示
➁もう一度クリックでメニュー非表示
➂ボタン以外のクリックでメニュー非表示

###発生している問題・エラーメッセージ
上の3つのうち1つずつは実現できました。
ですが3つを組み合わせると実現できません。

エラーはありません。

###試したこと
こちらがその表示切替コードになります。
それぞれは動くのですが、どこを直せば➀➁➂がすべて動くようになりますでしょうか?

html

1<p>こんにちは</p> 2<div class="E"> 3 <button type="button">メニュー</button> 4</div> 5 6<p>こんばんは</p> 7<div class="E"> 8 <button type="button">メニュー</button> 9</div>

jQuery

1// メニュー 2var menus = ` 3 <ul class="menus"> 4 <li>たべる</li> 5 <li>さわる</li> 6 </ul> 7`; 8 9// ➀ボタンクリックでメニュー表示 10$(document).on('click','.E > button:not(.is_click)', function(){ 11 $(this).addClass('is_click'); 12 $(this).after(menus); 13}); 14 15// ➁もう一度クリックでメニュー非表示 16$(document).on('click','.E > button.is_click', function(){ 17 $(this).removeClass('is_click'); 18 $(this).next('.menus').remove(); 19}); 20 21// ➂ボタン以外のクリックでメニュー非表示 22$(document).on('click',function(e) { 23 if(!$(e.target).closest('.E > button:not(.is_click)').length) { 24 $('.E > button').removeClass('is_click'); 25 $('.menus').remove(); 26 } 27}); 28 29

###補足
すみません、補足です。

➃複数のメニューが同時に表示されることは避けたい。

たとえば「こんにちは」のメニューを開いてる最中に、「こんばんは」のメニューを開いたら、「こんばんは」のメニューだけを表示できればと思っています。

jun68ykt👍を押しています

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

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

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

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

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

m.ts10806

2019/06/18 00:45

CSSもご提示ください。
yambejp

2019/06/18 00:49

とりあえず<il>を<li>に修正してください
narutona

2019/06/18 00:50

CSSはないです。すみません、HTML修正いたしました。
m.ts10806

2019/06/18 00:54

なるほどis_clickはフラグ替わりですね。何かしら装飾をしているのかと思ってました。了解です。
narutona

2019/06/18 00:56

すみません、is_clickまぎらわしかったですね。
m.ts10806

2019/06/18 00:58

いえいえ。コード最後までちゃんと見てれば分かったので、私の見逃しです
narutona

2019/06/19 00:16

お世話になっております。おかげさまで解決いたしました。また機会がありましたら宜しくお願い致します。
guest

回答4

0

ベストアンサー

こんにちは

とり急ぎの対応で最小限の修正で済ませるとすれば、➂ボタン以外のクリックでメニュー非表示if 条件に、以下のように、 e.target.tagName !== 'BUTTON' を追加すると、いかがでしょうか。

修正前:

javascript

1if(!$(e.target).closest('.E > button:not(.is_click)').length) {

  

修正後:

javascript

1if(e.target.tagName !== 'BUTTON' && !$(e.target).closest('.E > button:not(.is_click)').length) {

修正前だと、メニューが閉じているときにボタンをクリックしたときにも③のif の中が実行されてしまうので、修正後ではこれを防いでいます。

追記1

@narutonaさん

上記の回答では、ご質問に追加されている補足を満たすものになっていませんでした。追って補足も満たすものを検討します。

追記2

以下で要件を満たせているのではないかと思います。

javascript

1const openMenu = function(button) { 2 button.after(` 3 <ul class="menus"> 4 <li>たべる</li> 5 <li>さわる</li> 6 </ul>` 7 ).addClass('is_click'); 8} 9 10const closeMenu = function(button) { 11 button 12 .removeClass('is_click') 13 .siblings('.menus') 14 .remove(); 15}; 16 17$('.E').on('click', function(e) { 18 const t = $(e.target); 19 if (t.attr('type') === 'button') { 20 if (t.hasClass('is_click')) { 21 closeMenu(t); 22 } else { 23 closeMenu($('.E > button.is_click')); 24 openMenu(t); 25 } 26 } else if (t.hasClass('menus') || t.parent().hasClass('menus')) { 27 closeMenu($('button', this)); 28 } 29});

以下は上記のコードを動作確認するために、jsFiddle に上げたものです。動作確認のため、スタイルを追加し、また、ボタンを4個に増やしています。

追記3

先ほどの追記2のコードを、なるべくロジックを追いやすくなるように修正しました。

javascript

1const MENUS_HTML = ` 2 <ul class="menus"> 3 <li>たべる</li> 4 <li>さわる</li> 5 </ul> 6`; 7 8 9$.fn.menus = function(cmd, menus) { 10 switch (cmd) { 11 case 'open': 12 this.addClass('is_click') 13 .after(menus); 14 break; 15 case 'close': 16 this.removeClass('is_click') 17 .siblings('.menus') 18 .remove(); 19 break; 20 default: 21 break; 22 } 23}; 24 25 26$('.E').on('click', function({ target }) { 27 const e = $(target); 28 switch (target.tagName) { 29 case 'BUTTON': 30 if (e.hasClass('is_click')) { 31 e.menus('close'); 32 } else { 33 $('.E > .is_click').menus('close'); 34 e.menus('open', MENUS_HTML); 35 } 36 break; 37 case 'UL': 38 case 'LI': 39 $('.is_click', this).menus('close'); 40 break; 41 default: 42 break; 43 } 44}); 45 46

以上、参考になれば幸いです。

投稿2019/06/18 01:37

編集2019/06/18 23:04
jun68ykt

総合スコア9058

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

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

narutona

2019/06/18 23:43

色々な案をありがとうございます。メニューを引数にすれば別のメニューを表示するときにも使いまわせるコードになりますし、何よりswichというメソッドはとても便利で、大変勉強になりました。これから参考にさせて頂きたいコードとして、永久保存版です。 ただ「それ以外の場所でのクリックでメニューを閉じる」というのが実現できませんでした。質問がわかりにくかった中で考えを巡らせてくださってありがとうございます。
jun68ykt

2019/06/19 05:06

どういたしまして。解決されたようでよかったです ???? > ただ「それ以外の場所でのクリックでメニューを閉じる」というのが実現できませんでした。 とのことだったので、追記3 で作成したコードに若干コードを追加して https://jsfiddle.net/jun68ykt/dbz0mknt/7/ を作成しました。これは、 $(document).on('click', function(){ $('.is_click').menus('close'); }); を追加することで、「それ以外の場所でのクリックでメニューを閉じる」を実現していますが、div の中をクリックしたときに、上記が呼ばれないように $('.E').on に与えるコールバックの中で event.stopPropagation(); を使っています。この行をコメントアウトすると、「メニュー」をクリックしてもメニューは開きません。
narutona

2019/06/19 12:21

たびたびありがとうございます。わたしの自称自己解決しょぼっしょぼコードからベストアンサーをはずし、改めてこちらを選ばせて頂きます。それにしても、ご提示のコードは本当にとても勉強になりました。感謝です。
jun68ykt

2019/06/19 14:07

ありがとうございます。回答者冥利に尽きます。今後の学習が捗ることを祈念しております。草々
guest

0

.menuは付加したり削除したりしないといけないのでしょうか?

javascript

1<script> 2$(function(){ 3 $('.menus').hide(); 4 $(document).on('click','*',function(e){ 5 if($('.E button').index(this)>=0){ 6 $('.menus').toggle(); 7 e.stopPropagation(); 8 }else{ 9 $('.menus').hide(); 10 } 11 }); 12}); 13</script> 14<p>こんにちは</p> 15<div class="E"> 16 <button type="button">メニュー</button> 17</div> 18 19<p>こんばんは</p> 20<div class="E"> 21 <button type="button">メニュー</button> 22</div> 23 24<ul class="menus"> 25<li>たべる</li> 26<li>さわる</li> 27</ul>

調整版

javascript

1<script> 2$(function(){ 3 var menus = ` 4 <ul class="menus"> 5 <li>たべる</li> 6 <li>さわる</li> 7 </ul> 8`; 9 $(document).on('click','*',function(e){ 10 if($('.E button').index(this)>=0){ 11 $('.E').not($(this).closest('.E')).find('.menus').remove(); 12 if($(this).closest('.E').find('.menus').length>0) $('.menus').remove(); 13 else $(this).after(menus); 14 e.stopPropagation(); 15 }else{ 16 $('.menus').remove(); 17 } 18 }); 19}); 20</script> 21 22<p>おはよう</p> 23<div class="E"> 24 <button type="button">メニュー</button> 25</div> 26 27<p>こんにちは</p> 28<div class="E"> 29 <button type="button">メニュー</button> 30</div> 31 32<p>こんばんは</p> 33<div class="E"> 34 <button type="button">メニュー</button> 35</div>

投稿2019/06/18 01:04

編集2019/06/18 01:55
yambejp

総合スコア114812

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

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

narutona

2019/06/18 01:15

そうですね、できればいちいち付加したり削除したりしたいと思っています。ソースコードありがとうございます。勉強になります。
yambejp

2019/06/18 01:19

> 付加したり削除したりしたい そうなるとどこに付加したいのか曖昧です。 ボタンの後ろですか? その場合ボタンが複数あったり.Eが複数あったりした場合どうするのでしょうか?
narutona

2019/06/19 00:02 編集

>ボタンの後ろですか? はい、ボタンの後ろで考えています。つまり「.E」の中に「buttton」と「.menus」が並び、「.menus」が弟になる感じです。 >その場合ボタンが複数あったり.Eが複数あったりした場合 それらは実際に複数ありまして、表示メニューは常に1つを考えています。 これついては補足した➃の条件になりまして、クリックされた方のメニューだけが存在することになればと思っています。
yambejp

2019/06/18 01:56

追記しました、こんな感じでしょうか?
narutona

2019/06/19 00:02

すみません、チェックボックスになることは予想外でした。あと補足した➃の条件が実現できないようでした。質問がわかりにくかった中で考えを巡らせてくださってありがとうございます。
guest

0

CSSにトグル処理を任せると、シンプルに書けます。
(モバイル環境の為、コード未検証)

HTML

1<style> 2.menu-open, .menu-open:not(:checked)+.menu { 3 display: none; 4} 5</style> 6</head> 7<body> 8<label><input type="checkbox" class="menu-open">メニューA</label> 9<ul class="menu"> 10 <li>たべる</li> 11 <li>さわる</li> 12</ul> 13<label><input type="checkbox" class="menu-open">メニューB</label> 14<ul class="menu"> 15 <li>たべる</li> 16 <li>さわる</li> 17</ul> 18<script> 19jQuery(document).on('click', function (event) { 20 var target = event.target, thisInput = target.querySelector('input.menu-open'); 21 22 jQuery('input.menu-open:checked').filter(input => inpiut !== thisInput).prop('checked', false); 23}); 24</script>

Re: narutona さん

投稿2019/06/19 00:02

think49

総合スコア18162

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

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

narutona

2019/06/19 00:16 編集

入力しにくい中でありがとうございます。 動作しなかったみたいです。(https://jsfiddle.net/hvxe5yu4/) CSSの「+ .menu」の階層が違うために、「dislay:none;」が効かないのだと思います。 あと今回はメニューをJSでいちいち挿入する方法を考えていたので、ご提示のように初めからHTMLに書かれている方法は少しイメージと違いました。
guest

0

素人があれこれ考えた結果でお目汚しかと思いますが、下記で実現したかった➀➁➂➃がすべてできました。
https://jsfiddle.net/bkfer0zo/

ご回答いただいたyambejp様、jun68ykt様、think49様、そしてご意見をくださったmts10806様、皆様どうもありがとうございました。

jQuery

1// メニュー 2var menus = ` 3 <ul class="menus"> 4 <li>たべる</li> 5 <li>さわる</li> 6 </ul> 7`; 8 9// ➀ボタンクリックでメニュー表示 10// ➃複数のメニューが同時に表示されることは避けたい。 11$(document).on('click','.E > button:not(.is_click)', function(e){ 12 e.stopPropagation(); 13 $('.menus').remove(); 14 $(this).addClass('is_click'); 15 $(this).after(menus); 16}); 17 18// ➁もう一度クリックでメニュー非表示 19// ➂ボタン以外のクリックでメニュー非表示 20$(document).on('click','body', function(){ 21 $('.E > button').removeClass('is_click'); 22 $('.menus').remove(); 23}); 24 25// ついでにメニュー項目のクリックでメニューが閉じないようにする。 26$(document).on('click','.menus li', function(e){ 27 e.stopPropagation(); 28 const menu = $(this).text(); 29 alert('実行するメニューは'+menu+'です。'); 30});

投稿2019/06/18 23:40

編集2019/06/19 00:15
narutona

総合スコア23

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

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

narutona

2019/06/19 12:23

改めてjun68ykt様から高度でスマートな解決策を教えて頂いたため、ベストアンサーをそちらに変更致しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問