nodebb-plugin-ezoic-infinite 1.6.45 → 1.6.47
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 +130 -18
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -1515,11 +1515,7 @@ function buildOrdinalMap(items) {
|
|
|
1515
1515
|
(function () {
|
|
1516
1516
|
// Goal: keep ad injection intact. Only repair when we detect "pile-up" of between wraps.
|
|
1517
1517
|
var TOPIC_LI_SEL = 'li[component="category/topic"]';
|
|
1518
|
-
|
|
1519
|
-
// Note: Ezoic can inject <span class="ezoic-ad ...">; we normalize those into our wraps.
|
|
1520
|
-
var BETWEEN_WRAP_SEL = 'div.nodebb-ezoic-wrap.ezoic-ad-between, span.nodebb-ezoic-wrap.ezoic-ad-between, div.ezoic-ad-between, span.ezoic-ad-between';
|
|
1521
|
-
var BETWEEN_WRAP_CHILD_SEL = ':scope > div.nodebb-ezoic-wrap.ezoic-ad-between, :scope > span.nodebb-ezoic-wrap.ezoic-ad-between, :scope > div.ezoic-ad-between, :scope > span.ezoic-ad-between';
|
|
1522
|
-
var ORPHAN_EZOIC_CHILD_SEL = ':scope > span.ezoic-ad:not(.nodebb-ezoic-wrap), :scope > div.ezoic-ad:not(.nodebb-ezoic-wrap)';
|
|
1518
|
+
var BETWEEN_WRAP_SEL = 'div.nodebb-ezoic-wrap.ezoic-ad-between';
|
|
1523
1519
|
var HOST_CLASS = 'nodebb-ezoic-host';
|
|
1524
1520
|
|
|
1525
1521
|
var scheduled = false;
|
|
@@ -1611,19 +1607,7 @@ function buildOrdinalMap(items) {
|
|
|
1611
1607
|
if (!ul) return;
|
|
1612
1608
|
|
|
1613
1609
|
// Step 1: wrap any direct child between DIVs into LI hosts (makes list stable)
|
|
1614
|
-
|
|
1615
|
-
ul.querySelectorAll(BETWEEN_WRAP_CHILD_SEL).forEach(function(w){ ensureHostForWrap(w, ul); });
|
|
1616
|
-
|
|
1617
|
-
// Second: native injected Ezoic containers directly under the list.
|
|
1618
|
-
// They don't have our marker classes, so we convert them.
|
|
1619
|
-
ul.querySelectorAll(ORPHAN_EZOIC_CHILD_SEL).forEach(function(w){
|
|
1620
|
-
try { w.classList.add('nodebb-ezoic-wrap'); } catch(e) {}
|
|
1621
|
-
try { w.classList.add('ezoic-ad-between'); } catch(e) {}
|
|
1622
|
-
if (!w.getAttribute('data-ezoic-after')) {
|
|
1623
|
-
w.setAttribute('data-ezoic-after', '1');
|
|
1624
|
-
}
|
|
1625
|
-
ensureHostForWrap(w, ul);
|
|
1626
|
-
});
|
|
1610
|
+
ul.querySelectorAll(':scope > ' + BETWEEN_WRAP_SEL).forEach(function(w){ ensureHostForWrap(w, ul); });
|
|
1627
1611
|
|
|
1628
1612
|
// Step 2: only act if we see pile-up (avoid touching infinite scroll during normal flow)
|
|
1629
1613
|
if (!detectPileUp(ul)) return;
|
|
@@ -1708,3 +1692,131 @@ function buildOrdinalMap(items) {
|
|
|
1708
1692
|
})();
|
|
1709
1693
|
// ===== /V17 =====
|
|
1710
1694
|
|
|
1695
|
+
|
|
1696
|
+
|
|
1697
|
+
// ===== V17 empty-refresh (no move) =====
|
|
1698
|
+
// Goal: if a between-ad is visible but still has no ad iframe, gently poke Ezoic/GPT to render.
|
|
1699
|
+
(function () {
|
|
1700
|
+
var BETWEEN_WRAP_SEL = 'div.nodebb-ezoic-wrap.ezoic-ad-between';
|
|
1701
|
+
var seen = new WeakMap();
|
|
1702
|
+
var io = null;
|
|
1703
|
+
var showAdsCooldownUntil = 0;
|
|
1704
|
+
|
|
1705
|
+
function now() { return Date.now ? Date.now() : +new Date(); }
|
|
1706
|
+
|
|
1707
|
+
function getSlotId(wrap) {
|
|
1708
|
+
try {
|
|
1709
|
+
var gpt = wrap.querySelector('[id^="div-gpt-ad-"]');
|
|
1710
|
+
return gpt ? gpt.id : null;
|
|
1711
|
+
} catch (e) { return null; }
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
function hasAnyCreative(wrap) {
|
|
1715
|
+
try {
|
|
1716
|
+
// Any iframe (safeframe or normal) inside the wrap counts as rendered.
|
|
1717
|
+
if (wrap.querySelector('iframe')) return true;
|
|
1718
|
+
// Some formats use ins/amp/other nodes.
|
|
1719
|
+
if (wrap.querySelector('amp-ad, amp-embed, ins.adsbygoogle')) return true;
|
|
1720
|
+
} catch (e) {}
|
|
1721
|
+
return false;
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
function safeShowAds() {
|
|
1725
|
+
var t = now();
|
|
1726
|
+
if (t < showAdsCooldownUntil) return;
|
|
1727
|
+
showAdsCooldownUntil = t + 1200;
|
|
1728
|
+
|
|
1729
|
+
try {
|
|
1730
|
+
if (window.ezstandalone && typeof window.ezstandalone.showAds === 'function') {
|
|
1731
|
+
window.ezstandalone.showAds();
|
|
1732
|
+
return;
|
|
1733
|
+
}
|
|
1734
|
+
} catch (e) {}
|
|
1735
|
+
|
|
1736
|
+
// Fallback: nudge common listeners.
|
|
1737
|
+
try { window.dispatchEvent(new Event('scroll')); } catch (e) {}
|
|
1738
|
+
try { window.dispatchEvent(new Event('resize')); } catch (e) {}
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
function scheduleCheck(wrap) {
|
|
1742
|
+
try {
|
|
1743
|
+
if (!wrap || wrap.nodeType !== 1) return;
|
|
1744
|
+
if (hasAnyCreative(wrap)) return;
|
|
1745
|
+
|
|
1746
|
+
var meta = seen.get(wrap);
|
|
1747
|
+
var t = now();
|
|
1748
|
+
if (!meta) {
|
|
1749
|
+
meta = { firstSeen: t, checks: 0 };
|
|
1750
|
+
seen.set(wrap, meta);
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
// Give the normal pipeline time to render.
|
|
1754
|
+
if (meta.checks === 0) {
|
|
1755
|
+
setTimeout(function () { scheduleCheck(wrap); }, 700);
|
|
1756
|
+
meta.checks++;
|
|
1757
|
+
return;
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
if (hasAnyCreative(wrap)) return;
|
|
1761
|
+
|
|
1762
|
+
// Still empty -> poke.
|
|
1763
|
+
var id = getSlotId(wrap) || 'none';
|
|
1764
|
+
try { console.log('[EZ EMPTY]', id); } catch (e) {}
|
|
1765
|
+
safeShowAds();
|
|
1766
|
+
|
|
1767
|
+
// One more re-check shortly after the poke.
|
|
1768
|
+
setTimeout(function () {
|
|
1769
|
+
if (!wrap.isConnected) return;
|
|
1770
|
+
if (hasAnyCreative(wrap)) return;
|
|
1771
|
+
// If still empty after a poke, try once more (but do not loop forever).
|
|
1772
|
+
safeShowAds();
|
|
1773
|
+
}, 900);
|
|
1774
|
+
} catch (e) {}
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1777
|
+
function ensureIO() {
|
|
1778
|
+
if (io) return;
|
|
1779
|
+
if (!('IntersectionObserver' in window)) return;
|
|
1780
|
+
|
|
1781
|
+
io = new IntersectionObserver(function (entries) {
|
|
1782
|
+
for (var i = 0; i < entries.length; i++) {
|
|
1783
|
+
var e = entries[i];
|
|
1784
|
+
if (!e.isIntersecting) continue;
|
|
1785
|
+
scheduleCheck(e.target);
|
|
1786
|
+
}
|
|
1787
|
+
}, { root: null, rootMargin: '900px 0px 900px 0px', threshold: 0.01 });
|
|
1788
|
+
|
|
1789
|
+
// Observe existing wraps.
|
|
1790
|
+
try {
|
|
1791
|
+
var wraps = document.querySelectorAll(BETWEEN_WRAP_SEL);
|
|
1792
|
+
for (var j = 0; j < wraps.length; j++) io.observe(wraps[j]);
|
|
1793
|
+
} catch (e) {}
|
|
1794
|
+
|
|
1795
|
+
// Observe new wraps.
|
|
1796
|
+
try {
|
|
1797
|
+
var mo = new MutationObserver(function (muts) {
|
|
1798
|
+
for (var k = 0; k < muts.length; k++) {
|
|
1799
|
+
var m = muts[k];
|
|
1800
|
+
if (!m.addedNodes) continue;
|
|
1801
|
+
for (var n = 0; n < m.addedNodes.length; n++) {
|
|
1802
|
+
var node = m.addedNodes[n];
|
|
1803
|
+
if (!node || node.nodeType !== 1) continue;
|
|
1804
|
+
if (node.matches && node.matches(BETWEEN_WRAP_SEL)) {
|
|
1805
|
+
io.observe(node);
|
|
1806
|
+
} else if (node.querySelectorAll) {
|
|
1807
|
+
var inner = node.querySelectorAll(BETWEEN_WRAP_SEL);
|
|
1808
|
+
for (var q = 0; q < inner.length; q++) io.observe(inner[q]);
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
});
|
|
1813
|
+
mo.observe(document.body, { childList: true, subtree: true });
|
|
1814
|
+
} catch (e) {}
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
if (document.readyState === 'loading') {
|
|
1818
|
+
document.addEventListener('DOMContentLoaded', ensureIO, { once: true });
|
|
1819
|
+
} else {
|
|
1820
|
+
ensureIO();
|
|
1821
|
+
}
|
|
1822
|
+
})();
|