- ベストアンサー
イベントバブル、マウスオーバーなどに関する質問
- イベントバブルやマウスオーバーについての質問に対する要約文です。
- div内でのマウスアウトやマウスオーバーが思った通りに動作しない問題についての要約です。
- 質問者は、イベントが親要素に伝播するという理解で、イベントバブル防止策を取りましたが、一部のブラウザでうまく機能しないことに気付きました。また、境界線をまたぐ際にもマウスアウトが発生してしまい、その対策についても質問しています。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
バブリング(イベントフロー)を勝手に止めてはいけません。かつ、イベントフローを停止する正規の手段は event.stopPropagation() であり、event.cancelBubble は(もともと)IE の独自仕様です。 マウスオーバーとマウスアウトは、どちらをイベントの発生源とするかという視点の違いに過ぎず、本質的に同じイベントです。 ・event.target でマウスオーバーが生じたら、event.relatedTarget にはマウスアウトした要素がセットされる ・event.target でマウスアウトが生じたら、event.relatedTarget にはマウスオーバーした要素がセットされる ・IE8 以下の場合、event.fromElement にマウスアウトした要素、event.toElement にマウスオーバーした要素がセットされる したがって、どちらか一方を document で監視すれば事足りるのです。 // document で mouseover を監視すれば function onMouseOver (event) { // document 内で生じる mouseover と mouseout の両方を全て感知できる var over = event.target || event.toElement; var out = event.relatedTarget || event.fromElement; var tmp; if (out) { // ただしウィンドウ外へ出ていった場合は感知できない for (tmp = out; tmp; tmp = tmp.parentNode) { if (tmp.id === 'aDiv') break; } if (tmp) { // #aDiv の外に出ていった } } for (tmp = over; tmp; tmp = tmp.parentNode) { if (tmp.id === 'aDiv') break; } if (tmp) { // #aDiv の中に入った } // Selectors API2 を使えばもう少し分かりやすいが割愛 } もし、どうしても div 自体に onmouseout 属性を書いて「div から出ていった」ことを感知したい場合は、マウスの行き先(mouseout なら event.relatedTarget または event.toElement で分かる)が、div の中にないことをテストすれば良い。この辺は Dreamweaver の吐き出すコードでも昔からやっていることです。 <div onmouseout=" if (mouseIsOutside.call(this, event)) { // div から出ていった } ">...</div> function mouseIsOutside (event) { var r; var c; try { // DOM3 Core (Firefox, Opera10, Safari4) c = event.currentTarget; r = event.relatedTarget; return ! r || ! r.isSameNode(c) && 0 === (r.compareDocumentPosition(c) & Node.DOCUMENT_POSITION_CONTAINS); } catch (err) { try { // MSHMTL (IE, Opera9) c = this; r = event.toElement || event.relatedTarget; return ! r || c !== r && ! c.contains(r); } catch (err) { // DOM1 Core (Safari3) c = event.currentTarget; r = event.relatedTarget; while ((r = r.parentNode)) if (r === c) break; return ! r; } } } バブリングしない mouseenter、mouseleave(IE 由来で DOM3 Events に収録予定)を使っても良いのですが、いずれにせよバブリングを使えるなら document で一括監視でき、load やノードの挿入を監視してイベントハンドラを付け足す……のような変な作業をせずに済みます。
その他の回答 (3)
- 神崎 渉瑠(@taloo)
- ベストアンサー率44% (1016/2280)
すみません、訂正します。 >onmouseoutのかわりに、onmouseleaveというフックがあります。 フックではなくハンドラです。 (フックは別の言語、APIの呼び方でした)
お礼
返答ありがとうございます! 今、別の要件が入ったので、後で改めてお礼を述べさせていただきます。
補足
ありがとうございます。 onmouseleaveというのは初めて知りました。 使えそうですね。
- 神崎 渉瑠(@taloo)
- ベストアンサー率44% (1016/2280)
>まず、ここまでの理解は間違っていないでしょうか? その通りです。 ツールチップやプルダウンメニューなどを表示・非表示させる場合によくある問題です。 >そして、境界線をまたぐ際、マウスアウトになるのはどうにもならないのでしょうか? その問題に対応するために、 onmouseoutのかわりに、onmouseleaveというフックがあります。 onmouseleaveに対応していないブラウザでは、 私はevent.target、event.srcElementからparentNodeを調べていき、 onmouseoutをセットした要素と同じ物があればmouseoutしていないという判断、 同じ要素がなければ完全に外に出たとして、mouseout処理を続行 としています。 内側の要素でさらにonmouseoverやonmouseoutイベントを処理している場合で、イベントバブルを停止させている場合は、 target|srcElementがうまく取得できないこともあるので、 タイマーを使って1ミリ秒後にカーソルの位置を判断する、という方法をよく使っています。
お礼
返答ありがとうございます! 今、別の要件が入ったので、後で改めてお礼を述べさせていただきます。
補足
ありがとうございます。 「タイマーを使って1ミリ秒後にカーソルの位置を判断する」というのは考えました。 色々試してみます!
- babu_baboo
- ベストアンサー率51% (268/525)
お礼
返答ありがとうございます! 今、別の要件が入ったので、後で改めてお礼を述べさせていただきます。
補足
ありがとうございます! 基本的なことが詳しく書かれていますね。 色々試してみたいと思います。
お礼
返答ありがとうございます! 今、別の要件が入ったので、後で改めてお礼を述べさせていただきます。
補足
詳しいご回答ありがとうございます。 documentで監視するというのがよさそうですね。 いろいろ試してみます。