nodebb-plugin-ezoic-infinite 1.7.32 → 1.7.34
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 +41 -93
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 v36
|
|
3
3
|
*
|
|
4
4
|
* Historique des corrections majeures
|
|
5
5
|
* ────────────────────────────────────
|
|
@@ -30,19 +30,21 @@
|
|
|
30
30
|
* – Toujours désactivé pour les posts : NodeBB virtualise les posts
|
|
31
31
|
* hors-viewport → faux-orphelins → bug réinjection en haut.
|
|
32
32
|
*
|
|
33
|
-
* v34 moveDistantWrap
|
|
34
|
-
* et recréer. Ezoic garde une registry interne des placeholders — recréer
|
|
35
|
-
* un div avec le même id déclenche "already been defined" et bloque
|
|
36
|
-
* showAds(). En déplaçant le même nœud DOM, la registry reste valide.
|
|
33
|
+
* v34 moveDistantWrap — voir v38.
|
|
37
34
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
35
|
+
* v40 Recyclage slots via destroyPlaceholders+define+displayMore avec délais.
|
|
36
|
+
* Séquence : destroy → 300ms → define → 300ms → displayMore.
|
|
37
|
+
* Testé manuellement : fonctionne. displayMore = API Ezoic infinite scroll.
|
|
38
|
+
*
|
|
39
|
+
* v38 Pool épuisé = fin de quota Ezoic par page-view. ez.refresh() interdit
|
|
40
|
+
* sur la même page que ez.enable() — supprimé. moveDistantWrap supprimé :
|
|
41
|
+
* déplacer un wrap "already defined" ne re-sert aucune pub. Pool épuisé →
|
|
42
|
+
* break propre dans injectBetween. muteConsole : ajout warnings refresh.
|
|
41
43
|
*
|
|
42
44
|
* v36 Optimisations chemin critique (scroll → injectBetween) :
|
|
43
45
|
* – S.wrapByKey Map<anchorKey,wrap> : findWrap() passe de querySelector
|
|
44
46
|
* sur tout le doc à un lookup O(1). Mis à jour dans insertAfter,
|
|
45
|
-
*
|
|
47
|
+
* dropWrap et cleanup.
|
|
46
48
|
* – wrapIsLive allégé : pour les voisins immédiats on vérifie les
|
|
47
49
|
* attributs du nœud lui-même sans querySelector global.
|
|
48
50
|
* – MutationObserver : matches() vérifié avant querySelector() pour
|
|
@@ -51,9 +53,6 @@
|
|
|
51
53
|
* v35 Revue complète prod-ready :
|
|
52
54
|
* – initPools protégé contre ré-initialisation inutile (S.poolsReady).
|
|
53
55
|
* – muteConsole élargit à "No valid placeholders for loadMore".
|
|
54
|
-
* – moveDistantWrap appelle ezstandalone.refresh([id]) après déplacement
|
|
55
|
-
* pour forcer Ezoic à réactiver le placeholder sur son nouveau nœud.
|
|
56
|
-
* – A_SHOWN initialisé à '0' dans moveDistantWrap (évite NaN dans parseInt).
|
|
57
56
|
* – Commentaires et historique nettoyés.
|
|
58
57
|
*/
|
|
59
58
|
(function nbbEzoicInfinite() {
|
|
@@ -216,7 +215,7 @@
|
|
|
216
215
|
// Lookup O(1) dans le registre — vrai si le wrap EST encore dans le registre
|
|
217
216
|
// et connecté au DOM (le registre est tenu à jour par insertAfter/dropWrap).
|
|
218
217
|
if (S.wrapByKey.get(key) === wrap) return wrap.isConnected;
|
|
219
|
-
// Fallback :
|
|
218
|
+
// Fallback : registre pas encore à jour ou wrap non enregistré.
|
|
220
219
|
const colonIdx = key.indexOf(':');
|
|
221
220
|
const klass = key.slice(0, colonIdx);
|
|
222
221
|
const anchorId = key.slice(colonIdx + 1);
|
|
@@ -292,19 +291,20 @@
|
|
|
292
291
|
}
|
|
293
292
|
|
|
294
293
|
/**
|
|
295
|
-
* Pool épuisé :
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
* pour forcer Ezoic à réactiver la pub sur sa nouvelle position.
|
|
301
|
-
*
|
|
302
|
-
* Priorité : wraps non remplis (pas de pub visible perdue), puis remplis.
|
|
294
|
+
* Pool épuisé : recycle un wrap loin au-dessus du viewport.
|
|
295
|
+
* Séquence avec délais (destroyPlaceholders est asynchrone) :
|
|
296
|
+
* destroy([id]) → 300ms → define([id]) → 300ms → displayMore([id])
|
|
297
|
+
* displayMore = API Ezoic prévue pour l'infinite scroll.
|
|
298
|
+
* Priorité : wraps vides d'abord, remplis si nécessaire.
|
|
303
299
|
*/
|
|
304
|
-
function
|
|
305
|
-
const
|
|
306
|
-
|
|
300
|
+
function recycleAndMove(klass, targetEl, newKey) {
|
|
301
|
+
const ez = window.ezstandalone;
|
|
302
|
+
if (typeof ez?.destroyPlaceholders !== 'function' ||
|
|
303
|
+
typeof ez?.define !== 'function' ||
|
|
304
|
+
typeof ez?.displayMore !== 'function') return null;
|
|
307
305
|
|
|
306
|
+
const vh = window.innerHeight || 800;
|
|
307
|
+
const threshold = -vh * 4;
|
|
308
308
|
let bestEmpty = null, bestEmptyBottom = Infinity;
|
|
309
309
|
let bestFilled = null, bestFilledBottom = Infinity;
|
|
310
310
|
|
|
@@ -322,7 +322,6 @@
|
|
|
322
322
|
|
|
323
323
|
const best = bestEmpty ?? bestFilled;
|
|
324
324
|
if (!best) return null;
|
|
325
|
-
|
|
326
325
|
const id = parseInt(best.getAttribute(A_WRAPID), 10);
|
|
327
326
|
if (!Number.isFinite(id)) return null;
|
|
328
327
|
|
|
@@ -332,21 +331,18 @@
|
|
|
332
331
|
best.setAttribute(A_CREATED, String(ts()));
|
|
333
332
|
best.setAttribute(A_SHOWN, '0');
|
|
334
333
|
best.classList.remove('is-empty');
|
|
334
|
+
const ph = best.querySelector(`#${PH_PREFIX}${id}`);
|
|
335
|
+
if (ph) ph.innerHTML = '';
|
|
335
336
|
targetEl.insertAdjacentElement('afterend', best);
|
|
336
337
|
});
|
|
337
|
-
// Mettre à jour le registre : ancienne clé → nouvelle clé
|
|
338
338
|
if (oldKey && S.wrapByKey.get(oldKey) === best) S.wrapByKey.delete(oldKey);
|
|
339
339
|
S.wrapByKey.set(newKey, best);
|
|
340
340
|
|
|
341
|
-
//
|
|
342
|
-
try {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
try { ez.refresh([id]); } catch (_) {}
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
} catch (_) {}
|
|
341
|
+
// Délais requis : destroyPlaceholders est asynchrone en interne
|
|
342
|
+
const doDestroy = () => { try { ez.destroyPlaceholders([id]); } catch (_) {} setTimeout(doDefine, 300); };
|
|
343
|
+
const doDefine = () => { try { ez.define([id]); } catch (_) {} setTimeout(doDisplay, 300); };
|
|
344
|
+
const doDisplay = () => { try { ez.displayMore([id]); } catch (_) {} };
|
|
345
|
+
try { (typeof ez.cmd?.push === 'function') ? ez.cmd.push(doDestroy) : doDestroy(); } catch (_) {}
|
|
350
346
|
|
|
351
347
|
return { id, wrap: best };
|
|
352
348
|
}
|
|
@@ -462,14 +458,11 @@
|
|
|
462
458
|
|
|
463
459
|
const id = pickId(poolKey);
|
|
464
460
|
if (id) {
|
|
465
|
-
// Pool disponible : créer un nouveau wrap
|
|
466
461
|
const w = insertAfter(el, id, klass, key);
|
|
467
462
|
if (w) { observePh(id); inserted++; }
|
|
468
463
|
} else {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
if (!moved) continue;
|
|
472
|
-
observePh(moved.id);
|
|
464
|
+
const recycled = recycleAndMove(klass, el, key);
|
|
465
|
+
if (!recycled) break;
|
|
473
466
|
inserted++;
|
|
474
467
|
}
|
|
475
468
|
}
|
|
@@ -619,70 +612,23 @@
|
|
|
619
612
|
return injectBetween(klass, getItems(), interval, normBool(cfgShowFirst), poolKey);
|
|
620
613
|
};
|
|
621
614
|
|
|
622
|
-
if (kind === 'topic')
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
);
|
|
627
|
-
refreshStaleWraps();
|
|
628
|
-
return n;
|
|
629
|
-
}
|
|
615
|
+
if (kind === 'topic') return exec(
|
|
616
|
+
'ezoic-ad-message', getPosts,
|
|
617
|
+
cfg.enableMessageAds, cfg.messageIntervalPosts, cfg.showFirstMessageAd, 'posts'
|
|
618
|
+
);
|
|
630
619
|
|
|
631
620
|
if (kind === 'categoryTopics') {
|
|
632
621
|
pruneOrphansBetween();
|
|
633
|
-
|
|
622
|
+
return exec(
|
|
634
623
|
'ezoic-ad-between', getTopics,
|
|
635
624
|
cfg.enableBetweenAds, cfg.intervalPosts, cfg.showFirstTopicAd, 'topics'
|
|
636
625
|
);
|
|
637
|
-
refreshStaleWraps();
|
|
638
|
-
return n;
|
|
639
626
|
}
|
|
640
627
|
|
|
641
|
-
|
|
628
|
+
return exec(
|
|
642
629
|
'ezoic-ad-categories', getCategories,
|
|
643
630
|
cfg.enableCategoryAds, cfg.intervalCategories, cfg.showFirstCategoryAd, 'categories'
|
|
644
631
|
);
|
|
645
|
-
refreshStaleWraps();
|
|
646
|
-
return n2;
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
/**
|
|
650
|
-
* Appelle ez.refresh() sur les placeholders en DOM, non remplis,
|
|
651
|
-
* dans la zone visible (marges IO). Cela force Ezoic à re-servir
|
|
652
|
-
* une pub sur des slots qu'il avait refusé lors du showAds() initial.
|
|
653
|
-
* Limité à MAX_REFRESH_PER_RUN appels par invocation.
|
|
654
|
-
*/
|
|
655
|
-
const MAX_REFRESH_PER_RUN = 3;
|
|
656
|
-
|
|
657
|
-
function refreshStaleWraps() {
|
|
658
|
-
const ez = window.ezstandalone;
|
|
659
|
-
if (typeof ez?.refresh !== 'function') return;
|
|
660
|
-
|
|
661
|
-
const vh = window.innerHeight || 800;
|
|
662
|
-
const margin = (isMobile() ? 3500 : 2500);
|
|
663
|
-
const top = -margin;
|
|
664
|
-
const bot = vh + margin;
|
|
665
|
-
|
|
666
|
-
const ids = [];
|
|
667
|
-
for (const [, wrap] of S.wrapByKey) {
|
|
668
|
-
if (ids.length >= MAX_REFRESH_PER_RUN) break;
|
|
669
|
-
if (!wrap.isConnected || isFilled(wrap)) continue;
|
|
670
|
-
// Vérifier que le wrap a déjà eu un showAds (A_SHOWN > 0)
|
|
671
|
-
const shown = parseInt(wrap.getAttribute(A_SHOWN) || '0', 10);
|
|
672
|
-
if (!shown) continue;
|
|
673
|
-
try {
|
|
674
|
-
const rect = wrap.getBoundingClientRect();
|
|
675
|
-
if (rect.top > bot || rect.bottom < top) continue;
|
|
676
|
-
const id = parseInt(wrap.getAttribute(A_WRAPID), 10);
|
|
677
|
-
if (Number.isFinite(id) && id > 0) ids.push(id);
|
|
678
|
-
} catch (_) {}
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
if (!ids.length) return;
|
|
682
|
-
try {
|
|
683
|
-
const doRefresh = () => { try { ez.refresh(ids); } catch (_) {} };
|
|
684
|
-
Array.isArray(ez.cmd) ? ez.cmd.push(doRefresh) : doRefresh();
|
|
685
|
-
} catch (_) {}
|
|
686
632
|
}
|
|
687
633
|
|
|
688
634
|
// ── Scheduler ──────────────────────────────────────────────────────────────
|
|
@@ -772,6 +718,8 @@
|
|
|
772
718
|
const MUTED = [
|
|
773
719
|
'[EzoicAds JS]: Placeholder Id',
|
|
774
720
|
'No valid placeholders for loadMore',
|
|
721
|
+
'cannot call refresh on the same page',
|
|
722
|
+
'no placeholders are currently defined in Refresh',
|
|
775
723
|
'Debugger iframe already exists',
|
|
776
724
|
`with id ${PH_PREFIX}`,
|
|
777
725
|
];
|