мышиный центр без JQuery - PullRequest
13 голосов
/ 26 мая 2011

Каков наилучший способ реализовать событие типа mouseenter / mouseleave в Javascript без jQuery? Какова лучшая стратегия для кросс-браузерного использования? Я имею в виду какую-то проверку свойства event.relatedTarget / event.toElement в обработчиках событий mouseover / mouseout?

Хотелось бы услышать ваши мысли.

Ответы [ 4 ]

14 голосов
/ 26 мая 2011

(полностью изменил мой ужасный ответ. Давайте попробуем еще раз.)

Предположим, у вас есть следующие базовые кросс-браузерные методы событий:

var addEvent = window.addEventListener ? function (elem, type, method) {
        elem.addEventListener(type, method, false);
    } : function (elem, type, method) {
        elem.attachEvent('on' + type, method);
    };

var removeEvent = window.removeEventListener ? function (elem, type, method) {
        elem.removeEventListener(type, method, false);
    } : function (elem, type, method) {
        elem.detachEvent('on' + type, method);
    };

(Довольно просто, я знаю.)

Всякий раз, когда вы реализуете mouseenter / mouseleave, вы просто прикрепляете события к обычные события mouseover / mouseout, но затем проверьте две важные детали:

  1. Целью события является правильный элемент (или дочерний элемент правого элемента)
  2. RelatedTarget события не является дочерним для цели

Итак, нам также нужна функция, которая проверяет, является ли один элемент дочерним другой

function contains(container, maybe) {
    return container.contains ? container.contains(maybe) :
        !!(container.compareDocumentPosition(maybe) & 16);
}

Последняя «ошибка» - это то, как мы удалили слушатель события. Самый быстрый способ реализовать его можно, просто вернув новую функцию, которую мы добавляем.

Таким образом, мы получаем что-то вроде этого:

function mouseEnterLeave(elem, type, method) {
    var mouseEnter = type === 'mouseenter',
        ie = mouseEnter ? 'fromElement' : 'toElement',
        method2 = function (e) {
            e = e || window.event;
            var target = e.target || e.srcElement,
                related = e.relatedTarget || e[ie];
            if ((elem === target || contains(elem, target)) &&
                !contains(elem, related)) {
                    method();
            }
        };
    type = mouseEnter ? 'mouseover' : 'mouseout';
    addEvent(elem, type, method2);
    return method2;
}

Добавление события mouseenter будет выглядеть так:

var div = document.getElementById('someID'),
    listener = function () {
        alert('do whatever');
    };

mouseEnterLeave(div, 'mouseenter', listener);

Чтобы удалить событие, вам нужно сделать что-то вроде этого:

var newListener = mouseEnterLeave(div, 'mouseenter', listener);

// removing...
removeEvent(div, 'mouseover', newListener);

Это вряд ли идеально, но все, что осталось, это просто детали реализации. Важной частью было предложение if: mouseenter / mouseleave - это просто mouseover / mouseout, но проверяет, нацелены ли вы на нужный элемент, и если связанная цель является дочерней по отношению к цели.

2 голосов
/ 26 мая 2011

Лучший способ, имхо, - создать свою собственную систему событий.

Несколько лет назад Дин Эдвардс написал один из них, в котором я использовал реплики в прошлом.Однако его решение работает «из коробки».

http://dean.edwards.name/weblog/2005/10/add-event/

1 голос
/ 26 мая 2011

Джон Резиг представил свою заявку на конкурс , в котором его оценили лучшим (Примечание: Дин Эдвардс был одним из членов жюри). Так что, я бы сказал, проверьте это тоже.

Также не повредит переходить время от времени через jQuery, источник DOJO, чтобы увидеть лучшие практики, которые они используют, чтобы заставить его работать в кросс-браузерном режиме.

0 голосов
/ 18 мая 2013

другой вариант состоит в том, чтобы отличать истинные mouseout события от поддельных (порожденных детьми) событий с помощью проверки попадания. Вот так:

elt['onmouseout']=function(evt){
  if (!mouse_inside_bounding_box(evt,elt)) console.debug('synthetic mouseleave');
}

Я использовал что-то подобное в Chrome, и, будьте осторожны, это, похоже, помогло. Если у вас есть надежное событие mouseleave, указатель мыши становится тривиальным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...