初心者向けのjQuery入門講座|デザイナー向けのJavaScriptライブラリ

このエントリーをはてなブックマークに追加
索引
1章:jQuery入門
2章:jQuery基礎
3章:jQuery発展
番外編:研究

イベントフロー(3)

概要

mouseoverとmouseenterの違い

コンテンツ作成においてマウスオーバーの処理はよく利用されます。jQueryではマウスオーバーに関連するイベントは2つ(mouseoverイベントとmouseenterイベント)あり初心者にとって分かりにくいので、ここで説明します。2つの違いはセレクタで指定した要素内に別の要素がある(入れ子構造の)時に生じます

マウスオーバーに関連する2つのイベント
mouseoverイベント→セレクタで指定した要素の子孫要素にも反応する
mouseenterイベント→セレクタで指定した要素にしか反応しない

また同じように要素からマウスが外れた時のイベントも2つあります。

マウスアウトに関連する2つのイベント
mouseoutイベント→セレクタで指定した要素の子孫要素にも反応する
mouseleaveイベント→セレクタで指定した要素にしか反応しない

ほとんどの場合、セレクタで指定した要素にしか反応しないmouseenterイベントとmouseleaveイベントを利用すれば良いでしょう。これらのイベントを設定するメソッドはmouseenterメソッドmouseleaveメソッドです。動的な要素に利用する場合はonメソッドのイベント名の部分に設定してください。

解説

セレクタで指定した要素の子孫要素にも反応してしまう問題

サンプル(flow3/01.html)のソースを開いてbody内にdiv要素が2つあることを確認してください。div要素は入れ子になっており、内側はid属性がin、外側はid属性がoutと設定されています。

<div id="out">
	<div id="in"></div>
</div>

jQueryは以下の様に記述されています。ポイントはセレクタに設定された「#out」です。このことを踏まえて、外側(id属性out)のdiv要素にマウスオーバーしてください。当たり前ですが、アラートで「mouseover」と表示されます。続いて内側(id属性がin)にマウスオーバーしてください。すると不思議なことに、ここでもアラートが表示されてしまいます

$("#out").mouseover(function(){
	alert("mouseover")
});

これは以前説明したイベントフローが関係しています。内側の要素で発生したイベントが親要素に伝わっていくため、内側のdiv要素から外側のdiv要素にイベントが伝わりアラートが表示されるのです。

ここで前回説明したstopPropagationメソッドの利用を考えると思いますが、これは利用できません。これは受け取ったイベントを親の要素に伝えるのを停止しますが、子要素から送られてくるイベントの受け取り拒否はできないためです。 上図に当てはめて考えます。内側の要素を緑のdiv、外側の要素を赤のdivと考えてください。stopPropagationメソッドを利用するとセレクタで指定した#outから親の要素にイベントが伝わるのを停止できます。上図では赤から青への伝達が停止されます。しかし#inから#outに送られてくるイベントを停止することはできません。つまり緑から赤への伝達は停止されません。
これでは困るケースがあるので用意されているのがmouseenterイベントです。

バブリングしないイベント

この問題に対応するためmouseoverイベントとは別にmouseenterイベントが用意されました。このイベントの特徴はバブリングしないことです。
→参考:W3Cのmouseenterの説明で「Bubbles」の項目が「No」になっているのを確認してください。

ですからmouseenterメソッドを利用すると子要素(緑のdiv)にカーソルが重なっても、親の要素(赤いdiv)にイベントが渡らず、子要素(緑のdiv)にマウスカーソルが入ってもアラートが表示されないのです。 サンプル(flow3/01b.html)のソースを開いて、以下の様にmouseenterメソッドに変更されている以外は、すべてflow3/01.htmlと同じ事を確認してください。

$("#out").mouseenter(function(){
	alert("mouseenter")	
});

結果として、内側(id属性in)のdiv要素にマウスオーバーしてもアラートは表示されなくなります。こちらの方が混乱しないと思うので、こちらを利用するようにしましょう。

メモ

mouseoutイベントとmouseleaveイベント

マウスアウトに関連するイベントも2つありますが、説明は同じなのでサンプルだけ紹介します。子要素に反応してしまうmouseoutメソッドのサンプル(flow3/02.html)を確認してください。外側のdiv要素から内側のdiv要素にマウスが移動した時にもアラートが表示されてしまいます。

$("#out").mouseout(function(){
	alert("mouseout")	
});

しかしmouseleaveメソッドのサンプル(flow3/02b.html)では反応しません。外側のdiv要素(id属性out)から白いエリア(body要素)にでた時だけアラートが表示されます。

$("#out").mouseleave(function(){
	alert("mouseleave")	
});

hoverメソッドについて

ちなみに「初歩的なサンプル」で紹介したhoverメソッドはmouseenterイベントとmouseleaveイベントを利用しています。サンプル(flow3/test01.html)のソースを開いて、body内の構成はflow3/01.htmlと同じ事を確認してください。

jQueryは以下の様に記述されhoverメソッドによってマウスが#outに入ったら「mouseenter」、#outからでたら「mouseleave」と表示するようにしています。

function enterFunc(){
	alert("mouseenter")	
};
function leaveFunc(){
	alert("mouseleave")	
};
$(function (){
	$("#out").hover(enterFunc, leaveFunc);
})

サンプルでは内側のdiv要素(id属性はin)に反応しないことから、hoverメソッドがmouseenterイベントとmouseleaveイベントを利用している事が確認できます。

これでイベントフローの説明は終わりです。次回は利用する画像データを前もって読み込むプリロードについて説明します。

focus/blurとfocusin/focusout

mouseoverとmouseenterの関係(子孫要素に反応するか否か)と同じイベントが他にもあります。フォーカスした時に発生するイベントのfocusイベントとfocusinイベント、そしてフォーカスが外れた時に発生するイベントのblurイベントとfocusoutイベントです。

フォーカスされた時のイベント
focusinイベント→セレクタで指定した要素の子孫要素にも反応する
focusイベント→セレクタで指定した要素にしか反応しない
フォーカスが外れた時のイベント
focusoutイベント→セレクタで指定した要素の子孫要素にも反応する
blurイベント→セレクタで指定した要素にしか反応しない

mouseenterイベントやmouseleaveイベントと同様にfocusイベントとblurイベントはバブリングしないため、子孫要素で発生したイベントには反応しません。 マウスに関連するイベントと比較すると利用する機会も少ないと思いますが、合わせて覚えておくと良いでしょう。