FastComments.com

Написання розширень

Розробка Extensions

Контекст

FastComments надає можливість розширювати нашу основну функціональність за допомогою скриптів, які ми називаємо Extensions.

Extension може додавати додаткову розмітку до віджета коментарів, реєструвати обробники подій та виконувати довільний код.

Тут ви знайдете приклади Extensions, які ми маємо у виробничому середовищі, а також документацію про те, як писати Extensions.


Життєвий цикл розширення Internal Link

Скрипт для кожного розширення завантажується та виконується до того, як віджет коментарів почне завантажувати перший набір коментарів і відображати інтерфейс користувача.

На початковому завантаженні до об'єкта розширення буде додано такі дані:

  • config - Посилання на об'єкт config.
  • translations - Посилання на об'єкт translations.
  • commentsById - Посилання на всі коментарі за id.
  • root - Посилання на кореневий DOM-вузол.

Розширення повинні перевизначити необхідні функції, які віджет коментарів викликатиме у відповідні моменти.

Визначення розширення Internal Link

Найменше можливе розширення виглядає так:

Просте розширення
Copy CopyRun External Link
1
2(function () {
3 const extension = FastCommentsUI.extensions.find((extension) => {
4 return extension.id === 'my-extension';
5 });
6})();
7

Для цього прикладу збережіть цей файл як my-extension.js і зробіть його доступним за адресою https://example.com/my-extension.min.js.

Це розширення нічого не робить, окрім того, що при завантаженні воно отримує об'єкт розширення, створений основною бібліотекою коментарів.

This Extension object is a singleton and is not shared with any other extensions.

Далі, щоб завантажити наше розширення, ми повинні повідомити віджет коментарів про нього. Наприклад:

Using a Custom Extension
Copy CopyRun External Link
1
2<script async src="https://cdn.fastcomments.com/js/embed-v2-async.min.js"></script>
3<div id="fastcomments-widget"></div>
4<script>
5window.fcConfigs = [{
6 "tenantId": "demo",
7 "extensions": [
8 {
9 "id": "my-extension",
10 "path": "https://example.com/my-extension.min.js"
11 }
12 ]
13}];
14</script>
15

Для функціональних прикладів див. наступний розділ.


Об'єкт розширення Internal Link

Об’єкт розширення складається з наступного визначення:

Об’єкт розширення JSDoc
Copy CopyRun External Link
1
2/**
3 * Об’єкт розширення FastCommentsUI. Використовується для відкладеного завантаження певних компонентів.
4 * Наприклад, система відгуків не використовується всіма клієнтами, тому ми завантажуємо це розширення лише коли це потрібно.
5 *
6 * @typedef {Object} FastCommentsUIExtension
7 * @property {string} id
8 * @property {Element} scriptNode
9 * @property {Element} root - Кореневий DOM‑елемент віджета.
10 * @property {string} [css]
11 * @property {Object} config - Об’єкт конфігурації FastComments.
12 * @property {Object} commentsById - Посилання на об’єкт з усіма коментарями за ідентифікатором, який постійно оновлюється.
13 * @property {Object} translations - Посилання на всі переклади.
14 * @property {Function} reRenderComment - Посилання на функцію, яку можна викликати для повторного рендерингу коментаря.
15 * @property {Function} removeCommentAndReRender - Посилання на функцію, яку можна викликати для видалення коментаря з пам’яті та повторного рендерингу відповідної частини DOM.
16 * @property {Function} newBroadcastId - Посилання на функцію, яку можна викликати для створення нового broadcast‑id та додавання його до локального списку broadcast‑id, які ігноруються.
17 * @property {FastCommentsUIExtensionSetupEventHandlers} [setupEventHandlers]
18 * @property {FastCommentsUIExtensionPrepareCommentForSavingCallback} [prepareCommentForSaving] - Викликається з коментарем, який збираються опублікувати. Повернути false, щоб скасувати відправку (наприклад, коли прикріплений опитування неповний).
19 * @property {FastCommentsUIExtensionNewCommentCallback} [newComment]
20 * @property {FastCommentsUIExtensionReplyAreaFilter} [replyAreaFilter] - Фільтрує HTML для області коментаря.
21 * @property {FastCommentsUIExtensionWidgetFilter} [widgetFilter] - Фільтрує HTML для всього віджета під час рендерингу.
22 * @property {FastCommentsUIExtensionCommentTopFilter} [commentFilter] - Фільтрує HTML для кожного коментаря перед рендерингом.
23 * @property {FastCommentsUIExtensionReplyAreaFilter} [commentMenuFilter] - Фільтрує HTML для кожного меню коментаря перед рендерингом.
24 * @property {FastCommentsUIExtensionMenuFilter} [menuFilter] - Фільтрує HTML для всього віджета під час рендерингу.
25 * @property {FastCommentsUIExtensionReplyAreaTop} [replyAreaTop] - (LEGACY) Повертає HTML, який додається у верхню частину області відповіді.
26 * @property {FastCommentsUIExtensionWidgetTopCallback} [widgetTop] - (LEGACY) Повертає HTML, який додається у верхню частину віджета.
27 * @property {FastCommentsUIExtensionCommentTopCallback} [commentTop] - (LEGACY) Повертає HTML, який додається у верхню частину елементу коментаря.
28 * @property {FastCommentsUIExtensionCommentBottomCallback} [commentBottom] - (LEGACY) Повертає HTML, який додається у нижню частину елементу коментаря.
29 * @property {FastCommentsUIExtensionCommentBottomCallback} [commentContentBottom] - Повертає HTML, який додається після тексту коментаря, всередині елементу вмісту коментаря (використовується в опитуваннях).
30 * @property {Function} [replyAreaInputBottom] - Повертає HTML, який додається всередині рамки вводу коментаря, під текстовим полем (використовується в опитуваннях для вбудованого редактора опитувань). Приймає ідентифікатор батьківського коментаря або null для кореневої області відповіді.
31 * @property {Function} [onPollUpdate] - Викликається під час живої події, коли змінюються підрахунки голосів в опитуванні на сторінці.
32 * @property {Function} isSiteAdmin - Повертає, чи є переглядач адміністратором або модератором орендаря. Відомо після першого запиту.
33 * @property {FastCommentsUIExtensionMenuBottomCallback} [menuBottom] - (LEGACY) Повертає HTML, який додається у нижню частину елементу меню для кожного коментаря.
34 * @property {FastCommentsUIExtensionRenderCallback} [onRender]
35 * @ {FastCommentsUIExtensionConnectionStatusCallback} [onLiveConnectionStatusUpdate]
36 * @ {FastCommentsUIExtensionInitialRenderCallback} [onInitialRenderComplete]
37 * @ {FastCommentsUIExtensionPresenceUpdateCallback} [onPresenceUpdate]
38 */
39
40/**
41 * @callback FastCommentsUIExtensionSetupEventHandlers
42 * @param {Element} element - Кореневий елемент.
43 * @param {Object.<string, Function>} clickListeners - Обробники подій кліків за назвою класу, які можуть бути змінені за посиланням.
44 * @returns void
45 */
46
47/**
48 * @callback FastCommentsUIExtensionWidgetTopCallback
49 * @param {Object} moduleData
50 * @returns {string}
51 */
52
53/**
54 * @callback FastCommentsUIExtensionWidgetFilter
55 * @param {Object} moduleData
56 * @param {Object} html
57 * @returns {string}
58 */
59
60/**
61 * @callback FastCommentsUIExtensionCommentTopCallback
62 * @param {Object} comment
63 * @returns {string}
64 */
65
66/**
67 * @callback FastCommentsUIExtensionCommentTopFilter
68 * @param {Object} comment
69 * @param {string} html
70 * @returns {string}
71 */
72
73/**
74 * @callback FastCommentsUIExtensionCommentBottomCallback
75 * @param {Object} comment
76 * @returns {string}
77 */
78
79/**
80 * @callback FastCommentsUIExtensionMenuBottomCallback
81 * @param {Object} comment
82 * @returns {string}
83 */
84
85/**
86 * @callback FastCommentsUIExtensionMenuFilter
87 * @param {Object} comment
88 * @param {string} html
89 * @returns {string}
90 */
91
92/**
93 * @callback FastCommentsUIExtensionRenderCallback
94 * @returns {string}
95 */
96
97/**
98 * @callback FastCommentsUIExtensionConnectionStatusCallback
99 * @param {boolean} isConnected
100 * @returns {void}
101 */
102
103/**
104 * @callback FastCommentsUIExtensionInitialRenderCallback
105 * @returns {void}
106 */
107
108/**
109 * @callback FastCommentsUIExtensionReplyAreaTop
110 * @param {Object|null} currentUser
111 * @param {boolean} isSaving
112 * @param {boolean} isReplyOpen
113 * @param {string|null} parentId
114 * @returns {string}
115 */
116
117/**
118 * @callback FastCommentsUIExtensionReplyAreaFilter
119 * @param {Object|null} currentUser
120 * @param {boolean} isSaving
121 * @param {boolean} isReplyOpen
122 * @param {string|null} parentId
123 * @param {string|null} html
124 * @returns {string}
125 */
126
127/**
128 * @callback FastCommentsUIExtensionPrepareCommentForSavingCallback
129 * @param {Object} comment
130 * @param {string} parentId
131 */
132
133/**
134 * @callback FastCommentsUIExtensionNewCommentCallback
135 * @param {Object} comment
136 */
137
138/**
139 * @callback FastCommentsUIExtensionPresenceUpdateCallback
140 * @param {Object} update
141 */
142

API розширення Internal Link

Взаємодія з Extension проста: ми просто визначаємо посилання на функції, які хочемо викликати.

Продовжуючи попередній приклад, припустімо, що ми хочемо додати HTML зверху кожного коментаря:

Просте розширення — продовження
Copy CopyRun External Link
1
2(function () {
3 const extension = FastCommentsUI.extensions.find((extension) => {
4 return extension.id === 'my-extension';
5 });
6
7 extension.commentFilter = function(comment, html) {
8 return `<h3>The user's name is ${comment.commenterName}!</h3>` + html;
9 }
10})();
11

Коли ви повертаєте HTML таким чином, він буде об'єднаний з UI за допомогою алгоритму dom-diffing.

Ручний повторний рендер коментаря

Ми можемо дочекатися початкового завантаження сторінки і вручну повторно відрендерити коментар, викликавши reRenderComment:

Повторний рендер коментаря
Copy CopyRun External Link
1
2(function () {
3 const extension = FastCommentsUI.extensions.find((extension) => {
4 return extension.id === 'my-extension';
5 });
6
7 let renderCount = 0;
8
9 extension.commentFilter = function(comment, html) {
10 renderCount++;
11 return `<h3>The render count is ${renderCount}!</h3>` + html;
12 }
13
14 extension.onInitialRenderComplete = function() {
15 setInterval(function() {
16 extension.reRenderComment(extension.commentsById[Object.keys(extension.commentsById)[0]], function renderDone() {
17 console.log('Comment re-render done.');
18 });
19 }, 2000); // таймаут не обов'язковий, просто приклад.
20 }
21})();
22