MouseOver / MouseOut EventListener, наследующий дочерние узлы? - PullRequest
4 голосов
/ 06 декабря 2011

Редактировать: Решение

Спасибо Габи за помощь в поиске решения! Не совсем так, как я хотел, нашел лучшее решение, измененное из ответов. Я выполняю только функции mouseover / mouseout, когда два элемента (цель и связанная цель) не имеют общего родительского элемента .

Просто немного изменил пример Габи и все отлично работает. Пока ваше всплывающее окно находится в том же элементе div, что и любой другой, вызывающий его (даже если оно находится вне основного содержимого, вы можете добавить его с видимым переполнением), и вы не переходите между нераспространенными элементами на пути к нему, оно останусь в живых.

divContents.addEventListener('mouseover', mouseEnter(showPopup, divContents));
divContents.addEventListener('mouseout', mouseEnter(hidePopup, divContents));

Теперь модифицированный mouseEnter ...

function mouseEnter(_fn, _parent) {
    return function(_evt) {
        if(!shareParent(_evt.target, _evt.relatedTarget, _parent)) {
            _fn.call(this, _evt);  
        }
    }
};

function shareParent(_object1, _object2, _parent) {
    if (_object1 === _object2) { 
        return true;
    }
    while (_object1 && _object1 !== _parent) {
        _object1 = _object1.parentNode;
    }
    while (_object2 && _object2 !== _parent) {
        _object2 = _object2.parentNode;
    }

    return _object1 === _object2;
}

Решил мою проблему. Хорошо, потому что то, что я хочу запустить для событий mouseover и mouseout, произойдет только тогда, когда элементы не имеют общего родителя - именно так, как я намеревался при отображении всплывающих окон в любом случае.

Еще раз спасибо за пример кода от Gaby!

ПРИМЕЧАНИЕ: Нет проверки ошибок для родительской действительности в функции shareParent, не проверял, но он всегда должен возвращать true, когда достигает вершины дерева (при условии, что _parent на самом деле не родитель либо _object1 или _object2). Поэтому убедитесь, что родительский объект, который вы передаете ему, действителен.

Оригинальный вопрос:

У меня сейчас проблема с JavaScript.

Я пытаюсь создать элемент div, который динамически всплывает при наведении мыши. Div создается непосредственно рядом с объектом, который его порождает.

divCreator.addEventListener('mouseover', createPopup, true);
divCreator.addEventListener('mouseout', hidePopup, true);

Это создает всплывающее окно. Теперь, во всплывающем окне, когда я его создаю, я запускаю его перед тем, как добавить его в документ:

divPopup.addEventListener('mouseover', createPopup, true);
divPopup.addEventListener('mouseout', hidePopup, true);

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

Однако, с помощью этого метода, когда я нахожу курсор мыши на дочерний элемент, он обнаруживает событие mouseout от родительского элемента (divPopup) и закрывает div.

Можно ли, так сказать, сделать детей "прозрачными" для событий?

1 Ответ

6 голосов
/ 06 декабря 2011

Это событие обрабатывается двумя событиями.

Документы mouseenter W3 DOM3 и mouseleave W3 DOM3 документы но в настоящее время они находятся в рабочем проекте DOM3 Events .

Они были представлены Microsoft IE5.5, и Firefox добавил поддержку в v10.


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

код, адаптированный с http://blog.stchur.com/2007/03/15/mouseenter-and-mouseleave-events-for-firefox-and-other-non-ie-browsers/

divCreator.addEventListener('mouseover', mouseEnter(createPopup), true);
divCreator.addEventListener('mouseout', mouseEnter(hidePopup), true);


function mouseEnter(_fn)
{
   return function(_evt)
   {
      var relTarget = _evt.relatedTarget;
      if (this === relTarget || isAChildOf(this, relTarget))
         { return; }

      _fn.call(this, _evt);
   }
};

function isAChildOf(_parent, _child)
{
   if (_parent === _child) { return false; }
      while (_child && _child !== _parent)
   { _child = _child.parentNode; }

   return _child === _parent;
}

Демонстрация на http://jsfiddle.net/gaby/jMvHv/ ( откройте консоль для сообщений журнала )

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