Запретить onmouseout при наведении на дочерний элемент родительского абсолютного div БЕЗ jQuery - PullRequest
143 голосов
/ 15 января 2011

У меня проблемы с функцией onmouseout в абсолютном позиционном div.Когда мышь попадает в дочерний элемент в div, происходит событие mouseout, но я не хочу, чтобы оно срабатывало, пока мышь не вышла из родительского элемента, абсолютный div.

Как я могу предотвратить mouseoutсобытие от запуска, когда оно попадает в дочерний элемент БЕЗ jquery.

Я знаю, что это как-то связано с пузырями событий, но мне не повезло узнать, как это решить.

Я нашел похожий пост здесь: Как отключить события mouseout, запускаемые дочерними элементами?

Однако это решение использует jQuery.

Ответы [ 19 ]

91 голосов
/ 07 июня 2015

Использование onmouseleave.

Или, в jQuery, используйте mouseleave()

Это именно то, что вы ищете. Пример:

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

или, в jQuery:

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

пример: здесь .

87 голосов
/ 15 января 2011
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/

ПРИМЕЧАНИЕ что это проверяет только непосредственного родителя, если у родительского 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, РЕДАКТИРОВАТЬ обновленная ссылка

83 голосов
/ 17 сентября 2013

Для более простого чистого CSS-решения , которое работает в некоторых случаях ( IE11 или новее ), можно удалить детские pointer-events, установив для них значение none

.parent * {
     pointer-events: none;
}
27 голосов
/ 30 октября 2012

Вот более элегантное решение, основанное на том, что было ниже. это объясняет всплеск событий от более чем одного уровня детей. Он также учитывает проблемы с несколькими браузерами.

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);
12 голосов
/ 02 июня 2012

Спасибо Амджаду Масаду, который вдохновил меня.

У меня есть следующее решение, которое, кажется, работает в 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
    }
12 голосов
/ 07 мая 2014

Если вы используете jQuery, вы также можете использовать функцию "mouseleave", которая справится со всем этим для вас.

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

do_something сработает, когда мышь войдет в цель или любой из ее дочерних элементов., do_something_else срабатывает только тогда, когда мышь покидает цель и любого из ее дочерних элементов.

7 голосов
/ 18 июня 2013

Попробуйте mouseleave()

Пример:

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

   </div>
</div>

;)

6 голосов
/ 15 января 2011

Я думаю, что Quirksmode имеет все ответы, которые вам нужны (различные всплывающие окна браузеров и события mouseenter / mouseleave ), но я думаю, что наиболее распространенный вывод к этому беспорядку всплывающих событий - это использование фреймворка, такого как JQuery или Mootools (который имеет события mouseenter и mouseleave , которые в точности соответствуют тому, что вы интуитивно понимали).

Посмотрите, как они это делают, если хотите, сделайте это сами
или вы можете создать свою собственную версию "скупого среднего" Mootools только с частью события (и его зависимостями).

5 голосов
/ 26 декабря 2012

Я нашел очень простое решение,

просто используйте событие onmouseleave = "myfunc ()", чем событие onmousout = "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>

Надеюсь, это поможет:)

1 голос
/ 28 мая 2019

вместо onmouseout используйте onmouseleave.

Вы не показали нам свой конкретный код, поэтому я не могу показать вам на вашем конкретном примере, как это сделать.

Но это очень просто: просто замените onmouseout на onmouseleave.

Вот и все :) Итак, все просто:)

Если вы не уверены, как это сделать, см. Объяснение:

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

Мир торта :) Наслаждайтесь:)

...