События объекта Element
Самые полезные для нас на данный момент события, поддерживаемые объектом Element библиотеки Ext Core, представлены в табл. 15.1. Их довольно много, и некоторые из них поддерживаются только определенными элементами Web- страницы.
Таблица 15.1. События объекта Element
Привязка и удаление обработчиков событий
Метод on объекта Element выполняет привязку указанной функции к указанному событию данного элемента Web-страницы в качестве обработчика:
<экземпляр объекта Element>.on(<событие>, <функция-обработчик>)
Первым параметром методу передается строка с названием события, к которому выполняется привязка обработчика. Названия событий приведены в первом столбце табл. 15.1.
Второй параметр — функция, которая станет обработчиком события. Эта функция должна принимать следующие параметры:
— первый — экземпляр объекта EventObject, представляющий сведения о событии и позволяющий им управлять (мы рассмотрим этот объект потом);
— второй — экземпляр объекта HTMLElement, представляющий элемент Web-страницы, в котором изначально возникло данное событие.
Кроме того, в функцию-обработчик неявно передается еще один параметр — экземпляр объекта HTMLElement, представляющий элемент Web-страницы, в котором в данный момент обрабатывается данное событие, — тот самый элемент, к которому привязан этот обработчик. Событие могло возникнуть в нем изначально, а могло всплыть из дочернего элемента; подробнее об этом будет рассказано в следующем разделе. Данный параметр доступен в теле функции-обработчика через переменную this.
Пример:
Ext.get("navbar"). on("mouseover", function(e, t) { Ext.get(this). addClass("hovered");});
Здесь мы привязываем к списку navbar обработчик события mouseover. Первый параметр метода on определяет название события, которое мы хотим обрабатывать. Второй параметр этого метода содержит объявление функции-обработчика.
В теле функции-обработчика мы обращаемся к переменной this, чтобы получить экземпляр объекта HTMLElement, представляющий элемент Web-страницы, чье событие мы обрабатываем. Чтобы получить из него соответствующий экземпляр объекта Element, мы используем метод get. После чего привязываем к полученному экземпляру объекта Element стилевой класс hovered вызовом метода addClass.
Отметим, что наша функция-обработчик принимает два параметра, которые, впрочем, нигде в ее теле не используются. Так что мы можем вообще не указывать их в объявлении функции-обработчика:
Ext.get("navbar"). on("mouseover", function() {Ext.get(this). addClass("hovered");});
Мы можем оформить обработчик события в виде функции, имеющей имя, а потом указать это имя в качестве второго параметра метода on:
function navbarMouseOver() { Ext.get(this). addClass("hovered");}
Ext.get("navbar"). on("mouseover", navbarMouseOver);
Это полезно, если мы хотим привязать один обработчик сразу к нескольким событиям одного или нескольких элементов Web-страницы.
Метод removeAllListeners объекта Element удаляет все привязанные к данному элементу Web-страницы обработчики событий. Он не принимает параметров.
Пример:
Ext.get("navbar"). removeAllListeners();
Всплытие и действие по умолчанию
И еще два важных вопроса, без понимания которых невозможно писать эффективные обработчики событий, — всплытие событий и их действия по умолчанию.
Давайте рассмотрим пункты списков, формирующих полосу навигации, и "внешнего", и вложенного. Мы привязали к ним обработчики событий mouseOver и mouseOut — это выполняет второй Web-сценарий, написанный нами в главе 14. Его фрагмент приведен в листинге 15.5.
Листинг 15.5
var ceLinks = Ext.select("UL[id=navbar] LI"); ceLinks.on("mouseover", function(e, t) { Ext.get(this). addClass("hovered");});
ceLinks.on("mouseout", function(e, t) { Ext.get(this). removeClass("hovered");});
Откроем Web-страницу index.htm в Web-обозревателе и наведем курсор мыши на пункт "HTML" "внешнего" списка. Рамка вокруг него тотчас станет более темной. Уберем курсор — и рамка примет прежний цвет. Обработчики событий mouseOver и mouseOut работают.
Теперь наведем курсор мыши на один из пунктов вложенного списка, например, "AUDIO". Вокруг этого пункта также появится рамка. Что и неудивительно, ведь к пунктам вложенного списка также привязаны обработчики соответствующих событий.
Но при этом изменит свой цвет и рамка вокруг пункта "HTML" "внешнего" списка! Выходит, данные события возникают не только в пункте "AUDIO" вложенного списка, но и в пункте "HTML" "внешнего" списка, в который он вложен. Почему?
Вот тут мы столкнулись со всплытием событий. Событие, возникшее в каком-либо элементе Web-страницы, после этого возникает в его родителе, далее в родителе родителя и т. д., пока оно не достигнет секции тела Web-страницы (тега <BODY>). Можно сказать, что событие "всплывает" из элемента в элемент "вверх" по уровню их вложенности друг в друга.
Давайте рассмотрим всплытие событий на примере нашей полосы навигации. Мы наводим курсор мыши на пункт "AUDIO" вложенного списка. В нем (в теге <LI>) возникает событие mouseOver. Поскольку к данному пункту списка привязан обработчик этого события, Web-обозреватель его выполняет. Далее событие "всплывает" в сам вложенный список (тег <UL>). Никаких обработчиков событий мы к нему не привязали, поэтому событие сразу же следует в пункт "HTML" "внешнего" списка, в котором находится вложенный список. К нему, опять же, привязан обработчик события mouseOver, который выполняется Web-обозревателем. Далее событие "всплывает" во "внешний" список, контейнер cnavbar и секцию тела Web-страницы, в которой и прекращает свое существование.
Теперь посмотрим на пункт "AUDIO" вложенного списка. В него вложен тег <CODE>, в который, в свою очередь, вложена гиперссылка (тег <A>), а в нее — уже текст "AUDIO". Когда мы наводим курсор мыши на этот текст, событие mouseOver возникает-то в теге <A>! Потом оно "всплывает" в тег <CODE>, а уже после этого — в тег <LI>, формирующий пункт списка "AUDIO", где и обрабатывается.
А сейчас представим, что событие mouseOver не всплывает. Тогда, чтобы обработать его в пункте вложенного списка, нам пришлось бы привязывать разные обработчики к тегам <LI>, <CODE> и <A>. Представляете, сколько потребуется кода! Который в этом случае будет еще и заметно сложнее…
Так что всплытие событий — благо для Web-программиста. Благодаря ему мы можем писать обработчики, реагирующие на события сразу в нескольких элементах Web-страницы, — для этого достаточно привязать обработчик к родителю этих элементов. Так, кстати, часто и делают.
Теперь об обработке всплывающих событий. Мы уже знаем, что функция — обработчик события принимает три параметра: два — явно, третий — неявно.
— Первый явный параметр — экземпляр объекта EventObject, хранящий сведения о событии. Разговор о нем пока отложим.
— Второй явный параметр — экземпляр объекта HTMLElement, представляющий элемент Web-страницы, в котором изначально возникло это событие. Отметим — возникло изначально, т. е. событие гарантированно не всплыло в него из какого-либо дочернего элемента.
— Неявный параметр, доступный в теле функции-обработчика через переменную this, — экземпляр объекта HTMLElement, представляющий элемент Web-страницы, в котором это событие обрабатывается, т. е. тот элемент, к которому привязан обработчик. Причем событие могло как возникнуть в этом элементе изначально, так и всплыть из дочернего элемента.
Если событие всплыло в данный элемент Web-страницы из дочернего элемента, то оба эти параметра указывают на разные элементы Web-страницы. Помните об этом!
Ради эксперимента давайте изменим код второго Web-сценария, написанного в главе 14, так, как показано в листинге 15.6.
Листинг 15.6
var ceLinks = Ext.select("UL[id=navbar] LI"); ceLinks.on("mouseover", function(e, t) { Ext.get(t). addClass("hovered");});
ceLinks.on("mouseout", function(e, t) { Ext.get(t). removeClass("hovered");});
Здесь мы в теле функций-обработчиков получаем не элемент, в котором обрабатывается событие (переменная this), а элемент, в котором это событие изначально возникло (второй параметр этих функций t). Что получится в результате?
Наведем курсор мыши на текст пункта "AUDIO" списка. В теге <A> возникнет событие mouseover, которое потом всплывет в тег <CODE> и далее — в тег <LI>. В теге <LI> оно и будет обработано. Только стилевой класс hovered в результате будет привязан не к тегу <LI>, а к тегу <A>! А поскольку для этого тега больше никаких параметров рамки не задано (стилевой класс hovered задает только цвет рамки — см. главу 14), рамка вокруг него не появится. Совсем другой результат!
В табл. 15.1, перечисляющей события объекта Element, прямо указано, какие события всплывают, а какие — нет. Да-да, не все события относятся к всплывающим… Но такие "невсплывающие" события обычно очень специфичны и требуют обработки, что называется, на месте.