programing

jQuery 없이 상위 절대 DIV의 하위 요소를 호버링할 때 마우스 아웃 방지

yoursource 2022. 10. 22. 13:37
반응형

jQuery 없이 상위 절대 DIV의 하위 요소를 호버링할 때 마우스 아웃 방지

에 문제가 있습니다.onmouseout을 나누다마우스가 div의 하위 요소를 누르면 마우스 아웃 이벤트가 발생하지만 마우스가 부모인 절대 div에서 벗어날 때까지 실행되지 않도록 합니다.

할 수 요?mouseout이벤트가 jquery 없이 하위 요소에 도달했을 때 발생하는 이벤트입니다.

이게 이벤트 버블링과 관련이 있다는 건 알지만, 이 문제를 해결할 방법이 없어요.

비슷한 게시물을 찾았습니다.하위 요소에 의해 트리거되는 마우스 아웃 이벤트를 비활성화하려면 어떻게 해야 합니다.

그러나 이 솔루션은 jQuery를 사용합니다.

onmouseleave.

jQuery에서는 "jQuery를 사용합니다.mouseleave()

그것은 바로 당신이 찾고 있는 것입니다.예제:

<div class="outer" onmouseleave="yourFunction()">
    <div class="inner">
    </div>
</div>

또는 jQuery의 경우:

$(".outer").mouseleave(function(){
    //your code here
});

여기 예가 있습니다.

대부분의 경우 동작하는 단순한 순수 CSS 솔루션에서는 다음과 같이 설정하여 어린이용 CSS를 제거할 수 있습니다.none

.parent * {
     pointer-events: none;
}

브라우저 지원: IE11+

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 데모를 만들었다. 확인해봐...

크로스 사이트 지원용 EDIT FIXED 링크 http://jsfiddle.net/RH3tA/9/

는 직계 부모만 검사하므로 부모 div에 중첩된 자녀가 있으면 어떻게든 부모 요소를 탐색하여 "Orginal 요소"를 찾아야 합니다.

중첩된 하위 항목에 대한 편집 예제

크로스 브라우저용 EDIT Fixed

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 업데이트 링크

onmouseout을 사용하는 대신 onmouseleave를 사용합니다.

아직 구체적인 코드를 보여주지 않았기 때문에 구체적인 예로는 보여줄 수 없습니다.

단, 매우 간단합니다.onmouseout을 onmouseleave로 대체하기만 하면 됩니다.

이상입니다:) 심플합니다.

방법을 모르는 경우는, 다음의 설명을 참조해 주세요.

https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_onmousemove_leave_out

케이크의 평화 :) 즐기세요 :)

아래 내용을 바탕으로 한 보다 우아한 솔루션을 소개합니다.그것은 한 단계 이상의 아이들로부터 일어나는 사건을 설명한다.또한 크로스 브라우저 문제도 해결됩니다.

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

jQuery를 사용하는 경우 이 모든 것을 처리하는 "마우스 탈퇴" 기능도 사용할 수 있습니다.

$('#thetargetdiv').mouseenter(do_something);
$('#thetargetdiv').mouseleave(do_something_else);

do_something은 마우스가 targetdiv 또는 그 자식 중 하나를 입력하면 호출되며 do_something_something은 마우스가 targetdiv 및 그 자식 중 하나에서 벗어날 때만 호출됩니다.

저에게 영감을 준 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
    }

Quirksmode는 필요한 모든 답변(브라우저 버블링 동작과 마우스 엔터/마우스 탈퇴 이벤트)을 가지고 있다고 생각합니다만, 이 이벤트의 버블링에 관한 가장 일반적인 결론은 JQuery나 Mootools와 같은 프레임워크(마우스 엔터 이벤트와 마우스 탈퇴 이벤트, 정확히 당신이 직감적으로 생각할 수 있는 것)를 사용하는 것이라고 생각합니다.

.
또는 이벤트 부분(및 그 종속성)만으로 커스텀 "평균" 버전의 Mootools를 생성할 수 있습니다.

★★를 해 보세요.mouseleave()

예:

<div id="parent" mouseleave="function">
   <div id="child">

   </div>
</div>

;)

아주 간단한 해결책을 찾았어요

onmouseleave="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>

마우스 아웃 기능을 사용한 동일한 예:

<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>

도움이 되었으면 좋겠다:)

참조한 솔루션은 jquery를 사용하지만 mouseentermouseleave는 네이티브 dom 이벤트이므로 jquery 없이 사용할 수 있습니다.

이 문제를 해결하는 방법은 두 가지가 있습니다.

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) 콜백 함수로 이벤트 캡처 및 콜이벤트.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>

이렇게 해서 온마우스아웃이 아이, 손자, 손녀 등에게 돌아갈 때...style.display='none'MyDiv 마우스 아웃, 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'를 추가할 . "div" "div" "div"id="..."각 층에 배치됩니다.

되어 있는 할 수 는, 「 」의 「 」를 참조해 .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');
 }
}

e.relatedTarget에 자녀 클래스가 있는지 확인하고 true일 경우 함수를 반환합니다.

    if ($(e.relatedTarget).hasClass("ctrl-btn")){
        return;
    }

이것은 나에게 효과가 있는 코드입니다. 나는 html5 비디오 재생에 사용되었습니다.버튼의 호버 비디오 요소를 전환합니다.

element.on("mouseover mouseout", function(e) {

    if(e.type === "mouseout"){

        if ($(e.relatedTarget).hasClass("child-class")){
            return;
        }

    }

});

원래 요소의 오프셋을 확인하여 요소 경계의 페이지 좌표를 가져온 다음 마우스 아웃이 해당 범위를 벗어났을 때만 마우스 아웃 작업이 트리거되는지 확인합니다.더럽지만 효과가 있다.

$(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-mouseenter ★★★★★★★★★★★★★★★★★」ng-mouseleave벤트입입니니다

도입 사례:

커서가 아이콘 위에 있으면 전환되는 플로팅 네비게이션 메뉴를 만들었습니다.
이 메뉴는 각 페이지의 맨 위에 있었다.

  • 메뉴의 표시/숨김을 처리하기 위해 클래스를 전환합니다.
    ng-class="{down: vm.isHover}"
  • vm.isHover를 전환하려면 ng 마우스 이벤트를 사용합니다.
    ng-mouseenter="vm.isHover = true"
    ng-mouseleave="vm.isHover = false"

일단은 모든 것이 괜찮았고 예상대로 작동했다.
이치노

착신 문제:

을 사용법
커서가 목록의 요소 위에 있을 때 작업 패널을 추가했습니다.
위와 같은 코드를 사용하여 처리했습니다.

문제:

커서가 플로팅 네비게이션 메뉴에 있을 때와 엘리먼트 상단에 있을 때 서로 충돌하는 것을 알 수 있었습니다.
액션 패널이 표시되고 플로팅 내비게이션이 숨겨졌습니다.

문제는 커서가 플로팅 네비게이션 메뉴 위에 있어도 리스트 요소 ng-mouseenter가 트리거된다는 것입니다.
마우스 전파 이벤트가 자동으로 중단될 것으로 예상하기 때문에 이해가 안 됩니다.
저는 실망했고 그 문제를 알아내기 위해 시간을 좀 투자하고 있다고 말해야 합니다.

첫 번째 생각:

다음 항목을 사용하려고 했습니다.

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

포인터 이벤트(mouse move, mouveover 등)를 많이 조합했지만, 아무것도 도움이 되지 않습니다.

CSS 솔루션:

점점 더 많이 사용하는 단순한 css 속성을 가진 솔루션을 찾았습니다.

pointer-events: none;

기본적으로 (목록 요소에서) 다음과 같이 사용합니다.

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

이 까다로운 기능을 사용하면 ng-mouse 이벤트가 더 이상 트리거되지 않으며 커서가 위에 있고 목록의 요소 위에 있을 때 내 플로팅 탐색 메뉴가 닫히지 않습니다.

더 나아가려면:

예상대로 이 솔루션은 효과가 있지만 저는 마음에 들지 않습니다.
우리는 우리의 이벤트를 통제하지 않고 그것은 나쁘다.
할 수 있다', '접근할 수 있다', '접근할 수 있다', '접근할 수 있다', '접근할 수 합니다.vm.isHover가능하거나 불가능할 수도 있지만 어떤 식으로든 더럽힐 수도 있습니다.
누가 보고 싶으면 내가 바이올린을 켤 수 있어.

그럼에도 불구하고 다른 해결책이 없어요...
이야기가 길어서 감자를 줄 수 없으니 친구를 용서해 주세요.
어,는pointer-events: none생이인

작동시킬 수 있는 간단한 방법이 있습니다.동일한 클래스 이름을 설정한 요소 및 모든 하위 항목:

element.onmouseover = function(event){
 if (event.target.className == "name"){
 /*code*/
 }
}

바닐라즈도 그렇게 사용하실 수 있습니다.

document.querySelector('.product_items') && document.querySelector('.product_items').addEventListener('mouseleave', () => updateCart())


const updateCart = () => {
let total = 0;
document.querySelectorAll('input') && document.querySelectorAll('input').forEach(item => total += +item.value)
  document.getElementById('total').innerHTML = total
}
<div class="product_items">
  <div class="product_item">
    <div class="product_name">
    </div>
    <div class="multiply__btn">
      <button type="button">-</button>
      <input name="test" type="text">
      <button type="button">+</button>
    </div>
  </div>
  <div class="product_item">
    <div class="product_name">
    </div>
    <div class="multiply__btn">
      <button type="button">-</button>
      <input name="test" type="text">
      <button type="button">+</button>
    </div>
  </div>
  <div class="product_item">
    <div class="product_name">
    </div>
    <div class="multiply__btn">
      <button type="button">-</button>
      <input name="test" type="text">
      <button type="button">+</button>
    </div>
  </div>
</div>

<div id="total"></div>

mouseenter ★★★★★★★★★★★★★★★★★」mouseleave라고 하면 '', '이벤트', '이벤트'를 사용할 수 있습니다mouseover/mouseout'무엇보다'

는 이벤트 핸들러가 이벤트 핸들러를 합니다.out뒤이어 새로운 것이 있다over~하다마우스가 실제로 떠난 경우(데바운스 기간보다 오래) 제외).이것은 모든 사건에서 돔 노드를 기어가는 것보다 간단해 보인다.

의 「Debounce」가 으로 「를 했을 .out 모든 할 수 있습니다.out/over아이 요소에서 부풀어 오르는 이벤트입니다.

참고! 하위 요소에도 다음 수신기가 있는 경우 이 기능은 작동하지 않습니다.over "/"/"out이벤트 및 그 핸들러 콜event.stopPropogation()이벤트가 핸들러를 접속한 부모 요소에 버블하지 않도록 합니다.코드를 제어하고 있는 경우는, 반드시 문제가 되는 것은 아니지만, 주의해 주세요.

샘플 코드

자바스크립트



function mouseOverOutDebounce (element, debounceMs, mouseOverFn, mouseOutFn) {
    var over = false,
        debounceTimers = [];

    function mouseOver (evt) {
        if (over) {  // already OVER, existing interaction
            while (debounceTimers.length > 0) { // then we had a pending mouseout(s), cancel
                window.clearTimeout(debounceTimers.shift());
            }
        }
        else { // new OVER
            over = true;
            mouseOverFn(evt);
        }
    }
    function mouseOut (evt) {
        if (!over) return;  // already OUT, ignore.

        debounceTimers.push(window.setTimeout(function () {
            over = false;
            mouseOutFn(evt);
        }, debounceMs));
    }

    function removeEventListeners () {
        element.removeEventListener('mouseover', mouseOver);
        element.removeEventListener('mouseout', mouseOut);
    }
    
    element.addEventListener('mouseover', mouseOver);
    element.addEventListener('mouseout', mouseOut);

    return removeEventListeners;
}

var someEl = document.querySelector('.container'),
    textarea = document.querySelector('textarea'),
    mouseOver = function (evt) { report('mouseOVER', evt); },
    mouseOut = function (evt) { report('mouseOUT', evt); },
    removeEventListeners = mouseOverOutDebounce(someEl, 200, mouseOver, mouseOut);

function report(msg, data) {
    console.log(msg, data);
    textarea.value = textarea.value + msg + '\n';
}

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <style type="text/css">
        html, body {
            margin: 0;
            padding: 0;
        }
        body {
            margin: 5%;
        }
        .container {
            width: 300px;
            height: 600px;
            border: 10px solid red;
            background-color:  #dedede;
            float: left;
        }
        .container .square {
            width: 100px;
            height: 100px;
            background-color: #2086cf;
            margin: -10px 0 0 -10px; 
        }
        textarea {
            margin-left: 50px;
            width: 800px;
            height: 400px;
            background-color: #464646;
            font-family: monospace;
            color: white;
        }
        .bar {
            width: 2px;
            height: 30px;
            display: inline-block;
            margin-left: 2px;
            background-color: pink;
        }
    </style>
</head>
<body>

<div class="container">
    <div class="square"></div>

    <div class="bar"></div>
    <div class="bar"></div>
    <div class="bar"></div>
    <div class="bar"></div>
    <div class="bar"></div>
    <div class="bar"></div>
    <div class="bar"></div>
</div>

<textarea></textarea>


<script src="interactions.js"></script>
</body>
</html>

만지작거리다

https://jsfiddle.net/matp/9bhjkLct/5/

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

반응형