- ベストアンサー
jQueryでポップアップの中にポップアップ
- ポップアップ内でのhoverイベントを有効にするためには、liveを使用する必要があります。
- 後から追加された要素(ポップアップ)内でのhoverイベントを適用させるためには、mouseenterとmouseleaveを分けて指定する必要があります。
- ポップアップの上にカーソルを合わせることができずに困っています。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
#1です。 簡単なテストをしてみましたが、対象が孫以上の入れ子になっていると、 子までだとmouseenter/leaveの意味通りになるのですが、入れ子の時には、孫のmouseenterが発生する時に子のmouseleaveが発生しているようです。(mouseover/outと同じような感じ) それなので、mouseenter/leaveを使っていても自前でチェックをしてあげる必要があるみたい。 liveに自前のチェックを追加した形で、試みに作成してみました。 $(function(nestCheck){ $('.b').live({ mouseenter:function(e){ if(nestCheck(this, e)) $(this).css("position","relative").append('<div class="popup">'+ $($(this).children('.c').attr('href')).html()+'</div>'); }, mouseleave:function(e){ if(nestCheck(this, e)) $(this).css("position","static").children('div.popup').remove(); } }); }(function(parent, e){ for(var node=e.relatedTarget, flag=true; node; node=node.parentNode) if(node===parent) { flag=false; break; } return flag; }) ); 多分、見た目は意図通りの動作ではないかと思います。 しかしながら、どうも孫のmauseleave時に(子ではなく)親のmouseenterを完全には除けていないようで、あるマウスの動きのときにpopupが一時的に複数できた状態になるみたい。見かけ上は重なっているしmouseoutで全て削除されるのでわからないのですが、このままだと気持ち悪いですね。 もう少し考えないとダメみたいですが、何かのご参考にでもなれば。
その他の回答 (1)
- fujillin
- ベストアンサー率61% (1594/2576)
ちゃんと確認していませんので、半分は想像での回答ですが… mouseenter、mouseleaveのイベントが伝播するようになっているのか確認していませんが、多分そうだとして… liveで設定しておいて、作成される「a2a2#a1a2」のポップアップのの中のリンク(#a2)にmouseenterが発生すると、<div id="a3">は以下のような構成になります。 (どのタイミングでとらえるかで、若干変わるかも) <div id="a3"> <p>a3 <span class="b" style="position: absolute;"> <a class="c" href="#a2">#a2</a> <div class="popup"> <p>a2a2 <span class="b" style="position: absolute;"> <a class="c" href="#a1">#a1</a> <div class="popup"> <p>a1a1a1</p> </div> </span> a2 </p> </div> <div class="popup"> <p>a2a2 <span class="b"> <a class="c" href="#a1">#a1</a> </span> a2 </p> </div> </span> a3a3 </p> </div> 前半の入れ子の関係は意図なさっている通りと思いますが、mouseenterが元の親要素に伝播して、a2a2以下のpopupがもう一つ作成されていると想像されます。 この要素が表示されても、表示上は下にある同じものとまったく重なって表示されるために見た目には分かりません。 しかし、下側になったpopup内にある<span calss="b">からみるとmouseleaveが発生していることになるため、この一連のイベント処理の中でdiv要素が全て消されているということになっているのではないかと想像します。 表示側と、消す側(現在はまとめて消す処理になっている)が対になるようにしてあげることと、イベントの伝播に対して余分な処理をしないような工夫をすれば良いのではないでしょうか? 最初にも書きましたように、きちんと確認してはいませんので、はずしているかも知れません。
補足
ご回答ありがとうございました。 CSS部分を以下のように変更すると、ポップアップがちょっとずれて確認しやすいかと思います。 .popup {position:absolute;bottom:20px;left:20px;width:30em;padding:1px 5px;border:solid 1px #000;background:#fff;} div{padding:10px 0;} .b{padding:10px;background:#eee;} Firefoxのfirebugアドオンでmouseenter時のDOMの変化を確認したところ、 .popupが2つ以上生成されるという減少は確認されませんでした。 最終的に次のようにすることでいちおう考えていたものができました。 <html> <head></head> <style type="text/css"> .popup {position:absolute;bottom:20px;left:20px;width:30em;padding:1px 5px;border:solid 1px #000;background:#fff;} div{padding:10px 0;} .b{padding:10px;background:#eee;} </style> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js"></script> <script type="text/javascript"> $.fn.extend({ popupEvent : function(){ $('.b',this).bind({ mouseenter:function(){ $(this).css('position','relative').append('<div class="popup">'+$( $(this).children().filter('.c').attr('href') ).html()+'</div>').popupEvent(); $('#log').append('mouseenter<br>'); }, mouseleave:function(){ $(this).css('position','static').children().filter('div').remove(); $('#log').append('mouseleave<br>'); } }); } }); $(function(){ $('div').popupEvent(); }); </script> <body> <div id="a1"><p>a1a1a1</p></div> <div id="a2"><p>a2a2a2<span class="b"><a href="#a1" class="c">#a1</a></span></p></div> <div id="a3"><p>a3a3<span class="b"><a href="#a2" class="c">#a2</a></span>a3a3<span class="b"><a href="#a1" class="c">#a1</a></span>a3a3a3</p></div> <div id="a4"><p>a4<span class="b"><a href="#a3" class="c">#a3</a></span>a4a4</p></div> <div id="log"> </div> </body> </html> 後から追加された要素に.live()を使わずに.bind()でイベントを適用させられると知り、 試しにやってみたのですが、なぜこれでできて、.live()でできないのかがまだよくわかりません。 もしよろしければ何かアドバイスをいただけると助かります。 引き続きよろしくお願い致します。
お礼
回答ありがとうございました。 とても参考になりました。