07.03.2009, 06:13
|
Новичок на форуме
|
|
Регистрация: 16.08.2008
Сообщений: 9
|
|
Opera/IE баг с очередью обработки события несколькими элементами (напр onmouseover)
Нашел такой баг - если в ячейке таблицы есть внутри элементы, например, div, который занимает всю ячейку TD и для td задана функция onmouseover, а для div не задана нигде и никак, то в процессе обработки этой функции onmouseover в ней каким то чудом в качестве Event.srcElement фигурирует div хотя для него, повторюсь, не была никоим образом задана функция onmouseover. Этот баг есть и в ИЕ и в Опере, в опере он я бы сказал пожесче.
элементы кода:
так выглядит ячейка таблицы:
<td><div class="rc"><div class="dgr" onclick="f1(...);">X</div>123<br><b>Текст1</b><br>Текст2</div></td>
onmouseover всем ячейкам таблицы задает функция так (срабатывает при загрузке страницы):
в цикле пробегаем по всем ячейкам и
<цикл>
...
if(td.attachEvent) {
td.attachEvent('onmouseover', HighLightTD); td.attachEvent('onmouseout', HideTD);
}
if(td.addEventListener) {
td.addEventListener('mouseover', HighLightTD, true); td.addEventListener('mouseout', HideTD, true);}
...
Функции HighLigtTD и HideTD соотв подсвечивают или убирают подсветку с ячейки таблицы. Но не только. Подсветка/Хайд изначальна в Опере тоже глючили из-за описываемого бага. Но с этим я справился. Самый главный баг в том что функции HighLightTD/HideTD срабатывают и на наведение на внутренний div ячейки таблицы, хотя для них не устанавливались. Создается впечатление что это наследование внутренним дивом функции onmouseover ячейки таблицы td.
Ну для большей ясности
function HighLightTD(e)
{
if(!e) var e = window.event;
if(e.srcElement) td = e.srcElement; else td = e.currentTarget;
// !! для проверки делаем алерт
alert(td.tagName);
// и в этом алерте какимто чудом появится DIV хотя, повторюсь, на DIV эта функция не вешалась
...
}
итак:
<td onmouseover=...> <div> .. </div> </td>
наводим мышку на td сначала будет алерт с тэгом TD, а после сразуже с DIV
Помогите с этим разобраться, как исключить обработку события onmouseover для внутреннего div'a ячейки таблицы?
Да в Файрфокс всё прекрасно работает.
Последний раз редактировалось no., 07.03.2009 в 06:14.
Причина: дополнение
|
|
07.03.2009, 12:56
|
...
|
|
Регистрация: 13.10.2008
Сообщений: 225
|
|
Почитайте статью про события мыши на этом сайте, там упоминается об этом.
|
|
07.03.2009, 13:24
|
Новичок на форуме
|
|
Регистрация: 19.02.2008
Сообщений: 9,177
|
|
Одну из самых нужных особенностей DOM назвать багом -- это сильно
|
|
07.03.2009, 14:27
|
Новичок на форуме
|
|
Регистрация: 16.08.2008
Сообщений: 9
|
|
Багом называю потому как привык к самой правильной и ожидаемой, в большинстве случаев, обработке ХТМЛ/ДОМ/Ява со стороны ФайрФокс. И в этом случае он работает ожидаемо и правильно ИМХО. Не подскажите конкретную статейку? Я в общем то знаком более-менее с этой темой, и перед созданием темы поискал похожее но ответов не нашел :\
|
|
07.03.2009, 14:36
|
...
|
|
Регистрация: 13.10.2008
Сообщений: 225
|
|
Порядок срабатывания событий, а вообще было бы полезно всю статью прочитать для понимания механизма.
|
|
07.03.2009, 15:23
|
Новичок на форуме
|
|
Регистрация: 16.08.2008
Сообщений: 9
|
|
Уже прочитал и в общем-то этот механизм я знал (читал до этого на английском поэтому статья на русском + хорошо сделанные примеры более объяснили некоторые тонкости), НО! Это помогло понять более точнее природу БАГа в Опере, но всё же не то как этот баг победить. Баг тут, имхо, заключается в том что событие onmouseover родительского элемента срабатывает, затем срабатывает onmouseover дочернего и тут же - onmouseout родительского (такое впечатление) как будто бы событие дойдя до потомка (всплытие - bubble) ввело "мышь" в заблуждение, и она "подумала" что она уже ушла с элемента-родителя TD и запустился обработчик onmouseout. Это даже заметно - подсветка мелькает и тут же пропадает! Если сделать обычную подсветку бэкграунда родительского элемента, с учетом его текущего цвета (т.е. при подсветке (onmouseover) сохранять текущий цвет фона родителя, а потом его восстанавливать onmouseout) Вы увидите этот баг, т.к.
1. onmouseover - сделали цвет фона родителя color_new, сохранили цвет родителя в last_color
2. идет второй onmouseover, для внутреннего дива (как на этом этапе выявить что srcElement не тот что нам нужен и пропустить обработку функции? проверка srcElement.tagName как-то не помогает, это один важный вопрос, но его можно, при решении вопроса с подсветкой, обойти по-другому)
3. тут же срабатывает onmouseout для родителя (TD) - родителю вернули его старый цвет last_color
В итоге пробегаясь по таблице где в каждой ячейке есть внутренний див, который и делает этот баг, у нас ничего не подсвечивается - иногда заметно как ячейка очень быстро моргает, подсвечивается и тут же пропадает подсветка.
Я не могу понять почему происходит этот onmouseout когда мышь еще находится на элементе? Не баг ли это?
Последний раз редактировалось no., 07.03.2009 в 15:29.
|
|
07.03.2009, 15:51
|
Новичок на форуме
|
|
Регистрация: 16.08.2008
Сообщений: 9
|
|
Еще раз подумав: самый главный вопрос
из статьи:
Цитата:
|
При установке обработчиков методами attachEvent/detachEvent this внутри обработчика всегда указывает на объект window и совершенно бесполезен.
Поэтому при использовании этих методов в библиотеках и фреймворках добавляется дополнительная "обертка для обработчика", устанавливающая правильный this.
|
Как эта обертка делается? что-то вроде того: el.attachEvent('event', function(e) { f1(e, el); }); ?
|
|
07.03.2009, 20:35
|
|
|
Регистрация: 21.02.2008
Сообщений: 1,250
|
|
Сообщение от no.
|
Как эта обертка делается?
|
Я использую такую обертку:
/**
* Объявляем и сразу вызываем функции,
* чтоб не проверять поддержку методов
* каждый раз:
*/
var addEventListener = function() {
// Если браузер IE:
if (window.attachEvent)
// Возвращаем функцию для IE:
return function(element, event, callback) {
// Фиксуем callback, чтоб установить правильный
// this, и передавать объект события первым параметром:
callback.__callbackfix = function() {
callback.call(element, window.event);
};
// Устанавливаем обработчик (не забываем про "on")
return element.attachEvent("on" + event, callback.__callbackfix);
}
// Если браузер W3C-совместим:
if (window.addEventListener)
// Возвращаем функцию без фиксов:
return function(element, event, callback) {
// Последний параметр всегда false, для совместимости с IE:
return element.addEventListener(event, callback, false);
}
}();
var removeEventListener = function() {
// Если браузер IE:
if (window.detachEvent)
return function(element, event, callback) {
// Удаляем наш сохраненный в функции фикс:
return element.detachEvent("on" + event, callback.__callbackfix);
}
// Если браузер W3C-совместим:
if (window.addEventListener)
return function(element, event, callback) {
// Удаляем без фиксов:
return element.removeEventListener(event, callback, false);
}
}();
Он избавляет от всех проблем несовместимости, кроме тех, которые связаны с различными свойствами объекта события.
Но теперь, по крайней мере, в IE будет возможность удалять callback с фиксом "прозрачно".
Последний раз редактировалось Андрей Параничев, 07.03.2009 в 21:34.
|
|
08.03.2009, 04:55
|
Новичок на форуме
|
|
Регистрация: 16.08.2008
Сообщений: 9
|
|
Всем спасибо вроде разобрался с проблемой.
Для оперы просто изменил проверку на srcElement и поставил его на второе место, а на первое место currentTarget, который у последней оперы есть (давно ли?). А вот для IE пришлось делать обертку по типу того что я писал и Андрей Параничев, и вставлять в функцию оригинальный элемент вызова функции, т.е. TD + помогла статья с замыканиями.
Тему вроде можно закрывать.
|
|
|
|