FastComments.com

Писане на разширения

Разработване на разширения

Контекст

FastComments предоставя възможност за разширяване на основната ни функционалност чрез скриптове, които наричаме Extensions.

Един Extension може да добави допълнителна маркировка към коментарния уиджет, да добави слушатели на събития и да изпълнява произволен код.

Тук ще намерите примери за разширения, които имаме в продукция, както и документация за това как да пишете разширения.

Жизнен цикъл на разширението 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.

Това разширение не прави нищо, освен че при зареждане извлича обекта на разширението, създаден от основната библиотека за коментари.

Този Extension обект е единствен екземпляр и не се споделя с други разширения.

След това, за да заредим нашето разширение, трябва да уведомим коментарния уиджет за него. Например:

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. Използва се за lazy‑loading (мързеливо зареждане) на определени компоненти. Например, системата за отзиви не
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 - Препратка към обект, съдържащ всички коментари по ID, който се поддържа актуален.
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, който се добавя вътре в полето за въвеждане на коментар, под текстовото поле (използва се от анкети за вграден редактор на анкети). Приема ID на родителския коментар или null за главната кутия за отговор.
31 * @property {Function} [onPollUpdate] - Извиква се с живото събитие, когато броят на гласовете в анкета на страницата се промени.
32 * @property {Function} isSiteAdmin - Връща дали зрителят е администратор или модератор на наемателя. Известно след първото извличане.
33 * @property {FastCommentsUIExtensionMenuBottomCallback} [menuBottom] - (LEGACY) Връща HTML, който се добавя в долната част на елемента за меню за всеки коментар.
34 * @property {FastCommentsUIExtensionRenderCallback} [onRender]
35 * @property {FastCommentsUIExtensionConnectionStatusCallback} [onLiveConnectionStatusUpdate]
36 * @property {FastCommentsUIExtensionInitialRenderCallback} [onInitialRenderComplete]
37 * @property {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 по този начин, той ще бъде обединен в потребителския интерфейс чрез алгоритъм за 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