Борьба с наследованием события onmousemoveОтсебятина от 29 декабря 2008 года. Теги: Javascript HTML
Наконец добрался до captcha.kreker.org, чтобы переделать линейный бар навигации (пейджер). Планировалось изменить его внешний вид и добавить ползунок, на котором у меня и начались проблемы — в браузере IE, из-за наследования события onmousemove элементом ползунка, передавались координаты именно с его области (от 1 до 6, в размер ползунка), из-за этого ползунок прыгал в начало координат бара. Причем устаревший cancelBubble не помог, а stopPropagation не поддерживает даже 7 IE. Решение оказалось довольно простым.
А теперь подробней о проблеме.
Имеется ползунок:
Его HTML-код:
<div onmousemove="move(event)" class="pagebar" id="pager">
<div class="butbar" id="curs"></div>
</div>
Внутренний div — это ползунок, внешний — сам бар. Когда мы проводим по нему мышью, то передается событие в функцию move:
function move(e) {
e = (!e) ? window.event : e; //Для 6 IE события для отдельного элемента не существует. Есть только событие окна.
X = e.pageX || e.x; //Для IE & Opera x, для Firefox — pageX
//X — координата. Для IE относительно бара, для Firefox & Opera — относительно оси координат страницы
}
Далее я буду подразумевать, что в функцию move передаются координаты, а не объект.
Все прекрасно передается и вычисляется, но когда мы начинаем вести ползунок вправо, то курсор попадает в область элемента ползунка. В Firefox и Opera ползунок продолжает двигаться по траектории вправо, а вот в IE происходит резкий скачек ползунка в начало бара к координатам 1-6 относительно оси бара. Дело в том, что элемент ползунка наследует событие onMousemove у родителя-бара, но ось координат-то у него своя! И когда курсор попадает на ползунок, то передает в move свои координаты относительно оси координат ползунка, которые находятся в пределах от 1 до 6 (размеры ползунка 6x6px). Функция принимает их и кидает его в эти же координаты, только относительно оси координат бара, поэтому ползунок оказывается слева.
И в Firefox, и в Opera такого не происходит по простой причине — координаты курсора передаются относительно общей координатной оси страницы, то есть от левого края.
Первая мысль — запретить наследование событий для ползунка. Ранее для этого действа использовось свойство cancelBubble объекта event. Теперь — метод stopPropagation(). Но, на удивление, ни один из них не исправил ситуацию. Ползунок по-прежнему скачет как молодой жеребец.
Выкрутиться из ситуации, на первый взгляд, довольно просто. Необходимо прибавлять к переданным координатам от ползунка уже установленные его координаты. Определить, когда координаты передаются от ползунка можно несколькими способами. Самый интересный из них — свойство event.target. Оно передает объект, от которого пришло событие. С помощью id объекта можно идентифицировать, что перед нами ползунок. Но это свойство, к сожалению, не доступно в IE.
Чтобы понять, откуда приходит событие, необходимо задавать функцию с разными параметрами на событие каждому элементу:
<div onmousemove="move(event, false)" class="pagebar" id="pager">
<div onmousemove="move(event, true)" class="butbar" id="curs"></div>
</div>
В саму функцию move добавляем:
function move(e, bool) {
....
if (bool == true && navigator.userAgent.indexOf("MSIE") > 0)
X += Number(document.getElementById("curs").style.left.replace('px', ''));
Таким образом, когда курсор наводится на ползунок, то координаты с ползунка прибавляются к раннее ему установленным, и он продвигается вправо.
Но это решение не работает в одиночку, а оно работает в купе с cancelBubble!
function move(e, bool) {
e = (!e) ? window.event : e;
e.cancelBubble = true;
X = e.pageX || e.x;
if (bool == true && navigator.userAgent.indexOf("MSIE") > 0)
X += Number(document.getElementById("curs").style.left.replace('px', ''));
if (navigator.userAgent.indexOf("MSIE") < 0)
X -= document.getElementById("pager").offsetLeft; //Вычитаем смещение элемента относительно левого края страницы у браузеров, отличных от IE
....
}
Вот так бывает. С одной стороны программеры Microsoft пошли на уступок — нет необходимости вычитать смещение элемента, чтобы вычислить положение курсора в нем, а с другой — сделали головную боль. Возможно, и в неумелых моих руках.
|