Спонсор: Microsoft
Сибирский федеральный университет
Опубликован: 01.09.2010 | Доступ: свободный | Студентов: 3824 / 330 | Оценка: 4.08 / 3.78 | Длительность: 11:06:00
Лекция 11:

События. Объект event

Обработка событий занимает центральное место в разработке динамических веб-страниц. С точки зрения DOM API, событие – это сообщение, отправляемое в ответ на некоторое действие, например, завершение загрузки документа, перемещение или щелчок мыши, нажатие клавиши. Событие может быть принято (перехвачено) и обработано программными средствами. Обработчик события – это, как правило, функция, написанная на языке сценариев (например, JavaScript), которая выполняет действия, когда произошло соответствующее событие.

Вот список основных событий:

  • События окна и документа: onload – документ загружен и противоположное событие onunload – документ выгружен из окна. Применяется к элементам body и frameset и объекту window.
  • События мыши: onclick – (одиночный) щелчок мыши и ondblclick – двойной щелчок. Одиночный щелчок может быть разложен на два события, onmousedown – кнопка мыши нажата и onmouseup – кнопка мыши отпущена. Отслеживаются также перемещения мыши: onmouseover – указатель мыши пересек границу объекта внутрь, onmouseout - указатель мыши пересек границу объекта наружу и onmousemove – мышь перемещается над объектом. Применяется к большинству элементов.
  • События клавиатуры: onkeypressed – нажата и отпущена клавиша, производящая символ. Это событие разделяется на два, onkeydown – клавиша нажата и onkeyup –клавиша отпущена. Применяется к большинству элементов.
  • События HTML-формы onsubmit и onreset и элементов формы onfocus, onblur и onchange рассмотрены в лекции ""HTML формы"" .

Объект window.event создается браузером автоматически в момент возникновения события и доступен только внутри функции-обработчике события. Следует подчеркнуть, что модель объекта event в Internet Explorer существенно отличается от используемой в других браузерах, и требуется большое внимание при разработке динамических страниц, предназначенных для разных браузеров. Тем не менее, целый ряд свойств оказывается одинаковым во всех современных браузерах.

  • type – тип события без приставки "on". Например, событие onclick имеет тип click.
  • button – нажатая кнопка мыши (0 – ни одна, 1 – левая, 2 – правая, 3 – левая и правая, 4 – средняя, 5 – левая и средняя, 6 – правая и средняя, 7 – все три). Это свойство имеет смысл для событий мыши. В случае остальных событий имеет значение 0 независимо от действительного состояния кнопок.
  • clientX, clientY – координаты указателя мыши относительно верхнего левого угла клиентской области окна браузера.
  • screenX, screenY - координаты указателя мыши относительно верхнего левого угла дисплея.
  • keyCode – целочисленный код клавиши, которая вызвала событие клавиатуры. Коды клавиш различаются для различных аппаратных платформ (PC или Macintosh).
  • shiftKey, ctrlKey, altKey – истина ( true ), если во время события нажата также клавиша Shift, Ctrl или Alt, соответственно.
  • cancelBubble – запрещает ( true ) или разрешает ( false, по умолчанию) передачу события вверх по иерархии от элемента-источника к родительскому элементу. Каждое событие происходит на единственном элементе-источнике. Если элементу-источнику не сопоставлена функция-обработчик, событие передается вверх по дереву элементов, пока не встретит функцию-обработчик или не достигнет корневого элемента. Если функция-обработчик найдена, но не содержит cancelBubble=true, то передача вверх продолжается, если содержит, то прерывается.

На этом список общих свойств заканчивается. Большинство остальных свойств объекта event доступны в различных браузерах под разными именами.

  • Элемент-источник события в Internet Explorer доступен как свойство srcElement, в Mozilla Firefox и других как target.
  • События onmouseover и onmouseout в Internet Explorer показывают свойства-объекты откуда ( fromElement ) и куда ( toElement ). В Mozilla Firefox эти объекты являются свойством relatedTarget.

Список различий можно продолжить. Несмотря на различия в объектной модели между браузерами, писать веб-страницы, работающие в разных браузерах, можно и нужно. Рассмотрим это на примерах.

Передача объекта event функции-обработчику

Как было сказано, событие передается вверх по иерархии от элемента-источника к родительскому элементу и дальше. Процесс может быть остановлен присвоением свойству cancelBubble значения true.

<script type="text/javascript">
    function checkCancel() {
      if (window.event.shiftKey)
        window.event.cancelBubble = true;
    }
    function showSrc() {
      if (window.event.srcElement.tagName == "IMG")
        alert(window.event.srcElement.src);
    }
  </script>
...
<body onclick="showSrc()">
  <img onclick="checkCancel()" src="sample.gif">
</body>
...

В этом примере и элемент img, и его родительский элемент body имеют обработчик события onclick. При щелчке по изображению сначала вызывается функция checkCancel, которая проверяет состояние клавиши Shift. Если клавиша нажата, передача вверх по иерархии прекращается, если нет, выполняется также функция showSrc. К сожалению, этот пример работает только в Internet Explorer (начиная с версии 4.0). Различия в объектной модели Internet Explorer и большинства других браузеров максимальны именно в объекте event и доступе к нему. В случае Internet Explorer объект event доступен в функции-обработчике как глобальный объект, в других браузерах этот объект создается элементом-источником и доступен при вызове обработчика. Перепишем код следующим образом:

<script type="text/javascript">
    function checkCancel(e) {
      if (e.shiftKey)
        e.cancelBubble = true;
    }
    function showSrc(e) {
      if (e.srcElement.tagName == "IMG")
        alert(e.srcElement.src);
    }
  </script>
...
<body onclick="showSrc(event)">
  <img onclick="checkCancel(event)" src="sample.gif">
</body>
...

В этом варианте функция checkCancel работает как в Internet Explorer, так и в Mozilla Firefox, Apple Safari и Google Chrome, однако функция showSrc по-прежнему работает только в Internet Explorer. Дело в том, что элемент-источник события доступен в Internet Explorer как свойство события srcElement, а в других браузерах как target. Для учета различий можно применить один из нескольких методов:

  1. Написать отдельные страницы для каждого браузера. Его мы обсуждать не будем.
  2. Определить используемый браузер (при помощи объекта window.navigator ).
    function showSrc(e) {
          // userAgent в Internet Explorer любой версии содержит 
          // подстроку 'MSIE', которой нет в других браузерах
          var isIE = window.navigator.userAgent.indexOf('MSIE') > -1;
          if (isIE) {
            if (e.srcElement.tagName == "IMG")
              alert(e.srcElement.src);
          }
          else {
            if (e.target.tagName == "IMG")
              alert(e.target.src);
          }
        }

    Такой подход использовался и используется, однако он имеет существенный недостаток: мы не знаем, существует ли свойство target у объекта event в "другом" браузере.

  3. Определить наличие интересующего свойства. Этот подход считается более плодотворным.
    function showSrc(e) {
          var elem = null;
          if (e.srcElement)
            elem = e.srcElement;
          else if (e.target)
            elem = e.target;
    
          if (elem != null) {
            if (elem.tagName == "IMG")
              alert(elem.src);
          }
          else {
            alert("Ваш браузер не поддерживает DOM модель");
          }
        }

Передача элемента-источника функции-обработчику

Элемент (объект) может быть передан в сценарий как аргумент функции-обработчика.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<title>Динамический стиль JavaScript</title>

<script type="text/javascript">
  function ChangeStyleOver(elem) {
    elem.style.color = 'red';
    elem.style.fontSize = 'large';
  }
  function ChangeStyleOut(elem) {
    elem.style.color = 'Black';
    elem.style.fontSize = 'normal';
  }
</script>

</head>
<body>
  <p style='color: Black; font-size: normal;' onmouseover="ChangeStyleOver(this)"
    onmouseout="ChangeStyleOut(this)">
    Наведите мышь, чтобы увидеть изменения</p>
</body>
<html>

В этом примере стиль абзаца (элемент p ) задан в самом элементе. При наведении мыши (событие onmouseover ) вызывается функция ChangeStyleOver, в которую передается ссылка на объект-элемент (в этом контексте this указывает на элемент p ). Функция изменяет цвет текста (атрибут стиля color / свойство объекта style color ) и размер шрифта ( font-size / fontSize ). Обратите внимание на общее правило: все имена свойств начинаются со строчной буквы; если имя CSS атрибута содержит дефис (-), то дефис удаляется и следующая буква делается заглавной (стиль "спина верблюда"). Когда пользователь отводит мышь от элемента (событие onmouseout ), функция ChangeStyleOut возвращает стиль элемента к исходному. Изменения вступают в силу немедленно.

Замечание: Того же эффекта можно добиться без использования сценария. CSS псевдо-класс :hover применяется к элементу, над которым находится указатель мыши.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Динамический стиль CSS</title>
  <style type="text/css">
    p {
      color: Black;
      font-size: normal;
    }
    p:hover {
      color: red;
      font-size: large;
    }
  </style>
</head>
<body>
  <p>
    Наведите мышь, чтобы увидеть изменения</p>
</body>
<html>

Элемент !DOCTYPE в данном примере обязателен, если просматривать страницу в Internet Explorer 7.0 или более новом. В предыдущих версиях пример не работает, поскольку псевдо-класс :hover поддерживается только элементом a (гиперссылкой).

Связывание элемента-источника и события с функцией-обработчиком

Для того, чтобы обработать событие, произошедшее на том или ином элементе, элемент-источник и событие должны быть связаны со сценарием обработки события (функцией-обработчиком). Сделать это можно различными способами.

  1. Инструкция может помещаться в самом элементе.

    <p onmouseover="this.style.color='red'" onmouseout="this.style.color='blue'">
        текст</p>

    Ключевое слово this в этом контексте является ссылкой на элемент-источник (объект p, абзац). Такой подход удобен, когда нужно добавить небольшие инструкции в немногих местах.

  2. В элементе помещается вызов функции-обработчика.

    <p onmouseover="ChangeStyleOver()" onmouseout="ChangeStyleOut()">
        текст</p>

    Функция-обработчик может принимать аргументы, которые при вызове помещаются в круглые скобки. Специальными случаями является объект-источник ( this ) и событие ( event ), рассмотренные выше. Даже если список аргументов пуст, круглые скобки обязательны.

  3. Обработчик события может быть помещен в специальный блок сценария ( script ) с указанием элемента и события.

    <script type="text/javascript" for="oButton" event="onclick()">
        var sMessage1 = "Flip"
        var sMessage2 = "Flop"
        if (oButton.innerText == sMessage1) {
            oButton.innerText = sMessage2;
        }
        else {
          if (oButton.innerText == sMessage2) {
            oButton.innerText = sMessage1;
          }
        }
      </script>
    
      <button id="oButton">Flip</button>

    В этом примере сценарий выполняется, когда произошло событие, определенное в атрибуте EVENT, на элементе, id которого задан в атрибуте FOR. Пример работает только в Internet Explorer.

  4. Функция-обработчик может быть связана с объектом-источником и событием программно, если по какой-либо причине нежелательно помещать ее вызов в тэг элемента. Рассмотрим этот прием на примере.

Артур Гибадуллин
Артур Гибадуллин
Россия, г. Нижневартовск