nodebb-plugin-ezoic-infinite 1.6.38 → 1.6.40
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 +136 -5
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -501,20 +501,43 @@ function globalGapFixInit() {
|
|
|
501
501
|
// Best-effort refresh for Ezoic standalone when we defer placement.
|
|
502
502
|
// Some stacks won't fill ads if a placeholder is rendered while collapsed/0px.
|
|
503
503
|
let _refreshTimer = null;
|
|
504
|
+
|
|
505
|
+
function collectEzoicIds(root) {
|
|
506
|
+
const ids = new Set();
|
|
507
|
+
if (!root || !root.querySelectorAll) return [];
|
|
508
|
+
// Common Ezoic placeholder ids
|
|
509
|
+
root.querySelectorAll('[id^="ezoic-pub-ad-placeholder-"]').forEach(el => ids.add(el.id));
|
|
510
|
+
// Some integrations keep ids on wrappers
|
|
511
|
+
root.querySelectorAll('[data-ezoic-id]').forEach(el => {
|
|
512
|
+
if (el.id) ids.add(el.id);
|
|
513
|
+
});
|
|
514
|
+
return Array.from(ids);
|
|
515
|
+
}
|
|
516
|
+
|
|
504
517
|
function refreshAds(ids) {
|
|
505
|
-
if (!ids || !ids.length) return;
|
|
506
518
|
clearTimeout(_refreshTimer);
|
|
507
519
|
_refreshTimer = setTimeout(() => {
|
|
508
520
|
try {
|
|
509
521
|
if (window.ezstandalone && typeof window.ezstandalone.showAds === 'function') {
|
|
510
|
-
|
|
522
|
+
// Prefer a full rescan; fall back to ids if supported.
|
|
523
|
+
try {
|
|
524
|
+
window.ezstandalone.showAds();
|
|
525
|
+
} catch (e) {
|
|
526
|
+
if (ids && ids.length) window.ezstandalone.showAds(ids);
|
|
527
|
+
}
|
|
528
|
+
if (window.__EZ_DEBUG) console.debug('[ezoic-infinite] refreshAds (ezstandalone)', { ids });
|
|
511
529
|
return;
|
|
512
530
|
}
|
|
513
531
|
if (window.ez && typeof window.ez.showAds === 'function') {
|
|
514
|
-
|
|
532
|
+
try {
|
|
533
|
+
window.ez.showAds();
|
|
534
|
+
} catch (e) {
|
|
535
|
+
if (ids && ids.length) window.ez.showAds(ids);
|
|
536
|
+
}
|
|
537
|
+
if (window.__EZ_DEBUG) console.debug('[ezoic-infinite] refreshAds (ez)', { ids });
|
|
515
538
|
}
|
|
516
539
|
} catch (e) {}
|
|
517
|
-
},
|
|
540
|
+
}, 75);
|
|
518
541
|
}
|
|
519
542
|
|
|
520
543
|
function primePlaceholderPool(allIds) {
|
|
@@ -1699,12 +1722,116 @@ function buildOrdinalMap(items) {
|
|
|
1699
1722
|
});
|
|
1700
1723
|
}
|
|
1701
1724
|
|
|
1725
|
+
// -------- Viewport "poke" for empty Ezoic placeholders --------
|
|
1726
|
+
// Some Ezoic placeholders can be placed into the DOM already in-view, but
|
|
1727
|
+
// the ad stack only reacts on the next scroll tick. This keeps blocks from
|
|
1728
|
+
// staying blank until the user nudges the page.
|
|
1729
|
+
var io = null;
|
|
1730
|
+
var observedPlaceholders = typeof WeakSet !== 'undefined' ? new WeakSet() : null;
|
|
1731
|
+
|
|
1732
|
+
function isEzoicPlaceholder(el) {
|
|
1733
|
+
return !!(el && el.id && el.id.indexOf('ezoic-pub-ad-placeholder-') === 0);
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
function iframeCount(el) {
|
|
1737
|
+
try {
|
|
1738
|
+
return (el && el.querySelectorAll) ? el.querySelectorAll('iframe').length : 0;
|
|
1739
|
+
} catch (e) {
|
|
1740
|
+
return 0;
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
function pokePlaceholder(ph, reason) {
|
|
1745
|
+
if (!ph || !ph.id) return;
|
|
1746
|
+
// throttle per placeholder
|
|
1747
|
+
var now = Date.now();
|
|
1748
|
+
var last = 0;
|
|
1749
|
+
try { last = parseInt(ph.getAttribute('data-ez-poke-at') || '0', 10) || 0; } catch (e) {}
|
|
1750
|
+
if (now - last < 1200) return;
|
|
1751
|
+
try { ph.setAttribute('data-ez-poke-at', String(now)); } catch (e) {}
|
|
1752
|
+
|
|
1753
|
+
// Only poke if still empty
|
|
1754
|
+
if (iframeCount(ph) > 0) return;
|
|
1755
|
+
|
|
1756
|
+
if (DEBUG) {
|
|
1757
|
+
try { console.log('[EZ POKE]', reason || 'io', ph.id); } catch (e) {}
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
// Ask Ezoic to fill that specific placeholder
|
|
1761
|
+
refreshAds([ph.id]);
|
|
1762
|
+
|
|
1763
|
+
// And also emit a lightweight scroll/resize tick to trigger any lazy logic
|
|
1764
|
+
try { window.dispatchEvent(new Event('scroll')); } catch (e) {}
|
|
1765
|
+
try { window.dispatchEvent(new Event('resize')); } catch (e) {}
|
|
1766
|
+
|
|
1767
|
+
// One re-try shortly after, in case the first request was dropped.
|
|
1768
|
+
setTimeout(function () {
|
|
1769
|
+
try {
|
|
1770
|
+
if (iframeCount(ph) === 0) {
|
|
1771
|
+
refreshAds([ph.id]);
|
|
1772
|
+
try { window.dispatchEvent(new Event('scroll')); } catch (e2) {}
|
|
1773
|
+
}
|
|
1774
|
+
} catch (e3) {}
|
|
1775
|
+
}, 450);
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
function ensureIO() {
|
|
1779
|
+
if (io) return;
|
|
1780
|
+
if (!('IntersectionObserver' in window)) return;
|
|
1781
|
+
io = new IntersectionObserver(function (entries) {
|
|
1782
|
+
for (var i = 0; i < entries.length; i++) {
|
|
1783
|
+
var e = entries[i];
|
|
1784
|
+
if (!e || !e.isIntersecting) continue;
|
|
1785
|
+
var ph = e.target;
|
|
1786
|
+
if (!isEzoicPlaceholder(ph)) continue;
|
|
1787
|
+
if (iframeCount(ph) === 0) {
|
|
1788
|
+
pokePlaceholder(ph, 'in-view');
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
}, { root: null, rootMargin: '200px 0px', threshold: 0.01 });
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
function observePlaceholder(ph) {
|
|
1795
|
+
if (!ph) return;
|
|
1796
|
+
ensureIO();
|
|
1797
|
+
if (!io) return;
|
|
1798
|
+
if (observedPlaceholders) {
|
|
1799
|
+
if (observedPlaceholders.has(ph)) return;
|
|
1800
|
+
observedPlaceholders.add(ph);
|
|
1801
|
+
} else {
|
|
1802
|
+
// fallback: mark directly
|
|
1803
|
+
if (ph.getAttribute && ph.getAttribute('data-ez-observed') === '1') return;
|
|
1804
|
+
try { ph.setAttribute('data-ez-observed', '1'); } catch (e) {}
|
|
1805
|
+
}
|
|
1806
|
+
try { io.observe(ph); } catch (e) {}
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
function scanPlaceholders(root) {
|
|
1810
|
+
if (!root || !root.querySelectorAll) return;
|
|
1811
|
+
var list = [];
|
|
1812
|
+
try { list = root.querySelectorAll('div[id^="ezoic-pub-ad-placeholder-"]'); } catch (e) { list = []; }
|
|
1813
|
+
for (var i = 0; i < list.length; i++) observePlaceholder(list[i]);
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1702
1816
|
function initObserver() {
|
|
1703
1817
|
var ulEl = ensureUL();
|
|
1704
1818
|
if (!ulEl || mo) return;
|
|
1705
1819
|
|
|
1706
|
-
mo = new MutationObserver(function () {
|
|
1820
|
+
mo = new MutationObserver(function (mutations) {
|
|
1707
1821
|
scheduleReconcile();
|
|
1822
|
+
// Also observe any newly injected placeholders so in-view blanks get poked.
|
|
1823
|
+
try {
|
|
1824
|
+
for (var i = 0; i < (mutations || []).length; i++) {
|
|
1825
|
+
var m = mutations[i];
|
|
1826
|
+
if (!m || !m.addedNodes) continue;
|
|
1827
|
+
for (var j = 0; j < m.addedNodes.length; j++) {
|
|
1828
|
+
var n = m.addedNodes[j];
|
|
1829
|
+
if (!n) continue;
|
|
1830
|
+
if (isEzoicPlaceholder(n)) observePlaceholder(n);
|
|
1831
|
+
else scanPlaceholders(n);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
} catch (e) {}
|
|
1708
1835
|
});
|
|
1709
1836
|
|
|
1710
1837
|
mo.observe(ulEl, { childList: true, subtree: true });
|
|
@@ -1713,6 +1840,8 @@ function buildOrdinalMap(items) {
|
|
|
1713
1840
|
function init() {
|
|
1714
1841
|
initObserver();
|
|
1715
1842
|
scheduleReconcile();
|
|
1843
|
+
// initial scan for placeholders already in the DOM
|
|
1844
|
+
scanPlaceholders(document);
|
|
1716
1845
|
|
|
1717
1846
|
if (window.jQuery) {
|
|
1718
1847
|
try {
|
|
@@ -1724,6 +1853,8 @@ function buildOrdinalMap(items) {
|
|
|
1724
1853
|
scheduleReconcile();
|
|
1725
1854
|
setTimeout(scheduleReconcile, 120);
|
|
1726
1855
|
setTimeout(scheduleReconcile, 500);
|
|
1856
|
+
// re-scan after ajaxify/infinite load
|
|
1857
|
+
setTimeout(function () { scanPlaceholders(document); }, 50);
|
|
1727
1858
|
});
|
|
1728
1859
|
} catch (e) {}
|
|
1729
1860
|
}
|