Ответ 1
(Полностью изменил мой страшный ответ. Повторите попытку.)
Предположим, что у вас есть следующие базовые методы кросс-браузера:
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, но затем проверьте наличие двух важных данных:
- Целевой объект - это правый элемент (или дочерний элемент правильного элемента)
- Связанный с событиемTarget не является дочерним объектом цели
Поэтому нам также нужна функция, которая проверяет, является ли один элемент дочерним другой:
function contains(container, maybe) {
return container.contains ? container.contains(maybe) :
!!(container.compareDocumentPosition(maybe) & 16);
}
Последний "gotcha" - это то, как мы удаляем прослушиватель событий. Самый быстрый способ чтобы реализовать это, просто вернув новую функцию, которую мы добавляем.
Итак, у нас получилось что-то вроде этого:
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, но проверяя, настроен ли вы на правильный элемент, и если связанная цель - это ребенок цели.