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

Опишу проблему подробнее:

Я хочу показывать абсолютное позиционирование 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() } );
Без версии jQuery этого вопроса
Zach Saucier 09.02.2016 23:49
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
108
1
57 163
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Для простоты я бы просто немного реорганизовал html, чтобы поместить вновь отображаемый контент внутри элемента, к которому привязано событие mouseover:

<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, но это было сделано для облегчения восприятия примера.

Это действительно очень простое и понятное решение. Спасибо за напоминание. Но в моей конкретной ситуации, которая не совсем такая, как в вопросе, это не вариант. Спасибо хоть!

Sander Versluys 08.12.2008 23:51

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

Sander Versluys 09.12.2008 20:13

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

Да, idd, я только что реализовал подобное решение. Это действительно распространенная проблема. Мне действительно любопытно, какие еще есть решения ... Спасибо за ответ!

Sander Versluys 08.12.2008 23:45

Я просто проверяю, находятся ли координаты мыши вне элемента в событии 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
    }
}

Код урезан для удобочитаемости, из коробки не получится.

Вы ищете 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

zappan 02.03.2009 14:02

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

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

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

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

Ryan McGeary 09.12.2008 20:18
Ответ принят как подходящий

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

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

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

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

Помогла моя проблема, связанная с javascript, не связанная с jquery. Я использовал mouseenter / mouseout вместо mouseleave с моими слушателями событий!

Jo E. 03.02.2015 18:15

Для целей поиска это поведение событий мыши эквивалентно ROLL_OVER и ROLL_OUT в AS3.

Jeff Ward 14.09.2015 17:49

Избавило меня от головной боли. Странно, как при наведении курсора на дочерние элементы запускается родительское событие mouseout, хотя на самом деле оно все еще находится внутри родительского элемента.

javiniar.leonard 16.10.2015 11:20

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

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

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

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

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

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

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

Это действительно очень помогло при исправлении устаревшего кода, создающего собственные всплывающие окна с событиями mouseover и mouseleave.

C.M. 24.05.2018 20:32

Другие вопросы по теме