nodebb-plugin-ezoic-infinite 0.9.0 → 0.9.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 -4
- package/plugin.json +0 -3
- package/public/client.js +158 -349
- package/public/templates/admin/plugins/ezoic-infinite.tpl +1 -1
- package/public/style.css +0 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodebb-plugin-ezoic-infinite",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "Ezoic ads with infinite scroll using a pool of placeholder IDs",
|
|
5
5
|
"main": "library.js",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,8 +13,5 @@
|
|
|
13
13
|
],
|
|
14
14
|
"engines": {
|
|
15
15
|
"node": ">=18"
|
|
16
|
-
},
|
|
17
|
-
"nbbpm": {
|
|
18
|
-
"compatibility": "^4.0.0"
|
|
19
16
|
}
|
|
20
17
|
}
|
package/plugin.json
CHANGED
package/public/client.js
CHANGED
|
@@ -1,443 +1,252 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
/* globals ajaxify */
|
|
3
2
|
|
|
3
|
+
/* globals ajaxify */
|
|
4
4
|
window.ezoicInfiniteLoaded = true;
|
|
5
5
|
|
|
6
|
-
let cachedConfig
|
|
6
|
+
let cachedConfig;
|
|
7
7
|
let lastFetch = 0;
|
|
8
|
+
let debounceTimer;
|
|
9
|
+
|
|
8
10
|
let inFlight = false;
|
|
9
11
|
let rerunRequested = false;
|
|
10
|
-
let debounceTimer = null;
|
|
11
12
|
|
|
13
|
+
// Incremental state (prevents ads "jumping to the top")
|
|
12
14
|
let pageKey = null;
|
|
15
|
+
let injectedSlots = new Set(); // slotNumber per page
|
|
16
|
+
let usedIds = new Set(); // ids currently injected per page
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
let seenBetweenAfter = new Set(); // category: after absolute topic position
|
|
19
|
-
let fifoBetween = []; // [{afterPos, id}]
|
|
20
|
-
let seenMsgAfter = new Set(); // topic: after absolute post number
|
|
21
|
-
let fifoMsg = []; // [{afterPostNo, id}]
|
|
22
|
-
|
|
23
|
-
// Destroy spam guard
|
|
24
|
-
window.__ezoicLastDestroy = window.__ezoicLastDestroy || {};
|
|
25
|
-
window.__ezoicRecycling = false;
|
|
26
|
-
|
|
27
|
-
// ---------- Config ----------
|
|
28
|
-
async function fetchConfig() {
|
|
29
|
-
const now = Date.now();
|
|
30
|
-
if (cachedConfig && (now - lastFetch) < 5000) return cachedConfig;
|
|
31
|
-
lastFetch = now;
|
|
18
|
+
function resetPageState() {
|
|
19
|
+
injectedSlots = new Set();
|
|
20
|
+
usedIds = new Set();
|
|
21
|
+
}
|
|
32
22
|
|
|
23
|
+
function currentPageKey() {
|
|
24
|
+
// Stable key per ajaxified page
|
|
33
25
|
try {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
enableBetweenAds: true,
|
|
51
|
-
placeholderIds: '',
|
|
52
|
-
intervalPosts: 6,
|
|
53
|
-
enableMessageAds: true,
|
|
54
|
-
messagePlaceholderIds: '',
|
|
55
|
-
messageIntervalPosts: 3,
|
|
56
|
-
};
|
|
57
|
-
}
|
|
26
|
+
if (ajaxify && ajaxify.data) {
|
|
27
|
+
if (ajaxify.data.tid) return 'topic:' + ajaxify.data.tid;
|
|
28
|
+
if (ajaxify.data.cid) return 'category:' + ajaxify.data.cid;
|
|
29
|
+
if (ajaxify.data.template) return 'tpl:' + ajaxify.data.template + ':' + (ajaxify.data.url || window.location.pathname);
|
|
30
|
+
}
|
|
31
|
+
} catch (e) {}
|
|
32
|
+
return window.location.pathname;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function parsePool(raw) {
|
|
36
|
+
if (!raw) return [];
|
|
37
|
+
return Array.from(new Set(
|
|
38
|
+
String(raw).split(/[\n,;\s]+/)
|
|
39
|
+
.map(x => parseInt(x, 10))
|
|
40
|
+
.filter(n => Number.isFinite(n) && n > 0)
|
|
41
|
+
));
|
|
58
42
|
}
|
|
59
43
|
|
|
60
|
-
function
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
.filter(n => Number.isFinite(n) && n > 0);
|
|
44
|
+
async function fetchConfig() {
|
|
45
|
+
if (cachedConfig && Date.now() - lastFetch < 10000) return cachedConfig;
|
|
46
|
+
const res = await fetch('/api/plugins/ezoic-infinite/config', { credentials: 'same-origin' });
|
|
47
|
+
cachedConfig = await res.json();
|
|
48
|
+
lastFetch = Date.now();
|
|
49
|
+
return cachedConfig;
|
|
67
50
|
}
|
|
68
51
|
|
|
69
|
-
// ---------- Page detection ----------
|
|
70
52
|
function isTopicPage() {
|
|
71
|
-
|
|
72
|
-
if (ajaxify && ajaxify.data && ajaxify.data.tid) return true;
|
|
73
|
-
} catch (e) {}
|
|
74
|
-
return /^\/topic\//.test(window.location.pathname);
|
|
53
|
+
return $('[component="post/content"]').length > 0 || $('[component="post"][data-pid]').length > 0;
|
|
75
54
|
}
|
|
76
55
|
|
|
77
56
|
function isCategoryTopicListPage() {
|
|
78
|
-
return
|
|
57
|
+
return $('li[component="category/topic"]').length > 0;
|
|
79
58
|
}
|
|
80
59
|
|
|
81
|
-
function
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (ajaxify.data.tid) return `topic:${ajaxify.data.tid}`;
|
|
85
|
-
if (ajaxify.data.cid) return `category:${ajaxify.data.cid}`;
|
|
86
|
-
}
|
|
87
|
-
} catch (e) {}
|
|
88
|
-
return `path:${window.location.pathname}`;
|
|
89
|
-
}
|
|
60
|
+
function getTopicPosts() {
|
|
61
|
+
const $primary = $('[component="post"][data-pid]');
|
|
62
|
+
if ($primary.length) return $primary.not('.ezoic-ad-post');
|
|
90
63
|
|
|
91
|
-
function
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
fifoMsg = [];
|
|
98
|
-
window.__ezoicLastShowKey = null;
|
|
99
|
-
window.__ezoicLastShowAt = 0;
|
|
64
|
+
return $('[data-pid]').filter(function () {
|
|
65
|
+
const $el = $(this);
|
|
66
|
+
const hasContent = $el.find('[component="post/content"]').length > 0;
|
|
67
|
+
const nested = $el.parents('[data-pid]').length > 0;
|
|
68
|
+
return hasContent && !nested;
|
|
69
|
+
}).not('.ezoic-ad-post');
|
|
100
70
|
}
|
|
101
71
|
|
|
102
|
-
function
|
|
103
|
-
|
|
72
|
+
function getCategoryTopicItems() {
|
|
73
|
+
return $('li[component="category/topic"]').not('.ezoic-ad-topic');
|
|
104
74
|
}
|
|
105
75
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const now = Date.now();
|
|
109
|
-
if (window.__ezoicLastDestroy[id] && (now - window.__ezoicLastDestroy[id]) < 2000) return;
|
|
110
|
-
window.__ezoicLastDestroy[id] = now;
|
|
111
|
-
|
|
112
|
-
try {
|
|
113
|
-
window.ezstandalone = window.ezstandalone || {};
|
|
114
|
-
if (typeof window.ezstandalone.destroyPlaceholders === 'function') {
|
|
115
|
-
window.ezstandalone.destroyPlaceholders(id);
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
window.ezstandalone.cmd = window.ezstandalone.cmd || [];
|
|
119
|
-
window.ezstandalone.cmd.push(function () {
|
|
120
|
-
try {
|
|
121
|
-
if (typeof window.ezstandalone.destroyPlaceholders === 'function') {
|
|
122
|
-
window.ezstandalone.destroyPlaceholders(id);
|
|
123
|
-
}
|
|
124
|
-
} catch (e) {}
|
|
125
|
-
});
|
|
126
|
-
} catch (e) {}
|
|
76
|
+
function tagName($el) {
|
|
77
|
+
return ($el && $el.length ? (($el.prop('tagName') || '').toUpperCase()) : '');
|
|
127
78
|
}
|
|
128
79
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
wrap.style.display = 'none';
|
|
138
|
-
}
|
|
139
|
-
const ph = wrap.querySelector('[id^="ezoic-pub-ad-placeholder-"]');
|
|
140
|
-
if (ph && ph.children && ph.children.length) {
|
|
141
|
-
wrap.classList.add('ezoic-filled');
|
|
142
|
-
wrap.style.display = '';
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
};
|
|
80
|
+
function makeWrapperLike($target, classes, innerHtml, attrs) {
|
|
81
|
+
const t = tagName($target);
|
|
82
|
+
const attrStr = attrs ? ' ' + attrs : '';
|
|
83
|
+
if (t === 'LI') {
|
|
84
|
+
return '<li class="' + classes + ' list-unstyled"' + attrStr + '>' + innerHtml + '</li>';
|
|
85
|
+
}
|
|
86
|
+
return '<div class="' + classes + '"' + attrStr + '>' + innerHtml + '</div>';
|
|
87
|
+
}
|
|
146
88
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
89
|
+
function pickNextId(pool) {
|
|
90
|
+
for (const id of pool) {
|
|
91
|
+
if (!usedIds.has(id)) return id;
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
152
94
|
}
|
|
153
95
|
|
|
154
96
|
function callEzoic(ids) {
|
|
97
|
+
if (!ids || !ids.length) return;
|
|
98
|
+
|
|
155
99
|
window.ezstandalone = window.ezstandalone || {};
|
|
156
100
|
window.ezstandalone.cmd = window.ezstandalone.cmd || [];
|
|
157
101
|
|
|
158
|
-
const uniq = Array.from(new Set(ids || []));
|
|
159
|
-
if (!uniq.length) return;
|
|
160
|
-
|
|
161
|
-
// De-dupe rapid duplicates
|
|
162
|
-
const key = uniq.join(',');
|
|
163
|
-
const now = Date.now();
|
|
164
|
-
if (window.__ezoicLastShowKey === key && (now - (window.__ezoicLastShowAt || 0)) < 1200) return;
|
|
165
|
-
window.__ezoicLastShowKey = key;
|
|
166
|
-
window.__ezoicLastShowAt = now;
|
|
167
|
-
|
|
168
102
|
const run = function () {
|
|
169
103
|
try {
|
|
170
104
|
if (typeof window.ezstandalone.showAds === 'function') {
|
|
171
|
-
window.ezstandalone.showAds.apply(window.ezstandalone,
|
|
105
|
+
window.ezstandalone.showAds.apply(window.ezstandalone, ids);
|
|
172
106
|
return true;
|
|
173
107
|
}
|
|
174
108
|
} catch (e) {}
|
|
175
109
|
return false;
|
|
176
110
|
};
|
|
177
111
|
|
|
178
|
-
setupAdAutoHeight();
|
|
179
112
|
window.ezstandalone.cmd.push(function () { run(); });
|
|
180
113
|
|
|
181
|
-
//
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (tries < 6) setTimeout(retry, 800);
|
|
189
|
-
};
|
|
190
|
-
setTimeout(retry, 800);
|
|
191
|
-
}
|
|
192
|
-
} catch (e) {}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// ---------- Pool logic ----------
|
|
196
|
-
function pickNextId(pool, usedSet) {
|
|
197
|
-
for (const id of pool) {
|
|
198
|
-
if (!usedSet.has(id)) return id;
|
|
199
|
-
}
|
|
200
|
-
return null;
|
|
114
|
+
// retry a few times (Ezoic can load late)
|
|
115
|
+
let tries = 0;
|
|
116
|
+
const maxTries = 6;
|
|
117
|
+
const timer = setInterval(function () {
|
|
118
|
+
tries++;
|
|
119
|
+
if (run() || tries >= maxTries) clearInterval(timer);
|
|
120
|
+
}, 800);
|
|
201
121
|
}
|
|
202
122
|
|
|
203
|
-
function
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
fifo.sort((a, b) => (a.after - b.after));
|
|
208
|
-
while (fifo.length) {
|
|
209
|
-
const old = fifo.shift();
|
|
210
|
-
const el = document.querySelector(selector(old));
|
|
211
|
-
if (!el) continue;
|
|
212
|
-
|
|
213
|
-
// Don't recycle if it is right after the last real item (protect sentinel)
|
|
214
|
-
try {
|
|
215
|
-
if (avoidAfterNode && el.previousElementSibling === avoidAfterNode) {
|
|
216
|
-
fifo.push(old);
|
|
217
|
-
return null;
|
|
218
|
-
}
|
|
219
|
-
} catch (e) {}
|
|
220
|
-
|
|
221
|
-
el.remove();
|
|
222
|
-
usedSet.delete(old.id);
|
|
223
|
-
destroyEzoicId(old.id);
|
|
224
|
-
return old.id;
|
|
225
|
-
}
|
|
226
|
-
return null;
|
|
227
|
-
} finally {
|
|
228
|
-
window.__ezoicRecycling = false;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// ---------- Injection ----------
|
|
233
|
-
function injectBetweenAds(config) {
|
|
234
|
-
if (!config.enableBetweenAds) return;
|
|
235
|
-
const pool = parsePool(config.placeholderIds);
|
|
236
|
-
if (!pool.length) return;
|
|
237
|
-
|
|
238
|
-
const interval = Math.max(1, config.intervalPosts);
|
|
239
|
-
const items = Array.from(document.querySelectorAll('li[component="category/topic"]'));
|
|
240
|
-
if (!items.length) return;
|
|
123
|
+
function injectBetweenIncremental($items, pool, interval, wrapperClass) {
|
|
124
|
+
const total = $items.length;
|
|
125
|
+
const maxSlot = Math.floor(total / interval);
|
|
126
|
+
if (maxSlot <= 0) return [];
|
|
241
127
|
|
|
242
128
|
const newIds = [];
|
|
243
|
-
const lastItem = items[items.length - 1];
|
|
244
129
|
|
|
245
|
-
for (let
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
130
|
+
for (let slot = 1; slot <= maxSlot; slot++) {
|
|
131
|
+
if (injectedSlots.has(slot)) continue;
|
|
132
|
+
|
|
133
|
+
const index = slot * interval - 1;
|
|
134
|
+
const $target = $items.eq(index);
|
|
135
|
+
if (!$target.length) continue;
|
|
249
136
|
|
|
250
|
-
|
|
137
|
+
const id = pickNextId(pool);
|
|
251
138
|
if (!id) {
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
fifoBetween,
|
|
255
|
-
usedBetween,
|
|
256
|
-
(o) => `.ezoic-ad-topic[data-ezoic-after="${o.after}"][data-ezoic-id="${o.id}"]`,
|
|
257
|
-
lastItem
|
|
258
|
-
);
|
|
259
|
-
if (!id) break;
|
|
139
|
+
// pool exhausted: stop injecting further to avoid reusing ids and "jumping"
|
|
140
|
+
break;
|
|
260
141
|
}
|
|
261
142
|
|
|
262
|
-
const
|
|
263
|
-
const
|
|
264
|
-
wrap.className = 'ezoic-ad ezoic-ad-topic';
|
|
265
|
-
wrap.setAttribute('data-ezoic-after', String(pos));
|
|
266
|
-
wrap.setAttribute('data-ezoic-id', String(id));
|
|
267
|
-
wrap.innerHTML = `<div id="ezoic-pub-ad-placeholder-${id}"></div>`;
|
|
143
|
+
const placeholder = '<div id="ezoic-pub-ad-placeholder-' + id + '"></div>';
|
|
144
|
+
const html = makeWrapperLike($target, wrapperClass, placeholder, 'data-ezoic-slot="' + slot + '" data-ezoic-id="' + id + '"');
|
|
268
145
|
|
|
269
|
-
|
|
146
|
+
$target.after(html);
|
|
270
147
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
fifoBetween.push({ after: pos, id });
|
|
148
|
+
injectedSlots.add(slot);
|
|
149
|
+
usedIds.add(id);
|
|
274
150
|
newIds.push(id);
|
|
275
151
|
}
|
|
276
152
|
|
|
277
|
-
|
|
153
|
+
return newIds;
|
|
278
154
|
}
|
|
279
155
|
|
|
280
|
-
function
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if (idx) {
|
|
285
|
-
const n = parseInt(String(idx.textContent || '').replace('#', '').trim(), 10);
|
|
286
|
-
if (Number.isFinite(n)) return n;
|
|
287
|
-
}
|
|
288
|
-
} catch (e) {}
|
|
289
|
-
|
|
290
|
-
// Fallback: pid-based ordering not reliable, but DOM order is ok for interval within loaded window.
|
|
291
|
-
return null;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
function injectMessageAds(config) {
|
|
295
|
-
if (!config.enableMessageAds) return;
|
|
296
|
-
const pool = parsePool(config.messagePlaceholderIds);
|
|
297
|
-
if (!pool.length) return;
|
|
298
|
-
|
|
299
|
-
const interval = Math.max(1, config.messageIntervalPosts);
|
|
300
|
-
const posts = Array.from(document.querySelectorAll('[component="post"][data-pid]'));
|
|
301
|
-
if (!posts.length) return;
|
|
156
|
+
function injectMessageIncremental($posts, pool, interval) {
|
|
157
|
+
const total = $posts.length;
|
|
158
|
+
const maxSlot = Math.floor(total / interval);
|
|
159
|
+
if (maxSlot <= 0) return [];
|
|
302
160
|
|
|
303
161
|
const newIds = [];
|
|
304
|
-
const lastPost = posts[posts.length - 1];
|
|
305
162
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
// Ensure strictly increasing by DOM
|
|
309
|
-
numbers = numbers.map((x, i) => ({ el: x.el, no: x.no || (i + 1) }));
|
|
163
|
+
for (let slot = 1; slot <= maxSlot; slot++) {
|
|
164
|
+
if (injectedSlots.has(slot)) continue;
|
|
310
165
|
|
|
311
|
-
|
|
312
|
-
const
|
|
313
|
-
if (
|
|
314
|
-
if (seenMsgAfter.has(afterNo)) continue;
|
|
166
|
+
const index = slot * interval - 1;
|
|
167
|
+
const $target = $posts.eq(index);
|
|
168
|
+
if (!$target.length) continue;
|
|
315
169
|
|
|
316
|
-
|
|
317
|
-
if (!id)
|
|
318
|
-
id = recycleOldest(
|
|
319
|
-
fifoMsg,
|
|
320
|
-
usedMessages,
|
|
321
|
-
(o) => `.ezoic-ad-post[data-ezoic-after="${o.after}"][data-ezoic-id="${o.id}"]`,
|
|
322
|
-
lastPost
|
|
323
|
-
);
|
|
324
|
-
if (!id) break;
|
|
325
|
-
}
|
|
170
|
+
const id = pickNextId(pool);
|
|
171
|
+
if (!id) break;
|
|
326
172
|
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
wrap.setAttribute('data-ezoic-after', String(afterNo));
|
|
330
|
-
wrap.setAttribute('data-ezoic-id', String(id));
|
|
331
|
-
wrap.innerHTML = `<div class="ezoic-ad-message-inner"><div id="ezoic-pub-ad-placeholder-${id}"></div></div>`;
|
|
173
|
+
const inner = '<div class="content"><div id="ezoic-pub-ad-placeholder-' + id + '"></div></div>';
|
|
174
|
+
const html = makeWrapperLike($target, 'post ezoic-ad-post', inner, 'data-ezoic-slot="' + slot + '" data-ezoic-id="' + id + '"');
|
|
332
175
|
|
|
333
|
-
|
|
176
|
+
$target.after(html);
|
|
334
177
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
fifoMsg.push({ after: afterNo, id });
|
|
178
|
+
injectedSlots.add(slot);
|
|
179
|
+
usedIds.add(id);
|
|
338
180
|
newIds.push(id);
|
|
339
181
|
}
|
|
340
182
|
|
|
341
|
-
|
|
183
|
+
return newIds;
|
|
342
184
|
}
|
|
343
185
|
|
|
344
|
-
// ---------- Main refresh ----------
|
|
345
186
|
async function refreshAds() {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
187
|
+
// reset state when navigating (ajaxify)
|
|
188
|
+
const key = currentPageKey();
|
|
189
|
+
if (pageKey !== key) {
|
|
190
|
+
pageKey = key;
|
|
191
|
+
resetPageState();
|
|
192
|
+
// also cleanup any injected wrappers that may have been left by browser bfcache
|
|
193
|
+
$('.ezoic-ad-post, .ezoic-ad-between, .ezoic-ad-topic').remove();
|
|
349
194
|
}
|
|
195
|
+
|
|
196
|
+
if (inFlight) { rerunRequested = true; return; }
|
|
350
197
|
inFlight = true;
|
|
351
|
-
rerunRequested = false;
|
|
352
198
|
|
|
353
199
|
try {
|
|
354
200
|
const cfg = await fetchConfig();
|
|
355
|
-
if (cfg.excluded) return;
|
|
201
|
+
if (!cfg || cfg.excluded) return;
|
|
356
202
|
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}
|
|
203
|
+
const betweenPool = parsePool(cfg.placeholderIds);
|
|
204
|
+
const betweenInterval = Math.max(1, parseInt(cfg.intervalPosts, 10) || 6);
|
|
205
|
+
|
|
206
|
+
const messagePool = parsePool(cfg.messagePlaceholderIds);
|
|
207
|
+
const messageInterval = Math.max(1, parseInt(cfg.messageIntervalPosts, 10) || 3);
|
|
363
208
|
|
|
364
209
|
const onTopic = isTopicPage();
|
|
365
|
-
const onCategory = isCategoryTopicListPage()
|
|
210
|
+
const onCategory = !onTopic && isCategoryTopicListPage();
|
|
211
|
+
|
|
212
|
+
const $posts = onTopic ? getTopicPosts() : $();
|
|
213
|
+
const $topicItems = onCategory ? getCategoryTopicItems() : $();
|
|
366
214
|
|
|
367
|
-
if (
|
|
368
|
-
|
|
215
|
+
if (!$posts.length && !$topicItems.length) return;
|
|
216
|
+
|
|
217
|
+
const newIds = [];
|
|
218
|
+
|
|
219
|
+
// Your rule:
|
|
220
|
+
// - Category topic list: BETWEEN only
|
|
221
|
+
// - Topic page: MESSAGE only
|
|
222
|
+
if ($topicItems.length) {
|
|
223
|
+
if (cfg.enableBetweenAds && betweenPool.length) {
|
|
224
|
+
newIds.push(...injectBetweenIncremental($topicItems, betweenPool, betweenInterval, 'ezoic-ad-topic'));
|
|
225
|
+
}
|
|
226
|
+
callEzoic(newIds);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if ($posts.length) {
|
|
231
|
+
if (cfg.enableMessageAds && messagePool.length) {
|
|
232
|
+
newIds.push(...injectMessageIncremental($posts, messagePool, messageInterval));
|
|
233
|
+
}
|
|
234
|
+
callEzoic(newIds);
|
|
235
|
+
}
|
|
369
236
|
} finally {
|
|
370
237
|
inFlight = false;
|
|
371
|
-
if (rerunRequested)
|
|
238
|
+
if (rerunRequested) {
|
|
239
|
+
rerunRequested = false;
|
|
240
|
+
setTimeout(refreshAds, 120);
|
|
241
|
+
}
|
|
372
242
|
}
|
|
373
243
|
}
|
|
374
244
|
|
|
375
245
|
function debounceRefresh() {
|
|
376
|
-
|
|
377
|
-
debounceTimer = setTimeout(refreshAds,
|
|
246
|
+
clearTimeout(debounceTimer);
|
|
247
|
+
debounceTimer = setTimeout(refreshAds, 180);
|
|
378
248
|
}
|
|
379
249
|
|
|
380
|
-
|
|
381
|
-
(
|
|
382
|
-
|
|
383
|
-
$(window).on('action:ajaxify.start', function (ev, data) {
|
|
384
|
-
try {
|
|
385
|
-
const targetUrl = (data && (data.url || data.href)) ? String(data.url || data.href) : '';
|
|
386
|
-
if (targetUrl) {
|
|
387
|
-
const a = document.createElement('a');
|
|
388
|
-
a.href = targetUrl;
|
|
389
|
-
const targetPath = a.pathname || targetUrl;
|
|
390
|
-
if (targetPath === window.location.pathname) return;
|
|
391
|
-
}
|
|
392
|
-
} catch (e) {}
|
|
393
|
-
pageKey = null;
|
|
394
|
-
resetState();
|
|
395
|
-
cleanupOnNav();
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
$(window).on('action:ajaxify.end action:posts.loaded action:topics.loaded action:topic.loaded action:category.loaded', debounceRefresh);
|
|
399
|
-
|
|
400
|
-
// MutationObserver (new posts/topics appended)
|
|
401
|
-
try {
|
|
402
|
-
const obs = new MutationObserver(function (mutations) {
|
|
403
|
-
for (const m of mutations) {
|
|
404
|
-
if (!m.addedNodes) continue;
|
|
405
|
-
for (const n of m.addedNodes) {
|
|
406
|
-
if (!n || n.nodeType !== 1) continue;
|
|
407
|
-
if (n.matches && (n.matches('[component="post"][data-pid]') || n.matches('li[component="category/topic"]'))) {
|
|
408
|
-
debounceRefresh();
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
if (n.querySelector && (n.querySelector('[component="post"][data-pid]') || n.querySelector('li[component="category/topic"]'))) {
|
|
412
|
-
debounceRefresh();
|
|
413
|
-
return;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
});
|
|
418
|
-
obs.observe(document.body, { childList: true, subtree: true });
|
|
419
|
-
window.__ezoicInfiniteObserver = obs;
|
|
420
|
-
} catch (e) {}
|
|
421
|
-
|
|
422
|
-
// Poller fallback (count changes)
|
|
423
|
-
let lastPosts = 0;
|
|
424
|
-
let lastTopics = 0;
|
|
425
|
-
setInterval(function () {
|
|
426
|
-
const p = document.querySelectorAll('[component="post"][data-pid]').length;
|
|
427
|
-
const t = document.querySelectorAll('li[component="category/topic"]').length;
|
|
428
|
-
if (p !== lastPosts || t !== lastTopics) {
|
|
429
|
-
lastPosts = p; lastTopics = t;
|
|
430
|
-
debounceRefresh();
|
|
431
|
-
}
|
|
432
|
-
}, 1500);
|
|
433
|
-
|
|
434
|
-
// First run(s) - important for hard load
|
|
435
|
-
document.addEventListener('DOMContentLoaded', function () {
|
|
436
|
-
debounceRefresh();
|
|
437
|
-
setTimeout(debounceRefresh, 1500);
|
|
438
|
-
setTimeout(debounceRefresh, 5000);
|
|
439
|
-
setTimeout(debounceRefresh, 10000);
|
|
440
|
-
});
|
|
441
|
-
// In case this script loads after DOMContentLoaded
|
|
442
|
-
setTimeout(debounceRefresh, 800);
|
|
443
|
-
})();
|
|
250
|
+
$(document).ready(debounceRefresh);
|
|
251
|
+
$(window).on('action:ajaxify.end action:posts.loaded action:topic.loaded', debounceRefresh);
|
|
252
|
+
setTimeout(debounceRefresh, 1800);
|
package/public/style.css
DELETED