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

146

»» В данной статье используется исходный код для примеров. Сохраните эту страницу для тестирования приведенных ниже примеров.

В библиотеке jQuery имеется ряд методов, предназначенных для регистрации функций, которые должны вызываться при срабатывании событий на интересующих вас элементах. Эти методы перечислены в таблице ниже:

Методы для обработки событий
Описание Метод
bind(тип_события, функция), bind (тип_события, данные, функция) Добавляет обработчик событий в элементы, содержащиеся в объекте jQuery, с дополнительной возможностью передачи данных обработчику
bind(тип_события, логическое значение) Создает обработчик событий по умолчанию, который всегда возвращает false, тем самым предотвращая выполнение действия, предусмотренного по умолчанию. Аргумент логическое_значение позволяет управлять всплытием событий
bind(объект отображения) Добавляет набор обработчиков событий, заданных объектом отображения, во все элементы, содержащиеся в объекте jQuery
one(тип_события, функция), one(тип_события, данные, функция) Добавляет обработчик событий в каждый из элементов, содержащихся в объекте jQuery, с дополнительной возможностью передачи данных обработчику. Обработчик может быть выполнен не более одного раза для каждого из элементов, после чего он отсоединяется от элемента
unbind() Удаляет все обработчики событий из всех элементов, содержащихся в объекте jQuery
unbind(тип_события) Удаляет ранее зарегистрированный обработчик событий из всех элементов, содержащихся в объекте jQuery
unbind(тип_события, логическое_значение) Удаляет ранее зарегистрированный обработчик событий, всегда возвращающий значение false, из всех элементов, содержащихся в объекте jQuery
unbind(Event) Удаляет обработчик событий с использованием объекта Event

Различные разновидности метода bind() позволяют указывать функцию, которая должна вызываться при наступлении некоторого события, а поскольку мы имеем дело с jQuery, то эта функция будет применена по отношению к каждому из элементов, содержащихся в объекте jQuery, для которого был вызван метод bind(). Простой пример приведен ниже:

$(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": ""
        });
    }
	
});

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

Внутри функции-обработчика переменная this ссылается на набор элементов, к которому присоединен обработчик. Передаваемый обработчику объект Event является собственным объектом библиотеки jQuery и отличается от объекта Event, определенного в спецификации DOM. Свойства и методы объекта Event в jQuery описаны в таблице ниже:

Свойства и методы объекта Event в jQuery
Свойство/метод Описание Тип возвращаемого значения
currentTarget Возвращает текущий элемент, событие которого обрабатывается. Этот элемент не обязательно является источником события, так как последнее могло быть передано ему дочерним элементом посредством механизма "всплытия" событий вверх по DOM-дереву. Для определения источника события необходимо использовать свойство target HTMLElement
data Возвращает дополнительные данные, переданные методу bind() при регистрации обработчика object
isDefaultPrevented() Возвращает true, если для данного объекта событий ранее вызывался метод preventDefault() boolean
isImmediatePropagationsStopped() Возвращает true, если для данного объекта событий ранее вызывался метод stopImmediatePropagation() boolean
isPropagationsStopped() Возвращает true, если для данного объекта событий ранее вызывался метод stopPropagation() boolean
originalEvent Возвращает первоначальный DOM-объект Event event
pageX, pageY Координаты указателя мыши относительно левого верхнего угла документа number
preventDefault() Отменяет выполнение действий по умолчанию, связанных с данным событием void
relatedTarget Для событий мыши возвращает другой имеющий отношение к событию объект, если таковой имеется. Какой именно будет этот объект, зависит от конкретного события HTMLElement
result Результат, возвращенный обработчиком данного события при его последнем вызове object
stopImmediatePropagation() Отменяет выполнение любых других обработчиков, связанных с данным событием void
stopPropagation() Предотвращает всплытие события вверх по иерархии DOM, но разрешает обработчикам, связанным с текущим обрабатываемым элементом, получить данное событие void
target Возвращает элемент, являющийся источником события HTMLElement
timestamp Возвращает время наступления события number
type Возвращает тип события string
which Возвращает информацию о нажатой кнопке или клавише для событий, связанных с мышью или клавиатурой number

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

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

Очень часто обработка нескольких типов событий осуществляется с помощью одной функции. Как правило, это делается для событий, являющихся в определенной степени родственными. Типичным примером подобных событий могут служить события mouseenter и mouseout. Чтобы воспользоваться указанной возможностью, следует вызвать метод bind(), задав в качестве первого аргумента список событий, разделенных пробелами. Соответствующий пример приведен ниже:

$(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);
    }
	
});

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

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

Кроме того, для регистрации обработчиков событий можно использовать объект отображения. Свойствами этого объекта являются имена событий, а значениями свойств — функции, которые должны вызываться при наступлении событий. Пример использования метода bind() совместно с объектом отображения приведен ниже:

$(function() {
        
    $('img').bind({
        mouseenter: function() {
            $(this).css("border", "thick solid red");
        },
        mouseout: function() {
            $(this).css("border", "");
        }
    });
	
});

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

Передача данных обработчику событий

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

Пример определения и использования значения свойства data приведен ниже:

$(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);        
    }
	
});

Запустить пример

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

Отмена поведения браузера по умолчанию

Для некоторых событий предусмотрены действия по умолчанию, которые выполняются браузером, если источниками событий являются определенные элементы. Хорошим примером этого может служить щелчок на кнопке с атрибутом type, имеющим значение submit. Если элемент button находится внутри элемента form, то действием по умолчанию для браузера является отправка формы. Чтобы предотвратить выполнение этого действия, следует вызвать метод preventDefault() для объекта Event, как показано в примере ниже:

$(function() {
        
    $('button:submit').bind("click", function(e) {
        e.preventDefault();
    });
	
});

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

$(function() {
        
    $('button:submit').bind("click", false);
	
});

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

Удаление обработчиков событий

Для удаления обработчиков событий из элементов предназначен метод unbind(). Вызов метода unbind() без указания аргументов приводит к удалению всех обработчиков, связанных со всеми событиями, для всех элементов, содержащихся в объекте jQuery.

Можно прибегнуть к более избирательному подходу и передать события, которые вы хотите открепить от элементов, методу unbind() в качестве аргумента, как показано в примере ниже:

$(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);
    }
	
});

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

Установка разового обработчика событий

Метод one() позволяет зарегистрировать обработчик событий, который может быть выполнен не более одного раза для одного элемента, после чего удаляется из него. Соответствующий пример представлен в примере ниже:

$(function() {
        
    $('img').one("mouseenter", handleMouseEnter).one("mouseout", handleMouseOut);
    
    function handleMouseEnter(e) {
        $(this).css("border", "thick solid red");
    };
    
    function handleMouseOut(e) {
        $(this).css("border", "");
    };
	
});

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

Вызов обработчиков событий вручную

Для вызова обработчиков событий вручную предусмотрены методы, перечисленные в таблице ниже:

Методы для вызова обработчиков событий вручную
Метод Описание
trigger(тип_события) Запускает обработчики событий указанных типов для всех элементов, содержащихся в объекте jQuery
trigger(Event) Запускает обработчики указанного события для всех элементов, содержащихся в объекте jQuery
triggerHandler(тип_события) Запускает функцию-обработчик для первого из элементов, содержащихся в объекте jQuery, без выполнения действий по умолчанию или всплытия событий

Пример запуска обработчиков событий вручную приведен в примере ниже:

$(function() {
        
    $('img').bind({mouseenter: function() {
            $(this).css("border", "thick solid red");
        },
        mouseout: function() {
            $(this).css("border", "");
        }
    });
    
    $("<button>Запустить</button>").appendTo("#buttonDiv").bind("click", function (e) {              
        $('#row1 img').trigger("mouseenter");
        e.preventDefault();
    });
	
});

В этом сценарии с помощью метода bind() устанавливаются два обработчика событий для элементов img в документе. Затем мы вставляем в документ элемент button, используя для этого метод appendTo(), и регистрируем функцию-обработчик для события click с помощью метода bind().

После щелчка на созданной кнопке функция-обработчик выбирает элементы img, являющиеся потомками элемента со значением id, равным row1, и использует метод trigger() для вызова их обработчиков события mouseenter. Результат этого выглядит так, как если бы указатель мыши был наведен одновременно на все три элемента img.

Использование объекта Event

Объект Event можно использовать для запуска обработчиков событий, прикрепленных к другим элементам. Этот прием удобен для применения внутри обработчиков, как показано в примере ниже:

$(function() {
        
    $('#row1 img').bind("mouseenter", function() {
        $(this).css("border", "thick solid red");
    }).bind("mouseout", function() {
		$(this).css("border", "");
	});
        
    $('#row2 img').bind("mouseenter", function(e) {
        $(this).css("border", "thick solid blue");
        $('#row1 img').trigger(e);
    })
	.bind("mouseout", function(e) {
		$(this).css("border", "");
        $('#row1 img').trigger(e);
	});
	
});

Запустить пример

В этом примере мы используем метод bind() для добавления красной рамки вокруг элементов img, являющихся потомками элемента со значением id, равным row1, в ответ на наступление события mouseenter. Затем то же самое делается в отношении элементов img, являющихся потомками элемента со значением id, равным row2, но с использованием рамки синего цвета. При этом добавляется следующая инструкция:

$('#row1 img').trigger(e);

Это приводит к тому, что при наведении указателя мыши на один из элементов img, являющихся потомками элемента со значением id, равным row2, срабатывают также обработчики события этого же типа, прикрепленные к элементам img, являющимся потомками элемента со значением id, равным row1.

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

Использование метода triggerHandler()

Метод triggerHandler() также вызывает обработчики событий, однако при этом действия по умолчанию, предусмотренные для данного события, не выполняются и событие не распространяется вверх по дереву DOM. Кроме того, в отличие от метода trigger(), метод triggerHandler() вызывает функцию-обработчик лишь для первого из элементов, содержащихся в объекте jQuery.

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

$(function() {
        
    $('#row1 img').bind("mouseenter", function() {
        $(this).css("border", "thick solid red");
    }).bind("mouseout", function() {
		$(this).css("border", "");
	});
        
    $('#row2 img').bind("mouseenter", function(e) {
        $(this).css("border", "thick solid blue");
        $('#row1 img').triggerHandler("mouseenter");
    })
	.bind("mouseout", function(e) {
		$(this).css("border", "");
        $('#row1 img').triggerHandler("mouseout");
	});
	
});
Пройди тесты
Лучший чат для C# программистов