hover() は mouseenter と mouseleave を同時にセットする http://docs.jquery.com/Events/hover の引数の名前付けを見て、hover は mouseover と mouseout を同時に指定するものだと思っていたが違うらしい。
jquery-1.2.6.js の 2278 行付近 hover: function(fnOver, fnOut) {
return this.bind(‘mouseenter’, fnOver).bind(‘mouseleave’, fnOut); },
とあるように mouseenter と mouseleave に対して指定するものである。 over/outと enter/leave の違いは、http://docs.jquery.com/Events/mouseover の Demo みるとよくわかる。 ある領域 A にカーソルが載ったときに、領域 A 内に動的にブロック B を表示するという処理を次のようなに作っていた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 <html > <head > <meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" /> <meta http-equiv ="content-script-type" content ="text/javascript" > <script src ="jquery-1.2.6.js" > </script > <title > jquery mouseover / mouseout</title > <style type ="text/css" > <!--#A {color :#fff ;background-color :blue ;border :1px solid #000 ;width :300px ;height :200px ;position :relative ;} #B {color :#fff ;background-color :red ;border :1px solid #000 ;display :none ;width :200px ;height :100px ;position :absolute ;bottom :0 ;right :0 ;} #debug p {margin :0 ;line-height :110 %;font-size :9pt ;} //--></style > <script > <!--$(document ).ready(function ( ) { $("#A" ) .mouseover(function ( ) { $("#debug" ).append("<p>A: mouseover</p>" ); $("#B" ).appendTo(this ).show(); }) .mouseout(function ( ) { $("#debug" ).append("<p>A: mouseout</p>" ); $("#B" ).hide().appendTo(document .body); }); }); </script > </head > <body > <div id ="A" > A</div > <div id ="B" > B</div > <div id ="debug" > </div > </body > </html >
しかし、これだと表示されたブロック B にカーソルが載ったとき、A の mouseout が発生するためちらつきが起こってしまう(これは Firefox のときで IE ではちらつきではなく消えたままになった)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="content-script-type" content="text/javascript"> <script src="jquery-1.2.6.js"></script> <title>jquery mouseenter / mouseleave</title> <style type="text/css"><!-- #A { color:#fff; background-color:blue; border:1px solid #000; width:300px; height:200px; position:relative; } #B { color:#fff; background-color:red; border:1px solid #000; display:none; width:200px; height:100px; position:absolute; bottom:0; right:0; } #debug p { margin:0; line-height:110%; font-size:9pt; } //--></style> <script><!-- $(document).ready(function(){ $("#A").hover(function(){ $("#debug").append("<p>A: mouseenter</p>"); $("#B").appendTo(this).show(); }, function(){ $("#debug").append("<p>A: mouseleave</p>"); $("#B").hide().appendTo(document.body); }); /* $("#A") .bind("mouseenter", function(){ $("#debug").append("<p>A: mouseenter</p>"); $("#B").appendTo(this).show(); }) .bind("mouseleave", function(){ $("#debug").append("<p>A: mouseleave</p>"); $("#B").hide().appendTo(document.body); }); */ }); //--></script> </head> <body> <div id="A">A</div> <div id="B">B</div> <div id="debug"></div> </body> </html>
として hover (mouseenter/mouseleave) を使うとうまくいった。 これは jQuery のソースをみると下記のようにサブ要素上にまだあるかイベント内でフックして判定しているからである。
jQuery.event.special.mouseleave.handler 1 2 3 4 5 6 7 handler: function (event ) { if ( withinElement(event, this ) ) return true ;event.type = "mouseenter" ; return jQuery.event.handle.apply(this , arguments );}
ちなみにこのような動的な方法ではなく、元々
と書いてある場合は、上記の例(over/out も enter/leave)どちらでも動作する。
hover を unbind する方法 hover はイベントタイプとして存在するわけではないので、 $("#A").unbind("hover")
とは書けない。
1 $("#A").unbind("mouseover").unbind("mouseout");
とするのも駄目である。これだと前述のように、mouseenter と mouseleave からイベントバインドされているため上記の jQuery.event.special.mouseleave.handler がフックされたまま残ってしまうからだ。
1 $("#A").unbind("mouseenter").unbind("mouseleave");
とするのが正しい。
tilfin
freelance software engineer