nodebb-plugin-ezoic-infinite 1.5.37 → 1.5.39
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 +9 -156
- package/public/style.css +1 -18
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -11,21 +11,11 @@
|
|
|
11
11
|
const MAX_INSERTS_PER_RUN = 3;
|
|
12
12
|
|
|
13
13
|
// Preload before viewport (earlier load for smoother scroll)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
// When the user scrolls very fast, temporarily preload more aggressively.
|
|
20
|
-
// This helps ensure ads are already in-flight before the user reaches them.
|
|
21
|
-
const PRELOAD_MARGIN_DESKTOP_BOOST = '6500px 0px 6500px 0px';
|
|
22
|
-
const PRELOAD_MARGIN_MOBILE_BOOST = '4200px 0px 4200px 0px';
|
|
23
|
-
const BOOST_DURATION_MS = 2500;
|
|
24
|
-
const BOOST_SPEED_PX_PER_MS = 2.2; // ~2200px/s
|
|
25
|
-
|
|
26
|
-
// Allow a bit more parallelism; the perf profile can still dial this down on low-end devices.
|
|
27
|
-
const MAX_INFLIGHT_DESKTOP = 5;
|
|
28
|
-
const MAX_INFLIGHT_MOBILE = 4;
|
|
14
|
+
const PRELOAD_MARGIN_DESKTOP = '2600px 0px 2600px 0px';
|
|
15
|
+
const PRELOAD_MARGIN_MOBILE = '1500px 0px 1500px 0px';
|
|
16
|
+
|
|
17
|
+
const MAX_INFLIGHT_DESKTOP = 4;
|
|
18
|
+
const MAX_INFLIGHT_MOBILE = 3;
|
|
29
19
|
|
|
30
20
|
|
|
31
21
|
// Adaptive performance profile (device/network aware)
|
|
@@ -73,23 +63,17 @@ function getPerfProfile() {
|
|
|
73
63
|
return p;
|
|
74
64
|
}
|
|
75
65
|
|
|
76
|
-
function isBoosted() {
|
|
77
|
-
try { return Date.now() < (state.scrollBoostUntil || 0); } catch (e) { return false; }
|
|
78
|
-
}
|
|
79
|
-
|
|
80
66
|
function isMobile() {
|
|
81
67
|
try { return window && window.innerWidth && window.innerWidth < 768; } catch (e) { return false; }
|
|
82
68
|
}
|
|
83
69
|
|
|
84
70
|
function getPreloadRootMargin() {
|
|
85
|
-
|
|
86
|
-
return isBoosted() ? PRELOAD_MARGIN_DESKTOP_BOOST : PRELOAD_MARGIN_DESKTOP;
|
|
71
|
+
return isMobile() ? PRELOAD_MARGIN_MOBILE : PRELOAD_MARGIN_DESKTOP;
|
|
87
72
|
}
|
|
88
73
|
|
|
89
74
|
function getMaxInflight() {
|
|
90
75
|
const perf = getPerfProfile();
|
|
91
|
-
|
|
92
|
-
return base + (isBoosted() ? 1 : 0);
|
|
76
|
+
return isMobile() ? perf.maxInflightMobile : perf.maxInflightDesktop;
|
|
93
77
|
}
|
|
94
78
|
|
|
95
79
|
const SELECTORS = {
|
|
@@ -158,11 +142,6 @@ function mutationHasRelevantAddedNodes(mutations) {
|
|
|
158
142
|
inflight: 0,
|
|
159
143
|
pending: [],
|
|
160
144
|
pendingSet: new Set(),
|
|
161
|
-
|
|
162
|
-
// fast scroll boosting
|
|
163
|
-
scrollBoostUntil: 0,
|
|
164
|
-
lastScrollY: 0,
|
|
165
|
-
lastScrollTs: 0,
|
|
166
145
|
ioMargin: null,
|
|
167
146
|
|
|
168
147
|
// hero)
|
|
@@ -602,9 +581,6 @@ function startShow(id) {
|
|
|
602
581
|
try { ez.showAds(id); } catch (e) {}
|
|
603
582
|
try { state.usedOnce && state.usedOnce.add(id); } catch (e) {}
|
|
604
583
|
|
|
605
|
-
// Tighten any oversized reserved height once the creative is in the DOM.
|
|
606
|
-
try { scheduleTighten(id); } catch (e) {}
|
|
607
|
-
|
|
608
584
|
setTimeout(() => { clearTimeout(hardTimer); release(); }, 650);
|
|
609
585
|
};
|
|
610
586
|
|
|
@@ -619,83 +595,6 @@ function startShow(id) {
|
|
|
619
595
|
});
|
|
620
596
|
}
|
|
621
597
|
|
|
622
|
-
// ---------- height normalization (reduce empty space) ----------
|
|
623
|
-
// Some Ezoic / GPT wrappers reserve a larger min-height (e.g., 400px) than the rendered creative (e.g., 250px),
|
|
624
|
-
// leaving visible empty space. We “tighten” the reserved min-height to the actual iframe/container height after load.
|
|
625
|
-
const _heightObsByPlaceholder = new Map();
|
|
626
|
-
|
|
627
|
-
function tightenEzoicHeightFor(id) {
|
|
628
|
-
try {
|
|
629
|
-
const ph = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
|
|
630
|
-
if (!ph || !ph.isConnected) return;
|
|
631
|
-
|
|
632
|
-
const ad = ph.querySelector('span.ezoic-ad');
|
|
633
|
-
if (!ad) return;
|
|
634
|
-
|
|
635
|
-
// Prefer the safeframe/container size if present.
|
|
636
|
-
let h = 0;
|
|
637
|
-
const container = ad.querySelector('div[id$="__container__"]');
|
|
638
|
-
if (container) {
|
|
639
|
-
const r = container.getBoundingClientRect();
|
|
640
|
-
if (r && r.height) h = Math.max(h, r.height);
|
|
641
|
-
}
|
|
642
|
-
const iframe = ad.querySelector('iframe');
|
|
643
|
-
if (iframe) {
|
|
644
|
-
const r2 = iframe.getBoundingClientRect();
|
|
645
|
-
if (r2 && r2.height) h = Math.max(h, r2.height);
|
|
646
|
-
const attrH = parseInt(iframe.getAttribute('height') || '', 10);
|
|
647
|
-
if (Number.isFinite(attrH) && attrH > 0) h = Math.max(h, attrH);
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
// Fall back to inner wrapper height.
|
|
651
|
-
if (!h) {
|
|
652
|
-
const inner = ad.firstElementChild;
|
|
653
|
-
if (inner) {
|
|
654
|
-
const r3 = inner.getBoundingClientRect();
|
|
655
|
-
if (r3 && r3.height) h = Math.max(h, r3.height);
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
if (!h || h < 10) return;
|
|
660
|
-
const px = `${Math.ceil(h)}px`;
|
|
661
|
-
|
|
662
|
-
// Override inline min-height with an inline !important value.
|
|
663
|
-
try { ad.style.setProperty('min-height', px, 'important'); } catch (e) {}
|
|
664
|
-
// Keep height auto so responsive creatives can expand if needed.
|
|
665
|
-
try { ad.style.setProperty('height', 'auto', 'important'); } catch (e) {}
|
|
666
|
-
} catch (e) {}
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
function ensureHeightObserver(id) {
|
|
670
|
-
try {
|
|
671
|
-
if (_heightObsByPlaceholder.has(id)) return;
|
|
672
|
-
const ph = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
|
|
673
|
-
if (!ph || !ph.isConnected) return;
|
|
674
|
-
|
|
675
|
-
const ro = (typeof ResizeObserver === 'function') ? new ResizeObserver(() => {
|
|
676
|
-
tightenEzoicHeightFor(id);
|
|
677
|
-
}) : null;
|
|
678
|
-
|
|
679
|
-
if (ro) {
|
|
680
|
-
const ad = ph.querySelector('span.ezoic-ad');
|
|
681
|
-
const container = ad && ad.querySelector && ad.querySelector('div[id$="__container__"]');
|
|
682
|
-
const iframe = ad && ad.querySelector && ad.querySelector('iframe');
|
|
683
|
-
try { if (container) ro.observe(container); } catch (e) {}
|
|
684
|
-
try { if (iframe) ro.observe(iframe); } catch (e) {}
|
|
685
|
-
try { if (ad) ro.observe(ad); } catch (e) {}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
_heightObsByPlaceholder.set(id, ro || true);
|
|
689
|
-
} catch (e) {}
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
function scheduleTighten(id) {
|
|
693
|
-
// Run a couple of times (creatives may resize after initial load)
|
|
694
|
-
try { setTimeout(() => tightenEzoicHeightFor(id), 250); } catch (e) {}
|
|
695
|
-
try { setTimeout(() => tightenEzoicHeightFor(id), 1100); } catch (e) {}
|
|
696
|
-
try { ensureHeightObserver(id); } catch (e) {}
|
|
697
|
-
}
|
|
698
|
-
|
|
699
598
|
|
|
700
599
|
// ---------- preload / above-the-fold ----------
|
|
701
600
|
|
|
@@ -748,9 +647,7 @@ function scheduleTighten(id) {
|
|
|
748
647
|
// If already near the fold, arm & fire immediately
|
|
749
648
|
try {
|
|
750
649
|
const r = wrap.getBoundingClientRect();
|
|
751
|
-
|
|
752
|
-
// During boost (fast scroll), preload even farther.
|
|
753
|
-
const screens = isBoosted() ? 6.0 : 4.0;
|
|
650
|
+
const screens = 3.0;
|
|
754
651
|
const h = (window.innerHeight || 800);
|
|
755
652
|
if (r.top < screens * h && r.bottom > -screens * h) {
|
|
756
653
|
armPlaceholder(wrap, id);
|
|
@@ -777,7 +674,7 @@ function scheduleTighten(id) {
|
|
|
777
674
|
const targets = computeTargets(items.length, interval, showFirst);
|
|
778
675
|
let inserted = 0;
|
|
779
676
|
const perf = getPerfProfile();
|
|
780
|
-
const maxInserts = perf.maxInsertsPerRun
|
|
677
|
+
const maxInserts = perf.maxInsertsPerRun;
|
|
781
678
|
|
|
782
679
|
for (const afterPos of targets) {
|
|
783
680
|
if (inserted >= maxInserts) break;
|
|
@@ -956,14 +853,6 @@ function scheduleTighten(id) {
|
|
|
956
853
|
// reset perf profile cache
|
|
957
854
|
state.perfProfile = null;
|
|
958
855
|
|
|
959
|
-
// disconnect any ResizeObservers used for height tightening
|
|
960
|
-
try {
|
|
961
|
-
for (const v of _heightObsByPlaceholder.values()) {
|
|
962
|
-
try { v && v.disconnect && v.disconnect(); } catch (e) {}
|
|
963
|
-
}
|
|
964
|
-
_heightObsByPlaceholder.clear();
|
|
965
|
-
} catch (e) {}
|
|
966
|
-
|
|
967
856
|
// reset state
|
|
968
857
|
state.cfg = null;
|
|
969
858
|
state.allTopics = [];
|
|
@@ -1027,41 +916,6 @@ function scheduleTighten(id) {
|
|
|
1027
916
|
});
|
|
1028
917
|
}
|
|
1029
918
|
|
|
1030
|
-
function bindScroll() {
|
|
1031
|
-
let ticking = false;
|
|
1032
|
-
window.addEventListener('scroll', () => {
|
|
1033
|
-
// Detect very fast scrolling and temporarily boost preload/parallelism.
|
|
1034
|
-
try {
|
|
1035
|
-
const now = Date.now();
|
|
1036
|
-
const y = window.scrollY || window.pageYOffset || 0;
|
|
1037
|
-
if (state.lastScrollTs) {
|
|
1038
|
-
const dt = now - state.lastScrollTs;
|
|
1039
|
-
const dy = Math.abs(y - (state.lastScrollY || 0));
|
|
1040
|
-
if (dt > 0) {
|
|
1041
|
-
const speed = dy / dt; // px/ms
|
|
1042
|
-
if (speed >= BOOST_SPEED_PX_PER_MS) {
|
|
1043
|
-
const wasBoosted = isBoosted();
|
|
1044
|
-
state.scrollBoostUntil = Math.max(state.scrollBoostUntil || 0, now + BOOST_DURATION_MS);
|
|
1045
|
-
if (!wasBoosted) {
|
|
1046
|
-
// margin changed -> rebuild IO so existing placeholders get earlier preload
|
|
1047
|
-
ensurePreloadObserver();
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
state.lastScrollY = y;
|
|
1053
|
-
state.lastScrollTs = now;
|
|
1054
|
-
} catch (e) {}
|
|
1055
|
-
|
|
1056
|
-
if (ticking) return;
|
|
1057
|
-
ticking = true;
|
|
1058
|
-
window.requestAnimationFrame(() => {
|
|
1059
|
-
ticking = false;
|
|
1060
|
-
if (!isBlocked()) scheduleRun();
|
|
1061
|
-
});
|
|
1062
|
-
}, { passive: true });
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
919
|
// ---------- boot ----------
|
|
1066
920
|
|
|
1067
921
|
state.pageKey = getPageKey();
|
|
@@ -1071,7 +925,6 @@ function scheduleTighten(id) {
|
|
|
1071
925
|
ensureDomObserver();
|
|
1072
926
|
|
|
1073
927
|
bindNodeBB();
|
|
1074
|
-
bindScroll();
|
|
1075
928
|
|
|
1076
929
|
// First paint: try hero + run
|
|
1077
930
|
blockedUntil = 0;
|
package/public/style.css
CHANGED
|
@@ -1,26 +1,9 @@
|
|
|
1
1
|
/* Minimal styling for injected Ezoic wrappers.
|
|
2
2
|
Spacing (margins/padding) is intentionally NOT forced here, because it can be
|
|
3
3
|
configured inside Ezoic and may vary by placement/device.
|
|
4
|
-
|
|
5
|
-
Goals:
|
|
6
|
-
- prevent flex/centering styles from parent lists from affecting ad internals
|
|
7
|
-
- reduce layout jank when iframes resize during scroll
|
|
8
4
|
*/
|
|
9
5
|
|
|
10
6
|
.ezoic-ad {
|
|
11
|
-
display: block
|
|
12
|
-
position: relative;
|
|
7
|
+
display: block;
|
|
13
8
|
width: 100%;
|
|
14
|
-
overflow: hidden;
|
|
15
|
-
|
|
16
|
-
/* limit how far layout/paint changes propagate */
|
|
17
|
-
contain: layout paint style;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/* Keep ad content aligned to the top (avoids the "slides to bottom" look) */
|
|
21
|
-
.ezoic-ad iframe,
|
|
22
|
-
.ezoic-ad ins,
|
|
23
|
-
.ezoic-ad > div {
|
|
24
|
-
display: block !important;
|
|
25
|
-
vertical-align: top !important;
|
|
26
9
|
}
|