nodebb-plugin-ezoic-infinite 0.6.5 → 0.6.7
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/plugin.json +4 -1
- package/public/client.js +30 -27
- package/public/style.css +2 -0
package/package.json
CHANGED
package/plugin.json
CHANGED
package/public/client.js
CHANGED
|
@@ -12,12 +12,12 @@ let rerunRequested = false;
|
|
|
12
12
|
|
|
13
13
|
// Per-page incremental state
|
|
14
14
|
let pageKey = null;
|
|
15
|
-
let
|
|
15
|
+
let seenSlots = new Set(); // slots already processed (never cleared on eviction)
|
|
16
16
|
let usedIds = new Set(); // IDs currently present in DOM
|
|
17
|
-
let adsFIFO = []; // [{
|
|
17
|
+
let adsFIFO = []; // [{slot, id}] oldest first
|
|
18
18
|
|
|
19
19
|
function resetPageState() {
|
|
20
|
-
|
|
20
|
+
seenSlots = new Set();
|
|
21
21
|
usedIds = new Set();
|
|
22
22
|
adsFIFO = [];
|
|
23
23
|
}
|
|
@@ -58,36 +58,44 @@ function isCategoryTopicListPage() {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
function getTopicPosts() {
|
|
61
|
+
// Only real posts
|
|
61
62
|
const $primary = $('[component="post"][data-pid]');
|
|
62
|
-
if ($primary.length) return $primary
|
|
63
|
+
if ($primary.length) return $primary;
|
|
63
64
|
|
|
65
|
+
// Fallback: top-level with post/content
|
|
64
66
|
return $('[data-pid]').filter(function () {
|
|
65
67
|
const $el = $(this);
|
|
66
68
|
const hasContent = $el.find('[component="post/content"]').length > 0;
|
|
67
69
|
const nested = $el.parents('[data-pid]').length > 0;
|
|
68
70
|
return hasContent && !nested;
|
|
69
|
-
})
|
|
71
|
+
});
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
function getCategoryTopicItems() {
|
|
73
|
-
return $('li[component="category/topic"]')
|
|
75
|
+
return $('li[component="category/topic"]');
|
|
74
76
|
}
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
// If target's parent is UL/OL, wrapper MUST be LI (otherwise browser may move it to top)
|
|
79
|
+
function wrapperTagFor($target) {
|
|
80
|
+
if (!$target || !$target.length) return 'div';
|
|
81
|
+
const parentTag = ($target.parent().prop('tagName') || '').toUpperCase();
|
|
82
|
+
if (parentTag === 'UL' || parentTag === 'OL') return 'li';
|
|
83
|
+
const selfTag = ($target.prop('tagName') || '').toUpperCase();
|
|
84
|
+
if (selfTag === 'LI') return 'li';
|
|
85
|
+
return 'div';
|
|
78
86
|
}
|
|
79
87
|
|
|
80
88
|
function makeWrapperLike($target, classes, innerHtml, attrs) {
|
|
81
|
-
const
|
|
89
|
+
const tag = wrapperTagFor($target);
|
|
82
90
|
const attrStr = attrs ? ' ' + attrs : '';
|
|
83
|
-
if (
|
|
91
|
+
if (tag === 'li') {
|
|
84
92
|
return '<li class="' + classes + ' list-unstyled"' + attrStr + '>' + innerHtml + '</li>';
|
|
85
93
|
}
|
|
86
94
|
return '<div class="' + classes + '"' + attrStr + '>' + innerHtml + '</div>';
|
|
87
95
|
}
|
|
88
96
|
|
|
89
97
|
function cleanupWrappersOnNav() {
|
|
90
|
-
$('.ezoic-ad-post, .ezoic-ad-
|
|
98
|
+
$('.ezoic-ad-post, .ezoic-ad-topic, .ezoic-ad-between').remove();
|
|
91
99
|
}
|
|
92
100
|
|
|
93
101
|
function pickNextId(pool) {
|
|
@@ -105,7 +113,6 @@ function evictOldestOne() {
|
|
|
105
113
|
const $el = $(sel);
|
|
106
114
|
if ($el.length) $el.remove();
|
|
107
115
|
|
|
108
|
-
injectedSlots.delete(old.slot);
|
|
109
116
|
usedIds.delete(old.id);
|
|
110
117
|
return true;
|
|
111
118
|
}
|
|
@@ -145,7 +152,7 @@ function injectBetweenIncremental($items, pool, interval, wrapperClass) {
|
|
|
145
152
|
const newIds = [];
|
|
146
153
|
|
|
147
154
|
for (let slot = 1; slot <= maxSlot; slot++) {
|
|
148
|
-
if (
|
|
155
|
+
if (seenSlots.has(slot)) continue;
|
|
149
156
|
|
|
150
157
|
const index = slot * interval - 1;
|
|
151
158
|
const $target = $items.eq(index);
|
|
@@ -153,7 +160,6 @@ function injectBetweenIncremental($items, pool, interval, wrapperClass) {
|
|
|
153
160
|
|
|
154
161
|
let id = pickNextId(pool);
|
|
155
162
|
if (!id) {
|
|
156
|
-
// Pool full: evict oldest, then reuse freed ID
|
|
157
163
|
if (!evictOldestOne()) break;
|
|
158
164
|
id = pickNextId(pool);
|
|
159
165
|
if (!id) break;
|
|
@@ -162,16 +168,16 @@ function injectBetweenIncremental($items, pool, interval, wrapperClass) {
|
|
|
162
168
|
const placeholder = '<div id="ezoic-pub-ad-placeholder-' + id + '"></div>';
|
|
163
169
|
const html = makeWrapperLike(
|
|
164
170
|
$target,
|
|
165
|
-
wrapperClass,
|
|
171
|
+
wrapperClass + ' ezoic-ad',
|
|
166
172
|
placeholder,
|
|
167
173
|
'data-ezoic-slot="' + slot + '" data-ezoic-id="' + id + '"'
|
|
168
174
|
);
|
|
169
175
|
|
|
170
176
|
$target.after(html);
|
|
171
177
|
|
|
172
|
-
|
|
178
|
+
seenSlots.add(slot);
|
|
173
179
|
usedIds.add(id);
|
|
174
|
-
adsFIFO.push({
|
|
180
|
+
adsFIFO.push({ slot: slot, id: id });
|
|
175
181
|
newIds.push(id);
|
|
176
182
|
}
|
|
177
183
|
|
|
@@ -186,7 +192,7 @@ function injectMessageIncremental($posts, pool, interval) {
|
|
|
186
192
|
const newIds = [];
|
|
187
193
|
|
|
188
194
|
for (let slot = 1; slot <= maxSlot; slot++) {
|
|
189
|
-
if (
|
|
195
|
+
if (seenSlots.has(slot)) continue;
|
|
190
196
|
|
|
191
197
|
const index = slot * interval - 1;
|
|
192
198
|
const $target = $posts.eq(index);
|
|
@@ -199,19 +205,20 @@ function injectMessageIncremental($posts, pool, interval) {
|
|
|
199
205
|
if (!id) break;
|
|
200
206
|
}
|
|
201
207
|
|
|
202
|
-
|
|
208
|
+
// Do NOT use class "post" nor component="post" for ads: can break NodeBB infinite scroll.
|
|
209
|
+
const inner = '<div class="ezoic-ad-message-inner"><div id="ezoic-pub-ad-placeholder-' + id + '"></div></div>';
|
|
203
210
|
const html = makeWrapperLike(
|
|
204
211
|
$target,
|
|
205
|
-
'post ezoic-ad
|
|
212
|
+
'ezoic-ad-post ezoic-ad',
|
|
206
213
|
inner,
|
|
207
214
|
'data-ezoic-slot="' + slot + '" data-ezoic-id="' + id + '"'
|
|
208
215
|
);
|
|
209
216
|
|
|
210
217
|
$target.after(html);
|
|
211
218
|
|
|
212
|
-
|
|
219
|
+
seenSlots.add(slot);
|
|
213
220
|
usedIds.add(id);
|
|
214
|
-
adsFIFO.push({
|
|
221
|
+
adsFIFO.push({ slot: slot, id: id });
|
|
215
222
|
newIds.push(id);
|
|
216
223
|
}
|
|
217
224
|
|
|
@@ -219,7 +226,6 @@ function injectMessageIncremental($posts, pool, interval) {
|
|
|
219
226
|
}
|
|
220
227
|
|
|
221
228
|
async function refreshAds() {
|
|
222
|
-
// Reset state on navigation
|
|
223
229
|
const key = currentPageKey();
|
|
224
230
|
if (pageKey !== key) {
|
|
225
231
|
pageKey = key;
|
|
@@ -250,9 +256,6 @@ async function refreshAds() {
|
|
|
250
256
|
|
|
251
257
|
const newIds = [];
|
|
252
258
|
|
|
253
|
-
// Your rule:
|
|
254
|
-
// - Category topic list: BETWEEN only
|
|
255
|
-
// - Topic page: MESSAGE only
|
|
256
259
|
if ($topicItems.length) {
|
|
257
260
|
if (cfg.enableBetweenAds && betweenPool.length) {
|
|
258
261
|
newIds.push(...injectBetweenIncremental($topicItems, betweenPool, betweenInterval, 'ezoic-ad-topic'));
|
|
@@ -278,7 +281,7 @@ async function refreshAds() {
|
|
|
278
281
|
|
|
279
282
|
function debounceRefresh() {
|
|
280
283
|
clearTimeout(debounceTimer);
|
|
281
|
-
debounceTimer = setTimeout(refreshAds,
|
|
284
|
+
debounceTimer = setTimeout(refreshAds, 200);
|
|
282
285
|
}
|
|
283
286
|
|
|
284
287
|
$(document).ready(debounceRefresh);
|
package/public/style.css
ADDED