絶対位置のdivでonmouseout
関数に問題があります。マウスがdiv内の子要素にヒットすると、mouseoutイベントが発生しますが、マウスが親の絶対divから外れるまで発生しません。
Jqueryなしで子要素にヒットしたときにmouseout
イベントが発生しないようにするにはどうすればよいですか。
これはイベントのバブリングと関係があることは知っていますが、これを解決する方法を見つけることができません。
私はここで同様の投稿を見つけました: 子要素によってトリガーされたマウスアウトイベントを無効にする方法?
ただし、そのソリューションはjQueryを使用します。
function onMouseOut(event) {
//this is the original element the event handler was assigned to
var e = event.toElement || event.relatedTarget;
if (e.parentNode == this || e == this) {
return;
}
alert('MouseOut');
// handle mouse event here!
}
document.getElementById('parent').addEventListener('mouseout',onMouseOut,true);
簡単なJsFiddleデモを作成しました。必要なすべてのCSSとHTMLを使って、チェックしてみてください...
編集クロスブラウザサポート用の固定リンク http://jsfiddle.net/RH3tA/9/
NOTEこれは直接の親のみをチェックします。親divにネストされた子がある場合、「元の要素」
EDITネストされた子の例
EDITうまくいけばクロスブラウザ用に修正
function makeMouseOutFn(elem){
var list = traverseChildren(elem);
return function onMouseOut(event) {
var e = event.toElement || event.relatedTarget;
if (!!~list.indexOf(e)) {
return;
}
alert('MouseOut');
// handle mouse event here!
};
}
//using closure to cache all child elements
var parent = document.getElementById("parent");
parent.addEventListener('mouseout',makeMouseOutFn(parent),true);
//quick and dirty DFS children traversal,
function traverseChildren(elem){
var children = [];
var q = [];
q.Push(elem);
while (q.length > 0) {
var elem = q.pop();
children.Push(elem);
pushAll(elem.children);
}
function pushAll(elemArray){
for(var i=0; i < elemArray.length; i++) {
q.Push(elemArray[i]);
}
}
return children;
}
そして、新しい JSFiddle 、EDITリンクを更新しました
onmouseleave
を使用します。
または、jQueryでmouseleave()
を使用します
それはあなたが探している正確なものです。例:
<div class="outer" onmouseleave="yourFunction()">
<div class="inner">
</div>
</div>
または、jQueryで:
$(".outer").mouseleave(function(){
//your code here
});
例は here です。
場合によっては動作する単純な純粋なCSSソリューション( IE11以降 )では、子供の pointer-events
none
に設定することにより
.parent * {
pointer-events: none;
}
以下は、以下に基づいたよりエレガントなソリューションです。これは、複数のレベルの子供から発生するイベントを説明します。また、クロスブラウザの問題も考慮します。
function onMouseOut(this, event) {
//this is the original element the event handler was assigned to
var e = event.toElement || event.relatedTarget;
//check for all children levels (checking from bottom up)
while(e && e.parentNode && e.parentNode != window) {
if (e.parentNode == this|| e == this) {
if(e.preventDefault) e.preventDefault();
return false;
}
e = e.parentNode;
}
//Do something u need here
}
document.getElementById('parent').addEventListener('mouseout',onMouseOut,true);
私にインスピレーションを与えたAmjad Masadに感謝します。
私はIE9、FFおよびChromeで動作しているように見える次の解決策を持っていますが、コードは非常に短いです(複雑なクロージャと横断的な子物なし):
DIV.onmouseout=function(e){
// check and loop relatedTarget.parentNode
// ignore event triggered mouse overing any child element or leaving itself
var obj=e.relatedTarget;
while(obj!=null){
if(obj==this){
return;
}
obj=obj.parentNode;
}
// now perform the actual action you want to do only when mouse is leaving the DIV
}
JQueryを使用している場合は、「mouseleave」関数も使用できます。これは、これらすべてを処理します。
$('#thetargetdiv').mouseenter(do_something);
$('#thetargetdiv').mouseleave(do_something_else);
do_somethingは、マウスがtargetdivまたはその子のいずれかに入ったときに起動します。do_something_elseは、マウスがtargetdivおよびその子のいずれかを離れたときにのみ起動します。
mouseleave()
を試してください
例:
<div id="parent" mouseleave="function">
<div id="child">
</div>
</div>
;)
Quirksmode に必要な答えはすべてあると思います(異なるブラウザーのバブリング動作とmouseenter/mouseleaveイベント)、しかしそれに対する最も一般的な結論はイベントバブリングの混乱isJQueryやMootools(mouseenterおよびmouseleaveイベント。これはまさにあなたが直観したものです。
彼らがそれをどのように行うかを見てください、あなたが望むなら、自分でそれをしてください
orすることができます カスタムを作成する イベント部分(およびその依存関係)だけでMootoolsの「リーン平均」バージョン。
私は非常に簡単な解決策を見つけました、
onmousout = "myfunc()"イベントよりもonmouseleave = "myfunc()"イベントを使用するだけです
私のコードではうまくいきました!!
例:
<html>
<head>
<script type="text/javascript">
function myFunc(){
document.getElementById('hide_div').style.display = 'none';
}
function ShowFunc(){
document.getElementById('hide_div').style.display = 'block';
}
</script>
</head>
<body>
<div onmouseleave="myFunc()" style='border:double;width:50%;height:50%;position:absolute;top:25%;left:25%;'>
Hover mouse here
<div id='child_div' style='border:solid;width:25%;height:25%;position:absolute;top:10%;left:10%;'>
CHILD <br/> It doesn't fires if you hover mouse over this child_div
</div>
</div>
<div id="hide_div" >TEXT</div>
<a href='#' onclick="ShowFunc()">Show "TEXT"</a>
</body>
</html>
mouseout関数と同じ例:
<html>
<head>
<script type="text/javascript">
function myFunc(){
document.getElementById('hide_div').style.display = 'none';
}
function ShowFunc(){
document.getElementById('hide_div').style.display = 'block';
}
</script>
</head>
<body>
<div onmouseout="myFunc()" style='border:double;width:50%;height:50%;position:absolute;top:25%;left:25%;'>
Hover mouse here
<div id='child_div' style='border:solid;width:25%;height:25%;position:absolute;top:10%;left:10%;'>
CHILD <br/> It fires if you hover mouse over this child_div
</div>
</div>
<div id="hide_div">TEXT</div>
<a href='#' onclick="ShowFunc()">Show "TEXT"</a>
</body>
</html>
それが役に立てば幸い :)
onmouseoutの代わりにonmouseleaveを使用します。
あなたは私たちにあなたの特定のコードを見せていないので、あなたの特定の例でそれを行う方法を示すことはできません。
しかし、それは非常に簡単です。onmouseoutをonmouseleaveに置き換えるだけです。
それだけです:)それで、簡単です:)
方法がわからない場合は、次の説明を参照してください。
https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_onmousemove_leave_out
ケーキの平和:)それをお楽しみください:)
これを処理するには2つの方法があります。
1)コールバックでevent.targetの結果をチェックして、親divと一致するかどうかを確認します
var g_ParentDiv;
function OnMouseOut(event) {
if (event.target != g_ParentDiv) {
return;
}
// handle mouse event here!
};
window.onload = function() {
g_ParentDiv = document.getElementById("parentdiv");
g_ParentDiv.onmouseout = OnMouseOut;
};
<div id="parentdiv">
<img src="childimage.jpg" id="childimg" />
</div>
2)または、イベントキャプチャを使用して、コールバック関数でevent.stopPropagationを呼び出します
var g_ParentDiv;
function OnMouseOut(event) {
event.stopPropagation(); // don't let the event recurse into children
// handle mouse event here!
};
window.onload = function() {
g_ParentDiv = document.getElementById("parentdiv");
g_ParentDiv.addEventListener("mouseout", OnMouseOut, true); // pass true to enable event capturing so parent gets event callback before children
};
<div id="parentdiv">
<img src="childimage.jpg" id="childimg" />
</div>
mouseout
メソッド内でイベントが関連付けられている要素にアクセスできる場合、contains()
を使用して、event.relatedTarget
が子要素であるかどうかを確認できます。
event.relatedTarget
はマウスが渡された要素であるため、子要素でない場合は、要素からマウスアウトしました。
div.onmouseout = function (event) {
if (!div.contains(event.relatedTarget)) {
// moused out of div
}
}
Angular 5、6、および7
<div (mouseout)="onMouseOut($event)"
(mouseenter)="onMouseEnter($event)"></div>
それから
import {Component,Renderer2} from '@angular/core';
...
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit, OnDestroy {
...
public targetElement: HTMLElement;
constructor(private _renderer: Renderer2) {
}
ngOnInit(): void {
}
ngOnDestroy(): void {
//Maybe reset the targetElement
}
public onMouseEnter(event): void {
this.targetElement = event.target || event.srcElement;
console.log('Mouse Enter', this.targetElement);
}
public onMouseOut(event): void {
const elementRelated = event.toElement || event.relatedTarget;
if (this.targetElement.contains(elementRelated)) {
return;
}
console.log('Mouse Out');
}
}
私はこれで魅力のように動作させます:
function HideLayer(theEvent){
var MyDiv=document.getElementById('MyDiv');
if(MyDiv==(!theEvent?window.event:theEvent.target)){
MyDiv.style.display='none';
}
}
ああ、そしてMyDiv
タグは次のようなものです:
<div id="MyDiv" onmouseout="JavaScript: HideLayer(event);">
<!-- Here whatever divs, inputs, links, images, anything you want... -->
<div>
この方法では、onmouseoutが子、孫などに行くとき、style.display='none'
は実行されません。しかし、onmouseoutがMyDivから出ると実行されます。
したがって、伝播を停止したり、タイマーを使用したりする必要はありません...
例のおかげで、私は彼らからこのコードを作ることができました。
これが誰かを助けることを願っています。
次のように改善することもできます:
function HideLayer(theLayer,theEvent){
if(theLayer==(!theEvent?window.event:theEvent.target)){
theLayer.style.display='none';
}
}
そして、DIVタグは次のようになります。
<div onmouseout="JavaScript: HideLayer(this,event);">
<!-- Here whatever divs, inputs, links, images, anything you want... -->
<div>
より一般的なのは、1つのdivだけではなく、各レイヤーにid="..."
を追加する必要がないことです。
参照した solution はjqueryを使用していますが、 mouseenter および mouseleave はネイティブdomイベントであるため、jqueryなしで使用できます。
var elem = $('#some-id');
elem.mouseover(function () {
// Some code here
}).mouseout(function (event) {
var e = event.toElement || event.relatedTarget;
if (elem.has(e).length > 0) return;
// Some code here
});
元の要素のオフセットをチェックして要素の境界のページ座標を取得し、マウスアウトがこれらの境界から外れたときにのみマウスアウトアクションがトリガーされるようにします。汚れていますが、動作します。
$(el).live('mouseout', function(event){
while(checkPosition(this, event)){
console.log("mouseovering including children")
}
console.log("moused out of the whole")
})
var checkPosition = function(el, event){
var position = $(el).offset()
var height = $(el).height()
var width = $(el).width()
if (event.pageY > position.top
|| event.pageY < (position.top + height)
|| event.pageX > position.left
|| event.pageX < (position.left + width)){
return true
}
}
私はあなたと何かを共有したかっただけです。ng-mouseenter
およびng-mouseleave
イベントで苦労しました。
ケーススタディ:
カーソルがアイコンの上にあるときにトグルするフローティングナビゲーションメニューを作成しました。
このメニューは各ページの上部にありました。
ng-class="{down: vm.isHover}"
ng-mouseenter="vm.isHover = true"
ng-mouseleave="vm.isHover = false"
今のところ、すべてが正常であり、期待どおりに機能しました。
ソリューションはクリーンでシンプルです。
入ってくる問題:
特定のビューでは、要素のリストがあります。
カーソルがリストの要素の上にあるときにアクションパネルを追加しました。
上記と同じコードを使用して動作を処理しました。
問題:
カーソルがフローティングナビゲーションメニュー上にあり、要素の上部にもある場合、相互に競合があることがわかりました。
アクションパネルが表示され、フローティングナビゲーションが非表示になりました。
問題は、カーソルがフローティングナビゲーションメニュー上にある場合でも、リスト要素ng-mouseenterがトリガーされることです。
マウスの伝播イベントが自動的に中断されると予想されるため、それは意味がありません。
私は失望したと言わなければならず、その問題を見つけるためにしばらく時間を費やしています。
最初の考え:
私はこれらを使用しようとしました:
$event.stopPropagation()
$event.stopImmediatePropagation()
多数のngポインターイベント(mousemove、mouveover、...)を組み合わせましたが、私を助けてくれるものはありません。
CSSソリューション:
私はますます使用する単純なcssプロパティを持つソリューションを見つけました:
pointer-events: none;
基本的に、私はそれを(私のリスト要素で)そのように使用します:
ng-style="{'pointer-events': vm.isHover ? 'none' : ''}"
このトリッキーなものにより、ng-mouseイベントはトリガーされなくなり、カーソルがその上およびリストの要素の上にあるときにフローティングナビゲーションメニューが閉じなくなります。
さらに進むには:
ご想像のとおり、このソリューションは機能しますが、私はそれが好きではありません。
イベントを管理していないため、問題があります。
さらに、それを達成するにはvm.isHover
スコープへのアクセス権が必要です。これは不可能または可能ですが、何らかの方法で汚れている可能性があります。
誰かが見たいなら、私はフィドルを作ることができます。
それにもかかわらず、私は別の解決策を持っていません...
これは長い話です。ジャガイモをあげることはできませんので、私の友人を許してください。
とにかく、pointer-events: none
は命ですから、覚えておいてください。
親要素にCSSクラスまたはIDを追加した(または持っている)場合、次のようなことができます。
<div id="parent">
<div>
</div>
</div>
JavaScript:
document.getElementById("parent").onmouseout = function(e) {
e = e ? e : window.event //For IE
if(e.target.id == "parent") {
//Do your stuff
}
}
そのため、イベントは親div上にあるときにのみ実行されます。