nodebb-plugin-ezoic-infinite 1.6.42 → 1.6.44
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 +49 -5
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -1647,10 +1647,11 @@ function buildOrdinalMap(items) {
|
|
|
1647
1647
|
}
|
|
1648
1648
|
|
|
1649
1649
|
// --- Empty ad "poke" helper ---
|
|
1650
|
-
// Some GPT safeframe
|
|
1651
|
-
// We avoid
|
|
1650
|
+
// Some GPT / safeframe renders can stay visually blank until a *real* scroll happens.
|
|
1651
|
+
// We still avoid showAds()/refresh() (can hurt fill), but we mimic the user "micro scroll".
|
|
1652
1652
|
var ezEmptySeen = Object.create(null);
|
|
1653
1653
|
var ezEmptyPokeTimer = Object.create(null);
|
|
1654
|
+
var ezEmptyAttempts = Object.create(null);
|
|
1654
1655
|
|
|
1655
1656
|
function inViewportLoose(el) {
|
|
1656
1657
|
try {
|
|
@@ -1664,24 +1665,58 @@ function buildOrdinalMap(items) {
|
|
|
1664
1665
|
}
|
|
1665
1666
|
}
|
|
1666
1667
|
|
|
1668
|
+
function hasAnyIframe(divEl) {
|
|
1669
|
+
try {
|
|
1670
|
+
if (!divEl) return false;
|
|
1671
|
+
return !!divEl.querySelector('iframe');
|
|
1672
|
+
} catch (e) {
|
|
1673
|
+
return false;
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
function microScrollNudge() {
|
|
1678
|
+
try {
|
|
1679
|
+
// Only if the page can actually scroll
|
|
1680
|
+
var maxY = (document.documentElement && document.documentElement.scrollHeight) ? document.documentElement.scrollHeight : 0;
|
|
1681
|
+
if (maxY <= (window.innerHeight || 0) + 2) return;
|
|
1682
|
+
|
|
1683
|
+
var x = window.scrollX || 0;
|
|
1684
|
+
var y = window.scrollY || 0;
|
|
1685
|
+
// Nudge by 1px and restore on the next frame.
|
|
1686
|
+
window.scrollTo(x, y + 1);
|
|
1687
|
+
requestAnimationFrame(function(){
|
|
1688
|
+
try { window.scrollTo(x, y); } catch (e) {}
|
|
1689
|
+
});
|
|
1690
|
+
} catch (e) {}
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1667
1693
|
function pokeReflowForDivId(divId) {
|
|
1668
1694
|
try {
|
|
1669
1695
|
var el = document.getElementById(divId);
|
|
1670
1696
|
if (!el) return;
|
|
1671
1697
|
if (!inViewportLoose(el)) return;
|
|
1672
1698
|
|
|
1699
|
+
// If the slot already has an iframe, don't keep poking.
|
|
1700
|
+
if (hasAnyIframe(el)) return;
|
|
1701
|
+
|
|
1673
1702
|
// Force a tiny reflow/paint on the closest wrapper
|
|
1674
1703
|
var wrap = el.closest ? (el.closest('.ez-fixed-wrap') || el.parentElement) : el.parentElement;
|
|
1675
1704
|
if (!wrap) wrap = el;
|
|
1676
1705
|
|
|
1677
|
-
//
|
|
1706
|
+
// 1) Force layout
|
|
1707
|
+
try { void wrap.offsetHeight; } catch (e) {}
|
|
1708
|
+
|
|
1709
|
+
// 2) Toggle visibility for one frame (forces paint)
|
|
1678
1710
|
var prevVis = wrap.style.visibility;
|
|
1679
1711
|
wrap.style.visibility = 'hidden';
|
|
1680
1712
|
requestAnimationFrame(function(){
|
|
1681
1713
|
wrap.style.visibility = prevVis || '';
|
|
1682
|
-
//
|
|
1714
|
+
// 3) Fire synthetic events (cheap)
|
|
1683
1715
|
try { window.dispatchEvent(new Event('scroll')); } catch (e) {}
|
|
1684
1716
|
try { window.dispatchEvent(new Event('resize')); } catch (e) {}
|
|
1717
|
+
|
|
1718
|
+
// 4) If the slot was "empty", a real scroll often makes it fill immediately.
|
|
1719
|
+
microScrollNudge();
|
|
1685
1720
|
});
|
|
1686
1721
|
} catch (e) {}
|
|
1687
1722
|
}
|
|
@@ -1692,13 +1727,22 @@ function buildOrdinalMap(items) {
|
|
|
1692
1727
|
var now = Date.now();
|
|
1693
1728
|
// Cooldown per slot to avoid loops
|
|
1694
1729
|
if (ezEmptySeen[divId] && now - ezEmptySeen[divId] < 15000) return;
|
|
1730
|
+
// New window: reset attempts
|
|
1731
|
+
ezEmptyAttempts[divId] = 0;
|
|
1695
1732
|
ezEmptySeen[divId] = now;
|
|
1696
1733
|
|
|
1734
|
+
// Cap attempts per slot in a short window
|
|
1735
|
+
ezEmptyAttempts[divId] = (ezEmptyAttempts[divId] || 0) + 1;
|
|
1736
|
+
if (ezEmptyAttempts[divId] > 3) return;
|
|
1737
|
+
|
|
1697
1738
|
if (ezEmptyPokeTimer[divId]) return;
|
|
1739
|
+
// Multi-poke: fast + a couple of retries (covers slow GPT / lazy paint)
|
|
1698
1740
|
ezEmptyPokeTimer[divId] = setTimeout(function(){
|
|
1699
1741
|
ezEmptyPokeTimer[divId] = null;
|
|
1700
1742
|
pokeReflowForDivId(divId);
|
|
1701
|
-
|
|
1743
|
+
setTimeout(function(){ pokeReflowForDivId(divId); }, 350);
|
|
1744
|
+
setTimeout(function(){ pokeReflowForDivId(divId); }, 1200);
|
|
1745
|
+
}, 80);
|
|
1702
1746
|
} catch (e) {}
|
|
1703
1747
|
}
|
|
1704
1748
|
|