События
В i-bem.js
поддерживается два вида событий:
DOM-события — события на DOM-узле, связанном с блоком или элементом. Отражают взаимодействие пользователя с интерфейсом (клик, наведение мыши, ввод текста и т.п.). DOM-события обычно обрабатывает тот экземпляр блока или элемента, на DOM-узлах которого они возникают.
БЭМ-события — собственные события, генерируемые блоком или элементом. Позволяют организовать API для взаимодействия с блоком. БЭМ-события обычно обрабатывает экземпляр, отслеживающий состояние других блоков или элементов, на которых генерируются события.
DOM-события следует использовать только во взаимодействиях экземпляра со своим DOM-узлом или блока со своими элементами. Для взаимодействия с другими блоками или элементами предназначены БЭМ-события.
DOM-события
Работа с DOM-событиями в i-bem-dom
полностью реализована средствами фреймворка jQuery.
Подписка на DOM-события
Из экземпляра
Для подписки на DOM-события из экземпляра служит метод _domEvents()
, создающий специальный объект менеджера событий.
Метод принимает один опциональный параметр, задающий контекст, который может быть разных типов:
elemInstance
{Elem|BemDomCollection}
– экземпляр или коллекция элементов.elemClass
{String|Function|Object}
— класс, имя или описание элемента. Описанием служит хеш вида{ elem : MyElem, modName : 'my-mod', modVal : 'my-val' }
или{ elem : 'my-elem', modName : 'my-mod', modVal : 'my-val' }
.document
{Document|jQuery}
— документwindow
{Window|jQuery}
— окно
Менеджер событий обладает необходимым интерфейсом для подписки на события и отписки от них.
Пример
В момент инициализации экземпляра блока my-block
выполняется подписка на событие click
, при наступлении которого блок выставляет себе модификатор size
в значение big
.
bemDom.declBlock('my-block', {
onSetMod : {
'js' : {
'inited': function() {
this._domEvents().on('click', function() {
this.setMod('size', 'big');
});
}
}
}
});
Пример
При инициализации экземпляра блока my-form
выполняется подписка на событие click
элемента button
, при наступлении которого будет вызвана функция-обработчик _onSubmit
.
bemDom.declBlock('my-form', {
onSetMod : {
'js' : {
'inited': function() {
this._domEvents('button').on('click', this._onSubmit);
}
}
},
_onSubmit : function() { /* ... */ }
});
Примечание Функция-обработчик выполняется в контексте того экземпляра, от которого создавался менеджер событий.
Из класса
Для подписки на DOM-события из класса служит статический метод _domEvents()
, создающий специальный объект менеджера событий. Метод принимает один опциональный параметр, задающий контекст, который может быть разных типов:
elemClass
{String|Function|Object}
— класс, имя или описание элемента. Описанием служит хеш вида{ elem : MyElem, modName : 'my-mod', modVal : 'my-val' }
или{ elem : 'my-elem', modName : 'my-mod', modVal : 'my-val' }
.document
{Document|jQuery}
— документwindow
{Window|jQuery}
— окно
Менеджер событий обладает необходимым интерфейсом для подписки на события и отписки от них.
Пример
При инициализации класса блока my-form
выполняется подписка на событие click
всех элементов button
внутри любого блока my-form
, при наступлении которого выполнится инициализация блока my-form
(если он уже не проинициализирован) и у полученного экземпляра будет вызвана функция-обработчик _onSubmit
.
bemDom.declBlock('my-form', {
_onSubmit : function() { /* ... */ }
}, {
lazyInit : true,
onInit : function() {
this._domEvents('button').on('click', this.prototype._onSubmit);
}
});
Примечание Функция-обработчик выполняется в контексте того экземпляра, внутри которого случилось событие.
Удаление подписки на DOM-событие
Удаление подписки на DOM-события выполняется автоматически при уничтожении экземпляра. Тем не менее, с помощью менеджера событий можно удалить подписки вручную во время работы экземпляра.
_stopKeysListening : function() {
this._domEvents().un('keydown', this._onKeydown); // удаляем обработчик события 'keydown'
}
Объект DOM-события
Первым аргументом функция-обработчик получает jQuery-объект DOM-события — {jQuery.Event}.
Это позволяет использовать методы объекта stopPropagation
и preventDefault
для управления всплытием события и реакцией на него браузера.
bemDom.declBlock('my-form', {
onSetMod : {
'js' : {
'inited': function() {
this._domEvents('button').on('click', function(e) {
e.stopPropagation(); // останавливаем всплытие события
this._onSubmit();
});
}
}
},
_onSubmit : function() {
/* ... */
}
});
БЭМ-события
В отличие от DOM-событий, БЭМ-события генерируются не на DOM-элементах, а на экземплярах блоков и элементов.
Генерация БЭМ-события
Для генерации БЭМ-события используется метод экземпляра _emit(event, [data])
.
event
{String|events:Event}
— имя или объект события.[data]
{*}
— дополнительные данные для события, которые будут доступны во втором аргументе обработчика.
При взаимодействии пользователя с элементом управления блока возникают DOM-события. В ходе их обработки блоком можно создавать БЭМ-события. Это позволяет реализовать уровень абстракции над DOM-событиями.
Например, при клике по кнопке button
(DOM-событие click
) БЭМ-событие click
генерируется только в том случае, если у блока в этот момент не установлен модификатор disabled
:
bemDom.declBlock('button', {
onSetMod: {
'js': {
'inited': function() {
this._domEvents().on('click', this._onClick); // подписка на DOM-событие "click"
}
}
},
_onClick: function() {
if(!this.hasMod('disabled')) {
this._emit('click'); // создание БЭМ-события "click"
}
}
});
Подписка на БЭМ-события
Из экземпляра
Для подписки на БЭМ-события из экземпляра служит метод _events()
, создающий специальный объект менеджера событий. Метод принимает один опциональный параметр, задающий контекст, который может быть разных типов:
entityInstance
{Elem|BemDomCollection}
– экземпляр или коллекция БЭМ-сущностей.entityClass
{String|Function|Object}
— класс, имя или описание БЭМ-сущности. Описанием служит хеш вида{ block : MyBlock, modName : 'my-mod', modVal : 'my-val' }
,{ elem : MyElem, modName : 'my-mod', modVal : 'my-val' }
или{ elem : 'my-elem', modName : 'my-mod', modVal : 'my-val' }
.
Менеджер событий обладает необходимым интерфейсом для подписки на события и отписки от них, в том числе для работы с событиями на изменения модификатора.
Пример
В момент инициализации HTML-формы (экземпляра блока my-form
) выполняется поиск вложенной в форму кнопки button
и подписка на ее БЭМ-событие click
. В результате при нажатии на кнопку (экземпляр блока button
) будет выполнен метод _onSubmit
формы (экземпляр блока my-form
).
modules.define('my-form', ['i-bem-dom', 'button'], function(provide, bemDom, Button) {
provide(bemDom.declBlock(this.name, {
onSetMod: {
'js': {
'inited': function() {
this._events(this.findChildBlock(Button))
.on('click', this._onSubmit);
}
}
},
_onSubmit: function() { /* ... */ }
}));
});
Из класса
Для подписки на БЭМ-события из класса служит статический метод _events()
, создающий специальный объект менеджера событий.
Метод принимает один опциональный параметр, задающий контекст, который может быть разных типов:
entityClass
{String|Function|Object}
— класс, имя или описание БЭМ-сущности. Описанием служит хеш вида{ block : MyBlock, modName : 'my-mod', modVal : 'my-val' }
,{ elem : MyElem, modName : 'my-mod', modVal : 'my-val' }
или{ elem : 'my-elem', modName : 'my-mod', modVal : 'my-val' }
.
Менеджер событий обладает необходимым интерфейсом для подписки на события и отписки от них, в том числе для работы с событиями на изменения модификатора.
Пример
При инициализации класса блока my-form
выполняется подписка на событие click
любого блока button
внутри любого my-form
, при наступлении которого выполнится инициализация блока my-form
(если он уже не проинициализирован) и у полученного экземпляра будет вызвана функция-обработчик _onSubmit
.
modules.define('my-form', ['i-bem-dom', 'button'], function(provide, bemDom, Button) {
provide(bemDom.declBlock(this.name, {
_onSubmit: function() { /* ... */ }
}, {
lazyInit : true,
onInit : function() {
this._events(Button).on('click', this.prototype._onSubmit);
}
}));
});
Примечание Функция-обработчик выполняется в контексте того экземпляра класса, производящего подписку, внутри которого случилось событие.
Объект менеджера событий
Менеджер событий служит для унификации работы со всеми видами событий.
Обладает API:
Метод on(event, [data], fn)
служит для подписки на событие event
, обработчика fn
, с возможностью передачи опциональных данных data
. Принимает аргументы:
event
String|Object
— имя события, хеш для события при изменении модификатора или объект события (jQuery.Event
для DOM-событий илиevents:Event
для БЭМ-событий).[data]
*
— дополнительные данные для события, которые будут доступны в полеdata
объекта события.fn
Function
— функция-обработчик события.
Метод once(event, [data], fn)
служит для единоразовой подписки на событие event
, обработчика fn
, с возможностью передачи опциональных данных data
. Аргументы аналогичны методу on()
.
Метод un([event], [fn])
служит для удаления подписки на события.
Принимает аргументы:
[event]
String|Object
— опциональное имя события, хеш для события при изменении модификатора, или объект события (jQuery.Event
для DOM-событий илиevents:Event
для БЭМ-событий). В случае, если аргумент не указан, происходит удаление подписок на все события.[fn]
Function
— функция-обработчик события. В случае, если аргумент не указан, происходит удаление всех обработчиков событияevent
.
События при изменении модификаторов
В случае с БЭМ-событиями, существуют специальные события на изменение модификаторов, которые генерируются автоматически.
Для работы с такими событиями используется специальный хеш с полями:
modName
{String}
– имя модификатора.modVal
{String}
– значение модификатора. Со значением*
производится подписка на установку модификатора в любое значение. Со значением''
– на удаление модификатора.
Пример
В момент инициализации блок my-form
подписывается на событие изменения модификатора у вложенного блока button
.
К примеру, можно подписаться на:
установку модификатора
disabled
в любое значение;modules.define('my-form', ['i-bem-dom', 'button'], function(provide, bemDom, Button) { bemDom.declBlock('form', { onSetMod: { 'js': { 'inited': function() { this._events(this.findChildBlock(Button)) .on({ modName : 'disabled', modVal : '*' }, this._onButtonDisabledChange); } } }, _onButtonDisabledChange() {} }); });
установку модификатора
'disabled'
в значение'true'
;this._events(this.findChildBlock(Button)).on({ modName : 'disabled', modVal : 'true' }, this._onButtonDisable);
удаление модификатора
'disabled'
;this._events(this.findChildBlock(Button)).on({ modName : 'disabled', modVal : '' }, this._onButtonEnable);
Объект БЭМ-события
При вызове функция-обработчик получает аргументом объект, описывающий БЭМ-событие. Класс объекта БЭМ-события events.Event
определен в ym-модуле events
библиотеки bem-core.
Объект содержит поля:
type
{String}
— тип события. Аналогично jQuery.Event.type.target
{i-bem-dom:Entity}
— экземпляр блока или элемента, в котором произошло БЭМ-событие.data
{*}
— произвольные дополнительные данные, переданные как аргументdata
при подписке на БЭМ-событие.result
{*}
— последнее значение, возвращенное обработчиком данного события. Аналогично jQuery.Event.result.