Проблемы с событием mouseout
Я использую JavaScript, чтобы скрыть изображение и показать текст, скрытый под ним. Но когда текст показывается, если вы прокручиваете его, он запускает событие mouseout для контейнера, которое затем скрывает текст и снова показывает изображение, и оно просто переходит в странный цикл.
HTML выглядит так:
<div onmouseover="jsHoverIn('1')"
onmouseout="jsHoverOut('1')">
<div id="image1" />
<div id="text1" style="display: none;">
<p>some content</p>
<p>some more content</p>
</div>
</div>
И JavaScript (он использует scriptaculous):
function jsHoverIn(id) {
if(!visible[id]) {
new Effect.Fade ("image" + id, {queue: { position: 'end', scope: id } });
new Effect.Appear ("text" + id, {queue: { position: 'end', scope: id } });
visible[id] = true;
}
}
function jsHoverOut (id) {
var scope = Effect.Queues.get(id);
scope.each(function(effect) { effect.cancel(); });
new Effect.Fade ("text" + id, {queue: { position: 'end', scope: id } });
new Effect.Appear ("image" + id, {queue: { position: 'end', scope: id } });
visible[id] = false;
}
Это кажется действительно простым, но я просто не могу обернуть голову вокруг этого.
6 ответов
Я бы дал контейнер div:
position: relative;
и добавьте третий div в контейнер (должен быть последним дочерним элементом контейнера) с помощью:
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
и вместо этого поймайте события mouseover и mouseout в этом div.
Поскольку у него нет дочерних элементов, вы не должны получать ложные события mouseover и mouseout, распространяющиеся на него.
Редактировать:
Я считаю, что происходит, когда курсор перемещается из родительского элемента в дочерний элемент, событие mouseout происходит в родительском элементе, а событие mouseover - в дочернем элементе. Однако, если обработчик наведения мыши на дочернем элементе не перехватывает событие и не останавливает его распространение, родительский элемент также получит событие mouseover.
Похоже, что вы действительно хотите mouseenter
/mouseleave
(Собственные события IE, но легко подражать):
// Observe mouseEnterLeave on mouseover/mouseout
var mouseEnterLeave = function(e) {
var rel = e.relatedTarget, cur = e.currentTarget;
if (rel && rel.nodeType == 3) {
rel = rel.parentNode;
}
if(
// Outside window
rel == undefined ||
// Firefox/other XUL app chrome
(rel.tagName && rel.tagName.match(/^xul\:/i)) ||
// Some external element
(rel && rel != cur && rel.descendantOf && !rel.descendantOf(cur))
) {
e.currentTarget.fire('mouse:' + this, e);
return;
}
};
$(yourDiv).observe('mouseover', mouseEnterLeave.bind('enter'));
$(yourDiv).observe('mouseout', mouseEnterLeave.bind('leave'));
// Use mouse:enter and mouse:leave for your events
$(yourDiv).observe(!!Prototype.Browser.IE ? 'mouseenter' : 'mouse:enter', yourObserver);
$(yourDiv).observe(!!Prototype.Browser.IE ? 'mouseleave' : 'mouse:leave', yourObserver);
Кроме того, патч prototype.js и использовать mouseenter
а также mouseleave
с уверенностью. Обратите внимание, что я расширил проверку для выхода из окна или ввода XUL Chrome; казалось, это исправило некоторые крайние случаи в Firefox для меня.
Разве событие onmouseover не должно быть в изображении div, а событие onmouseout - в текстовом div?
@Ryan Логическое значение действительно не помогает, оно просто избегает цикла, но событие mouseover по-прежнему запускается, и текст становится скрытым.
@Brian Раньше так и было, но вело себя так же.
Я не уверен, что это будет соответствовать остальной части вашего стиля, но, возможно, если вы изменили CSS на div текста, чтобы он был такого же размера, как изображение, или установили размер внешнего div, то при наведении курсора мыши Событие сработало, размер внешнего div не изменился бы настолько, чтобы вызвать событие mouseout.
Имеет ли это смысл?
Попробуйте использовать onmouseenter вместо onmouseover и onmouseleave вместо onmouseout.
Это может быть не лучшим решением, но вы можете установить глобальную логическую переменную, которая будет доступна обоим методам, которая будет просто указывать, было ли последним действием HoverIn или HoverOut. Вы можете использовать эту логическую переменную, чтобы определить, должен ли код выполняться или нет.
if (bWasHoverIn){
...
}