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

Обектът extension се състои от следната дефиниция:

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

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