2008-12-08 5 views
95

Опишите проблему подробно:Как отключить события мыши, вызванные дочерними элементами?

Я хочу показать абсолютное положение div при наведении указателя мыши на элемент. Это очень просто с jQuery и работает отлично. Но когда мышь переходит через один из дочерних элементов, она запускает событие mouseout из содержащего div. Как заставить javascript запускать событие mouseout содержащего элемента при зависании дочернего элемента.

Какой лучший и самый короткий способ сделать это с помощью jQuery?

Вот упрощенный пример, чтобы проиллюстрировать, что я имею в виду:

Html:

<a>Hover Me</a> 
<div> 
    <input>Test</input> 
    <select> 
    <option>Option 1</option> 
    <option>Option 2</option> 
    </select> 
</div> 

Javascript/JQuery:

$('a').hover(function() { $(this).next().show() } 
       function() { $(this).next().hide() }); 
+0

[Без версии jQuery] (http://stackoverflow.com/q/4697758/2065702) этого вопроса – 2016-02-09 20:49:18

ответ

195

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

Самый простой способ сделать это с последними версиями JQuery является использование mouseenter и mouseleave события, а не mouseover и mouseout.

Вы можете проверить поведение быстро с:

$(".myClass").on({ 
    'mouseenter':function() { console.log("enter"); }, 
    'mouseleave':function() { console.log("leave"); } 
}); 
18

Ради простоты, я бы просто реорганизовать HTML ~ бит, чтобы поместить вновь отображаемый контент внутри элемента, к которому привязано событие привязки:

<div id="hoverable"> 
    <a>Hover Me</a> 
    <div style="display:none;"> 
    <input>Test</input> 
    <select> 
     <option>Option 1</option> 
     <option>Option 2</option> 
    </select> 
    </div> 
</div> 

Тогда вы могли бы сделать что-то вроде этого:

$('#hoverable').hover(function() { $(this).find("div").show(); }, 
         function() { $(this).find("div").hide(); }); 

Примечание: Я не рекомендую встроенный CSS, но это было сделано, чтобы сделать пример легче переваривается.

+0

T его действительно очень простое и чистое решение. Спасибо за напоминание. Но в моей конкретной ситуации, которая не совсем такая, как в вопросе, это вариант nog. Спасибо хоть! – 2008-12-08 20:51:21

+0

После того как вы попробовали разные методы, описанные другими здесь, в SO, я вернулся к вашему методу и сделал его работу в моем случае. Ура! :-) – 2008-12-09 17:13:48

0

Способ, которым я обычно рассматривал эту обработку, заключается в задержке около 1/2 секунды между перемещением мыши из элемента HoverMe. При перемещении мыши в наведенный элемент вам нужно установить некоторую переменную, которая сигнализирует о том, что вы нависаете над элементом, а затем в основном остановите зависающую часть от скрытия, если эта переменная установлена. Затем вам нужно добавить аналогичную функцию скрытия OnMouseOut из зависающего элемента, чтобы она исчезла при удалении мыши. Извините, я не могу дать вам какой-либо код или что-то более конкретное, но я надеюсь, что это укажет вам в правильном направлении.

+0

Да, я только что реализовал такое решение. Это очень распространенная проблема. Мне действительно интересно, какое другое решение есть ... Спасибо за ответ! – 2008-12-08 20:45:07

3

Я просто проверяю, находится ли координата мыши вне элемента в событии mouseout.

Это работает, но это много кода для такой простой вещи :(

function mouseOut(e) 
{ 
    var pos = GetMousePositionInElement(e, element); 
    if (pos.x < 0 || pos.x >= element.size.X || pos.y < 0 || pos.y >= element.size.Y) 
    { 
     RealMouseOut(); 
    } 
    else 
    { 
     //Hit a child-element 
    } 
} 

Код вырублен для удобства чтения, не будет работать из коробки.

+0

Хм я тоже думал об этом. Он чувствует себя немного грязным ... но это очень прямолинейно. – 2008-12-08 20:47:29

7

Вы ищете JQuery эквивалент в JavaScript предотвращения пузырения событий

Проверьте это:.

http://docs.jquery.com/Events/jQuery.Event#event.stopPropagation.28.29

В основном вам нужно поймать событие в дочерних узлах DOM и остановить их распространение в дереве DOM. Другой способ, хотя на самом деле не предлагается (поскольку он может серьезно нарушать существующие события на вашей странице), заключается в том, чтобы установить захват событий на определенный элемент на странице, и он получит все события. Это полезно для поведения DnD и т. Д., Но определенно не для вашего случая.

+0

Я всегда знал, что это должен быть чистый способ сделать это, но я не могу заставить его работать. Изучит документы лучше. Благодаря! – 2008-12-08 20:49:05

+0

это работает так, как должно, не знаю, почему вы не могли заставить его работать .. просто информация, ссылка на документы изменилась, новая ссылка http://docs.jquery.com/Events/jQuery.Event # event.stopPropagation.28.29 – zappan 2009-03-02 11:02:18

1

Я согласен с Райаном.

Ваша проблема в том, что «следующий» div не является «дочерним» из A. Невозможно, чтобы HTML или jQuery знали, что ваш элемент «a» связан с дочерним div в DOM. Обертывание их и наложение зависания на обертку означает, что они связаны.

Обратите внимание, что его код не соответствует лучшим практикам. Не устанавливайте скрытый стиль внутри элементов; если пользователь имеет CSS, но не javascript, элемент будет скрыт и не сможет быть показан. Лучшая практика заключается в том, чтобы поместить это объявление в событие document.ready.

0

Это старый вопрос, но он никогда не устаревает. Правильный ответ должен быть указан bytebrite.

Я хотел бы только указать разницу между mouseover/mouseout и mouseenter/mouseleave. Вы можете прочитать полезное объяснение here (перейдите в самую нижнюю часть страницы для рабочей демонстрации). Когда вы используете mouseout, событие останавливается, когда мышь входит в другой элемент, даже если это дочерний элемент. С другой стороны, когда вы используете mouseleave, событие не запускается, когда мышь контролирует дочерний элемент, и это поведение, которое OP хотел бы достичь.

8

Yeap, ребята, использовать .mouseleave вместо .mouseout:

$('div.sort-selector').mouseleave(function() { 
    $(this).hide(); 
}); 

Или даже использовать его в сочетании с live:

$('div.sort-selector').live('mouseleave', function() { 
    $(this).hide(); 
}); 
0

Я решил эту проблему, добавив pointer-events: none; на моих дочерних элементов CSS

Смежные вопросы