Отправляет email-рассылки с помощью сервиса Sendsay

Введение в Behaviors

  Все выпуски  

Собственные события мыши.


Информационный Канал Subscribe.Ru

Выпуск 8

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

С одной стороны существуют события onmouseout и onmouseover, которые генерируются как раз тогда, когда мышь покидает элемент или входит в пределы элемента. Но когда web-программист пытается использовать данные события, то он сталкивается с одной проблемой. Поясню на примере. Ниже приведен код тестового html-документа (samp-008-a.html):

<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
  <title>Пример событий onmouseover и onmouseout</title>
 </head>
 <body>
  <table border=1px onmouseover="alert('onmouseover');" onmouseout="alert('omouseout');">
   <tr><td>Первая ячейка</td></tr>
   <tr><td>Вторая ячейка</td></tr>
  </table>
</body>
</html>

samp-008-a.html

Мышь располагается над первой ячейкой. Переведем мышь на вторую ячейку. Казалось бы, мышь не покидала границ строки таблицы (то есть содержимого тега <table>), и события onmouseover и onmouseout не должны генерироваться. Однако, если вы скопируете этот пример в отдельный файл и запустите его, то увидите, что при перемещении с одной ячейки на другую генерируются оба события: onmouseover и onmouseout.

Это события реально генерируются в ячейках таблицы. Когда мышь перемещается из ячейки в ячейку, она сначала покидает одну ячейку и тег <tr>, ее реализующий, генерирует событие onmouseout. Потом мышь заходит на вторую ячейку, и уже вторая ячейка генерирует событие onmouseover. Согласно спецификации DOM (document object model - объектная модель документа), данные события, должны быть обработаны в этом теге, если у тега прописаны собственные обработчики событий. Но самое интересное, что после этого шага, событие передается от вложенного тега (в нашем случае тег <tr>) тегу-контейнеру (в нашем случае тег <table>). Таким образом, события onmouseover и onmouseout, хотя и не генерируются самим тегом <table>, но обработчики этих событий все равно вызываются.

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

Но одна из прелестей html-компонентов как раз и состоит в том, что они позволяют создавать свои собственные события, которые будут обрабатываться так же, как и события, генерируемые браузером. Для того что бы придать html-компоненту возможность генерировать собственные события, в описании html-компонента необходимо указать тег public:event.

И сегодня мы как раз и рассмотрим один html-компонент, который генерирует два события, отмечающие вход и выход мыши в пределы элемента. Назовем их my_mousein и my_mouseout. События не могут возникнуть из ничего - какие-то события должны привести к вызову обработчика события в html-компоненте, и уже в обработчике должно быть сгенерировано собственное событие html-компонента. Таким образом, задача распадается на две подзадачи. Во-первых, необходимо прописать в оглавлении теги public:event, со всеми необходимыми атрибутами (спецификацию на этот тег можно посмотреть здесь). Во-вторых, определить внешние (то-есть генерируемые вне html-компонента) события, служащие для запуска генерации собственных событий и придумать алгоритм их обработки. Ниже приведен листинг этого компонента (my-mouse.htc).

<public:component>
<public:attach event='oncontentready' onevent='event_oncontentready()' />
<public:event id='m_in' name='my_mousein' />
<public:event id='m_out' name='my_mouseout' />
<script language='jscript'>
 function is_child(obj_child)
 {
  if (obj_child == null) return false;
  obj_current = obj_child;
  while (obj_current.tagName != "BODY" && obj_current != null)
  {
   if (obj_current == element)
    return true;
   else
    obj_current = obj_current.parentElement;
  }
  return false;
 }
 function event_onmouseout()
 {
  if (!is_child(window.event.toElement))
   m_out.fire();
 }
 function event_onmouseover()
 {
  if (!is_child(window.event.fromElement))
   m_in.fire();
 }
 function event_oncontentready()
 {
  element.attachEvent("onmouseout", event_onmouseout);
  element.attachEvent("onmouseover", event_onmouseover);
 }
</script>
</public:component>

my-mouse.htc

Весь код компонента разбит на четыре функции. Самой интересной является функция is_child(), которая определяет, является ли объект, переданный данной функции, объектом-потомком элемента, которому назначен html-компонент или нет. В основу этой функции положена очень простая идея: если переданный объект является потомком, то, поднимаясь по дереву элементов от узла потомка к узлу родителю, функция рано или поздно поднимется к данному элементу. Если же переданный объект не является потомком данного элемента, то в конце концов функция поднимется к корню дерева элементов (то есть к тегу BODY) или получит значение null.

Две функции, event_onmouseover() и event_onmouseout(), используются в качестве обработчиков событий onmouseover и onmouseout. При этом функция is_child() используется в обоих случаях для того, что бы отфильтровать те ситуации, когда мышь пересекает пределы элемента. Последняя функция используется только для назначения обработчиков событий event_onmouseover и event_onmouseout.

Для того, что бы Вы смогли поэкспериментировать с этим html-компонентом, ниже приведены листинги каскадной таблицы стилей (samp-008.css) и html-документа (samp-008-b.html).

.my-mouse {behavior: url(my-mouse.htc);}

samp-008.css

<html>
 <head>
  <link rel="stylesheet" href="samp-008.css" type="text/css">
  <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
  <title>Пример обработки собственных событий</title>
 </head>
 <body>
  <table border=3px class='my-mouse' my_mousein="alert('my_mousein');" my_mouseout="alert('my_mouseout');">
   <tr><td>Первая ячейка</td></tr>
   <tr><td>Вторая ячейка</td></tr>
  </table>
  <div id=debug>
  </div>
</body>
</html>

samp-008-b.html

Html-документ, приведенный последнем листинге, в отличии от html-документа, приведенного в начале выпуска, содержит уже обработчики наших событий. Разница в реакции на перемещение мыши очевидна.

Тексты этих листингов необходимо скопировать в соответствующие файлы (смотри подписи) и поместить в одну директорию. В качестве альтернативы можно использовать архив lesson-08.zip, содержащий все файлы, рассмотренные выпуском. В следующем выпуске мы вкратце рассмотрим какие блоки и как будут взаимодействовать, для того, что бы совместно реализовать меню.


Архив рассылки

Автор рассылки

P.S. Рассылка создана в первую очередь для читателя, а уже во вторую - что бы потешить самолюбие автора (меня). Так что, если Вам что-то непонятно, или Вы имеете какие-то пожелания, пишите мне.



http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное