nodebb-plugin-ezoic-infinite 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/public/client.js +77 -58
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -1,24 +1,17 @@
|
|
|
1
|
-
/* globals ajaxify */
|
|
2
1
|
'use strict';
|
|
3
2
|
|
|
3
|
+
/* globals ajaxify */
|
|
4
4
|
window.ezoicInfiniteLoaded = true;
|
|
5
5
|
|
|
6
6
|
let cachedConfig;
|
|
7
7
|
let lastFetch = 0;
|
|
8
|
-
let debounceTimer;
|
|
9
8
|
|
|
9
|
+
let debounceTimer;
|
|
10
10
|
let lastSignature = null;
|
|
11
|
+
|
|
11
12
|
let inFlight = false;
|
|
12
13
|
let rerunRequested = false;
|
|
13
14
|
|
|
14
|
-
async function fetchConfig() {
|
|
15
|
-
if (cachedConfig && Date.now() - lastFetch < 10000) return cachedConfig;
|
|
16
|
-
const res = await fetch('/api/plugins/ezoic-infinite/config', { credentials: 'same-origin' });
|
|
17
|
-
cachedConfig = await res.json();
|
|
18
|
-
lastFetch = Date.now();
|
|
19
|
-
return cachedConfig;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
15
|
function parsePool(raw) {
|
|
23
16
|
if (!raw) return [];
|
|
24
17
|
return Array.from(new Set(
|
|
@@ -28,18 +21,28 @@ function parsePool(raw) {
|
|
|
28
21
|
));
|
|
29
22
|
}
|
|
30
23
|
|
|
31
|
-
function
|
|
32
|
-
|
|
24
|
+
async function fetchConfig() {
|
|
25
|
+
if (cachedConfig && Date.now() - lastFetch < 10000) return cachedConfig;
|
|
26
|
+
const res = await fetch('/api/plugins/ezoic-infinite/config', { credentials: 'same-origin' });
|
|
27
|
+
cachedConfig = await res.json();
|
|
28
|
+
lastFetch = Date.now();
|
|
29
|
+
return cachedConfig;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Robust DOM-based detection (no dependency on ajaxify template timing)
|
|
33
|
+
function isTopicPage() {
|
|
34
|
+
return $('[component="post/content"]').length > 0 || $('[component="post"][data-pid]').length > 0;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
function
|
|
36
|
-
return
|
|
37
|
+
function isCategoryTopicListPage() {
|
|
38
|
+
return $('li[component="category/topic"]').length > 0;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
function getTopicPosts() {
|
|
40
|
-
if (!isTopicTemplate()) return $();
|
|
41
42
|
const $primary = $('[component="post"][data-pid]');
|
|
42
43
|
if ($primary.length) return $primary.not('.ezoic-ad-post');
|
|
44
|
+
|
|
45
|
+
// Fallback: top-level data-pid containing post/content
|
|
43
46
|
return $('[data-pid]').filter(function () {
|
|
44
47
|
const $el = $(this);
|
|
45
48
|
const hasContent = $el.find('[component="post/content"]').length > 0;
|
|
@@ -49,7 +52,6 @@ function getTopicPosts() {
|
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
function getCategoryTopicItems() {
|
|
52
|
-
if (!isCategoryTemplate()) return $();
|
|
53
55
|
return $('li[component="category/topic"]').not('.ezoic-ad-topic');
|
|
54
56
|
}
|
|
55
57
|
|
|
@@ -57,11 +59,12 @@ function tagName($el) {
|
|
|
57
59
|
return ($el && $el.length ? (($el.prop('tagName') || '').toUpperCase()) : '');
|
|
58
60
|
}
|
|
59
61
|
|
|
60
|
-
function
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
function makeWrapperLike($target, classes, innerHtml) {
|
|
63
|
+
const t = tagName($target);
|
|
64
|
+
if (t === 'LI') {
|
|
65
|
+
return '<li class="' + classes + ' list-unstyled" data-ezoic-ad="1">' + innerHtml + '</li>';
|
|
66
|
+
}
|
|
67
|
+
return '<div class="' + classes + '" data-ezoic-ad="1">' + innerHtml + '</div>';
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
function computeWindowSlots(totalItems, interval, poolSize) {
|
|
@@ -73,15 +76,13 @@ function computeWindowSlots(totalItems, interval, poolSize) {
|
|
|
73
76
|
return out;
|
|
74
77
|
}
|
|
75
78
|
|
|
76
|
-
function
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
return '<div class="' + classes + '" data-ezoic-ad="1">' + innerHtml + '</div>';
|
|
79
|
+
function removeOurWrappers() {
|
|
80
|
+
$('.ezoic-ad-post').remove();
|
|
81
|
+
$('.ezoic-ad-between').remove();
|
|
82
|
+
$('.ezoic-ad-topic').remove();
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
function
|
|
85
|
+
function insertBetween($items, ids, interval, wrapperClass) {
|
|
85
86
|
const total = $items.length;
|
|
86
87
|
const slotsToRender = computeWindowSlots(total, interval, ids.length);
|
|
87
88
|
if (!slotsToRender.length) return [];
|
|
@@ -101,7 +102,7 @@ function insertBetweenGeneric($items, ids, interval, wrapperClass) {
|
|
|
101
102
|
return activeIds;
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
function
|
|
105
|
+
function insertMessageAds($posts, ids, interval) {
|
|
105
106
|
const total = $posts.length;
|
|
106
107
|
const slotsToRender = computeWindowSlots(total, interval, ids.length);
|
|
107
108
|
if (!slotsToRender.length) return [];
|
|
@@ -122,31 +123,45 @@ function insertAdMessagesBetweenReplies($posts, ids, interval) {
|
|
|
122
123
|
return activeIds;
|
|
123
124
|
}
|
|
124
125
|
|
|
125
|
-
function
|
|
126
|
+
function signatureFor($posts, $topicItems) {
|
|
127
|
+
if ($posts.length) {
|
|
128
|
+
const lastPid = $posts.last().attr('data-pid') || '';
|
|
129
|
+
return 'topic:' + $posts.length + ':' + lastPid;
|
|
130
|
+
}
|
|
131
|
+
if ($topicItems.length) {
|
|
132
|
+
const lastTid = $topicItems.last().attr('data-tid') || '';
|
|
133
|
+
return 'category:' + $topicItems.length + ':' + lastTid;
|
|
134
|
+
}
|
|
135
|
+
return 'none';
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Call Ezoic when ready (retry a few times, non-destructive)
|
|
139
|
+
function callEzoic(ids) {
|
|
126
140
|
if (!ids || !ids.length) return;
|
|
127
141
|
|
|
128
|
-
// Ezoic supports showAds(101,102,103) and recommends a single call with all ids.
|
|
129
142
|
window.ezstandalone = window.ezstandalone || {};
|
|
130
143
|
window.ezstandalone.cmd = window.ezstandalone.cmd || [];
|
|
131
|
-
|
|
144
|
+
|
|
145
|
+
const run = function () {
|
|
132
146
|
try {
|
|
133
147
|
if (typeof window.ezstandalone.showAds === 'function') {
|
|
134
148
|
window.ezstandalone.showAds.apply(window.ezstandalone, ids);
|
|
149
|
+
return true;
|
|
135
150
|
}
|
|
136
151
|
} catch (e) {}
|
|
137
|
-
|
|
138
|
-
}
|
|
152
|
+
return false;
|
|
153
|
+
};
|
|
139
154
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
155
|
+
// Use cmd queue first (best if Ezoic loads later)
|
|
156
|
+
window.ezstandalone.cmd.push(function () { run(); });
|
|
157
|
+
|
|
158
|
+
// Also retry a few times in case cmd isn't flushed promptly
|
|
159
|
+
let tries = 0;
|
|
160
|
+
const maxTries = 6;
|
|
161
|
+
const timer = setInterval(function () {
|
|
162
|
+
tries++;
|
|
163
|
+
if (run() || tries >= maxTries) clearInterval(timer);
|
|
164
|
+
}, 800);
|
|
150
165
|
}
|
|
151
166
|
|
|
152
167
|
async function refreshAds() {
|
|
@@ -163,34 +178,38 @@ async function refreshAds() {
|
|
|
163
178
|
const messagePool = parsePool(cfg.messagePlaceholderIds);
|
|
164
179
|
const messageInterval = Math.max(1, parseInt(cfg.messageIntervalPosts, 10) || 3);
|
|
165
180
|
|
|
166
|
-
const
|
|
167
|
-
const
|
|
181
|
+
const onTopic = isTopicPage();
|
|
182
|
+
const onCategory = !onTopic && isCategoryTopicListPage();
|
|
183
|
+
|
|
184
|
+
const $posts = onTopic ? getTopicPosts() : $();
|
|
185
|
+
const $topicItems = onCategory ? getCategoryTopicItems() : $();
|
|
168
186
|
|
|
169
187
|
if (!$posts.length && !$topicItems.length) return;
|
|
170
188
|
|
|
171
|
-
const
|
|
172
|
-
if (
|
|
173
|
-
lastSignature =
|
|
189
|
+
const sig = signatureFor($posts, $topicItems);
|
|
190
|
+
if (sig === lastSignature) return;
|
|
191
|
+
lastSignature = sig;
|
|
174
192
|
|
|
175
|
-
|
|
193
|
+
removeOurWrappers();
|
|
176
194
|
|
|
177
195
|
const activeIds = [];
|
|
178
196
|
|
|
179
|
-
//
|
|
197
|
+
// Your rule:
|
|
198
|
+
// - Category topic list: BETWEEN only
|
|
199
|
+
// - Topic page: MESSAGE only
|
|
180
200
|
if ($topicItems.length) {
|
|
181
201
|
if (cfg.enableBetweenAds && betweenPool.length) {
|
|
182
|
-
activeIds.push(...
|
|
202
|
+
activeIds.push(...insertBetween($topicItems, betweenPool, betweenInterval, 'ezoic-ad-topic'));
|
|
183
203
|
}
|
|
184
|
-
|
|
204
|
+
callEzoic(activeIds);
|
|
185
205
|
return;
|
|
186
206
|
}
|
|
187
207
|
|
|
188
|
-
// Topic pages: MESSAGE only (between replies)
|
|
189
208
|
if ($posts.length) {
|
|
190
209
|
if (cfg.enableMessageAds && messagePool.length) {
|
|
191
|
-
activeIds.push(...
|
|
210
|
+
activeIds.push(...insertMessageAds($posts, messagePool, messageInterval));
|
|
192
211
|
}
|
|
193
|
-
|
|
212
|
+
callEzoic(activeIds);
|
|
194
213
|
}
|
|
195
214
|
} finally {
|
|
196
215
|
inFlight = false;
|
|
@@ -203,9 +222,9 @@ async function refreshAds() {
|
|
|
203
222
|
|
|
204
223
|
function debounceRefresh() {
|
|
205
224
|
clearTimeout(debounceTimer);
|
|
206
|
-
debounceTimer = setTimeout(refreshAds,
|
|
225
|
+
debounceTimer = setTimeout(refreshAds, 200);
|
|
207
226
|
}
|
|
208
227
|
|
|
209
228
|
$(document).ready(debounceRefresh);
|
|
210
229
|
$(window).on('action:ajaxify.end action:posts.loaded action:topic.loaded', debounceRefresh);
|
|
211
|
-
setTimeout(debounceRefresh,
|
|
230
|
+
setTimeout(debounceRefresh, 2000);
|