-
Notifications
You must be signed in to change notification settings - Fork 1
Widgets
Для подключения js-виджетов, которые должны работать только в рамках какого-то блока, нужно использовать атрибут data-js-widgets="..."
. При желании, можно указать несколько таких виджетов через запятую.
<section data-reload-sections="…">
<div data-js-widgets="/js/some_widget1.js, /js/some_widget2.js"></div>
<div></div>
</section>
Этот атрибут можно указать у любого DOM-элемента. При инициализации виджета этот элемент будет передан ему соответствующим параметром.
Виджеты пишутся по стандарту AMD. Определяющая функция должна возвращать объект, который расширяет базовый интерфейс.
Пример минимально достаточного виджета:
define([], function(){
return {}
});
define([], function(){
return {
domEvents:
// (см. ниже domEvents)
},
moduleEvents: {
// (см. ниже moduleEvents)
},
init: function(){
// Опциональная функция. Вызывается в самом начале, если определена.
// Поле @element является ссылкой на DOM-элемент, к которому
// этот виджет был подключен
},
turnOn: function(){
// Optional function.
// Вызывает в ситуации, когда виджет «включается».
},
turnOff: function(){
// Optional function.
// Вызывается в ситуации, когда виджет «выключается».
// Используется очень редко. Имеет смысл использовать
// Только для отписки от событий, которые были навешены
// вручную внутри turnOn()
}
}
});
Для более аккуратной работы с памятью и для предотвращения лишних утечек
рекомендуется использовать соответствующие поля — domEvents
и moduleEvents
.
Внутри инстанцированного виджета доступна переменная @element
, которая является ссылкой на корневой DOM-элемент, в рамках которого инстанцирован виджет. (к которому этот виджет был подключен).
Используется для подписки на DOM-события, которые могут случиться на child-элементах виджета. Например:
domEvents: {
"click #someId": "callbackName",
"click #someSecondId": someFunction,
"click #someThirdId": function(evt, element){ … }
"click @element": "secondCallbackName"
}
callbackName: function(evt, targetEl) {
// evt — стандартный объект события
// evt.target - DOM-node, на которой произошло событие (клик мышкой)
// targetEl — тот элемент, на который была оформлена подписка.
// this — контекст объекта самого виджета (важно!)
}
Обратите внимание, что someFunction
, также как и анонимная функция вызовутся тоже в контексте этого виджета.
targetEl
введен специально для ситуаций, когда вы повесили обработчик на общий контейнер, а внутри, например есть картинка — тогда браузер изначально в event событии будет считать, что evt.target — это картинка. Тем не менее targetEl
будет тем самым нужным контейнером.
Напомним, что @element — это корневой DOM-элемент, на котором инстанцирован виджет.
Используется для подписки на кастомные события, использующиеся внутри архитектуры, либо в других таких же виджетах. События таково рода проходят глобально, через внутренний модуль events
.
moduleEvents:
"someCustomEventName": "callbackName"
"anotherEventName": {
handler: "anotherCallback",
isSync: false,
recall: false,
}
}
callbackName: function(data){
// data — сопроводительные данные, если таковые были в момент генерации события
}
Также есть возможность использовать дополнительные параметры подписки, которые свойственны модулю events
. В таком случае надо указывать объект, где имя хендлера передается в поле handler
.
isSync
— означает, что хендлер надо вызвать синхронно. По умолчанию false
.
recall
— если true
и такое событие уже случалось раньше, до момента инициализации виджета, то сразу же вызывает handler
с данными последнего случая события. По умолчанию false
.
Optional functions. Используются очень редко.
turnOn()
— для навешивания событий, которые никак нельзя навесить через domEvents
и moduleEvents
. Вызывается автоматически при первой инициализации и в моменты «включения» виджета — например, когда пользователь идет назад по истории.
turnOff()
— для отписки от таких «ручных» событий. Вызывается в моменты «выключения» виджета. Например, когда DOM-элемент, к которому приписан виджет, изымается из DOM дерева.
Например: window.onscroll
, window.onresize
или что-то еще подобное.
Тем не менее, если есть возможность всю работу, например,
с window.onscroll
вынести в отдельный модуль, который будет
триггерить нужные события через events
(см. ниже), то лучше это сделать.
turnOn: function() {
$(window).on("scroll.myWidget", $.proxy(@_onScroll, @))
},
turnOff: function() {
$(window).off("scroll.myWidget")
},
_onScroll: function(evt) {
// … some actions on scrolling …
}
Для того, чтобы создавать события, на которые могут подписаться другие виджеты, нужно задействовать базовый модуль events
.
define(["events"], function(events){
init: function(){
events.trigger("my-widget-event", [customData1, customData2, ...])
}
});
В таком случае, в другом виджете (или, если угодно, в том же самом ;) подписка будет выглядеть таким образом:
define([], function(events){
moduleEvents: {
"my-widget-event": "myWidgetEventCallback"
}
myWidgetEventCallback: function(data){
// data = [customData1, customData2, …]
}
init: function(){
// ...
}
});