Веб-страницы, по большей части, ориентированы на события. В библиотеках, таких как jQuery, предусмотрены вспомогательные методы, облегчающие понимание этой функции. В этом уроке мы рассмотрим расширение этих методов для создания ваших собственных событий в пространстве имен.
События в JavaScript
Перед роскошью библиотек JavaScript, если вы хотите добавить простое событие click к элементу, вам необходимо выполнить следующие действия для поддержки всех браузеров:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
var elt = document.getElementById(«#myBtn»);
if(elt.addEventListener)
{
elt.addEventListener(«click», function() {
alert(‘button clicked’);
});
}
else if(elt.attachEvent)
{
elt.attachEvent(«onclick», function() {
alert(‘button clicked’);
});
}
else
{
elt.onclick = function() {
alert(‘button clicked’);
};
}
|
Теперь библиотеки JavaScript поставляются с вспомогательными методами, чтобы сделать управление событиями более понятным. Например, выполнение вышеизложенного в jQuery гораздо более сжато.
|
1
2
3
|
$(«#myBtn»).click(function() {
alert(‘button clicked’);
});
|
Независимо от вашей реализации, есть три основных части событий:
- Слушатель — ждет или «слушает» событие, чтобы выстрелить.
- Диспетчер — запускает событие для запуска.
- Обработчик — функция, выполняемая при возникновении события.
В нашем событии click в начале урока слушатель — это событие click, ожидающее нажатия на элемент #myBtn. При щелчке по элементу #myBtn он отправляет и запускает обработчик; которая в данном случае является анонимной функцией для отображения сообщения alert ().
Шаг 1: Настройка нашей страницы
jQuery позволяет нам сделать еще один шаг и создать собственные события. В этом руководстве мы будем использовать неупорядоченный список списка каталогов и добавим функциональность с помощью пользовательских событий, которые будут сворачивать и расширять каталоги. Давайте начнем с нашей базовой структуры страницы, которая будет использоваться в следующих примерах.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Strict//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd»>
<html xmlns=»http://www.w3.org/1999/xhtml» xml:lang=»en» lang=»en»>
<head>
<title>jQuery Custom Events</title>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ />
<style type=»text/css»>
body {background: #fefefe;
#tree {color: #333;
.directory {list-style-image: url(‘images/directory.png’);}
.css {list-style-image: url(‘images/css.png’);}
.html {list-style-image: url(‘images/html.png’);}
.js {list-style-image: url(‘images/js.png’);}
.gif,
.png,
.jpg {list-style-image: url(‘images/image.png’);}
</style>
</head>
<body>
<ul id=»tree»>
<li>root/
<ul>
<li>index.html</li>
<li>about.html</li>
<li>gallery.html</li>
<li>contact.html</li>
<li>assets/
<ul>
<li>images/
<ul>
<li>logo.png</li>
<li>background.jpg</li>
</ul>
</li>
<li>js/
<ul>
<li>jquery.js</li>
<li>myscript.js</li>
</ul>
</li>
<li>css/
<ul>
<li>page.css</li>
<li>typography.css</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<script type=»text/javascript» src=»http://google.com/jsapi»></script>
<script type=»text/javascript»>
google.load(«jquery», «1»);
google.setOnLoadCallback(function() {
$(function() {
addIcons();
});
function addIcons()
{
$(«#tree li»).each(function() {
if($(this).children(«ul»).length)
{
$(this).addClass(«directory»);
}
else
{
var txt = $(this).text();
var fileType = txt.substr(txt.indexOf(«.») + 1);
$(this).addClass(fileType);
}
});
}
});
</script>
</body>
</html>
|
Здесь мы создаем простой список каталогов, используя неупорядоченный список. Мы включили jQuery из CDN Google JSAPI и назвали addIcons (), который добавляет изображения каждого файла и папки в зависимости от указанного расширения файла. Эта функция предназначена исключительно для эстетических целей. В этом нет необходимости ни для одного из пользовательских кодов событий, которые мы собираемся реализовать. Результат этого шага и можно посмотреть здесь .
Шаг 2: .bind () и .trigger ()
Прежде чем мы начнем добавлять события в наш пример списка каталогов, нам нужно понять, как работают .bind () и .trigger (). Мы используем bind (), чтобы прикрепить событие ко всем соответствующим элементам, которые в данный момент находятся на странице. Затем используйте .trigger (), если вы хотите отправить событие. Давайте посмотрим на быстрый пример.
|
1
2
3
4
5
|
$(«#myBtn»).bind(«click», function(evt) {
alert(‘button clicked’);
});
$(«#myBtn»).trigger(«click»);
|
В приведенном выше коде при щелчке элемента с идентификатором «myBtn» появится предупреждающее сообщение. Кроме того, наш триггер () фактически запустит событие click сразу после загрузки страницы. Просто помните, что bind () — это то, как вы прикрепляете событие. Пока .trigger (), вы заставляете событие отправляться и запускаете обработчик события.
Шаг 3: Пользовательские события с использованием .bind () и .trigger ()
Метод .bind () не ограничивается только событиями браузера, но может использоваться для реализации ваших собственных пользовательских событий. Давайте начнем с создания пользовательских событий с именем collapse и развернем наш пример с перечнем каталогов.
Во-первых, давайте свяжем событие свертывания со всеми каталогами, представленными в нашем неупорядоченном списке.
|
1
|
$(«#tree li:parent»).bind(«collapse», function(evt) {
|
Здесь мы находим все элементы, которые являются родителями, и передаем сжатие имени события в метод .bind (). Мы также назвали первый параметр evt , который представляет объект события jQuery.
|
1
|
$(evt.target).children().slideUp().end().addClass(«collapsed»);
|
Теперь мы выбираем цель мероприятия и перемещаем всех его детей. Кроме того, у нас был свернут класс CSS к нашему элементу каталога.
|
1
|
}).bind(«expand», function(evt) {
|
Мы присоединяемся к событиям и присоединяем наше расширение к этой линии.
|
1
2
|
$(evt.target).children().slideDown().end().removeClass(«collapsed»);
});
|
В противоположность нашему обработчику событий коллапса , в обработчике событий расширения мы сдвигаем все дочерние элементы элементов каталога и удаляем свернутый класс из нашего целевого элемента. Собираем все вместе.
|
1
2
3
4
5
|
$(«#tree li:parent»).bind(«collapse», function(evt) {
$(evt.target).children().slideUp().end().addClass(«collapsed»);
}).bind(«expand», function(evt) {
$(evt.target).children().slideDown().end().removeClass(«collapsed»);
});
|
Только этот код ничего не сделает для нас, потому что события разворачиваются и разворачиваются , неизвестны и понятия не имеют, когда их отправлять. Поэтому мы добавляем наш метод .trigger (), когда хотим, чтобы эти события запускались.
|
1
2
3
4
5
6
7
8
9
|
$(«#tree li:parent»).bind(«collapse», function(evt) {
$(evt.target).children().slideUp().end().addClass(«collapsed»);
}).bind(«expand», function(evt) {
$(evt.target).children().slideDown().end().removeClass(«collapsed»);
})).toggle(function() { // toggle between
$(this).trigger(«collapse»);
}, function() {
$(this).trigger(«expand»);
});
|
Если мы запустим этот код, наши каталоги теперь будут переключаться при нажатии между активацией события разворачивания и развертывания . Но если вы щелкнете по вложенному каталогу, вы заметите, что наши события запускаются несколько раз за клик. Это из-за пузыря событий.
Захват событий и пузыри
Когда вы щелкаете элемент на странице, событие перемещается или захватывается от самого верхнего родителя, к которому прикреплено событие, к намеченной цели. Это тогда пузыри от намеченной цели назад самый верхний родитель.

Например, когда мы щелкаем папку css /, наше событие записывается через root /, assets /, а затем css /. Затем он отправляет пузыри css /, assets /, затем в root /. Следовательно, обработчик выполняется три раза. Мы можем исправить это, добавив простое условие в обработчик для намеченной цели.
|
1
2
3
4
|
if(evt.target == evt.currentTarget)
{
(evt.target).children().slideUp().end().addClass(«collapsed»);
}
|
Этот код будет проверять каждую текущую цель события относительно намеченной цели или currentTarget. Когда у нас есть совпадение, только тогда скрипт выполнит событие коллапса. После обновления события разворачивания и развертывания наша страница будет функционировать, как и ожидалось.
Пространство имен событий
Пространство имен обеспечивает контекст для событий. Пользовательские события, свернутые и развернутые , неоднозначны. Добавление пространства имен в пользовательское событие jQuery — это структурированное имя события, за которым следует пространство имен . Мы создадим наше пространство имен под названием TreeEvent, потому что наши события представляют действия и функциональные возможности древовидной структуры папок. После того, как мы добавили пространства имен к нашим событиям, код теперь будет выглядеть так:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
$(«#tree li:parent»).bind(«collapse.TreeEvent», function(evt) {
if(evt.target == evt.currentTarget)
{
$(evt.target).children().slideUp().end().addClass(«collapsed»);
}
}).bind(«expand.TreeEvent», function(evt) {
if(evt.target == evt.currentTarget)
{
$(evt.target).children().slideDown().end().removeClass(«collapsed»);
}
}).toggle(function() {
$(this).trigger(«collapse.TreeEvent»);
}, function() {
$(this).trigger(«expand.TreeEvent»);
});
|
Все, что нам нужно было изменить, — это имена событий в методах .bind () и .trigger () как для событий разворачивания, так и для разворачивания . Теперь у нас есть функциональный пример использования пользовательских событий в пространстве имен.
Обратите внимание, что мы можем легко удалить события из элементов, используя метод unbind ().
|
1
2
|
$(«#tree li:parent»).unbind(«collapse.TreeEvent»);
$(«#tree li:parent»).unbind(«.TreeEvent»);
|
API специальных событий
Другой способ настроить пользовательское событие в jQuery — использовать API специальных событий . По этому API не так много документации, но Брэндом Аарон, основной участник jQuery, написал две отличные публикации в блоге ( http://brandonaaron.net/blog/2009/03/26/special-events и http: / /brandonaaron.net/blog/2009/06/4/jquery-edge-new-special-event-hooks ), чтобы помочь нам понять доступные методы. Ниже приводится краткое объяснение методов.
- add — аналогично настройке, но вызывается для каждого связываемого события.
- setup — вызывается, когда событие связано.
- удалить — аналогично разрыву, но вызывается для каждого события, которое не связано.
- teardown — вызывается, когда событие не связано.
- обработчик — вызывается при отправке события.
Теперь давайте посмотрим, как мы можем объединить наши пользовательские события в специальное событие, которое мы будем называть toggleCollapse .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
jQuery.event.special.toggleCollapse = {
setup: function(data, namespaces) {
for(var i in namespaces)
{
if(namespaces[i] == «TreeEvent»)
{
jQuery(this).bind(‘click’, jQuery.event.special.toggleCollapse.TreeEvent.handler);
}
}
},
teardown: function(namespaces) {
for(var i in namespaces)
{
if(namespaces[i] == «TreeEvent»)
{
jQuery(this).unbind(‘click’, jQuery.event.special.toggleCollapse.TreeEvent.handler);
}
}
},
TreeEvent: {
handler: function(event) {
if(event.target == event.currentTarget)
{
var elt = jQuery(this);
var cssClass = «collapsed»;
if(elt.hasClass(cssClass))
{
elt.children().slideDown().end().removeClass(cssClass);
}
else
{
elt.children().slideUp().end().addClass(cssClass);
}
event.type = «toggleCollapse»;
jQuery.event.handle.apply(this, arguments);
}
}
}
};
$(«#tree li:parent»).bind(«toggleCollapse.TreeEvent», function(evt) {});
|
Давайте посмотрим на это раздел за разделом.
|
01
02
03
04
05
06
07
08
09
10
|
jQuery.event.special.toggleCollapse = {
setup: function(data, namespaces) {
for(var i in namespaces)
{
if(namespaces[i] == «TreeEvent»)
{
jQuery(this).bind(‘click’, jQuery.event.special.toggleCollapse.TreeEvent.handler);
}
}
},
|
Первая строка jQuery.event.special.toggleCollapse создает новое специальное событие с именем toggleCollapse . Затем у нас есть метод установки, который перебирает все пространства имен этого события. Как только он находит TreeEvent , он связывает событие click с соответствующими элементами, которые при вызове события будут вызывать jQuery.event.special.toggleCollapse.TreeEvent.handler . Обратите внимание, что мы используем событие click в отличие от функции toggle (), которую мы использовали раньше. Это связано с тем, что toggle () — это не событие, а вспомогательная функция взаимодействия.
|
1
2
3
4
5
6
7
8
9
|
teardown: function(namespaces) {
for(var i in namespaces)
{
if(namespaces[i] == «TreeEvent»)
{
jQuery(this).unbind(‘click’, jQuery.event.special.toggleCollapse.TreeEvent.handler);
}
}
},
|
Наш метод разрыва аналогичен нашему методу настройки, но вместо этого мы открепим событие click от всех соответствующих элементов.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
TreeEvent: {
handler: function(event) {
if(event.target == event.currentTarget)
{
var elt = jQuery(this);
var cssClass = «collapsed»;
if(elt.hasClass(cssClass))
{
elt.children().slideDown().end().removeClass(cssClass);
}
else
{
elt.children().slideUp().end().addClass(cssClass);
}
event.type = «toggleCollapse»;
jQuery.event.handle.apply(this, arguments);
}
}
}
};
|
Здесь мы используем пространство имен TreeEvent для абстрагирования обработчика. В обработчике мы переключаемся между свернутым и расширенным состоянием в зависимости от того, содержит ли соответствующий элемент класс CSS «свернутый». Наконец, мы устанавливаем тип события равным нашему имени события toggleCollapse и используем метод apply (), который будет выполнять аргумент обратного вызова, когда мы связываем это специальное событие.
|
1
|
$(«#tree li:parent»).bind(«toggleCollapse.TreeEvent», function(evt) {});
|
Наконец, мы связываем наше специальное мероприятие с каталогами нашего каталога. Наш окончательный результат можно посмотреть здесь .
Дополнительные ресурсы
Ниже приведены несколько дополнительных ресурсов, которые могут оказаться полезными при работе с пользовательскими событиями. Спасибо за прочтение!
- API событий jQuery
- Объект события jQuery
- Пользовательские события в MooTools
- Пользовательские события в прототипе
- Подпишитесь на нас в Твиттере или подпишитесь на ленту Nettuts + RSS для получения лучших учебных материалов по веб-разработке.
