nodebb-plugin-ezoic-infinite 0.8.7 → 0.8.9
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 +65 -250
- package/public/style.css +2 -4
package/package.json
CHANGED
package/plugin.json
CHANGED
package/public/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
/* globals ajaxify */
|
|
3
2
|
|
|
3
|
+
/* globals ajaxify */
|
|
4
4
|
window.ezoicInfiniteLoaded = true;
|
|
5
5
|
|
|
6
6
|
let cachedConfig;
|
|
@@ -10,23 +10,22 @@ let debounceTimer;
|
|
|
10
10
|
let inFlight = false;
|
|
11
11
|
let rerunRequested = false;
|
|
12
12
|
|
|
13
|
-
// Per-page state
|
|
13
|
+
// Per-page state (keyed by tid/cid)
|
|
14
14
|
let pageKey = null;
|
|
15
15
|
|
|
16
|
-
// Topic page: anchor ads to absolute post number
|
|
17
|
-
let seenAfterPostNo = new Set();
|
|
18
|
-
let usedIds = new Set();
|
|
19
|
-
let fifo = [];
|
|
16
|
+
// Topic page state: anchor ads to absolute post number (not DOM index)
|
|
17
|
+
let seenAfterPostNo = new Set(); // post numbers we've already inserted an ad after
|
|
18
|
+
let usedIds = new Set(); // ids currently in DOM
|
|
19
|
+
let fifo = []; // [{afterPostNo, id}]
|
|
20
20
|
|
|
21
|
-
// Category
|
|
22
|
-
let seenAfterTopicPos = new Set();
|
|
23
|
-
let fifoCat = [];
|
|
21
|
+
// Category page state: anchor to absolute topic position if available
|
|
22
|
+
let seenAfterTopicPos = new Set(); // topic positions we've inserted after
|
|
23
|
+
let fifoCat = []; // [{afterPos, id}]
|
|
24
24
|
|
|
25
25
|
function resetState() {
|
|
26
26
|
seenAfterPostNo = new Set();
|
|
27
27
|
seenAfterTopicPos = new Set();
|
|
28
|
-
|
|
29
|
-
usedIdsBetween = new Set();
|
|
28
|
+
usedIds = new Set();
|
|
30
29
|
fifo = [];
|
|
31
30
|
fifoCat = [];
|
|
32
31
|
}
|
|
@@ -51,7 +50,7 @@ function parsePool(raw) {
|
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
async function fetchConfig() {
|
|
54
|
-
if (cachedConfig && Date.now() - lastFetch <
|
|
53
|
+
if (cachedConfig && Date.now() - lastFetch < 10000) return cachedConfig;
|
|
55
54
|
const res = await fetch('/api/plugins/ezoic-infinite/config', { credentials: 'same-origin' });
|
|
56
55
|
cachedConfig = await res.json();
|
|
57
56
|
lastFetch = Date.now();
|
|
@@ -59,10 +58,7 @@ async function fetchConfig() {
|
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
function isTopicPage() {
|
|
62
|
-
|
|
63
|
-
if (ajaxify && ajaxify.data && ajaxify.data.tid) return true;
|
|
64
|
-
} catch (e) {}
|
|
65
|
-
return /^\/topic\//.test(window.location.pathname);
|
|
61
|
+
return $('[component="post/content"]').length > 0 || $('[component="post"][data-pid]').length > 0;
|
|
66
62
|
}
|
|
67
63
|
|
|
68
64
|
function isCategoryTopicListPage() {
|
|
@@ -73,7 +69,7 @@ function getTopicPosts() {
|
|
|
73
69
|
const $primary = $('[component="post"][data-pid]');
|
|
74
70
|
if ($primary.length) return $primary;
|
|
75
71
|
|
|
76
|
-
//
|
|
72
|
+
// fallback: top-level with post/content
|
|
77
73
|
return $('[data-pid]').filter(function () {
|
|
78
74
|
const $el = $(this);
|
|
79
75
|
const hasContent = $el.find('[component="post/content"]').length > 0;
|
|
@@ -86,7 +82,7 @@ function getCategoryTopicItems() {
|
|
|
86
82
|
return $('li[component="category/topic"]');
|
|
87
83
|
}
|
|
88
84
|
|
|
89
|
-
// If target's parent is UL/OL, wrapper
|
|
85
|
+
// If target's parent is UL/OL, wrapper MUST be LI (otherwise browser may move it to top)
|
|
90
86
|
function wrapperTagFor($target) {
|
|
91
87
|
if (!$target || !$target.length) return 'div';
|
|
92
88
|
const parentTag = ($target.parent().prop('tagName') || '').toUpperCase();
|
|
@@ -106,202 +102,69 @@ function makeWrapperLike($target, classes, innerHtml, attrs) {
|
|
|
106
102
|
}
|
|
107
103
|
|
|
108
104
|
function cleanupOnNav() {
|
|
109
|
-
$('.ezoic-ad-post, .ezoic-ad-topic').remove();
|
|
105
|
+
$('.ezoic-ad-post, .ezoic-ad-topic, .ezoic-ad-between').remove();
|
|
110
106
|
}
|
|
111
107
|
|
|
112
|
-
function pickNextId(pool
|
|
108
|
+
function pickNextId(pool) {
|
|
113
109
|
for (const id of pool) {
|
|
114
|
-
if (!
|
|
110
|
+
if (!usedIds.has(id)) return id;
|
|
115
111
|
}
|
|
116
112
|
return null;
|
|
117
|
-
} finally {
|
|
118
|
-
window.__ezoicRecycling = false;
|
|
119
|
-
}
|
|
120
113
|
}
|
|
121
114
|
|
|
122
|
-
function
|
|
123
|
-
window.__ezoicLastDestroy = window.__ezoicLastDestroy || {};
|
|
124
|
-
const now = Date.now();
|
|
125
|
-
if (window.__ezoicLastDestroy[id] && now - window.__ezoicLastDestroy[id] < 2000) {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
window.__ezoicLastDestroy[id] = now;
|
|
129
|
-
try {
|
|
130
|
-
window.ezstandalone = window.ezstandalone || {};
|
|
131
|
-
window.ezstandalone.cmd = window.ezstandalone.cmd || [];
|
|
132
|
-
const fn = function () {
|
|
133
|
-
try {
|
|
134
|
-
if (typeof window.ezstandalone.destroyPlaceholders === 'function') {
|
|
135
|
-
window.ezstandalone.destroyPlaceholders(id);
|
|
136
|
-
}
|
|
137
|
-
} catch (e) {}
|
|
138
|
-
};
|
|
139
|
-
if (typeof window.ezstandalone.destroyPlaceholders === 'function') fn();
|
|
140
|
-
else window.ezstandalone.cmd.push(fn);
|
|
141
|
-
} catch (e) {}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function recycleOldestTopicId($posts) {
|
|
145
|
-
if (window.__ezoicRecycling) return null;
|
|
146
|
-
window.__ezoicRecycling = true;
|
|
147
|
-
try {
|
|
148
|
-
if (!fifo.length) return null;
|
|
115
|
+
function removeOldestTopicAd() {
|
|
149
116
|
fifo.sort((a, b) => a.afterPostNo - b.afterPostNo);
|
|
117
|
+
const old = fifo.shift();
|
|
118
|
+
if (!old) return false;
|
|
150
119
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const $el = $(sel);
|
|
155
|
-
if (!$el.length) continue;
|
|
120
|
+
const sel = '.ezoic-ad-post[data-ezoic-after="' + old.afterPostNo + '"][data-ezoic-id="' + old.id + '"]';
|
|
121
|
+
const $el = $(sel);
|
|
122
|
+
if ($el.length) $el.remove();
|
|
156
123
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if ($last.length && $el.prev().is($last)) {
|
|
161
|
-
fifo.push(old);
|
|
162
|
-
return null;
|
|
163
|
-
}
|
|
164
|
-
} catch (e) {}
|
|
165
|
-
|
|
166
|
-
$el.remove();
|
|
167
|
-
usedIdsMsg.delete(old.id);
|
|
168
|
-
destroyEzoicId(old.id);
|
|
169
|
-
return old.id;
|
|
170
|
-
}
|
|
171
|
-
return null;
|
|
172
|
-
} finally {
|
|
173
|
-
window.__ezoicRecycling = false;
|
|
174
|
-
}
|
|
124
|
+
usedIds.delete(old.id);
|
|
125
|
+
// DO NOT delete seenAfterPostNo to prevent re-insertion in the top area
|
|
126
|
+
return true;
|
|
175
127
|
}
|
|
176
128
|
|
|
177
|
-
function
|
|
178
|
-
if (window.__ezoicRecycling) return null;
|
|
179
|
-
window.__ezoicRecycling = true;
|
|
180
|
-
try {
|
|
181
|
-
if (!fifoCat.length) return null;
|
|
129
|
+
function removeOldestCategoryAd() {
|
|
182
130
|
fifoCat.sort((a, b) => a.afterPos - b.afterPos);
|
|
131
|
+
const old = fifoCat.shift();
|
|
132
|
+
if (!old) return false;
|
|
183
133
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const $el = $(sel);
|
|
188
|
-
if (!$el.length) continue;
|
|
134
|
+
const sel = '.ezoic-ad-topic[data-ezoic-after="' + old.afterPos + '"][data-ezoic-id="' + old.id + '"]';
|
|
135
|
+
const $el = $(sel);
|
|
136
|
+
if ($el.length) $el.remove();
|
|
189
137
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if ($last.length && $el.prev().is($last)) {
|
|
193
|
-
fifoCat.push(old);
|
|
194
|
-
return null;
|
|
195
|
-
}
|
|
196
|
-
} catch (e) {}
|
|
197
|
-
|
|
198
|
-
$el.remove();
|
|
199
|
-
usedIdsBetween.delete(old.id);
|
|
200
|
-
destroyEzoicId(old.id);
|
|
201
|
-
return old.id;
|
|
202
|
-
}
|
|
203
|
-
return null;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
function setupAdAutoHeight() {
|
|
207
|
-
if (window.__ezoicAutoHeightAttached) return;
|
|
208
|
-
window.__ezoicAutoHeightAttached = true;
|
|
209
|
-
|
|
210
|
-
try {
|
|
211
|
-
const ro = new ResizeObserver(function () {
|
|
212
|
-
document.querySelectorAll('.ezoic-ad').forEach(function (wrap) {
|
|
213
|
-
// Collapse until content is injected
|
|
214
|
-
if (!wrap.classList.contains('ezoic-filled')) {
|
|
215
|
-
wrap.style.display = 'none';
|
|
216
|
-
}
|
|
217
|
-
wrap.style.minHeight = '0px';
|
|
218
|
-
wrap.style.height = 'auto';
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
function attach() {
|
|
223
|
-
document.querySelectorAll('.ezoic-ad').forEach(function (wrap) {
|
|
224
|
-
// Collapse until content is injected
|
|
225
|
-
if (!wrap.classList.contains('ezoic-filled')) {
|
|
226
|
-
wrap.style.display = 'none';
|
|
227
|
-
}
|
|
228
|
-
if (wrap.__ezoicRO) return;
|
|
229
|
-
wrap.__ezoicRO = true;
|
|
230
|
-
ro.observe(wrap);
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
attach();
|
|
235
|
-
setTimeout(attach, 600);
|
|
236
|
-
setTimeout(attach, 1600);
|
|
237
|
-
} catch (e) {}
|
|
138
|
+
usedIds.delete(old.id);
|
|
139
|
+
return true;
|
|
238
140
|
}
|
|
239
141
|
|
|
240
142
|
function callEzoic(ids) {
|
|
143
|
+
// ids optional; if omitted, we will scan DOM for unrendered placeholders
|
|
241
144
|
window.ezstandalone = window.ezstandalone || {};
|
|
242
145
|
window.ezstandalone.cmd = window.ezstandalone.cmd || [];
|
|
243
146
|
|
|
244
|
-
const markAndFilterByIds = function (list) {
|
|
245
|
-
const out = [];
|
|
246
|
-
list.forEach(function (id) {
|
|
247
|
-
const sel = '.ezoic-ad[data-ezoic-id="' + id + '"]';
|
|
248
|
-
const wraps = document.querySelectorAll(sel);
|
|
249
|
-
let anyUnrendered = false;
|
|
250
|
-
wraps.forEach(function (w) {
|
|
251
|
-
if (w.getAttribute('data-ezoic-rendered') !== '1') {
|
|
252
|
-
anyUnrendered = true;
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
if (!wraps.length) {
|
|
256
|
-
// fallback: if wrapper is missing, allow showAds (Ezoic might still handle placeholder)
|
|
257
|
-
out.push(id);
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
if (anyUnrendered) {
|
|
261
|
-
wraps.forEach(function (w) { w.setAttribute('data-ezoic-rendered', '1'); });
|
|
262
|
-
out.push(id);
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
return out;
|
|
266
|
-
};
|
|
267
|
-
|
|
268
147
|
const collect = function () {
|
|
269
148
|
const list = [];
|
|
270
|
-
document.querySelectorAll('.ezoic-ad').forEach(function (
|
|
271
|
-
// Collapse until content is injected
|
|
272
|
-
if (!wrap.classList.contains('ezoic-filled')) {
|
|
273
|
-
wrap.style.display = 'none';
|
|
274
|
-
}
|
|
275
|
-
if (wrap.getAttribute('data-ezoic-rendered') === '1') return;
|
|
276
|
-
const ph = wrap.querySelector('[id^="ezoic-pub-ad-placeholder-"]');
|
|
277
|
-
if (ph && ph.children && ph.children.length) {
|
|
278
|
-
// Content injected
|
|
279
|
-
wrap.classList.add('ezoic-filled');
|
|
280
|
-
wrap.style.display = '';
|
|
281
|
-
}
|
|
282
|
-
if (!ph) return;
|
|
149
|
+
document.querySelectorAll('.ezoic-ad [id^="ezoic-pub-ad-placeholder-"]').forEach(function (ph) {
|
|
283
150
|
const idStr = ph.id.replace('ezoic-pub-ad-placeholder-', '');
|
|
284
151
|
const id = parseInt(idStr, 10);
|
|
285
152
|
if (!Number.isFinite(id) || id <= 0) return;
|
|
286
|
-
|
|
153
|
+
|
|
154
|
+
const wrap = ph.closest('.ezoic-ad');
|
|
155
|
+
if (!wrap) return;
|
|
156
|
+
if (wrap.getAttribute('data-ezoic-rendered') === '1') return;
|
|
157
|
+
|
|
287
158
|
list.push(id);
|
|
159
|
+
wrap.setAttribute('data-ezoic-rendered', '1');
|
|
288
160
|
});
|
|
161
|
+
// de-dupe
|
|
289
162
|
return Array.from(new Set(list));
|
|
290
163
|
};
|
|
291
164
|
|
|
292
|
-
const
|
|
293
|
-
const toShow = input ? markAndFilterByIds(input) : collect();
|
|
165
|
+
const toShow = (ids && ids.length) ? Array.from(new Set(ids)) : collect();
|
|
294
166
|
if (!toShow.length) return;
|
|
295
167
|
|
|
296
|
-
// De-dupe rapid duplicate calls (observer/poller can fire twice)
|
|
297
|
-
const key = toShow.join(',');
|
|
298
|
-
const now = Date.now();
|
|
299
|
-
if (window.__ezoicLastShowKey === key && (now - (window.__ezoicLastShowAt || 0)) < 1200) {
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
window.__ezoicLastShowKey = key;
|
|
303
|
-
window.__ezoicLastShowAt = now;
|
|
304
|
-
|
|
305
168
|
const run = function () {
|
|
306
169
|
try {
|
|
307
170
|
if (typeof window.ezstandalone.showAds === 'function') {
|
|
@@ -338,15 +201,13 @@ function callEzoic(ids) {
|
|
|
338
201
|
}
|
|
339
202
|
|
|
340
203
|
function getPostNumber($post) {
|
|
341
|
-
|
|
204
|
+
const di = parseInt($post.attr('data-index'), 10);
|
|
205
|
+
if (Number.isFinite(di) && di > 0) return di;
|
|
206
|
+
|
|
342
207
|
const txt = ($post.find('a.post-index').first().text() || '').trim();
|
|
343
208
|
const m = txt.match(/#\s*(\d+)/);
|
|
344
209
|
if (m) return parseInt(m[1], 10);
|
|
345
210
|
|
|
346
|
-
// fallback data-index (often 0/1 based)
|
|
347
|
-
const di = parseInt($post.attr('data-index'), 10);
|
|
348
|
-
if (Number.isFinite(di) && di >= 0) return di + 1;
|
|
349
|
-
|
|
350
211
|
return NaN;
|
|
351
212
|
}
|
|
352
213
|
|
|
@@ -363,20 +224,16 @@ function injectTopicMessageAds($posts, pool, interval) {
|
|
|
363
224
|
|
|
364
225
|
$posts.each(function () {
|
|
365
226
|
const $p = $(this);
|
|
366
|
-
// Never insert after the last post
|
|
227
|
+
// Never insert after the last real post: it can break NodeBB infinite scroll
|
|
367
228
|
if ($p.is($posts.last())) return;
|
|
368
|
-
|
|
369
229
|
const postNo = getPostNumber($p);
|
|
370
230
|
if (!Number.isFinite(postNo) || postNo <= 0) return;
|
|
371
231
|
|
|
372
232
|
if (postNo % interval !== 0) return;
|
|
373
233
|
if (seenAfterPostNo.has(postNo)) return;
|
|
374
234
|
|
|
375
|
-
let id = pickNextId(pool
|
|
376
|
-
if (!id) {
|
|
377
|
-
id = recycleOldestTopicId($posts);
|
|
378
|
-
if (!id) return;
|
|
379
|
-
}
|
|
235
|
+
let id = pickNextId(pool);
|
|
236
|
+
if (!id) { return; }
|
|
380
237
|
|
|
381
238
|
const inner = '<div class="ezoic-ad-message-inner"><div id="ezoic-pub-ad-placeholder-' + id + '"></div></div>';
|
|
382
239
|
const html = makeWrapperLike(
|
|
@@ -389,7 +246,7 @@ function injectTopicMessageAds($posts, pool, interval) {
|
|
|
389
246
|
$p.after(html);
|
|
390
247
|
|
|
391
248
|
seenAfterPostNo.add(postNo);
|
|
392
|
-
|
|
249
|
+
usedIds.add(id);
|
|
393
250
|
fifo.push({ afterPostNo: postNo, id: id });
|
|
394
251
|
newIds.push(id);
|
|
395
252
|
});
|
|
@@ -402,20 +259,16 @@ function injectCategoryBetweenAds($items, pool, interval) {
|
|
|
402
259
|
|
|
403
260
|
$items.each(function () {
|
|
404
261
|
const $it = $(this);
|
|
405
|
-
// Never insert after the last topic item (
|
|
262
|
+
// Never insert after the last real topic item (keeps NodeBB infinite scroll working)
|
|
406
263
|
if ($it.is($items.last())) return;
|
|
407
|
-
|
|
408
264
|
const pos = getTopicPos($it);
|
|
409
265
|
if (!Number.isFinite(pos) || pos <= 0) return;
|
|
410
266
|
|
|
411
267
|
if (pos % interval !== 0) return;
|
|
412
268
|
if (seenAfterTopicPos.has(pos)) return;
|
|
413
269
|
|
|
414
|
-
let id = pickNextId(pool
|
|
415
|
-
if (!id) {
|
|
416
|
-
id = recycleOldestCategoryId($items);
|
|
417
|
-
if (!id) return;
|
|
418
|
-
}
|
|
270
|
+
let id = pickNextId(pool);
|
|
271
|
+
if (!id) { return; }
|
|
419
272
|
|
|
420
273
|
const placeholder = '<div id="ezoic-pub-ad-placeholder-' + id + '"></div>';
|
|
421
274
|
const html = makeWrapperLike(
|
|
@@ -428,7 +281,7 @@ function injectCategoryBetweenAds($items, pool, interval) {
|
|
|
428
281
|
$it.after(html);
|
|
429
282
|
|
|
430
283
|
seenAfterTopicPos.add(pos);
|
|
431
|
-
|
|
284
|
+
usedIds.add(id);
|
|
432
285
|
fifoCat.push({ afterPos: pos, id: id });
|
|
433
286
|
newIds.push(id);
|
|
434
287
|
});
|
|
@@ -437,9 +290,6 @@ function injectCategoryBetweenAds($items, pool, interval) {
|
|
|
437
290
|
}
|
|
438
291
|
|
|
439
292
|
async function refreshAds() {
|
|
440
|
-
const now = Date.now();
|
|
441
|
-
if (window.__ezoicRefreshThrottle && now - window.__ezoicRefreshThrottle < 250) return;
|
|
442
|
-
window.__ezoicRefreshThrottle = now;
|
|
443
293
|
const key = getPageKey();
|
|
444
294
|
if (pageKey !== key) {
|
|
445
295
|
pageKey = key;
|
|
@@ -460,20 +310,17 @@ async function refreshAds() {
|
|
|
460
310
|
const messagePool = parsePool(cfg.messagePlaceholderIds);
|
|
461
311
|
const messageInterval = Math.max(1, parseInt(cfg.messageIntervalPosts, 10) || 3);
|
|
462
312
|
|
|
463
|
-
const hasTopicList = isCategoryTopicListPage();
|
|
464
313
|
const onTopic = isTopicPage();
|
|
465
|
-
const onCategory =
|
|
314
|
+
const onCategory = !onTopic && isCategoryTopicListPage();
|
|
466
315
|
|
|
467
316
|
const newIds = [];
|
|
468
317
|
|
|
469
|
-
// Rule: topic list => between only ; topic page => message only
|
|
470
318
|
if (onCategory) {
|
|
471
319
|
const $items = getCategoryTopicItems();
|
|
472
320
|
if (cfg.enableBetweenAds && betweenPool.length && $items.length) {
|
|
473
321
|
newIds.push(...injectCategoryBetweenAds($items, betweenPool, betweenInterval));
|
|
474
322
|
}
|
|
475
323
|
callEzoic(newIds);
|
|
476
|
-
// also ensure any unrendered placeholders are rendered
|
|
477
324
|
callEzoic();
|
|
478
325
|
return;
|
|
479
326
|
}
|
|
@@ -484,6 +331,7 @@ async function refreshAds() {
|
|
|
484
331
|
newIds.push(...injectTopicMessageAds($posts, messagePool, messageInterval));
|
|
485
332
|
}
|
|
486
333
|
callEzoic(newIds);
|
|
334
|
+
callEzoic();
|
|
487
335
|
}
|
|
488
336
|
} finally {
|
|
489
337
|
inFlight = false;
|
|
@@ -499,47 +347,28 @@ function debounceRefresh() {
|
|
|
499
347
|
debounceTimer = setTimeout(refreshAds, 220);
|
|
500
348
|
}
|
|
501
349
|
|
|
502
|
-
$(document).ready(
|
|
503
|
-
|
|
504
|
-
$(window).on('action:ajaxify.start', function (ev, data) {
|
|
505
|
-
// IMPORTANT: do not cleanup on infinite scroll loads; only when navigating to a different page.
|
|
506
|
-
try {
|
|
507
|
-
const targetUrl = (data && (data.url || data.href)) ? String(data.url || data.href) : '';
|
|
508
|
-
if (targetUrl) {
|
|
509
|
-
const a = document.createElement('a');
|
|
510
|
-
a.href = targetUrl;
|
|
511
|
-
const targetPath = a.pathname || targetUrl;
|
|
512
|
-
// If we're staying on the same logical page (same path), don't wipe ads/state
|
|
513
|
-
if (targetPath === window.location.pathname) {
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
} catch (e) {}
|
|
518
|
-
pageKey = null;
|
|
519
|
-
resetState();
|
|
520
|
-
cleanupOnNav();
|
|
521
|
-
});
|
|
350
|
+
$(document).ready(debounceRefresh);
|
|
522
351
|
$(window).on('action:ajaxify.end action:posts.loaded action:topic.loaded action:topics.loaded action:category.loaded', debounceRefresh);
|
|
352
|
+
setTimeout(debounceRefresh, 2200);
|
|
523
353
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
// Observer + poller: ensure we rerun when NodeBB injects new items
|
|
354
|
+
// Fallback: some themes/devices don't emit the expected events for infinite scroll.
|
|
355
|
+
// Observe DOM additions and trigger a refresh when new posts/topics are appended/prepended.
|
|
527
356
|
(function setupEzoicObserver() {
|
|
528
357
|
if (window.__ezoicInfiniteObserver) return;
|
|
529
358
|
try {
|
|
530
|
-
const trigger = function () { debounceRefresh(); };
|
|
531
|
-
|
|
532
359
|
const obs = new MutationObserver(function (mutations) {
|
|
533
360
|
for (const m of mutations) {
|
|
534
361
|
if (!m.addedNodes || !m.addedNodes.length) continue;
|
|
535
362
|
for (const n of m.addedNodes) {
|
|
536
363
|
if (!n || n.nodeType !== 1) continue;
|
|
364
|
+
// direct match
|
|
537
365
|
if (n.matches && (n.matches('[component="post"][data-pid]') || n.matches('li[component="category/topic"]'))) {
|
|
538
|
-
|
|
366
|
+
debounceRefresh();
|
|
539
367
|
return;
|
|
540
368
|
}
|
|
369
|
+
// descendant match
|
|
541
370
|
if (n.querySelector && (n.querySelector('[component="post"][data-pid]') || n.querySelector('li[component="category/topic"]'))) {
|
|
542
|
-
|
|
371
|
+
debounceRefresh();
|
|
543
372
|
return;
|
|
544
373
|
}
|
|
545
374
|
}
|
|
@@ -547,19 +376,5 @@ setTimeout(function () { setupAdAutoHeight(); debounceRefresh(); }, 2200);
|
|
|
547
376
|
});
|
|
548
377
|
obs.observe(document.body, { childList: true, subtree: true });
|
|
549
378
|
window.__ezoicInfiniteObserver = obs;
|
|
550
|
-
|
|
551
|
-
let lastPostCount = 0;
|
|
552
|
-
let lastTopicCount = 0;
|
|
553
|
-
setInterval(function () {
|
|
554
|
-
try {
|
|
555
|
-
const posts = document.querySelectorAll('[component="post"][data-pid]').length;
|
|
556
|
-
const topics = document.querySelectorAll('li[component="category/topic"]').length;
|
|
557
|
-
if (posts !== lastPostCount || topics !== lastTopicCount) {
|
|
558
|
-
lastPostCount = posts;
|
|
559
|
-
lastTopicCount = topics;
|
|
560
|
-
trigger();
|
|
561
|
-
}
|
|
562
|
-
} catch (e) {}
|
|
563
|
-
}, 1500);
|
|
564
379
|
} catch (e) {}
|
|
565
380
|
})();
|
package/public/style.css
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
.ezoic-ad{
|
|
2
|
-
.ezoic-ad
|
|
3
|
-
.ezoic-ad-message-inner{padding:0;margin:0;}
|
|
4
|
-
.ezoic-ad-message-inner > div{margin:0;padding:0;}
|
|
1
|
+
.ezoic-ad-post{margin:0.75rem 0;}
|
|
2
|
+
.ezoic-ad-message-inner{padding:0.75rem 0;}
|