Як відключити події миші, викликані дочірніми елементами?


107

Докладно опишіть проблему:

Я хочу показати абсолютний розміщений div при наведенні на елемент. З jQuery це дуже просто і працює чудово. Але коли миша переходить один з дочірніх елементів, вона запускає подію, що міститься в діві, що містить. Як запобігти тому, щоб javascript запускав подію елемента, що містив елемент, що міститься, при наведенні на нього дочірнього елемента.

Який найкращий і найкоротший спосіб зробити це за допомогою 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() } );

1
Без версії jQuery цього питання
Зак Сосьє

Відповіді:


209

Питання трохи старе, але я натрапив на це днями.

Найпростіший спосіб зробити це з останніми версіями jQuery - це використовувати mouseenterта mouseleaveподії, а не mouseoverта mouseout.

Ви можете швидко перевірити поведінку за допомогою:

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

4
Допоміг мою проблему, пов’язану з JavaScript. Я використовував mouseenter / mouseout замість mouseleave зі своїми слухачами подій!
Джо Е.

1
Для пошуку, ці події миші події еквівалентні ROLL_OVERта ROLL_OUTв AS3.
Джефф Уорд

2
Врятував мені деякі головні болі. Як не дивно, як наведення на дочірні елементи запускає батьківську mouseoutподію, коли насправді вона все ще знаходиться у батьківському елементі.
javiniar.leonard

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, але це було зроблено, щоб приклад легше засвоювався.


Це дійсно дуже просте і чисте рішення. Дякую, що нагадали. Але в моїй конкретній ситуації, що не зовсім так, як у питанні, це варіант. Дякую, хоча!
Сандер Верслейс

Спробувавши різні методи, як описано іншими тут, в SO, я повернувся до вашого методу і змусив його працювати в моєму випадку. Так! :-)
Сандер Верслуйс

11

Хлопці, хлопці, використовуйте .mouseleaveзамість .mouseout:

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

Або навіть використовувати його в поєднанні з live:

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

8

Ви шукаєте еквівалент jQuery для запобігання подій, що запобігають події Javascript.

Заціни:

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

По суті, вам потрібно зафіксувати подію в дитячих вузлах DOM, і там зупинити їх розповсюдження вгору по дереву DOM. Інший спосіб, хоча насправді не пропонується (оскільки він може сильно зіпсуватись із існуючими подіями на вашій сторінці), - встановити захоплення подій певним елементом на сторінці, і він отримає всі події. Це корисно для поведінки DnD та іншого, але точно не для вашого випадку.


це працює як слід, не знаю, чому ви не могли змусити його працювати .. просто інформація, посилання на документи змінилося, нове посилання - docs.jquery.com/Events/jQuery.Event#event.stopPropagation. 28.29
запан

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

Вирізаний код для читабельності не вийде з поля.


1

Я згоден з Райаном.

Ваша проблема полягає в тому, що "наступний" div не є "дитиною" від A. Немає можливості для HTML або jQuery знати, що ваш елемент "a" пов'язаний з дочірнім ділом у DOM. Обгортання їх та наведення наведення на обертку означає, що вони пов’язані.

Зауважте, що його код не відповідає найкращим практикам. Не встановлюйте прихований стиль накреслення елементів; якщо у користувача є CSS, але не JavaScript, елемент буде приховано і не зможе бути показаний. Кращою практикою є внесення цієї декларації до події документ.


Я повністю згоден з тим, щоб розмістити приховування у документі. Вбудований css був просто передати повний робочий приклад найпростішим можливим способом. Я відредагую свою відповідь, щоб зробити це зрозумілим.
Райан Макгірі

1

Я вирішив цю проблему, додавши pointer-events: none;в свою дитину елементи css


Це дійсно дуже допомогло, коли виправляли застарілий код, створюючи власні попури з подіями миші та миші
CM

0

Як я зазвичай бачив цю обробку, це затримка приблизно на 1/2 секунди між переміщенням миші від елемента HoverMe. Під час переміщення миші в елемент, що наближається, ви хочете встановити певну змінну, яка сигналізує про те, що ви навісаєте елемент, а потім, в основному, зупинити заховану частину від приховування, якщо ця змінна встановлена. Тоді вам доведеться додати аналогічну функцію приховування OnMouseOut від наближеного елемента, щоб зникнути при видаленні миші. Вибачте, я не можу надати вам жодного коду чи чогось більш конкретного, але сподіваюся, що це направить вас у правильному напрямку.


Так, idd Я щойно реалізував таке рішення. Це дійсно поширена проблема. Мені дуже цікаво, яке ще рішення є ... Дякую за відповідь!
Сандер Верслуйс

0

Це старе питання, але воно ніколи не застаріло. Правильна відповідь повинна бути тією, що дається bytebrite .

Я хотів би лише зазначити різницю між mouseover / mouseout та mouseenter / mouseleave. Ви можете прочитати чудове та корисне пояснення тут (перегляньте робочу демонстрацію в самій нижній частині сторінки). Під час використання mouseoutподія припиняється, коли миша вводить інший елемент, навіть якщо це дочірній елемент. З іншого боку, коли ви використовуєте mouseleave, подія не спрацьовує, коли миша перевершує дочірній елемент, і це поведінка, яку хотів би досягти ОП.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.