Опубликован: 01.07.2011 | Доступ: свободный | Студентов: 6432 / 1052 | Оценка: 4.07 / 3.64 | Длительность: 10:34:00
Лекция 11:

Обработка событий с помощью JavaScript

< Лекция 10 || Лекция 11: 12 || Лекция 12 >

Ссылки на объект события

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

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

addEvent(document.getElementById("check-it-out"), "click", eventCheck);
function eventCheck (evt) {
  var eventReference = (typeof evt !== "undefined")? evt : event;
  var eventTarget = (typeof eventReference.target !== "undefined")? eventReference.target : eventReference.srcElement;
}

В первой строке в функции eventCheck проверяется, что имеется объект события, передаваемый в функцию. Если имеется, он автоматически становится первым параметром функции, получающим имя evt в этом примере. Если он не существует, что означает, что текущим web-браузером будет Internet Explorer, она обращается к глобальному свойству объекта window с именем event.

Вторая строка ищет свойство target по установленной ссылке события. Если оно не существует, она обращается к свойству srcElement, реализованному в Internet Explorer.

Примечание: Это управление и поведение также реализуется с помощью указанной выше функции addEvent, где объект event стандартизован для одинаковой работы во всех браузерах web. Однако показанный выше код написан таким образом, как будто это не так, чтобы показать различия web-браузеров.

Проверка специфического свойства события

Давайте попробуем это реализовать. Следующий пример выполняет различные блоки кода в зависимости от нажатой клавиши:

addEvent(document.getElementById("user-name"), "keyup", whatKey);
function whatKey (evt) {
  var eventReference = (typeof evt !== "undefined")? evt : event;
  var keyCode = eventReference.keyCode;
  if (keyCode === 13) {
    // Была нажата клавиша Enter 
    // Код для проверки и последующей отправки формы
  }
  else if (keyCode === 9) {
    // Нажата клавиша Tab 
    // Код, возможно, для очистки поля
  }
}

Код внутри функции whatKey проверяет свойство происходящего события, а именно keyCode, чтобы узнать, какая клавиша была фактически нажата на клавиатуре. Число 13 соответствует клавише Enter, а число 9 клавише Tab.

Поведение события по умолчанию и всплытие событий

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

Предотвращение поведения событий по умолчанию

Также как и с моделью событий и различиями между объектами событий, существует два способа обойти эту проблему, чтобы обеспечить поддержку IE и всех других браузеров. Созданный на основе предыдущего кода для получения ссылки на объект события следующий код содержит остановку поведения ссылки по умолчанию, возникающего при щелчке на ссылке:

addEvent(document.getElementById("stop-default"), "click", stopDefaultBehavior);
function stopDefaultBehavior (evt) {
  var eventReference = (typeof evt !== "undefined")? evt : event;
  if (eventReference.preventDefault) {
    eventReference.preventDefault();
  }
  else {
    eventReference.returnValue = false;
  }
}

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

Если этот метод не поддерживается, код задает для returnValue объекта глобального события значение false, тем самым останавливая поведение по умолчанию в Internet Explorer.

Остановка всплытия событий

Рассмотрим следующую иерархию HTML:

<div>
  <ul>
    <li>
      <a href="http://www.opera.com/" id="stop-default">Opera</a>
    </li>
    <li>
      <a href="http://www.opera.com/products/dragonfly/" id="stop-default">Opera Dragonfly</a>
    </li>
  </ul>	
</div>

Предположим, что событие onclick используетcя для всех элементов a, элементов li и элемента ul. Событие onclick будет сначала вызывать обработчик событий ссылки, затем элементов списка, и, наконец, обработчик событий неупорядоченного списка.

Если пользователь щелкает на ссылке, то, скорее всего, не требуется вызывать никакие возможные обработчики событий для элемента-предка li, но вместо этого просто позволить пользователю перейти на соответствующую страницу. Однако если пользователь щелкает на элементе li вне ссылки, можно использовать обработчик событий для элемента li, а также элемента ul.

Отметим, что при включении модели событий DOM level 2 и метода useCapture, т.е. при использовании перехвата событий, он будет начинаться с неупорядоченного списка, затем элемент списка, и, наконец, ссылка. Однако, так как перехват событий не доступен для выбора в Internet Explorer, такая функциональность очень редко используется в реальной практике.

Вот как надо писать код, чтобы остановить всплывание событий:

addEvent(document.getElementById("stop-default"), "click", cancelEventBubbling);
function cancelEventBubbling (evt) {
  var eventReference = (typeof evt !== "undefined")? evt : event;
  if (eventReference.stopPropagation) {
    eventReference.stopPropagation();
  }
  else {
    eventReference.cancelBubble = true;
  }
}

Законченный пример обработки событий

Здесь собран вместе пример страницы, демонстрирующий добавление обработчика событий и предотвращение действия по умолчанию для этого события, в зависимости от определенного критерия. Обработчик событий проверяет, разрешено ли отправить форму, в зависимости от того, заполнил ли пользователь все поля или нет. Код JavaScript имеет следующий вид:

addEvent(window, "load", function () {
  var contactForm = document.getElementById("contact-form");
  if (contactForm) {
    addEvent(contactForm, "submit", function (evt) {
      var firstName = document.getElementById("first-name");
      var lastName = document.getElementById("last-name");
      if (firstName && lastName) {
        if (firstName.value.length === 0 || lastName.value.length === 0) {
          alert("You have to fill in all fields, please.");
          evt.preventDefault();
        }
      }
    });
  }
});

Заключение

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

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

Контрольные вопросы

  • Что такое событие?
  • В чем различие между перехватом события и всплытием события?
  • Можно ли управлять выполнением события, т.е. останавливать поведение по умолчанию. Как?
  • В чем основная проблема функции attachEvent (http://dev.opera.com/articles/view/handling-events-with-javascript/javascript-event-handling-example.html) и области действия, которая порождает споры сообщества web-разработчиков на JavaScript?

Об авторе


Роберт Наймен занимался разработкой web-интерфейса в течение десяти лет, при этом JavaScript всегда был его основной областью интересов. Он увлеченно поддерживает блог Robert's talk (http://www.robertnyman.com/), посвященный web-разработке.

Он живет со своей прекрасной семьей в Швеции и, пока все спят, встает по ночам писать. Кроме того, он вынашивает тайную мечту однажды разбогатеть и получить возможность написать книгу о реальных вещах за пределами мира web.

< Лекция 10 || Лекция 11: 12 || Лекция 12 >
Александр Мельников
Александр Мельников

В лекции №7 результат работы ни одного скрипта кроме первого не выводит результат на странице браузера, ни одного. Почему. Автор, разъясните пожалуйста. Сокурсники, можете помочь понять?

Юлия Максимова
Юлия Максимова

Я пишу в блокноте, сохраняю с разрешением html и открываю через браузер. Пустой лист

Это задание после первой лекции,  в чем его выполнить, чтобы увидеть результат или как?

Артемий Емеличев
Артемий Емеличев
Россия, г. Череповец
Игорь Хан
Игорь Хан
Узбекистан, Ташкент, Ташкентский педагогический институт иностранных языков, 1990