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

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

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

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

jQuery

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

Q&A

解決済

2回答

24279閲覧

トグル要素が開いている時のみ処理をする方法

castail

総合スコア117

JavaScript

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

jQuery

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

1グッド

0クリップ

投稿2016/02/01 13:34

以下の構成で「accordion_trigger」要素をトリガーに隣接する「togglearea」がスライドトグルで開閉するアコーディオン要素があります。
開いた時「accordion_trigger」には「active」クラスが付与されます。

lang

1$(".accordion_trigger").on("click", function() { 2$(this).next().slideToggle(); 3$(this).toggleClass("active"); 4});

lang

1 2<div id="anchor01" class="accordion_trigger">トグル要素1のトリガー</div> 3<div class="togglearea">トグル要素1で開く内容</div> 4<div id="anchor02" class="accordion_trigger">トグル要素2のトリガー</div> 5<div class="togglearea">トグル要素2で開く内容</div> 6<div id="anchor03" class="accordion_trigger">トグル要素3のトリガー</div> 7<div class="togglearea">トグル要素3で開く内容</div> 8<div id="anchor04" class="accordion_trigger">トグル要素4のトリガー</div> 9<div class="togglearea">トグル要素4で開く内容</div> 10

さらに、以下「humberger」で「drop_menu」が開くハンバーガーメニューで上記「anchor」IDへのページ内リンクナビゲーションが別途存在します。

lang

1<p class="humberger">ハンバーガーメニュー</p> 2<div id="drop_menu"> 3 <div> 4 <ul> 5 <li><a href="#anchor01">トグル要素1</a></li> 6 <li><a href="#anchor02">トグル要素2</a></li> 7 <li><a href="#anchor03">トグル要素3</a></li> 8 <li><a href="#anchor04">トグル要素4</a></li> 9 </ul> 10 </div> 11</div>

「drop_menu」の各リンクをクリックした際、遷移先のトグル要素が閉の時のみ開の処理を行いたいです。

lang

1 2$(function(){ 3 $("#drop_menu div ul li:eq(0) a").click(function(){ 4 $("#drop_menu div ul").slideUp('slow'); 5$(".accordion_trigger:eq(0)").next().slideToggle(); 6$(".accordion_trigger:eq(0)").toggleClass("active"); 7 }); 8}); 9$(function(){ 10 $("#drop_menu div ul li:eq(1) a").click(function(){ 11 $("#drop_menu div ul").slideUp('slow'); 12$(".accordion_trigger:eq(1)").next().slideToggle(); 13$(".accordion_trigger:eq(1)").toggleClass("active"); 14 }); 15}); 16$(function(){ 17 $("#drop_menu div ul li:eq(2) a").click(function(){ 18 $("#drop_menu div ul").slideUp('slow'); 19$(".accordion_trigger:eq(2)").next().slideToggle(); 20$(".accordion_trigger:eq(2)").toggleClass("active"); 21 }); 22}); 23$(function(){ 24 $("#drop_menu div ul li:eq(3) a").click(function(){ 25 $("#drop_menu div ul").slideUp('slow'); 26$(".accordion_trigger:eq(3)").next().slideToggle(); 27$(".accordion_trigger:eq(3)").toggleClass("active"); 28 }); 29}); 30

以上の処理を試したのですが、すでに開の時も動作してしまいうまくいかない状態です。ここからすでに開いているときは処理しないという条件分岐の仕方がわからずご質問させていただきました。

ご教授の程よろしくお願いいたします。

dsk👍を押しています

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

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

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

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

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

guest

回答2

0

自分だったらこうする、という風にしました。
アコーディオントリガーを押すと、スライドトグルで開閉というのは元々の実装でほぼ問題ないと思います。

  • 「drop_menu」の各リンクをクリックした際、遷移先のトグル要素が閉の時のみ開の処理を行いたい。

こちらについては、条件分岐させるよりは、トリガーを押すと要素をスライドダウンする機能だけを持つ別物として、設定を作ってしまいます。

なので、ハンバーガーメニューの方に、「accordion_trigger」とは別の「open_trigger」というクラスを当てて、要素を取得するようにしています。

  • accordion_triggerをクリック → スライドトグルで開閉する+クラスの付け外し。
  • open_triggerをクリック → スライドダウンする+クラスの付与。

上記のような関係にします。スライドダウンであれば、そもそも開いている要素に対して行っても、閉じてしまうことはありません。

なお、ハンバーガーメニューをクリックした時、スライドダウンさせる要素をターゲットとして取得しなければなりません。
そちらについては、aタグのhref属性設定されている「#anchor1」の文字列を利用して、
$('#anchor1')という形で取得できるように書き、ターゲットとなるトリガーをまず取得しています。
そのトリガーの隣の要素が、ターゲットとなるトグル要素として取得できます。

HTML

1<p class="humberger">ハンバーガーメニュー</p> 2<div id="drop_menu"> 3 <div> 4 <ul class="drop_menu_list"> 5 <li><a href="#anchor1" class="open_trigger">トグル要素1</a></li> 6 <li><a href="#anchor2" class="open_trigger">トグル要素2</a></li> 7 <li><a href="#anchor3" class="open_trigger">トグル要素3</a></li> 8 <li><a href="#anchor4" class="open_trigger">トグル要素4</a></li> 9 </ul> 10 </div> 11</div> 12 13<div id="anchor1" class="accordion_trigger">トグル要素1のトリガー</div> 14<div class="togglearea">トグル要素1で開く内容</div> 15<div id="anchor2" class="accordion_trigger">トグル要素2のトリガー</div> 16<div class="togglearea">トグル要素2で開く内容</div> 17<div id="anchor3" class="accordion_trigger">トグル要素3のトリガー</div> 18<div class="togglearea">トグル要素3で開く内容</div> 19<div id="anchor4" class="accordion_trigger">トグル要素4のトリガー</div> 20<div class="togglearea">トグル要素4で開く内容</div>

javascript

1var SAMPLE = SAMPLE || {}; 2 3SAMPLE.Accordion = function() { 4 this.init(); 5} 6 7SAMPLE.Accordion.prototype = { 8 init: function() { 9 this.$toggleTrigger = $('.accordion_trigger'); 10 this.$openTrigger = $('.open_trigger'); 11 this.$dropMenuList = $('.drop_menu_list'); 12 13 this.bindEvent(); 14 }, 15 bindEvent: function() { 16 var _self = this; 17 18 this.$toggleTrigger.on("click", function(e) { 19 e.preventDefault(); 20 _self.slideToggle(this); 21 }); 22 23 this.$openTrigger.on("click", function(e) { 24 e.preventDefault(); 25 _self.slideUp(); 26 _self.slideDown(this); 27 }); 28 }, 29 slideToggle: function(trigger) { 30 var $trigger = $(trigger), 31 $targetArea = $trigger.next(); 32 33 $trigger.toggleClass('active'); 34 $targetArea.slideToggle(); 35 }, 36 slideUp: function(){ 37 this.$dropMenuList.slideUp(); 38 }, 39 slideDown: function(trigger){ 40 var $trigger = $(trigger), 41 targetId = $trigger.attr('href'), 42 $targetTrigger = $(targetId), 43 $targetArea = $targetTrigger.next(); 44 45 $targetTrigger.addClass('active'); 46 $targetArea.slideDown(); 47 } 48}; 49 50new SAMPLE.Accordion();

もし、実装するなら私なら上記の書き方をしますが、
投稿者さんの記述スタイルに近い書き方だと、こうなります。

javascript

1$('.accordion_trigger').on('click', function() { 2 var $trigger = $(this), 3 $targetArea = $trigger.next(); 4 5 $trigger.toggleClass('active'); 6 $targetArea.slideToggle(); 7}); 8 9$('#drop_menu div ul li a').on('click', function() { 10 var $openTrigger = $(this), 11 targetId = $openTrigger.attr('href'), 12 $targetTrigger = $(targetId), 13 $targetArea = $targetTrigger.next(); 14 15 $("#drop_menu div ul").slideUp('slow'); 16 17 $targetTrigger.addClass('active'); 18 $targetArea.slideDown(); 19});

投稿2016/02/03 02:55

編集2016/02/03 03:24
yamato_hikawa

総合スコア2092

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

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

castail

2016/02/05 00:11

ご回答頂きありがとうございます。 せっかくご回答頂いたの申し訳無いのですが、先にご回答頂いた「unau」様をベストアンサーとさせて頂きます。
guest

0

ベストアンサー

まず、slideToggle() は表示されていない (slideUp されている) 要素なら slideDown し、
表示されている (slideDown されている) 要素なら slideUp する、というアニメーションです。
アニメーション終了後は (アニメーション中も) 対象要素に何らかのクラスがつくのではなく、style="..." の形で属性が付き、要素の高さが変わっていき最終的に style="display: none" になったりするようです。
ですので、対象要素の開/閉は、その要素の表示/非表示で判断することになるでしょう。

なので、この部分の処理は、

javascript

1$(function(){ 2 $("#drop_menu div ul li:eq(0) a").click(function(){ 3 // $("#drop_menu div ul").slideUp('slow'); // <- これは不要そうなのでコメントアウトしました 4 $(".accordion_trigger:eq(0)").next().slideToggle(); 5 $(".accordion_trigger:eq(0)").toggleClass("active"); 6 }); 7});

次のようにすると、お望みの処理になるのではないかと思います。

javascript

1$(function(){ 2 $("#drop_menu div ul li:eq(0) a").click(function(){ 3 var $target = $(".accordion_trigger:eq(0)").next(); 4 if ($target.is(':hidden')) { $target.slideDown(); } 5 $(".accordion_trigger:eq(0)").toggleClass("active"); 6 }); 7});

さらに、繰り返しが多いので、うまいことプラグイン化しちゃうといいんだろうな、と思います。たとえば、次のように。

javascript

1!function($){ 2 $.fn.myplugin = function() { 3 var $body = $('body'); 4 this.each(function() { 5 var $trigger = $(this); 6 var $target = $trigger.next(); 7 $trigger.click(function() { 8 $target.slideToggle(); 9 }); 10 $body.find('a[href=\\#' + $trigger.attr('id') + ']').click(function() { 11 if ($target.is(':hidden')) { $target.slideDown(); } 12 }); 13 }); 14 } 15}(jQuery);

これを使う HTML 側に書くスクリプトはこうなります。

html

1 <script> 2 $(function() { 3 $('.accordion_trigger').myplugin(); 4 }); 5 </script>

最後に。もし、active というクラスで表示を切り替えたいのであれば、slideToggle() のアニメーション終了時に実行されるコールバックの中で active をつけたりはずしたりするといいのではないでしょうか。

css

1div.togglearea { 2 height: 100px; 3 border: 2px 2px 2px 2px; 4 border-color: gray; 5} 6div.active { 7 background-color: pink; 8}

javascript

1!function($){ 2 $.fn.myplugin = function() { 3 var $body = $('body'); 4 this.each(function() { 5 var $trigger = $(this); 6 var $target = $trigger.next(); 7 $target.hide().removeClass('active'); 8 $trigger.click(function() { 9 $target.slideToggle(function() { 10 $target.toggleClass('active'); 11 }); 12 }); 13 $body.find('a[href=\\#' + $trigger.attr('id') + ']').click(function() { 14 if ($target.is(':hidden')) { 15 $target.slideDown(function() { 16 $target.addClass('active'); 17 }); 18 } 19 }); 20 }); 21 } 22}(jQuery);

投稿2016/02/01 16:11

unau

総合スコア2468

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

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

castail

2016/02/02 02:03

ご回答ありがとうございます。 = > // $("#drop_menu div ul").slideUp('slow'); // <- これは不要そうなのでコメントアウトしました お伝え漏れでしたが、こちらのdrop_menuはハンバーガーメニューから開くスライドメニューであるためメニュー選択後は非表示にする必要があり上記記述はその処理です。 - >さらに、繰り返しが多いので、うまいことプラグイン化しちゃうといいんだろうな、と思います。たとえば、次のように。 こちらもご説明不足でしたが今回外部jsを読み込みことができないためhtml内に全て記述する必要があります。 = 上記を踏まえ参考に以下の記述で試しましたがうまく動作しませんでした。 = $(function(){ $("#drop_menu div ul li:eq(0) a").click(function(){ $("#drop_menu div ul").slideUp('slow'); var $target = $(".accordion_trigger:eq(0)").next(); if ($target.is(':hidden')) { $target.slideDown(); } $(".accordion_trigger:eq(0)").toggleClass("active"); }); $("#drop_menu div ul li:eq(1) a").click(function(){ $("#drop_menu div ul").slideUp('slow'); var $target = $(".accordion_trigger:eq(1)").next(); if ($target.is(':hidden')) { $target.slideDown(); } $(".accordion_trigger:eq(1)").toggleClass("active"); }); $("#drop_menu div ul li:eq(2) a").click(function(){ $("#drop_menu div ul").slideUp('slow'); var $target = $(".accordion_trigger:eq(2)").next(); if ($target.is(':hidden')) { $target.slideDown(); } $(".accordion_trigger:eq(2)").toggleClass("active"); }); $("#drop_menu div ul li:eq(3) a").click(function(){ $("#drop_menu div ul").slideUp('slow'); var $target = $(".accordion_trigger:eq(3)").next(); if ($target.is(':hidden')) { $target.slideDown(); } $(".accordion_trigger:eq(3)").toggleClass("active"); }); }); = 不備などあればご指摘願えませんでしょうか?
castail

2016/02/02 02:11

大変申し訳ございません。 上記記述は正常に動作しておりました。 他スクリプトの干渉の問題でした。 この度は迅速・的確なご教授誠にありがとうございました。 心から感謝申し上げます。
unau

2016/02/02 07:51

プラグイン化は外部 js じゃなくてもできますが、まあお役に立てたようでよかったです。私自身、検証しているうちにいろいろ試して、 is(':hidden') とか slideToggle() とか初めて使ってみたので、勉強になりました
castail

2016/02/02 09:26

何度も申し訳ありません。 再度確認したところ以下の記述では開の場合で「accordion_trigger」にすでに「active」が付与されている場合でも「toggleClass」が実行されてしまいます。 = $("#drop_menu div ul li:eq(0) a").click(function(){ $("#drop_menu div ul").slideUp('slow'); var $target = $(".accordion_trigger:eq(0)").next(); if ($target.is(':hidden')) { $target.slideDown(); } $(".accordion_trigger:eq(0)").toggleClass("active"); }); = おそらく後半のプラグイン化した場合記述を読み解けばいいのでしょうが、上記プラグイン化してない記述への応用方法がわかりませんでした。 知識が足りず誠に恐縮ですがご教授いただけませんでしょうか?
unau

2016/02/02 11:54

最初の回答に書いたのですが、 (1) is(':hidden') メソッドが true になるか false になるか (2) slideUp(), slideDown(), slideToggle() で最終的に表示されたり、非表示になったり というのは、「active」クラスがついているかどうか、には直接関係ありません。「active」クラスにどういうスタイルがついているのかご呈示いただいていないので、間接的に影響があるかどうかは判断できません。「active」クラスを付けたり外したりする意図もまだよくわかっていません。 ご呈示のコードにコメントをつけると次のようになります。 ------- ここから $("#drop_menu div ul li:eq(0) a").click(function(){ $("#drop_menu div ul").slideUp('slow'); var $target = $(".accordion_trigger:eq(0)").next(); if ($target.is(':hidden')) { $target.slideDown(); } // 内容が隠れていればスライドして出す (※) $(".accordion_trigger:eq(0)").toggleClass("active"); // 上の if のブロックを抜けているので必ず実行される }); ------- ここまで ご注意いただきたいのは、(※) の部分は「active」クラスがついているかどうかを見ているのではなく、表示されているか否かを見ているということです。 お望みの動きがまだ十分わかっていないのですが、先のコードを書き直すと次のようになるでしょうか。 ------- ここから var $menu_ul = $('#drop_menu div ul'); $menu_ul.find('ul li:eq(0) a').click(function(){ $menu_ul.slideUp('slow'); var $trigger = $('.accordion_trigger:eq(0)'); var $target = $trigger.next(); if ($target.is(':hidden')) { // target が隠れていたら $target.slideDown($trigger.addClass('active')); // スライドしながら表示して、表示し終わったら「active」クラスをつける } else { // target が表示されていたら $trigger.removeClass('active'); // 「active」クラスをはずして $target.slideUp(); // スライドしながら隠す } }); ------- ここまで 表示する際、先に「active」クラスをつけ、その後でスライドしながら表示する、というのであれば、slideDown() のコールバックで addClass() を呼ぶのではなく、先に addClass() を呼んでから slideDown() を呼ぶといいと思います。 これでお望みの動きになったでしょうか。
castail

2016/02/05 00:10 編集

ご連絡が遅くなり大変申し訳ございません。 度々のご回答ありがとうございます。 ご親切にコメントまで記載して頂き大変助かりました。 ご教授いただいた内容で実現できました! この度は誠にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問