Отсебятина Статьи Проекты
Облако тегов
Web CMS CSS htaccess HTML Javascript MySQL Php Безопасность Мониторы Новостная лента Оптимизация Ошибки Разработка сайта Часы Юзабилити оптимизация ошибки

Борьба с наследованием события 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 пошли на уступок — нет необходимости вычитать смещение элемента, чтобы вычислить положение курсора в нем, а с другой — сделали головную боль. Возможно, и в неумелых моих руках.

Оставить сообщение






Любое копирование должно сопровождаться ссылкой на сайт.
Если вам что-то не понравилось — сообщайте.
Кича Владимир
x
Мне не нравится этот сайт, удалить его