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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "0.9.0",
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
@@ -22,8 +22,5 @@
22
22
  "scripts": [
23
23
  "public/client.js"
24
24
  ],
25
- "css": [
26
- "public/style.css"
27
- ],
28
25
  "templates": "public/templates"
29
26
  }
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 = null;
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
- // Separate state per "mode" so category and topic don't leak ids
15
- let usedBetween = new Set();
16
- let usedMessages = new Set();
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
- const res = await fetch('/api/admin/settings/ezoic-infinite', { credentials: 'same-origin' });
35
- const data = await res.json();
36
- cachedConfig = {
37
- excluded: !!data.excluded,
38
- enableBetweenAds: data.enableBetweenAds !== false,
39
- placeholderIds: String(data.placeholderIds || '').trim(),
40
- intervalPosts: parseInt(data.intervalPosts, 10) || 6,
41
-
42
- enableMessageAds: data.enableMessageAds !== false,
43
- messagePlaceholderIds: String(data.messagePlaceholderIds || '').trim(),
44
- messageIntervalPosts: parseInt(data.messageIntervalPosts, 10) || 3,
45
- };
46
- return cachedConfig;
47
- } catch (e) {
48
- return cachedConfig || {
49
- excluded: false,
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 parsePool(text) {
61
- return String(text || '')
62
- .split(/\r?\n|,|;/g)
63
- .map(s => s.trim())
64
- .filter(Boolean)
65
- .map(s => parseInt(s, 10))
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
- try {
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 document.querySelectorAll('li[component="category/topic"]').length > 0;
57
+ return $('li[component="category/topic"]').length > 0;
79
58
  }
80
59
 
81
- function getPageKey() {
82
- try {
83
- if (ajaxify && ajaxify.data) {
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 resetState() {
92
- usedBetween = new Set();
93
- usedMessages = new Set();
94
- seenBetweenAfter = new Set();
95
- seenMsgAfter = new Set();
96
- fifoBetween = [];
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 cleanupOnNav() {
103
- document.querySelectorAll('.ezoic-ad-post, .ezoic-ad-topic, .ezoic-ad').forEach(el => el.remove());
72
+ function getCategoryTopicItems() {
73
+ return $('li[component="category/topic"]').not('.ezoic-ad-topic');
104
74
  }
105
75
 
106
- // ---------- Ezoic helpers ----------
107
- function destroyEzoicId(id) {
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
- // Auto-height: hide until filled
130
- function setupAdAutoHeight() {
131
- if (window.__ezoicAutoHeightAttached) return;
132
- window.__ezoicAutoHeightAttached = true;
133
-
134
- const attach = function () {
135
- document.querySelectorAll('.ezoic-ad').forEach(function (wrap) {
136
- if (!wrap.classList.contains('ezoic-filled')) {
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
- attach();
148
- setTimeout(attach, 500);
149
- setTimeout(attach, 1500);
150
- setTimeout(attach, 3000);
151
- setInterval(attach, 1000);
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, uniq);
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
- // Retry only if showAds isn't available yet
182
- try {
183
- if (typeof window.ezstandalone.showAds !== 'function') {
184
- let tries = 0;
185
- const retry = function () {
186
- tries++;
187
- if (run()) return;
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 recycleOldest(fifo, usedSet, selector, avoidAfterNode) {
204
- if (window.__ezoicRecycling) return null;
205
- window.__ezoicRecycling = true;
206
- try {
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 i = 0; i < items.length; i++) {
246
- const pos = i + 1; // absolute position in loaded list
247
- if (pos % interval !== 0) continue;
248
- if (seenBetweenAfter.has(pos)) continue;
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
- let id = pickNextId(pool, usedBetween);
137
+ const id = pickNextId(pool);
251
138
  if (!id) {
252
- // recycle oldest
253
- id = recycleOldest(
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 anchor = items[i];
263
- const wrap = document.createElement('li');
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
- anchor.insertAdjacentElement('afterend', wrap);
146
+ $target.after(html);
270
147
 
271
- seenBetweenAfter.add(pos);
272
- usedBetween.add(id);
273
- fifoBetween.push({ after: pos, id });
148
+ injectedSlots.add(slot);
149
+ usedIds.add(id);
274
150
  newIds.push(id);
275
151
  }
276
152
 
277
- if (newIds.length) callEzoic(newIds);
153
+ return newIds;
278
154
  }
279
155
 
280
- function getPostNumberFromPost(postEl) {
281
- // Prefer post-index text (#72)
282
- try {
283
- const idx = postEl.querySelector('a.post-index');
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
- // Determine absolute post numbers if available; else use DOM position
307
- let numbers = posts.map((p, i) => ({ el: p, no: getPostNumberFromPost(p) || (i + 1) }));
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
- for (const entry of numbers) {
312
- const afterNo = entry.no;
313
- if (afterNo % interval !== 0) continue;
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
- let id = pickNextId(pool, usedMessages);
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 wrap = document.createElement('div');
328
- wrap.className = 'ezoic-ad ezoic-ad-post';
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
- entry.el.insertAdjacentElement('afterend', wrap);
176
+ $target.after(html);
334
177
 
335
- seenMsgAfter.add(afterNo);
336
- usedMessages.add(id);
337
- fifoMsg.push({ after: afterNo, id });
178
+ injectedSlots.add(slot);
179
+ usedIds.add(id);
338
180
  newIds.push(id);
339
181
  }
340
182
 
341
- if (newIds.length) callEzoic(newIds);
183
+ return newIds;
342
184
  }
343
185
 
344
- // ---------- Main refresh ----------
345
186
  async function refreshAds() {
346
- if (inFlight) {
347
- rerunRequested = true;
348
- return;
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 key = getPageKey();
358
- if (key !== pageKey) {
359
- pageKey = key;
360
- resetState();
361
- cleanupOnNav();
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() && !onTopic;
210
+ const onCategory = !onTopic && isCategoryTopicListPage();
211
+
212
+ const $posts = onTopic ? getTopicPosts() : $();
213
+ const $topicItems = onCategory ? getCategoryTopicItems() : $();
366
214
 
367
- if (onCategory) injectBetweenAds(cfg);
368
- if (onTopic) injectMessageAds(cfg);
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) setTimeout(refreshAds, 50);
238
+ if (rerunRequested) {
239
+ rerunRequested = false;
240
+ setTimeout(refreshAds, 120);
241
+ }
372
242
  }
373
243
  }
374
244
 
375
245
  function debounceRefresh() {
376
- if (debounceTimer) clearTimeout(debounceTimer);
377
- debounceTimer = setTimeout(refreshAds, 250);
246
+ clearTimeout(debounceTimer);
247
+ debounceTimer = setTimeout(refreshAds, 180);
378
248
  }
379
249
 
380
- // ---------- Observers / Events ----------
381
- (function setupTriggers() {
382
- // Ajaxify navigation: only cleanup when URL changes
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);
@@ -1,5 +1,5 @@
1
1
  <div class="acp-page-container">
2
- <h2>Ezoic Infinite Ads</h2>
2
+ <h2>Ezoic - Publicités Infinite Scroll Ads</h2>
3
3
 
4
4
  <form class="ezoic-infinite-settings" role="form">
5
5
  <h4 class="mt-3">Pubs entre les posts (bloc simple)</h4>
package/public/style.css DELETED
@@ -1,4 +0,0 @@
1
- .ezoic-ad{min-height:0 !important;height:auto !important;padding:0 !important;margin:0.5rem 0;}
2
- .ezoic-ad:not(.ezoic-filled){display:none !important;}
3
- .ezoic-ad-message-inner{padding:0;margin:0;}
4
- .ezoic-ad-message-inner > div{margin:0;padding:0;}