development

jQuery없이 부모 절대 div의 자식 요소를 가리킬 때 onmouseout 방지

big-blog 2020. 6. 13. 09:26
반응형

jQuery없이 부모 절대 div의 자식 요소를 가리킬 때 onmouseout 방지


onmouseout절대 포지티브 div에서 함수에 문제가 있습니다. 마우스가 div의 자식 요소에 부딪 치면 mouseout 이벤트가 발생하지만 마우스가 부모 인 절대 div에서 벗어날 때까지 마우스를 발사하지는 않습니다.

mouseoutjquery없이 자식 요소에 도달했을 때 이벤트가 발생 하지 않도록하려면 어떻게해야합니까 ?

나는 이것이 이벤트 버블 링과 관련이 있다는 것을 알고 있지만, 이것을 해결하는 방법을 찾는 데 운이 없다.

비슷한 게시물을 발견했습니다 : 자식 요소에 의해 트리거 된 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);

CSS와 HTML이 필요한 빠른 JsFiddle 데모를 만들었습니다.

크로스 브라우저 지원을위한 수정 된 링크 수정 http://jsfiddle.net/RH3tA/9/

부모 div에 자식이 중첩되어 있으면 바로 부모 만 확인한다는 점에 유의 하십시오. "일반 요소"를 찾고있는 부모 요소를 어떻게 든 통과해야합니다.

중첩 된 자식에 대한 편집

편집 크로스 브라우저를 위해 수정되었습니다.

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
});

예가 여기 있습니다 .


경우에 따라 작동 하는 더 간단한 순수 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>

;)


생각 쿼크 모드는 모든 당신이 필요로하는 답변 (다른 브라우저 버블 링 행동하고있다 mouseenter /하는 MouseLeave 이벤트),하지만 난 그 이벤트 버블 링 혼란에 가장 일반적인 결론은 생각 입니다 JQuery와 또는 Mootools의합니다 (이 같은 프레임 워크의 사용 mouseenter을 하고 mouseleave 이벤트, 이것은 당신이 직감 했던 것입니다).

원하는 경우 직접 수행
하거나 이벤트 부분 (및 그 종속 항목)만으로 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

케이크의 평화 :) 그것을 즐기십시오 :)


이것을 처리하는 두 가지 방법이 있습니다.

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>

나는 이것을 매력처럼 작동시킵니다 :

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>

따라서 더 일반적인 것은 하나의 div뿐만 아니라 id="..."각 레이어 에 추가 할 필요가 없습니다 .


mouseout메소드 내부에서 이벤트가 첨부 된 요소에 액세스 할 수있는 경우 contains()이를 사용 하여 event.relatedTarget하위 요소인지 여부를 확인할 수 있습니다 .

으로 event.relatedTarget는 자식 요소가 아닌 경우 마우스로 통과되는 요소, 당신은 요소 밖으로 마우스를 올리면있다.

div.onmouseout = function (event) {
    if (!div.contains(event.relatedTarget)) {
        // moused out of div
    }
}

언급 솔루션 이 jquery를 사용 하지만 mouseentermouseleave 는 기본 dom 이벤트이므로 jquery없이 사용할 수 있습니다.


각도 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');
 }
}

원래 요소의 오프셋을 확인하여 요소 경계의 페이지 좌표를 얻은 다음 mouseout이 해당 범위를 벗어날 때만 mouseout 동작이 트리거되는지 확인하십시오. 더럽지 만 작동합니다.

$(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
}
}

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
});

부모 요소에 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에있을 때만 물건이 실행됩니다.


난 그냥 당신과 뭔가를 공유하고 싶었다.
나는 몇 가지 어려움을 가지고 ng-mouseenterng-mouseleave이벤트.

사례 연구 :

I created a floating navigation menu which is toggle when the cursor is over an icon.
This menu was on top of each page.

  • To handle show/hide on the menu, I toggle a class.
    ng-class="{down: vm.isHover}"
  • To toggle vm.isHover, I use the ng mouse events.
    ng-mouseenter="vm.isHover = true"
    ng-mouseleave="vm.isHover = false"

For now, everything was fine and worked as expected.
The solution is clean and simple.

The incoming problem:

In a specific view, I have a list of elements.
I added an action panel when the cursor is over an element of the list.
I used the same code as above to handle the behavior.

The problem:

I figured out when my cursor is on the floating navigation menu and also on the top of an element, there is a conflict between each other.
The action panel showed up and the floating navigation was hide.

The thing is that even if the cursor is over the floating navigation menu, the list element ng-mouseenter is triggered.
It makes no sense to me, because I would expect an automatic break of the mouse propagation events.
I must say that I was disappointed and I spend some time to find out that problem.

First thoughts:

I tried to use these :

  • $event.stopPropagation()
  • $event.stopImmediatePropagation()

I combined a lot of ng pointer events (mousemove, mouveover, ...) but none help me.

CSS solution:

I found the solution with a simple css property that I use more and more:

pointer-events: none;

Basically, I use it like that (on my list elements):

ng-style="{'pointer-events': vm.isHover ? 'none' : ''}"

With this tricky one, the ng-mouse events will no longer be triggered and my floating navigation menu will no longer close himself when the cursor is over it and over an element from the list.

To go further:

As you may expect, this solution works but I don't like it.
We do not control our events and it is bad.
Plus, you must have an access to the vm.isHover scope to achieve that and it may not be possible or possible but dirty in some way or another.
I could make a fiddle if someone want to look.

Nevertheless, I don't have another solution...
It's a long story and I can't give you a potato so please forgive me my friend.
Anyway, pointer-events: none is life, so remember it.

참고URL : https://stackoverflow.com/questions/4697758/prevent-onmouseout-when-hovering-child-element-of-the-parent-absolute-div-withou

반응형