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

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

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

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

jQuery

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

Q&A

解決済

2回答

3062閲覧

ios端末でスライドメニューの開閉の際、領域外のタップで閉じたい

nyamo

総合スコア21

JavaScript

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

jQuery

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

0グッド

0クリップ

投稿2016/06/08 04:45

編集2016/06/08 21:44

ios端末でスライドメニューの開閉の際、領域外のタップで閉じたいのですが、
on clickであれば問題なく動作しても、hammer.jsを使用した際のtapでは開いた瞬間に閉じてしまい困っています。

■追記
.hammer().on("tap touchstart")とすることで、領域外のタップで閉じるようになりました。ただ、tapも動作してしまうので挙動は怪しいです。
ifで"tap"と"touchstart"の振り分けをしようと思いましたが、iosではtapもtouchstartも動いてしまうので、別の事で振り分けないとダメそうです。

$("body").hammer().on("tap", function() { $(".casemenu").slideUp(); });

上記ではPCで確認した際、chromeのみ開いた瞬間に閉じてしまいましたので、

$("body").hammer().on("tap", function(e) { if (!$(e.target).closest('.casemenu').length) { $(".casemenu").slideUp(); }

上記の様にしたところ、chromeでも正常に動作し、PCでは問題ありませんが、ios safariとios firefoxで確認したら、タップした瞬間に閉じられてしまいます。

ボタンをタップした時にbodyにも伝達されているのが問題だと思うのですが、iosに対応するにはどうしたらよいのでしょうか。

もしわかる方がいらっしゃいましたらお教え頂けると幸いです。
よろしくお願い致します。

■追記
https://jsfiddle.net/nyamo/szL8jq7m/1/
クリックの場合は、ボタン>bodyの順でios以外閉じます。

javascript

1$(".casebutton").on("click", function(e){ 2$(".casemenu").hide(); 3$(this).parents(".all").children(".casemenu").slideDown("fast"); 4return false; 5}); 6// クリックでスライドを閉じる 7$("body").on("click", function(e) { 8if (!$(e.target).closest('.casemenu').length) { 9$(".casemenu").slideUp("fast"); 10} 11});

ですが、.hammer().on("tap")では、body>ボタンの順にしなければios以外閉じれないのも気になるところです。どちらも結局、iosで閉じれないので意味のない事ですが・・・。

javascript

1// クリックでスライドを閉じる 2$("body").hammer().on("tap", function(e) { 3if (!$(e.target).closest('.casemenu').length) { 4$(".casemenu").slideUp("fast"); 5} 6}); 7 8$(".casebutton").hammer().on("tap", function(ev){ 9$(".casemenu").hide(); 10$(this).parents(".all").children(".casemenu").slideDown("fast"); 11return false; 12});

html

1<header> 2ヘッダー 3</header> 4<body> 5<div class="all"> 6<div class="case"> 7<button type="button" class="casebutton">選択</button> 8</div> 9<div class="casemenu"> 10<label class="caseradio"><input type="radio"/>ああああ</label> 11<label class="caseradio"><input type="radio"/>いいいい</label> 12<label class="caseradio"><input type="radio"/>うううう</label> 13<label class="caseradio"><input type="radio"/>ええええ</label> 14</div> 15</div> 16</body>

css

1.casemenu { 2 display: none; 3 background-color: #000; 4 border: 1px solid #000; 5 width: 100px; 6} 7.caseradio { 8 display: block; 9 margin-bottom: 1px; 10 text-align: left; 11 background-color: #fff; 12}

javascript

1$(".casebutton").hammer().on("tap", function(){ 2$(".casemenu").hide(); 3$(this).parents(".all").children(".casemenu").slideDown(); 4return false; 5}); 6$("body").hammer().on("tap", function() { 7$(".casemenu").slideUp(); 8});

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

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

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

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

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

guest

回答2

0

ベストアンサー

stopPropagation() を使えばイベント伝播を止められると思います。

JavaScript

1$( '.casebutton' ).hammer().on( 'tap', function( e ) { 2 e.stopPropagation(); 3 $( '.casemenu' ).hide(); 4 $( this ).parents( '.all' ).children( '.casemenu' ).slideDown(); 5 return false; 6} );

【jQuery のバブリング、preventDefault() や stopPropagation() の使用例 | Tips Note by TAM】
http://www.tam-tam.co.jp/tipsnote/javascript/post5050.html

【jQuery: イベント処理を中断するには?(preventDefault/stopPropagation/stopImmediatePropagation) - Build Insider】
http://www.buildinsider.net/web/jqueryref/022


追記1:

【Event delegation and how to stopPropagation preventDefaults · hammerjs/hammer.js Wiki · GitHub】
https://github.com/hammerjs/hammer.js/wiki/Event-delegation-and-how-to-stopPropagation---preventDefaults

ev.gesture.stopPropagation()

【Prevent tap on parent element · Issue #652 · hammerjs/hammer.js · GitHub】
https://github.com/hammerjs/hammer.js/issues/652

【GitHub - josdejong/propagating-hammerjs: Extend hammer.js with event propagation】
https://github.com/josdejong/propagating-hammerjs
Fix用ライブラリだと思われます。


追記2:

書いておられるコードでは、bodyと.casebutton それぞれのイベントが割り当てられているため、tap の度に両方走っていたようです。イベントを引き受ける関数をひとつにし、それでもbody⇒.casebutton の順で発生するイベントを一旦Timeout で外す方法でFirefoxで動きました。

JavaScript

1jQuery( function() { 2 var _timeout; 3 $( '.casebutton, body' ).hammer().on( 'tap', function( e ) { 4 var tgt = e.currentTarget.tagName.toLowerCase(); 5 if ( tgt === 'body' ) { 6 if ( _timeout ) { clearTimeout( _timeout ); } 7 _timeout = setTimeout( 'close_menu()', 100 ); 8 } else { 9 if ( _timeout ) { clearTimeout( _timeout ); } 10 $( '.casemenu' ).hide(); 11 $( this ).parents( '.all' ).children( '.casemenu' ).slideDown(); 12 }; 13 return false; 14 } ); 15 window.close_menu = function() { 16 $( '.casemenu' ).slideUp(); 17 } 18} );

HTML

1<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> 2<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script> 3<script src="https://cdn.jsdelivr.net/jquery.hammerjs/2.0.0/jquery.hammer.js"></script>

追記2:

iPad では一応動きました。iOSとデスクトップではイベント伝播の順番が逆になっていたため、それを無理やり検知する方針で組めばできました。もっとスマートなコードにも出来るとは思われますが、力尽きました。

動くサンプル:https://jsfiddle.net/4rdoa7t0/9/

JavaScript

1jQuery( function() { 2 var _timeout = [] 3 , funcAddT = function( t ){ _timeout.push( t ); } 4 , funcClearT = function(){ 5 _timeout.forEach( function( t ){ clearTimeout( t ); } ); 6 _timeout = []; 7 } 8 ; 9 $( 'body, .casebutton, .casemenu' ).hammer().on( 'tap', function( e ) { 10 var tgt = e.currentTarget.tagName.toLowerCase(); 11 if ( tgt === 'body' ) { 12 if ( _timeout.length ) { // button が先行した場合 13 funcClearT(); 14 // 何もしない 15 } else { 16 funcClearT(); 17 funcAddT( setTimeout( 'close_menu()', 100 ) ); // body が先行した場合 18 } 19 20 } else if ( $(e.currentTarget).hasClass('casemenu') ) { 21 if ( _timeout.length ) { 22 funcClearT(); // body が先行した場合 23 } else { 24 funcClearT(); 25 funcAddT( setTimeout( 'null_func()', 100 ) ); // button が先行した場合 26 } 27 } else { 28 if ( _timeout.length ) { 29 funcClearT(); // body が先行した場合 30 } else { 31 funcClearT(); 32 funcAddT( setTimeout( 'null_func()', 100 ) ); // button が先行した場合 33 } 34 $( '.casemenu' ).hide(); 35 $( this ).parents( '.all' ).children( '.casemenu' ).slideDown(); 36 }; 37 return false; 38 } ); 39 window.close_menu = function() { 40 $( '.casemenu' ).slideUp(); 41 funcClearT(); 42 } 43 window.null_func = function() { 44 funcClearT(); 45 } 46} );

投稿2016/06/08 05:25

編集2016/06/09 10:05
kei344

総合スコア69398

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

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

nyamo

2016/06/08 09:58

回答ありがとうございます。 e.stopPropagation();では無理で、その変わりにif (!$(event.target).closest('#target').length)を使用している次第です。
kei344

2016/06/08 15:02

誤:function() { 正:function( e ) { 少し書き間違えていたので回答を修正します。 e.stopPropagation(); が効かない事例とフィックス用ライブラリを見つけたので追記します。
nyamo

2016/06/08 18:10

ev.gesture.stopPropagation()とpropagating-hammerjsの両方を試してみましたが、やはりiosのみ直ぐに閉じてしまいます。もしくは、領域外のタップやクリックで閉じられなくなります。 .casebuttonのボタンを押したら、bodyも押されてしまっているので、stopPropagation()で停止させてやるのは間違いないのですが、なぜかiosではダメみたいです。
kei344

2016/06/08 18:59

コードを追記しました。
nyamo

2016/06/08 19:08

回答ありがとうございます。 https://jsfiddle.net/nyamo/szL8jq7m/5/ やはり、PCブラウザでは問題ないのですが、ios端末で閲覧すると直ぐに閉じてしまいます。
kei344

2016/06/09 10:06

さらにコードを追記しました。
nyamo

2016/06/09 13:42 編集

回答ありがとうございます。こちらで問題なく動きました。 tap touchstartとUAの振り分けでやり直していましたが、こちらの方が安定した動作をするので使わせていただきます。というか、iOSとデスクトップではイベント伝播の順番が逆なんですね・・・。 ご協力ありがとうございました。
guest

0

こんな処理ではどうでしょうか?
関数化すれば同じケースで利用できます。

javascript

1 2var $el = $('#hoge'),//メニュー 3 closeMenu = function(){ 4 //閉じる処理 5 }; 6 7$(document).click(function(e){ 8 if(!$.contains($el[0], e.target)){ 9 closeMenu(); 10 } 11}); 12

投稿2016/06/08 06:16

fuji_fe

総合スコア93

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

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

nyamo

2016/06/08 10:07 編集

回答ありがとうございます。 こちらの処理ですが、.on( 'click', function()であれば問題なく動作するのですが、.hammer().on("tap", function()にすると、やはり開いた瞬間に閉じてしまいます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問