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

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

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

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

jQuery

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

Q&A

解決済

1回答

3931閲覧

レスポンシブ時にPC/SPで、アコーディオンメニューの挙動を変えたい。

uio

総合スコア19

JavaScript

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

jQuery

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

0グッド

0クリップ

投稿2016/07/19 03:50

編集2016/07/19 08:16

お世話になります。

現在、レスポンシブ時にPC時とSP時で、アコーディオンメニューの動きを少し変えたく、
以下のようにプログラムを書いています。

【アコーディオンメニュー】

// アコーディオンメニュー $(window).on('load resize', function(){ $('body').on( 'click','.click-btn', function( ev ) { // ev.target がイベントの起こった要素 var l = $( ev.target ).parents( '#globalMenu' ).length; if ( l > 0 ) { // メニュー内のイベントか判定 $( '.child-list' ).toggleClass('open01'); var over_flg = $('.product-child .click-btn,.child-list').hover(function(){ over_flg = true; }, function(){ over_flg = false; }); // メニュー領域外をクリックしたらメニューを閉じる $('body').click(function() { if (over_flg == false) { $('.child-list').removeClass('open01'); } }); } } ); } );

【HTML】

<div class="header-bottom"> <nav class="gnav mainnav" id="globalMenu"> <ul class="list" id="menu"> <li><a href="#">A</a></li> <li><a href="#">B</a></li> <li class="product-child"><span class="click-btn">C</span> <ul class="menu-hidden child-list"> <li><a href="#">D</a></li> <li><a href="#">E</a></li> <li><a href="#">F</a></li> </ul> </li> <li><a href="#">G</a></li> </ul> </nav> </div>

先日、こちらで同様の質問させていただいたのですが、(https://teratail.com/questions/41408)
その際、SP時に動かない原因をご指摘いただき、無事に解決までできた状態でしたが、
その後、その動きに一つ新たな動きを追加しようとしたところまた動かなくなってしまいました。

追加で実装したい動きは、
PC/SPでは、【HTML】6行目「C」ボタンを押した際に、通常通りアコーディオンを表示し、
PCでは、アコーディオンメニュー領域外をクリックするとアコーディオンメニューが閉じる、
SPでは、領域外クリックで閉じる動きはしない、
という動きを取り入れたいと思っております。

【PC/SPで動作可能なjavascript】(領域外で閉じる動作なし)

$( function() { // アコーディオンメニュー $('body').on( 'click','.click-btn', function( ev ) { // ev.target がイベントの起こった要素 var l = $( ev.target ).parents( '#globalMenu' ).length; if ( l > 0 ) { // メニュー内のイベントか判定 $( '.child-list' ).toggleClass( 'open01' ); } else { $( '.child-list' ).removeClass( 'open01' ); } } ); } );

現状では、1度のみの処理であればPC/SP共に動くのですが、
2回目以降の処理がされない状況です。
例えばPC時で一度アコーディオンメニューを開くと、SPリサイズ時に動かくなってしまうという状況です。

リセット処理がうまくいっていないのかと思い、
$(window).on('load resize'...を入れてみたのですが、動きませんでした。

もし何か少しでもお分かりの方がいらっしゃいましたら、ぜひご教授ください。
どうぞよろしくお願い申し上げます。

//--------
※ブラウザ幅指定のコードが抜けておりました、申し訳ございません。
追加いたしました。

$(window).on('load resize', function(){ $('body').on( 'click','.click-btn', function( ev ) { // ev.target がイベントの起こった要素 var l = $( ev.target ).parents( '#globalMenu' ).length; if ( l > 0 ) { // メニュー内のイベントか判定 $( '.child-list' ).toggleClass('open01'); if(window.innerWidth > 768){ var over_flg = true; $('.click-btn,.child-list').hover(function(){ over_flg = true; }, function(){ over_flg = false; }); // メニュー領域外をクリックしたらメニューを閉じる $('body').click(function() { if (over_flg == false) { $('.child-list').removeClass('open01'); } }); } } } ); } );

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

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

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

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

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

guest

回答1

0

ベストアンサー

以下のようにしてみてはいかがでしょうか。

javascript

1// アコーディオンメニュー 2$(window).on('load resize', function(){ 3 $('body').on( 'click','.click-btn', function( ev ) { 4 // ev.target がイベントの起こった要素 5 var l = $( ev.target ).parents( '#globalMenu' ).length; 6 7 if ( l > 0 ) { // メニュー内のイベントか判定 8 $( '.child-list' ).toggleClass('open01'); 9 10 var over_flg = true; 11 $('.product-child .click-btn,.child-list').hover(function(){ 12 over_flg = true; 13 }, function(){ 14 over_flg = false; 15 }); 16 17 // メニュー領域外をクリックしたらメニューを閉じる 18 $('body').click(function() { 19 if (over_flg == false) { 20 $('.child-list').removeClass('open01'); 21 } 22 }); 23 } 24 } ); 25} );

.hover().on()とかと同じようにイベントを設定しているだけですので、元のコードではover_flgは更新されません。

追記

私なら以下のようにするかと思います。

javascript

1$(function(){ 2 3 // 各イベントで利用するためにこの位置で定義 4 var over_flg = true; 5 6 $(document).on("click", ".click-btn", function(ev){ 7 // イベントの伝播を防ぐ 8 ev.stopPropagation(); 9 10 // ev.target がイベントの起こった要素 11 var l = $( ev.target ).parents( '#globalMenu' ).length; 12 13 if ( l > 0 ) { // メニュー内のイベントか判定 14 // ここではPC・SPは関係ないのでクラスの付与・除去のみを行う 15 $( '.child-list' ).toggleClass('open01'); 16 } 17 }); 18 19 // ここでhoverイベントを設定(PCのみ動作する) 20 $('.product-child .click-btn,.child-list').hover(function(){ 21 over_flg = true; 22 }, function(){ 23 over_flg = false; 24 }); 25 26 // メニュー領域外をクリックしたらメニューを閉じる 27 $('body').click(function() { 28 if(window.innerWidth > 768){ // ウィンドウサイズからPC・SPを判定 29 if (over_flg == false) { 30 $('.child-list').removeClass('open01'); 31 } 32 } 33 }); 34});

上記は検証していませんので、動かないかもしれません。(これから検証します)

検証結果

レスポンシブ時にPC/SPで、アコーディオンメニューの挙動を変えたい。検証
検証した結果、動作するかと思います。

投稿2016/07/19 06:31

編集2016/07/19 10:02
orange0190

総合スコア1698

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

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

uio

2016/07/19 07:41 編集

>orange0190様 ご回答いただきありがとうございます。 いただいたコードで試してみましたところ、PC時は問題なく動くようになりました。 over_flgの変数宣言が更新されていないという点に気付きませんでした。 勉強になりました。ありがとうございます。 ただ、SP時には動かない状態は変わらない状況です。 アコーディオンボタン(「C」ボタン)を押した際の、HTMLの方での動きは以下のgifのような動きになっております。 https://gyazo.com/975a1813f1edf74e57ff9acc6a9c2911 何らかの読み込みはされているとは思うのですが、 toggleClassで指定したopen01のクラスの読み込みがされません。 javascriptの初歩的な部分での認識不足で大変申し訳ございませんが、 もし、if内で下に書いた処理を一度行うと、その上に書いた部分の処理は($( '.child-list' ).toggleClass('open01');)の処理(読み込み)はされないのでしょうか。。 もしそうだとした場合には、どのように対処したらよろしいのでしょうか..。 また、見当違いのところがありましたら申し訳ございません。 もし何かお分かりになるところがございましたら、ご指摘頂けましたら幸いです。 どうぞよろしくお願いいたします。
orange0190

2016/07/19 07:49

そもそもPCかSPかはどのように判定しているのですか?
uio

2016/07/19 08:23 編集

ご指摘いただきありがとうございます。 ブラウザ幅判別のためのコード部分が抜けておりましたので、質問内容内の一番下に幅指定をしたコードを追加させていただきました。 こちらの環境では入っていた状態でテストしておりましたが、貼り付けの際に確認不足でミスがありました、大変失礼いたしました。
uio

2016/07/19 08:55

追記させていただきます。 その後、$( '.child-list' ).toggleClass('open01'); の下に alert();を入れると動作ができました。ですが、表示されたアラートを閉じてしまうと、 アコーディオンメニューも閉じてしまいます。 何か原因は考えられますでしょうか。
orange0190

2016/07/19 09:14 編集

SPでは.hover()は正常に動作しません。そのため、over_flgは常にtrueとなり、最初のtoggleClass()でクラスが付与された後に、正直理由は不明瞭ですが、$('.child-list').removeClass('open01')でクラスが除去されています。 後ほど私ならというコードを追加しますので参考にしてください。
uio

2016/07/19 10:01

>orange0190様 素晴らしいコード、本当にありがとうございます。 無事に動きました。感動して鳥肌立ちました。 ご指摘いただいたコードと理解を比べてみて、 わかっていなかったポイントとしては、 // 各イベントで利用するためにこの位置で定義 var over_flg = true; 各イベントで使うものは、一番上で定義する必要があるということ、理解いたしました。その点なんとなくそうなのかなとは思っていたのですが、確信に変わりました。ありがとうございます。 // イベントの伝播を防ぐ ev.stopPropagation();  これはちょっとなぜここで伝播を防ぐ必要があるのか、 今は理由がまだわかりませんが、調べてちょっと勉強してみます。ありがとうございます。 // メニュー領域外をクリックしたらメニューを閉じる 以下のコード部分 確かに、PC時にのみ入れたい動作でしたがwindow.innerWidthを入れる位置で迷っていました。ここに入れればよかったんだという感じで、すごく納得です。 ありがとうございます。 orange0190様、この度は本当にありがとうございました。 すごく勉強になりました。これからも、もっともっと勉強して、 レベルを上げていきたいと思います。 ありがとうございました。
orange0190

2016/07/19 10:03

>これはちょっとなぜここで伝播を防ぐ必要があるのか、 >今は理由がまだわかりませんが、調べてちょっと勉強してみます。ありがとうございます。 これはbodyのイベントも発火してしまうためです。
uio

2016/07/19 10:13

>これはbodyのイベントも発火してしまうためです。 なるほどです。一番上のfunctionの中にクリックのイベントが2つあって、その両方に発火してしまうため・・ということでしょうか。まだまだ理解不足、勉強不足でした。 もっと基礎固めてきます。最後までわざわざご丁寧にご回答いただき、本当に感謝しております。ありがとうございました!  また何かこちらでご質問させていただくことがあるかもしれませんが、 今後ともどうぞよろしくお願いいたします。
uio

2016/07/19 11:52

>orange0190様 すみません、検証URLに今気がつきました。色々まだ使い勝手がわかっていなく、気づくのが遅くなり、申し訳ございません。本当にご親切にここまでご対応いただき、なんと申し上げていいのか・・。本当に感謝しております。ありがとうございました!  勉強頑張ります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問