ドロップダウンメニューのHTML構成

ベースになるHTMLの構成は以下の通り。id='menu'が設定されているh1要素をクリックしたら次の要素のul要素がドロップダウン表示されるという動きを作りたい。CSSでの調整は割愛。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>プルダウン(スライド)サンプル</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
  <h1 id="menu">レシピ</h1>
  <ul class="recipe">
    <li>肉じゃが</li>
    <li>カレー</li>
    <li>グラタン</li>
    <li>ハンバーグ</li>
  </ul>
</body>
</html>

slideUpとslideDownで実装してみる

ul要素が表示しているときにはslideUpで戻し、表示していないときにはslideDownで表示するように実装してみる。

$(function(){
  $("#menu").on("click", function(){
    if ($(this).next().css("display") == "none"){
      $(this).next().slideDown();
    } else {
      $(this).next().slideUp();
    }
  });
});

動くけどなんかダサい。何回$(this).next()書くんだという話なので、もう少しシンプルに書きたい。

slideToggleで実装してみる

slideにはトグル処理(ON/OFF切り替え)があるので、そちらに書き換えて再実装。

$(function(){
  $("#menu").on("click", function(){
    $(this).next().slideToggle();
  });
});

動くけどさらにおかしな動きが。クリック連打するとビヨンビヨンなってしまう。まぁ、イベントがキューにたまってしまうかなんだけどね。かといって、stop()を挟んでキューをクリアしても途中で止まって戻るという不自然な動きになってしまうのでこれもボツ。

アニメーション中の処理制御

きれいに実装するのであれば、アニメーションしている最中はslideToggleを発火させないようにすればよい。ということで、現在アニメーション中の要素を抽出する:animatedセレクタを使用して判定を実装します。

$(function(){
  $("#menu").on("click", function(){
    $(this).next().not(":animated").slideToggle();
  });
});

notメソッドで「アニメーションしていなかったら」という否定文にします。アニメーションしていなかったらslideToggleを実行するといういたってシンプルなもの。

プラグイン化してプルダウンのスピードを自由に

以前、jQueryプラグインの作り方を書いたのでせっかくなので無駄にプラグイン化をしてみる。以下の記述を別ファイル(jquery.slide.js)として保存します。

;(function($){
  $.fn.slide = function(options){
    var defaults = {
      "speed": 500
    };
    var settings = $.extend( {}, defaults, options );

    return this.each(function(){
      $(this).on("click", function(){
        $(this).next().not(":animated").slideToggle(settings.speed);
      });
    });
  };
}(jQuery));

デフォルト値としてspeedパラメータを500(ミリ秒)に設定しておきます。これをHTMLファイル側で引数を渡してコールします。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>プルダウン(スライド)サンプル</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script src="jquery.slide.js"></script>
  <script>
    $(function(){
      $("#menu").slide({speed: 1000});
    });
  </script>
</head>
<body>
  <h1 id="menu">レシピ</h1>
  <ul class="recipe">
    <li>肉じゃが</li>
    <li>カレー</li>
    <li>グラタン</li>
    <li>ハンバーグ</li>
  </ul>
</body>
</html>

できた!\(^o^)/ 完成〜!

GitHub
※[jquery.slide.js]フォルダに今回の記事のソースコードが入っています。