Главная страница   /   9.1. Обработка событий (Pro jQuery

Pro jQuery

Pro jQuery

Адам Фриман

9.1. Обработка событий

jQuery предоставляет набор методов, которые позволяют зарегистрировать функции, которые вызываются, когда указанные события срабатывают для интересующих вас элементов. Эти методы описаны в таблице 9-2.

Таблица 9-2: Методы для обработки событий
Метод Описание
bind(eventType, function)
bind(eventType, data, function)
Добавляют обработчик события для элементов в объекте jQuery, опционально с данными
bind(eventType, boolean) Создает обработчик по умолчанию, который всегда возвращает false, предотвращая действие по умолчанию. Аргумент boolean контролирует баблинг событий
bind(map) Добавляет набор обработчиков событий, основываясь на объекте-карте для всех элементов в объекте jQuery
one(eventType, function)
one(eventType, data, function)
Добавляют обработчик события для каждого элемента в объекте jQuery, опционально с данными. Как только событие произошло, обработчик перестанет быть зарегистрированным для элемента
unbind() Удаляет все обработчики событий для всех элементов в объекте jQuery
unbind(eventType) Удаляет ранее зарегистрированный обработчик событий для всех элементов в объекте jQuery
unbind(eventType, boolean) Удаляет ранее зарегистрированный всегда false обработчик событий для всех элементов в объекте jQuery
unbind(Event) Удаляет обработчик событий при помощи объекта Event

Метод bind позволяет указать функцию, которая будет вызвана, когда сработает событие; и поскольку это jQuery, то функция будет использована для всех элементов в объекте jQuery, для которых вы используете метод bind. В листинге 9-1 показан простой пример.

Листинг 9-1: Использование метода bind для регистрации функции обработчика событий
<!DOCTYPE html>
<html>
<head>
	<title>Example</title>
	<script src="jquery-1.7.js" type="text/javascript"></script>
	<link rel="stylesheet" type="text/css" href="styles.css" />
	<script type="text/javascript">
		$(document).ready(function () {
			$('img').bind("mouseenter", handleMouseEnter)
				.bind("mouseout", handleMouseOut);

			function handleMouseEnter(e) {
				$(this).css({
					"border": "thick solid red",
					"opacity": "0.5"
				});
			};

			function handleMouseOut(e) {
				$(this).css({
					"border": "",
					"opacity": ""
				});
			}
		});
	</script>
</head>
<body>
	<h1>Jacqui's Flower Shop</h1>
	<form method="post">
		<div id="oblock">
			<div class="dtable">
				<div id="row1" class="drow">
					<div class="dcell">
						<img src="astor.png" /><label for="astor">Astor:</label>
						<input name="astor" value="0" required />
					</div>
					<div class="dcell">
						<img src="daffodil.png" /><label for="daffodil">Daffodil:</label>
						<input name="daffodil" value="0" required />
					</div>
					<div class="dcell">
						<img src="rose.png" /><label for="rose">Rose:</label>
						<input name="rose" value="0" required />
					</div>
				</div>
				<div id="row2" class="drow">
					<div class="dcell">
						<img src="peony.png" /><label for="peony">Peony:</label>
						<input name="peony" value="0" required />
					</div>
					<div class="dcell">
						<img src="primula.png" /><label for="primula">Primula:</label>
						<input name="primula" value="0" required />
					</div>
					<div class="dcell">
						<img src="snowdrop.png" /><label for="snowdrop">Snowdrop:</label>
						<input name="snowdrop" value="0" required />
					</div>
				</div>
			</div>
		</div>
		<div id="buttonDiv">
			<button type="submit">Place Order</button></div>
	</form>
</body>
</html>

В этом примере я выбираю в документе все элементы img и использую метод bind для регистрации функций обработчиков для событий mouseenter и mouseout. Эти обработчики используют метод css, чтобы установить значения для свойств border и opacity. Когда пользователь двигает курсором мыши по одному из элементов img, рисуется рамка, а рисунок становится более прозрачным, возвращаясь к своему предыдущему состоянию, когда курсор мышки выходит из его области.

Когда jQuery вызывает функцию обработчика, переменная this указывает на элемент, к которому присоединен обработчик. Объект, переданный функции обработчика, является собственным объектом Event в jQuery, который отличается от объекта Event, определенного DOM спецификацией. В таблице 9-3 описаны свойства и методы объекта Event в jQuery.

Таблица 9-3: Члены объекта Event в jQuery
Имя Описание Возвращает
currentTarget Получает элемент, чей слушатель сейчас вызван HTMLElement
data Получает опциональные данные, переданные методу bind, когда был зарегистрирован обработчик. Для информации смотрите следующий раздел. Object
isDefaultPrevented() Возвращает true, если был вызван метод preventDefault Boolean
isImmediatePropagationStopped() Возвращает true, если был вызван метод Возвращает true, если был вызван метод stopImmediatePropagation Boolean
isPropagationStopped() Возвращает true, если был вызван метод stopPropagation Boolean
originalEvent Возвращает оригинальный DOM объект Event Event
pageX
pageY
Возвращает позицию мышки относительно левого края документа number
preventDefault() Предотвращает выполнение действия по умолчанию, связанного с событием void
relatedTarget Для событий, связанных с мышкой, возвращает соответствующий элемент. Это зависит от того, какое событие было вызвано HTMLElement
result Возвращает результат последнего обработчика событий, который обрабатывал это событие Object
stopImmediatePropagation() Предотвращает вызов любого другого обработчика для этого события void
stopPropagation() Предотвращает события от баблинга, но позволяет обработчикам, связанным с текущим целевым элементом, принять событие void
target Получает элемент, который включил событие HTMLElement
timeStamp Получает время, когда было запущено событие number
type Получает тип события string
which Получает кнопку или клавишу, которые были нажаты для события, связанного с мышкой или клавиатурой number

jQuery объект Event также определяет большинство свойств стандартного DOM Event объекта. Таким образом, почти во всех ситуациях, вы можете считать, что jQuery объект Event обладает расширенным функционалом, определенным стандартным DOM.

Регистрация функции для обработки нескольких типов событий

Общепринятым техническим приемом является использование одной функции для обработки двух или более видов событий. Эти события обычно как-то связаны, например, как события mouseenter и mouseout. Когда используется метод bind, можно указать в первом аргументе несколько типов событий, разделяя их пробелом. В листинге 9-2 представлен пример.

Листинг 9-2: Регистрация функции для обработки нескольких типов событий
<script type="text/javascript">
	$(document).ready(function () {

		$('img').bind("mouseenter mouseout", handleMouse);

		function handleMouse(e) {
			var cssData = {
				"border": "thick solid red",
				"opacity": "0.5"
			}
			if (event.type == "mouseout") {
				cssData.border = "";
				cssData.opacity = "";
			}
			$(this).css(cssData);
		}
	});
</script>

В этом скрипте я использовал единственный вызов метода bind, чтобы указать, что события mouseenter и mouseout должны быть обработаны функцией handleMouse для всех элементов img в документе. Конечно, можно использовать единственную функцию и цепочкой вызвать метод bind, например так:

$('img').bind("mouseenter", handleMouse).bind("mouseout", handleMouse);

Также можно зарегистрировать обработчики, используя объект-карту. Свойства объекта являются именами событий, а их значения являются функциями, которые будут вызваны, когда сработает событие. В листинге 9-3 показано использование объекта-карты с методом bind.

Листинг 9-3: Использование объекта-карты для регистрации обработчиков событий
<script type="text/javascript">
	$(document).ready(function () {
		$('img').bind({
			mouseenter: function () {
				$(this).css("border", "thick solid red");
			},
			mouseout: function () {
				$(this).css("border", "");
			}
		});
	});
</script>

В этом примере я определил функции обработчика внутри, как часть объекта-карты. Метод bind получает информацию о событиях, которые меня интересуют, и моих функциях и создает указанные мной связи.

Добавление данных функциям обработки событий

В метод bind можно добавить объект, который потом jQuery сделает доступным для функции обработчика при помощи свойства Event.data. Это может быть полезно при использовании одной функции для обработки событий для различных наборов элементов. Значение data может помочь определить, какой вид отклика требуется. В листинге 9-4 показано, как определять и использовать данные.

Листинг 9-4: Передача данных функции обработки событий через метод bind
<script type="text/javascript">
	$(document).ready(function () {
		$('img:odd').bind("mouseenter mouseout", "red", handleMouse);
		$('img:even').bind("mouseenter mouseout", "blue", handleMouse);
		function handleMouse(e) {
			var cssData = {
				"border": "thick solid " + e.data,
			}
			if (event.type == "mouseout") {
				cssData.border = "";
			}
			$(this).css(cssData);
		}
	});
</script>

В этом скрипте я использую аргумент в методе bind, чтобы указать, какой цвет рамки должен быть отображен, когда сработает событие mouseenter. Для нечетных элементов img рамка будет красной, для четных элементов – синей. В функции обработки событий я использую свойство Event.data, чтобы получить данные и использовать их для создания значения CSS свойства border. Результат можно увидеть на рисунке 9-1.

Рисунок 9-1: Передача данных функции-обработчику через метод bind

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

Как я упоминал в главе 2, некоторые события предполагают выполнение действий по умолчанию (default action), когда они (события) срабатывают для определенных элементов. Хороший пример этого – это когда пользователь кликает по кнопке, чьим type атрибутом является submit. Если button содержится в элементе form, действием по умолчанию для браузера является отправка формы. Чтобы предотвратить действие по умолчанию, можно вызвать метод preventDefault для объекта Event, как показано в листинге 9-5.

Листинг 9-5: Предотвращение действия по умолчанию для события
<script type="text/javascript">
	$(document).ready(function () {
		$('button:submit').bind("click", function (e) {
			e.preventDefault();
		});
	});
</script>

Обычно вы запрещаете действие по умолчанию, если хотите, чтобы вместо него было выполнено какое-то другое действие. Например, вы не даете браузеру отправить форму, потому что вы хотите сделать это при помощи Ajax (о котором мы поговорим в главах 14 и 15). Вместо написания однострочной функции можно использовать метод bind, как показано в листинге 9-6.

Листинг 9-6: Использование метода bind для создания обработчика, который запрещает действие по умолчанию
<script type="text/javascript">
	$(document).ready(function () {
		$('button:submit').bind("click", false);
	});
</script>

Первый аргумент – это событие или события, чьи действия по умолчанию вы хотите запретить, а во втором аргументе вы можете указать, должен ли быть запрещен баблинг по DOM для этого события (что такое баблинг, я рассказал в главе 2).

Удаление функции обработки событий

Метод unbind удаляет функцию обработчика из элемента. Можно удалить все обработчики, связанные со всеми событиями, для всех элементов в объекте jQuery, если вызвать метод unbind без аргументов, как показано в листинге 9-7.

Листинг 9-7: Удаление всех обработчиков событий
<script type="text/javascript">
	$(document).ready(function () {
		$('img').bind("mouseenter mouseout", handleMouse);

		$('img[src*=rose]').unbind();

		function handleMouse(e) {
			var cssData = {
				"border": "thick solid red",
				"opacity": "0.5"
			}
			if (event.type == "mouseout") {
				cssData.border = "";
				cssData.opacity = "";
			}
			$(this).css(cssData);
		}
	});
</script>

В этом примере я использую метод bind для обработки событий mouseenter и mouseout для всех элементов img, а потом использую метод unbind, чтобы удалить всех обработчиков для элементов img, чей src атрибут содержит rose. Вы можете выборочно удалить события, если добавите их (события, которые вы хотите удалить) в качестве аргумента методу unbind, как показано в листинге 9-8.

Листинг 9-8: Выборочное удаление событий
<script type="text/javascript">
	$(document).ready(function () {
		$('img').bind("mouseenter mouseout", handleMouse);

		$('img[src*=rose]').unbind("mouseout");

		function handleMouse(e) {
			var cssData = {
				"border": "thick solid red",
				"opacity": "0.5"
			}
			if (event.type == "mouseout") {
				cssData.border = "";
				cssData.opacity = "";
			}
			$(this).css(cssData);
		}
	});
</script>

В этом скрипте я удаляю только событие mouseout, оставляя нетронутым обработчик для события mouseenter.

Удаление событий изнутри функции обработки событий

И последним вариантом удаления событий является удаление изнутри функции обработки событий. Это может быть полезным, только если вы, например, хотите, чтобы событие было обработано конкретное число раз. В листинге 9-9 содержится простой пример.

Листинг 9-9: Удаление события изнутри функции обработки событий
<script type="text/javascript">
	$(document).ready(function () {

		$('img').bind("mouseenter", handleMouseEnter).bind("mouseout", handleMouseExit);

		var handledCount = 0;

		function handleMouseEnter(e) {
			$(this).css("border", "thick solid red");
		}
		function handleMouseExit(e) {
			$(this).css("border", "");
			handledCount++;
			if (handledCount == 2) {
				$(this).unbind(e);
			}
		}
	});
</script>

В функции handleMouseEvent я наращиваю счетчик каждый раз, когда я обрабатываю событие mouseout. После того, как событие было дважды обработано, объект Event передается методу unbind, чтобы освободить функцию в качестве обработчика. jQuery сам получает от объекта нужные подробности.

Выполнение обработки события один раз

Метод one позволяет регистрировать обработчик события, который только один раз будет выполнен для элемента, а затем удален. В листинге 9-10 представлен пример.

Листинг 9-10: Использование метода one для регистрации функции обработки событий, которая будет выполнена только один раз
<script type="text/javascript">
	$(document).ready(function () {
		$('img').one("mouseenter", handleMouseEnter).one("mouseout", handleMouseOut);

		function handleMouseEnter(e) {
			$(this).css("border", "thick solid red");
		};
		function handleMouseOut(e) {
			$(this).css("border", "");
		};
	});
</script>

Я использовал метод one для регистрации обработчика для событий mouseenter и mouseout. Функция обработчика будет вызвана, когда пользователь подведет мышку и выведет ее из области одного из элементов img, а затем функция перестанет быть связанной с этим элементом (но только для этого элемента, у других все еще будут обработчики, пока пользователь не подвигает по ним мышкой).