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

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

ただいまの
回答率

90.38%

  • JavaScript

    21546questions

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

  • jQuery

    8566questions

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

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

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 12K+

castail

score 117

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

$(".accordion_trigger").on("click", function() {            
$(this).next().slideToggle();            
$(this).toggleClass("active");
});
<div id="anchor01" class="accordion_trigger">トグル要素1のトリガー</div>
<div class="togglearea">トグル要素1で開く内容</div>
<div id="anchor02" class="accordion_trigger">トグル要素2のトリガー</div>
<div class="togglearea">トグル要素2で開く内容</div>
<div id="anchor03" class="accordion_trigger">トグル要素3のトリガー</div>
<div class="togglearea">トグル要素3で開く内容</div>
<div id="anchor04" class="accordion_trigger">トグル要素4のトリガー</div>
<div class="togglearea">トグル要素4で開く内容</div>

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

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

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

$(function(){
    $("#drop_menu div ul li:eq(0) a").click(function(){
        $("#drop_menu div ul").slideUp('slow');
$(".accordion_trigger:eq(0)").next().slideToggle();            
$(".accordion_trigger:eq(0)").toggleClass("active");
    });
});
$(function(){
    $("#drop_menu div ul li:eq(1) a").click(function(){
        $("#drop_menu div ul").slideUp('slow');
$(".accordion_trigger:eq(1)").next().slideToggle();            
$(".accordion_trigger:eq(1)").toggleClass("active");
    });
});
$(function(){
    $("#drop_menu div ul li:eq(2) a").click(function(){
        $("#drop_menu div ul").slideUp('slow');
$(".accordion_trigger:eq(2)").next().slideToggle();            
$(".accordion_trigger:eq(2)").toggleClass("active");
    });
});
$(function(){
    $("#drop_menu div ul li:eq(3) a").click(function(){
        $("#drop_menu div ul").slideUp('slow');
$(".accordion_trigger:eq(3)").next().slideToggle();            
$(".accordion_trigger:eq(3)").toggleClass("active");
    });
});

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

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

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

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


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

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

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

!function($){
  $.fn.myplugin = function() {
    var $body = $('body');
    this.each(function() {
      var $trigger = $(this);
      var $target = $trigger.next();
      $trigger.click(function() {
        $target.slideToggle();
      });
      $body.find('a[href=\\#' + $trigger.attr('id') + ']').click(function() {
        if ($target.is(':hidden')) { $target.slideDown(); }
      });
    });
  }
}(jQuery);


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

<script>
    $(function() {
      $('.accordion_trigger').myplugin();      
    });
  </script>

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

div.togglearea {
  height: 100px;
  border: 2px 2px 2px 2px;
  border-color: gray;
}
div.active {
  background-color: pink;
}
!function($){
  $.fn.myplugin = function() {
    var $body = $('body');
    this.each(function() {
      var $trigger = $(this);
      var $target = $trigger.next();
      $target.hide().removeClass('active');
      $trigger.click(function() {
        $target.slideToggle(function() {
          $target.toggleClass('active');
        });
      });
      $body.find('a[href=\\#' + $trigger.attr('id') + ']').click(function() {
        if ($target.is(':hidden')) {
           $target.slideDown(function() {
             $target.addClass('active');
           });
          }
      });
    });
  }
}(jQuery);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/02/02 18: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");
    });

    =

    おそらく後半のプラグイン化した場合記述を読み解けばいいのでしょうが、上記プラグイン化してない記述への応用方法がわかりませんでした。

    知識が足りず誠に恐縮ですがご教授いただけませんでしょうか?

    キャンセル

  • 2016/02/02 20: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() を呼ぶといいと思います。

    これでお望みの動きになったでしょうか。

    キャンセル

  • 2016/02/05 09:09 編集

    ご連絡が遅くなり大変申し訳ございません。

    度々のご回答ありがとうございます。
    ご親切にコメントまで記載して頂き大変助かりました。
    ご教授いただいた内容で実現できました!

    この度は誠にありがとうございました。

    キャンセル

+1

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

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

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

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

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

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

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

<p class="humberger">ハンバーガーメニュー</p>
<div id="drop_menu">
  <div>
    <ul class="drop_menu_list">
      <li><a href="#anchor1" class="open_trigger">トグル要素1</a></li>
      <li><a href="#anchor2" class="open_trigger">トグル要素2</a></li>
      <li><a href="#anchor3" class="open_trigger">トグル要素3</a></li>
      <li><a href="#anchor4" class="open_trigger">トグル要素4</a></li>
    </ul>
  </div>
</div>

<div id="anchor1" class="accordion_trigger">トグル要素1のトリガー</div>
<div class="togglearea">トグル要素1で開く内容</div>
<div id="anchor2" class="accordion_trigger">トグル要素2のトリガー</div>
<div class="togglearea">トグル要素2で開く内容</div>
<div id="anchor3" class="accordion_trigger">トグル要素3のトリガー</div>
<div class="togglearea">トグル要素3で開く内容</div>
<div id="anchor4" class="accordion_trigger">トグル要素4のトリガー</div>
<div class="togglearea">トグル要素4で開く内容</div>
var SAMPLE = SAMPLE || {};

SAMPLE.Accordion = function() {
  this.init();
}

SAMPLE.Accordion.prototype = {
  init: function() {
    this.$toggleTrigger = $('.accordion_trigger');
    this.$openTrigger = $('.open_trigger');
    this.$dropMenuList = $('.drop_menu_list');

    this.bindEvent();
  },
  bindEvent: function() {
    var _self = this;

    this.$toggleTrigger.on("click", function(e) {
      e.preventDefault();
      _self.slideToggle(this);
    });

    this.$openTrigger.on("click", function(e) {
      e.preventDefault();
      _self.slideUp();
      _self.slideDown(this);
    });
  },
  slideToggle: function(trigger) {
    var $trigger = $(trigger),
        $targetArea =  $trigger.next();

    $trigger.toggleClass('active');
    $targetArea.slideToggle();
  },
  slideUp: function(){
     this.$dropMenuList.slideUp();
  },
  slideDown: function(trigger){
    var $trigger = $(trigger),
        targetId = $trigger.attr('href'),
        $targetTrigger = $(targetId),
        $targetArea = $targetTrigger.next();

    $targetTrigger.addClass('active');
    $targetArea.slideDown();
  }
};

new SAMPLE.Accordion();

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

$('.accordion_trigger').on('click', function() {
  var $trigger = $(this),
      $targetArea = $trigger.next();

  $trigger.toggleClass('active');
  $targetArea.slideToggle();
});

$('#drop_menu div ul li a').on('click', function() {
  var $openTrigger = $(this),
      targetId = $openTrigger.attr('href'),
      $targetTrigger = $(targetId),
      $targetArea = $targetTrigger.next();

  $("#drop_menu div ul").slideUp('slow');

  $targetTrigger.addClass('active');
  $targetArea.slideDown();
});

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/02/05 09:11

    ご回答頂きありがとうございます。

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

    キャンセル

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

  • ただいまの回答率 90.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • JavaScript

    21546questions

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

  • jQuery

    8566questions

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