【jQuery】子要素に移動したときにホバー判定が外れてしまう場合の対処法(ドロップダウンメニューを例に)

ドロップダウンメニューを作ったときに、カーソルがメニュー全体の要素から外れたら(ホバー解除されたら)ドロップダウンメニューを格納する、という処理をjQueryを用いて実装してみました。

HTMLはこんな感じ。


<ul>
  <li>section1</li>
  <li>section2</li>
  <li>section3</li>
  <li>section4</li>
</ul>

ul、liを使ってドロップダウンメニューの構造を記述しています。
別途CSSで整形していますが、その部分は割愛。

jQueryはこんな感じです。


$("ul").mouseout(function(){
  $("ul").slideUp("fast");
});

「mouseout」でul要素からホバーが外れたのを検知し、ul要素をslideUpで格納するという処理。

これでうまくいくかと思ったのですが・・・

どうやら、子要素の「li」を移動したときにもホバーが外れたと認識される様子。

解決方法


$("ul").mouseout(function(){
  var hovering = false;
  $(":hover").each(function(){
    if($(this).prop("tagName") == "UL"){
      hovering = true;
    }
  });
  if(!hovering){
    $("ul").slideUp("fast");
  }
});

$(":hover")

はホバーしている要素全てを配列で取得します。

ホバーしている要素をeachで回し、もしul要素が含まれていればhoveringフラグを立てます。

prop("tagName")

で要素名を取得することができますが、大文字表記になっているので注意。

eachを回し終わった後でhoveringフラグが立っていなければ($(“:hover”)配列にul要素が含まれていなければ)slideUpします。

これでulの領域全体からホバーが外れた時のみ、ドロップダウンメニューを格納する処理をしてました。

ちなみに上の例ではul要素で処理をしていましたが、クラス名を使う場合はif文の条件式を以下のようにします。


//$(this).prop("tagName") == "UL"  ←これは要素で判定するとき
$(this).attr("class") == "nav"  //←こっちはクラス名で判定するとき

ul要素のクラス名が「nav」のときは上記のような記述になります。
このとき「.nav」としないように。
classの値を比較しているので、HTMLでの「class=”○○”」の値です。

コメント