もっと便利に!jQueryでラクラクサイト制作(実践サンプル付き)

第4回ドロップダウンメニューの実装

jQueryを利用してナビゲーションを実装する

第3回・4回はナビゲーションの実装について説明しています。前回はアコーディオンパネルの実装を行いましたので、今回はドロップダウンメニューを実装してみましょう。まずは完成したドロップダウンメニューを見てください。

ドロップダウンメニュー
ドロップダウンメニュー

今回の記事で使うメソッドの紹介と簡単な説明

前回同様本題に入る前に、まずはドロップダウンメニューを実装するにあたって必要になるメソッドなどを紹介をしていきます。前回説明した通り、メソッドとは任意のjQueryオブジェクトに対して実行する命令文です。

jQueryオブジェクト

第1回、2回でセレクタについて説明しましたが、セレクタで取得できる要素はひとつではありません。例えば$('div')のようにすると、HTML上の全てのDIV要素をjQueryオブジェクトとして取得します。要素は配列としてHTML出現順に保存されていきます。Firebugのconsoleを使って確認してみましょう。gihyo.jpのトップページで実行してみます。gihyoのサイトではjQueryを使用していませんが、以下の手順に従ってFireQuery付属のjQuerifyを使えば、jQueryを使っていないサイトでもjQueryをロードさせることができます。

  1. jQuerifyをクリックしてjQueryをロードする(jQueryを使っていないページの場合⁠

    jQuerifyをクリックしてjQueryをロードする

  2. jQuerifyが有効になったことを確認 $jq()で使えるようになる

    jQuerifyが有効になったことを確認 $jq()で使えるようになる
  3. consoleに実行したい命令を入力する

    consoleに実行したい命令を入力する
  4. 結果の出力

    結果の出力

出力されたデータの通り、jQueryオブジェクトには複数のDIV要素が内包されています。例えばDIV要素の数を知りたいときは$('div').lengthで調べることができます。⁠FireQueryでは$jq('div'))

DIV要素の数を調べる
DIV要素の数を調べる

each()

eachメソッドは対象の複数のjQueryオブジェクトに対してそれぞれ関数を実行するメソッドです。関数の引数にiを持たせることで、現在のループ回数を得ることができます。前述の$('div')に対してeachメソッドを実行してみましょう。

eachメソッドの実行
eachメソッドの実行
eachメソッド実行結果
eachメソッド実行結果

上記のサンプルでは、DIV要素の数分、iを実行しています。

hover()

hoverメソッドは対象のjQueryオブジェクトのmouseover,mouseoutイベントに任意の関数をbindするメソッドです。hoverメソッドの第1引数にmouseover、第2引数にmouseoutにそれぞれ割り当てる関数を持たせます。hoverメソッドの簡単なサンプルを用意しましたので確認してみてください。

hover()-HTML
<ahref="#">ここにマウスカーソルをのせたり外したりしてください</a>
hover()-JS
jQuery(function($){
  $('a').hover(function(){
    console.log('mouseover');
  },function(){
    console.log('mouseout');
  });
});

parent()

parentメソッドは対象のjQueryオブジェクトの親要素を取得して返すメソッドです。

parent()-HTML
<p><ahref="#"id="child">consoleにA要素の親要素を表示します</a></p>
parent()-JS
jQuery(function($){
  console.log($('#child').parent());
});

ドロップダウンメニューの実装

HTMLは基本的なULリストの入れ子で、CSSで第2階層のメニューは下に表示し、第3階層以降のメニューは右に表示するように定義しています。HTMLソースは長くなるので2つ目以降を省略しています。

ドロップダウンメニュー-HTML
<ulid="menu">
  <li>
    <ahref="#">メニュー1</a>
    <ul>
      <li><ahref="#">メニュー1-1</a></li>
      <li><ahref="#">メニュー1-2</a>
        <ul>
          <li><ahref="#">メニュー1-2-1</a></li>
          <li><ahref="#">メニュー1-2-2</a></li>
          <li><ahref="#">メニュー1-2-3</a>
            <ul>
              <li><ahref="#">メニュー1-2-3-1</a></li>
              <li><ahref="#">メニュー1-2-3-2</a></li>
              <li><ahref="#">メニュー1-2-3-3</a></li>
              <li><ahref="#">メニュー1-2-3-4</a></li>      
            </ul>
          </li>
          <li><ahref="#">メニュー1-2-4</a></li>      
        </ul>
      </li>
      <li><ahref="#">メニュー1-3</a>
        <ul>
          <li><ahref="#">メニュー1-3-1</a></li>
          <li><ahref="#">メニュー1-3-2</a></li>
          <li><ahref="#">メニュー1-3-3</a></li>
          <li><ahref="#">メニュー1-3-4</a></li>      
        </ul>
      </li>
      <li><ahref="#">メニュー1-4</a></li>      
    </ul>
  </li>
</ul>
ドロップダウンメニュー-CSS
ul#menu {
  padding: 15px 0 0 15px;
}

  ul#menu li {
    float: left;
    position: relative;
  }

    ul#menu li a {
      border: solid #ccc 1px;
      border-right: none;
      padding: 10px;
      display: block;
      width:100px;
      background: #eee;
    }
    ul#menu li a.last-child {
      border-right: solid #ccc 1px;
    }
    ul#menu li a:hover,
    ul#menu li a.active {
      color: #fff;
      background: #666 !important;;
    }

    ul#menu li a.dropMenuPrev {
      background: #bbb;
    }

    ul#menu li ul {
      position: absolute;
      top:100%;
      left: 0;
    }

      ul#menu li ul li {
        float: none;
        *display: inline;
      }
        ul#menu li ul li a {
          border:
solid #ccc 1px;
          border- bottom: none;
        }
        ul#menu li ul li
a.last-child {
          border- bottom: 
solid #ccc 1px;
        }

          ul#menu li
ul li ul {
&nbsp ;&nbsp ;          top: 0;
&nbsp ;&nbsp ;          left: 
100%;
          }
ドロップダウンメニュー-JS
jQuery(function($){
  // 最後のLI要素の子要素にあたるA要素の classにはlast-childを振る
  $('#menu li:last-child > a').addClass('last-child');
  
  // 1) #menu子要素のULは全てドロップダウンメ ニューなのでその親要 
素を取得しておく
  var dropMenuParent = $('ul','#menu').parent();
  
  // 2) 全てのdropMenuParentで同じ関数を実行する
  dropMenuParent.each(function(){
    
    // 3) 親の直下の子要素がドロップダウンメ ニューになる 
ので取得する
    var dropMenu = $('>ul',this);
    
    // 4) dropMenuを隠した上で、直前の要素(こ こではアン 
カー要素)のclassにdropMenuPrevを振る
    dropMenu.hide().prev().addClass('dropMenuPrev');
    
    // 5) thisはdropMenuParent[i]を指す
    // dropMenuParent[i]にhoverメソッド を利用して
    // mouseover, out時の処理を割り当てる
    $(this).hover(function(){
    
      // 6) mouseoverでdropMenu を表示した後
      // 直前のA要素のclass にactiveを振る
      dropMenu.show().prev().addClass ('active');
    },function(){
    
      // 7) mouseoutでdropMenu を非表示にした後
      // 直前のA要素のclass からactiveを取り除く
      dropMenu.hide().prev().removeClass 
('active');
    });
  });
});

ul#menuの子・孫にあたるUL要素がドロップダウンメニュー部分にあたるので、dropMenuParentとしてドロップダウンメニューの親要素たちを参照できるように変数として保存しておきます。⁠1)

前回でも少し出てきましたが、jQueryメソッド内でのthisはjQueryオブジェクトになり、eachメソッド内でのthisは上の例で言うと、dropMenuParent[i]になります。

jQueryオブジェクトの項目で説明した通り、⁠要素は配列としてHTML出現順に保存されていく」ので、例えばHTMLの中に3つDIV要素があるとき、

vardiv=$('div');

divは[div,div,div]として扱え、eachメソッドでは配列の中身それぞれに関数を実行していくので、1回目の実行ではthisはdiv[0]になります。

eachメソッド内では、親要素直下のUL要素をdropMenuとして参照できるようにしておき、hideメソッドで非表示にした上で、スタイルを当てるため直前のA要素(prev())のclassにdropMenuPrevを割り当てておきます。⁠2⁠⁠~⁠4)

最後にhoverメソッドを使って(5)dropMenuParentにmouseover時にはdropMenuを表示(6),mouseout時には非表示にするようにそれぞれ関数をbindして完成です。⁠7)

いかがだったでしょうか。要点さえ押さえればこのようなナビゲーションも簡単な短いコードで実装できてしまうところが、jQueryの魅力のひとつではないでしょうか。

おすすめ記事

記事・ニュース一覧