• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:イベントバブル、マウスオーバーなどに関して)

イベントバブル、マウスオーバーなどに関する質問

このQ&Aのポイント
  • イベントバブルやマウスオーバーについての質問に対する要約文です。
  • div内でのマウスアウトやマウスオーバーが思った通りに動作しない問題についての要約です。
  • 質問者は、イベントが親要素に伝播するという理解で、イベントバブル防止策を取りましたが、一部のブラウザでうまく機能しないことに気付きました。また、境界線をまたぐ際にもマウスアウトが発生してしまい、その対策についても質問しています。

質問者が選んだベストアンサー

  • ベストアンサー
  • Chaire
  • ベストアンサー率60% (79/130)
回答No.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 やノードの挿入を監視してイベントハンドラを付け足す……のような変な作業をせずに済みます。

charlie432
質問者

お礼

返答ありがとうございます! 今、別の要件が入ったので、後で改めてお礼を述べさせていただきます。

charlie432
質問者

補足

詳しいご回答ありがとうございます。 documentで監視するというのがよさそうですね。 いろいろ試してみます。

その他の回答 (3)

回答No.3

すみません、訂正します。 >onmouseoutのかわりに、onmouseleaveというフックがあります。 フックではなくハンドラです。 (フックは別の言語、APIの呼び方でした)

charlie432
質問者

お礼

返答ありがとうございます! 今、別の要件が入ったので、後で改めてお礼を述べさせていただきます。

charlie432
質問者

補足

ありがとうございます。 onmouseleaveというのは初めて知りました。 使えそうですね。

回答No.2

>まず、ここまでの理解は間違っていないでしょうか? その通りです。 ツールチップやプルダウンメニューなどを表示・非表示させる場合によくある問題です。 >そして、境界線をまたぐ際、マウスアウトになるのはどうにもならないのでしょうか? その問題に対応するために、 onmouseoutのかわりに、onmouseleaveというフックがあります。 onmouseleaveに対応していないブラウザでは、 私はevent.target、event.srcElementからparentNodeを調べていき、 onmouseoutをセットした要素と同じ物があればmouseoutしていないという判断、 同じ要素がなければ完全に外に出たとして、mouseout処理を続行 としています。 内側の要素でさらにonmouseoverやonmouseoutイベントを処理している場合で、イベントバブルを停止させている場合は、 target|srcElementがうまく取得できないこともあるので、 タイマーを使って1ミリ秒後にカーソルの位置を判断する、という方法をよく使っています。

charlie432
質問者

お礼

返答ありがとうございます! 今、別の要件が入ったので、後で改めてお礼を述べさせていただきます。

charlie432
質問者

補足

ありがとうございます。 「タイマーを使って1ミリ秒後にカーソルの位置を判断する」というのは考えました。 色々試してみます!

回答No.1
charlie432
質問者

お礼

返答ありがとうございます! 今、別の要件が入ったので、後で改めてお礼を述べさせていただきます。

charlie432
質問者

補足

ありがとうございます! 基本的なことが詳しく書かれていますね。 色々試してみたいと思います。