nodebb-plugin-ezoic-infinite 1.7.63 → 1.7.65
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 +57 -60
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* NodeBB Ezoic Infinite Ads — client.js
|
|
2
|
+
* NodeBB Ezoic Infinite Ads — client.js v69
|
|
3
3
|
*
|
|
4
4
|
* Historique
|
|
5
5
|
* ──────────
|
|
@@ -7,28 +7,19 @@
|
|
|
7
7
|
* v20 Table KIND. IO fixe. Fix TCF locator.
|
|
8
8
|
* v25 Fix scroll-up / virtualisation NodeBB.
|
|
9
9
|
* v28 Wraps persistants pendant la session.
|
|
10
|
-
* v35 S.poolsReady. muteConsole élargi.
|
|
11
10
|
* v36 S.wrapByKey Map O(1). MutationObserver optimisé.
|
|
12
|
-
* v38
|
|
13
|
-
* v40 Recyclage destroyPlaceholders+define+displayMore (délais 300ms).
|
|
14
|
-
* v43 Seuil recyclage -1vh + unobserve avant déplacement.
|
|
11
|
+
* v38 Pool épuisé → break propre (ez.refresh supprimé).
|
|
15
12
|
* v49 Fix normalizeExcludedGroups (JSON.parse tableau NodeBB).
|
|
16
|
-
* v51 fetchConfig backoff 10s. IO recrée au resize.
|
|
17
|
-
* v52 pruneOrphansBetween supprimé (NodeBB virtualise
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* v58 tcfObs survit aux navigations : ne plus déconnecter dans cleanup().
|
|
27
|
-
* L'iframe __tcfapiLocator doit exister en permanence pour le CMP —
|
|
28
|
-
* la fenêtre entre cleanup() et ajaxify.end causait des erreurs
|
|
29
|
-
* "Cannot read properties of null (postMessage)" et disparition des pubs.
|
|
30
|
-
* v57 Nettoyage prod : A_SHOWN/A_CREATED supprimés, normBool Set O(1),
|
|
31
|
-
* muteConsole étend aux erreurs CMP getTCData, code nettoyé.
|
|
13
|
+
* v51 fetchConfig backoff 10s. IO recrée au resize.
|
|
14
|
+
* v52 pruneOrphansBetween supprimé (NodeBB virtualise les topics).
|
|
15
|
+
* v56 scheduleEmptyCheck supprimé (collapse prématuré).
|
|
16
|
+
* v58 tcfObs survit aux navigations (iframe CMP permanente).
|
|
17
|
+
* v62 is-empty réintroduit, déclenché à l'insertion du wrap.
|
|
18
|
+
* v64 recycleAndMove supprimé (slots restaient en 'unused' après destroy).
|
|
19
|
+
* v67 define(allIds) au boot — Ezoic enregistre tous les slots en interne.
|
|
20
|
+
* v68 setIsSinglePageApplication(true) + newPage() à chaque navigation.
|
|
21
|
+
* v69 Nettoyage prod final : S.recycling orphelin supprimé, helpers Ezoic
|
|
22
|
+
* SPA extraits en fonctions dédiées, commentaires legacy retirés.
|
|
32
23
|
*/
|
|
33
24
|
(function nbbEzoicInfinite() {
|
|
34
25
|
'use strict';
|
|
@@ -40,11 +31,11 @@
|
|
|
40
31
|
const A_ANCHOR = 'data-ezoic-anchor'; // "kindClass:stableId"
|
|
41
32
|
const A_WRAPID = 'data-ezoic-wrapid'; // id Ezoic
|
|
42
33
|
|
|
43
|
-
const EMPTY_CHECK_MS = 5_000; //
|
|
44
|
-
const MAX_INSERTS_RUN = 6;
|
|
45
|
-
const MAX_INFLIGHT = 4;
|
|
46
|
-
const SHOW_THROTTLE_MS = 900;
|
|
47
|
-
const BURST_COOLDOWN_MS = 200;
|
|
34
|
+
const EMPTY_CHECK_MS = 5_000; // collapse wrap vide 5s après insertion
|
|
35
|
+
const MAX_INSERTS_RUN = 6; // insertions max par appel runCore
|
|
36
|
+
const MAX_INFLIGHT = 4; // showAds() simultanés max
|
|
37
|
+
const SHOW_THROTTLE_MS = 900; // anti-spam showAds() par id
|
|
38
|
+
const BURST_COOLDOWN_MS = 200; // délai min entre deux bursts
|
|
48
39
|
|
|
49
40
|
const IO_MARGIN_DESKTOP = '2500px 0px 2500px 0px';
|
|
50
41
|
const IO_MARGIN_MOBILE = '3500px 0px 3500px 0px';
|
|
@@ -60,7 +51,7 @@
|
|
|
60
51
|
* sel sélecteur CSS des éléments cibles
|
|
61
52
|
* baseTag préfixe tag pour querySelector d'ancre
|
|
62
53
|
* anchorAttr attribut DOM stable → clé unique du wrap
|
|
63
|
-
* ordinalAttr attribut 0-based pour
|
|
54
|
+
* ordinalAttr attribut 0-based pour calcul de l'intervalle (null = fallback positionnel)
|
|
64
55
|
*/
|
|
65
56
|
const KIND = {
|
|
66
57
|
'ezoic-ad-message': { sel: SEL.post, baseTag: '', anchorAttr: 'data-pid', ordinalAttr: 'data-index' },
|
|
@@ -80,13 +71,12 @@
|
|
|
80
71
|
lastShow: new Map(),
|
|
81
72
|
io: null,
|
|
82
73
|
domObs: null,
|
|
83
|
-
tcfObs: null,
|
|
74
|
+
tcfObs: null, // survit aux navigations — ne jamais déconnecter
|
|
84
75
|
mutGuard: 0,
|
|
85
76
|
inflight: 0,
|
|
86
77
|
pending: [],
|
|
87
78
|
pendingSet: new Set(),
|
|
88
79
|
wrapByKey: new Map(), // anchorKey → wrap DOM node
|
|
89
|
-
recycling: new Set(), // ids en cours de séquence destroy→define→displayMore
|
|
90
80
|
runQueued: false,
|
|
91
81
|
burstActive: false,
|
|
92
82
|
burstDeadline: 0,
|
|
@@ -138,16 +128,26 @@
|
|
|
138
128
|
S.pools.posts = parseIds(cfg.messagePlaceholderIds);
|
|
139
129
|
S.pools.categories = parseIds(cfg.categoryPlaceholderIds);
|
|
140
130
|
S.poolsReady = true;
|
|
141
|
-
// Déclarer tous les ids
|
|
131
|
+
// Déclarer tous les ids en une seule fois — requis pour que showAds()
|
|
132
|
+
// fonctionne sur des slots insérés dynamiquement (infinite scroll).
|
|
142
133
|
const allIds = [...S.pools.topics, ...S.pools.posts, ...S.pools.categories];
|
|
143
|
-
if (allIds.length)
|
|
134
|
+
if (allIds.length) ezCmd(ez => ez.define(allIds));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ── Helpers Ezoic ──────────────────────────────────────────────────────────
|
|
138
|
+
|
|
139
|
+
function ezCmd(fn) {
|
|
140
|
+
try {
|
|
144
141
|
window.ezstandalone = window.ezstandalone || {};
|
|
145
142
|
const ez = window.ezstandalone;
|
|
146
|
-
const
|
|
147
|
-
typeof ez.cmd?.push === 'function' ? ez.cmd.push(
|
|
148
|
-
}
|
|
143
|
+
const exec = () => { try { fn(ez); } catch (_) {} };
|
|
144
|
+
typeof ez.cmd?.push === 'function' ? ez.cmd.push(exec) : exec();
|
|
145
|
+
} catch (_) {}
|
|
149
146
|
}
|
|
150
147
|
|
|
148
|
+
function notifyEzoicSpa() { ezCmd(ez => ez.setIsSinglePageApplication?.(true)); }
|
|
149
|
+
function notifyEzoicNewPage() { ezCmd(ez => ez.newPage?.()); }
|
|
150
|
+
|
|
151
151
|
// ── Page identity ──────────────────────────────────────────────────────────
|
|
152
152
|
|
|
153
153
|
function pageKey() {
|
|
@@ -355,28 +355,27 @@
|
|
|
355
355
|
if (ph?.isConnected) try { getIO()?.observe(ph); } catch (_) {}
|
|
356
356
|
}
|
|
357
357
|
|
|
358
|
-
function enqueueShow(id) {
|
|
359
|
-
if (!id || isBlocked()) return;
|
|
360
|
-
if (ts() - (S.lastShow.get(id) ?? 0) < SHOW_THROTTLE_MS) return;
|
|
361
|
-
if (S.inflight >= MAX_INFLIGHT) {
|
|
362
|
-
if (!S.pendingSet.has(id)) { S.pending.push(id); S.pendingSet.add(id); }
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
startShow(id);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
358
|
function scheduleEmptyCheck(id) {
|
|
369
359
|
setTimeout(() => {
|
|
370
360
|
try {
|
|
371
361
|
const ph = document.getElementById(`${PH_PREFIX}${id}`);
|
|
372
362
|
const wrap = ph?.closest?.(`.${WRAP_CLASS}`);
|
|
373
363
|
if (!wrap || !ph?.isConnected) return;
|
|
374
|
-
// Collapse uniquement si vraiment vide après 60s
|
|
375
364
|
if (!isFilled(wrap)) wrap.classList.add('is-empty');
|
|
376
365
|
} catch (_) {}
|
|
377
366
|
}, EMPTY_CHECK_MS);
|
|
378
367
|
}
|
|
379
368
|
|
|
369
|
+
function enqueueShow(id) {
|
|
370
|
+
if (!id || isBlocked()) return;
|
|
371
|
+
if (ts() - (S.lastShow.get(id) ?? 0) < SHOW_THROTTLE_MS) return;
|
|
372
|
+
if (S.inflight >= MAX_INFLIGHT) {
|
|
373
|
+
if (!S.pendingSet.has(id)) { S.pending.push(id); S.pendingSet.add(id); }
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
startShow(id);
|
|
377
|
+
}
|
|
378
|
+
|
|
380
379
|
function drainQueue() {
|
|
381
380
|
if (isBlocked()) return;
|
|
382
381
|
while (S.inflight < MAX_INFLIGHT && S.pending.length) {
|
|
@@ -405,16 +404,11 @@
|
|
|
405
404
|
const t = ts();
|
|
406
405
|
if (t - (S.lastShow.get(id) ?? 0) < SHOW_THROTTLE_MS) { clearTimeout(timer); return release(); }
|
|
407
406
|
S.lastShow.set(id, t);
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
try { document.getElementById(`${PH_PREFIX}${id}`)?.closest?.(`.${WRAP_CLASS}`)?.classList.remove('is-empty'); } catch (_) {}
|
|
411
|
-
window.ezstandalone = window.ezstandalone || {};
|
|
412
|
-
const ez = window.ezstandalone;
|
|
413
|
-
const doShow = () => {
|
|
407
|
+
try { ph.closest?.(`.${WRAP_CLASS}`)?.classList.remove('is-empty'); } catch (_) {}
|
|
408
|
+
ezCmd(ez => {
|
|
414
409
|
try { ez.showAds(id); } catch (_) {}
|
|
415
410
|
setTimeout(() => { clearTimeout(timer); release(); }, 700);
|
|
416
|
-
};
|
|
417
|
-
Array.isArray(ez.cmd) ? ez.cmd.push(doShow) : doShow();
|
|
411
|
+
});
|
|
418
412
|
} catch (_) { clearTimeout(timer); release(); }
|
|
419
413
|
});
|
|
420
414
|
}
|
|
@@ -515,11 +509,11 @@
|
|
|
515
509
|
function cleanup() {
|
|
516
510
|
blockedUntil = ts() + 1500;
|
|
517
511
|
mutate(() => document.querySelectorAll(`.${WRAP_CLASS}`).forEach(dropWrap));
|
|
518
|
-
S.cfg
|
|
512
|
+
S.cfg = null;
|
|
519
513
|
_cfgErrorUntil = 0;
|
|
520
|
-
S.poolsReady
|
|
521
|
-
S.pools
|
|
522
|
-
S.cursors
|
|
514
|
+
S.poolsReady = false;
|
|
515
|
+
S.pools = { topics: [], posts: [], categories: [] };
|
|
516
|
+
S.cursors = { topics: 0, posts: 0, categories: 0 };
|
|
523
517
|
S.mountedIds.clear();
|
|
524
518
|
S.lastShow.clear();
|
|
525
519
|
S.wrapByKey.clear();
|
|
@@ -530,8 +524,8 @@
|
|
|
530
524
|
S.runQueued = false;
|
|
531
525
|
if (S.domObs) { S.domObs.disconnect(); S.domObs = null; }
|
|
532
526
|
// tcfObs intentionnellement préservé : l'iframe __tcfapiLocator doit
|
|
533
|
-
//
|
|
534
|
-
// des erreurs CMP postMessage
|
|
527
|
+
// rester en vie pendant toute la session — la déconnecter entre deux
|
|
528
|
+
// navigations cause des erreurs CMP postMessage.
|
|
535
529
|
}
|
|
536
530
|
|
|
537
531
|
// ── MutationObserver DOM ───────────────────────────────────────────────────
|
|
@@ -627,7 +621,9 @@
|
|
|
627
621
|
$(window).on('action:ajaxify.end.nbbEzoic', () => {
|
|
628
622
|
S.pageKey = pageKey();
|
|
629
623
|
blockedUntil = 0;
|
|
630
|
-
muteConsole();
|
|
624
|
+
muteConsole();
|
|
625
|
+
ensureTcfLocator();
|
|
626
|
+
notifyEzoicNewPage();
|
|
631
627
|
patchShowAds(); getIO(); ensureDomObserver(); requestBurst();
|
|
632
628
|
});
|
|
633
629
|
const burstEvts = [
|
|
@@ -666,6 +662,7 @@
|
|
|
666
662
|
muteConsole();
|
|
667
663
|
ensureTcfLocator();
|
|
668
664
|
warmNetwork();
|
|
665
|
+
notifyEzoicSpa(); // NodeBB est une SPA — Ezoic ajuste son cycle interne
|
|
669
666
|
patchShowAds();
|
|
670
667
|
getIO();
|
|
671
668
|
ensureDomObserver();
|