nodebb-plugin-ezoic-infinite 1.6.16 → 1.6.18
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 +145 -76
- package/public/style.css +3 -7
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -1511,103 +1511,172 @@ function buildOrdinalMap(items) {
|
|
|
1511
1511
|
|
|
1512
1512
|
|
|
1513
1513
|
|
|
1514
|
-
// =====
|
|
1514
|
+
// ===== V14.1 Hook any between-wrap and tether to nearest topic LI =====
|
|
1515
1515
|
(function () {
|
|
1516
|
-
|
|
1517
|
-
|
|
1516
|
+
var BETWEEN_SEL = 'div.nodebb-ezoic-wrap.ezoic-ad-between';
|
|
1517
|
+
var HOST_CLASS = 'nodebb-ezoic-host';
|
|
1518
|
+
var TOKEN_ATTR = 'data-ezoic-anchor-token';
|
|
1519
|
+
var pendingSweep = false;
|
|
1520
|
+
var lastSweep = 0;
|
|
1521
|
+
var COOLDOWN = 120;
|
|
1522
|
+
|
|
1523
|
+
function token() {
|
|
1524
|
+
try { return String(Date.now()) + '-' + Math.random().toString(16).slice(2); } catch (e) { return String(Date.now()); }
|
|
1525
|
+
}
|
|
1518
1526
|
|
|
1519
|
-
function
|
|
1527
|
+
function closestTopicLi(node) {
|
|
1528
|
+
// Find the topic <li> that this wrap should be associated with:
|
|
1529
|
+
// prefer previous sibling <li> that is NOT a host, else climb to nearest previous in the list.
|
|
1520
1530
|
try {
|
|
1521
|
-
|
|
1522
|
-
var
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1531
|
+
if (!node) return null;
|
|
1532
|
+
var cur = node;
|
|
1533
|
+
// If wrap is inside a host li, start from host
|
|
1534
|
+
if (cur.closest) {
|
|
1535
|
+
var host = cur.closest('li.' + HOST_CLASS);
|
|
1536
|
+
if (host) cur = host;
|
|
1537
|
+
}
|
|
1538
|
+
// Find list container
|
|
1539
|
+
var ul = cur.parentElement;
|
|
1540
|
+
while (ul && !(ul.tagName === 'UL' || ul.tagName === 'OL')) ul = ul.parentElement;
|
|
1541
|
+
if (!ul) return null;
|
|
1542
|
+
|
|
1543
|
+
// Start from current element position within ul
|
|
1544
|
+
var prev = cur.previousElementSibling;
|
|
1545
|
+
while (prev) {
|
|
1546
|
+
if (prev.tagName === 'LI' && !(prev.classList && prev.classList.contains(HOST_CLASS))) return prev;
|
|
1547
|
+
prev = prev.previousElementSibling;
|
|
1548
|
+
}
|
|
1549
|
+
} catch (e) {}
|
|
1550
|
+
return null;
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
function ensureHostForWrap(wrap) {
|
|
1554
|
+
try {
|
|
1555
|
+
if (!wrap || wrap.nodeType !== 1) return;
|
|
1556
|
+
if (!(wrap.matches && wrap.matches(BETWEEN_SEL))) return;
|
|
1557
|
+
|
|
1558
|
+
// Already in a host?
|
|
1559
|
+
var host = wrap.closest ? wrap.closest('li.' + HOST_CLASS) : null;
|
|
1560
|
+
var ul = wrap.parentElement;
|
|
1561
|
+
while (ul && !(ul.tagName === 'UL' || ul.tagName === 'OL')) ul = ul.parentElement;
|
|
1562
|
+
if (!ul) return;
|
|
1563
|
+
|
|
1564
|
+
// Ensure wrap is inside UL only via LI host (never direct ul>div)
|
|
1565
|
+
if (!host) {
|
|
1566
|
+
host = document.createElement('li');
|
|
1567
|
+
host.className = HOST_CLASS;
|
|
1568
|
+
host.setAttribute('role', 'listitem');
|
|
1569
|
+
host.style.listStyle = 'none';
|
|
1570
|
+
host.style.width = '100%';
|
|
1571
|
+
// Insert host at wrap position
|
|
1572
|
+
ul.insertBefore(host, wrap);
|
|
1573
|
+
host.appendChild(wrap);
|
|
1574
|
+
} else if (host.parentElement !== ul) {
|
|
1575
|
+
// move host into correct list container if needed
|
|
1576
|
+
ul.appendChild(host);
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
// Tether to nearest topic li and tag both with same token
|
|
1580
|
+
var anchorLi = closestTopicLi(host) || closestTopicLi(wrap);
|
|
1581
|
+
if (anchorLi) {
|
|
1582
|
+
var t = anchorLi.getAttribute(TOKEN_ATTR);
|
|
1583
|
+
if (!t) {
|
|
1584
|
+
t = token();
|
|
1585
|
+
anchorLi.setAttribute(TOKEN_ATTR, t);
|
|
1586
|
+
}
|
|
1587
|
+
host.setAttribute(TOKEN_ATTR, t);
|
|
1588
|
+
// keep host just after anchor
|
|
1589
|
+
if (host.previousElementSibling !== anchorLi) {
|
|
1590
|
+
anchorLi.insertAdjacentElement('afterend', host);
|
|
1591
|
+
}
|
|
1592
|
+
} else {
|
|
1593
|
+
// No anchor -> it's dangerous; mark host so we can drop it later
|
|
1594
|
+
host.setAttribute('data-ezoic-orphan', '1');
|
|
1595
|
+
}
|
|
1596
|
+
} catch (e) {}
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
function sweepAll() {
|
|
1600
|
+
var now = Date.now();
|
|
1601
|
+
if (now - lastSweep < COOLDOWN) return;
|
|
1602
|
+
lastSweep = now;
|
|
1603
|
+
|
|
1604
|
+
try {
|
|
1605
|
+
// 1) repair direct ul>div wraps
|
|
1606
|
+
var bad = document.querySelectorAll('ul > ' + BETWEEN_SEL + ', ol > ' + BETWEEN_SEL);
|
|
1607
|
+
bad.forEach(ensureHostForWrap);
|
|
1608
|
+
|
|
1609
|
+
// 2) ensure any between wrap anywhere is hosted+tethered
|
|
1610
|
+
var wraps = document.querySelectorAll(BETWEEN_SEL);
|
|
1611
|
+
wraps.forEach(ensureHostForWrap);
|
|
1612
|
+
|
|
1613
|
+
// 3) reconcile/drop hosts that lost their anchor (virtualized)
|
|
1614
|
+
var hosts = document.querySelectorAll('li.' + HOST_CLASS + '[' + TOKEN_ATTR + ']');
|
|
1615
|
+
hosts.forEach(function(host){
|
|
1537
1616
|
try {
|
|
1538
|
-
var
|
|
1539
|
-
if (
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1617
|
+
var ul = host.parentElement;
|
|
1618
|
+
if (!ul) { host.remove(); return; }
|
|
1619
|
+
var t = host.getAttribute(TOKEN_ATTR);
|
|
1620
|
+
if (!t) { host.remove(); return; }
|
|
1621
|
+
var anchor = ul.querySelector('li[' + TOKEN_ATTR + '="' + t + '"]');
|
|
1622
|
+
if (!anchor) {
|
|
1623
|
+
host.remove();
|
|
1624
|
+
return;
|
|
1625
|
+
}
|
|
1626
|
+
if (host.previousElementSibling !== anchor) {
|
|
1627
|
+
anchor.insertAdjacentElement('afterend', host);
|
|
1545
1628
|
}
|
|
1546
1629
|
} catch (e) {}
|
|
1547
1630
|
});
|
|
1631
|
+
|
|
1632
|
+
// 4) drop explicit orphans
|
|
1633
|
+
var orphans = document.querySelectorAll('li.' + HOST_CLASS + '[data-ezoic-orphan="1"]');
|
|
1634
|
+
orphans.forEach(function(h){ try { h.remove(); } catch(e) {} });
|
|
1548
1635
|
} catch (e) {}
|
|
1549
1636
|
}
|
|
1550
1637
|
|
|
1551
|
-
function
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
t = setTimeout(function(){ t = null; killStickyIn(document); }, 120);
|
|
1560
|
-
}, { passive: true });
|
|
1638
|
+
function scheduleSweep() {
|
|
1639
|
+
if (pendingSweep) return;
|
|
1640
|
+
pendingSweep = true;
|
|
1641
|
+
requestAnimationFrame(function(){
|
|
1642
|
+
pendingSweep = false;
|
|
1643
|
+
sweepAll();
|
|
1644
|
+
});
|
|
1645
|
+
}
|
|
1561
1646
|
|
|
1562
|
-
|
|
1647
|
+
function installObservers() {
|
|
1648
|
+
// Observe the document for any between-wrap insertion/moves
|
|
1563
1649
|
try {
|
|
1564
1650
|
if (typeof MutationObserver !== 'undefined') {
|
|
1565
1651
|
var mo = new MutationObserver(function(muts){
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
if (m.attributeName === 'style' || m.attributeName === 'class') {
|
|
1572
|
-
killStickyIn(m.target && m.target.closest ? (m.target.closest('.nodebb-ezoic-wrap') || document) : document);
|
|
1573
|
-
}
|
|
1574
|
-
} else if (m.addedNodes && m.addedNodes.length) {
|
|
1575
|
-
for (var j=0;j<m.addedNodes.length;j++){
|
|
1576
|
-
var n = m.addedNodes[j];
|
|
1577
|
-
if (!n || n.nodeType !== 1) continue;
|
|
1578
|
-
if (n.matches && (n.matches('.nodebb-ezoic-wrap') || n.matches('.ezads-sticky-intradiv'))) {
|
|
1579
|
-
killStickyIn(n);
|
|
1580
|
-
} else if (n.querySelector) {
|
|
1581
|
-
if (n.querySelector('.nodebb-ezoic-wrap, .ezads-sticky-intradiv')) killStickyIn(n);
|
|
1582
|
-
}
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
|
-
}
|
|
1586
|
-
} catch (e) {}
|
|
1587
|
-
});
|
|
1588
|
-
mo.observe(document.documentElement || document.body, {
|
|
1589
|
-
subtree: true,
|
|
1590
|
-
childList: true,
|
|
1591
|
-
attributes: true,
|
|
1592
|
-
attributeFilter: ['style','class']
|
|
1652
|
+
for (var i=0;i<muts.length;i++){
|
|
1653
|
+
var m = muts[i];
|
|
1654
|
+
if (m.addedNodes && m.addedNodes.length) { scheduleSweep(); break; }
|
|
1655
|
+
if (m.removedNodes && m.removedNodes.length) { scheduleSweep(); break; }
|
|
1656
|
+
}
|
|
1593
1657
|
});
|
|
1658
|
+
mo.observe(document.documentElement || document.body, { childList: true, subtree: true });
|
|
1594
1659
|
}
|
|
1595
1660
|
} catch (e) {}
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
function init() {
|
|
1664
|
+
scheduleSweep();
|
|
1665
|
+
window.addEventListener('scroll', scheduleSweep, { passive: true });
|
|
1666
|
+
window.addEventListener('resize', scheduleSweep, { passive: true });
|
|
1596
1667
|
|
|
1597
|
-
// NodeBB events
|
|
1598
1668
|
if (window.jQuery) {
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
});
|
|
1605
|
-
} catch (e) {}
|
|
1669
|
+
window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', function(){
|
|
1670
|
+
setTimeout(scheduleSweep, 0);
|
|
1671
|
+
setTimeout(scheduleSweep, 250);
|
|
1672
|
+
setTimeout(scheduleSweep, 900);
|
|
1673
|
+
});
|
|
1606
1674
|
}
|
|
1675
|
+
installObservers();
|
|
1607
1676
|
}
|
|
1608
1677
|
|
|
1609
|
-
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded',
|
|
1610
|
-
else
|
|
1678
|
+
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
|
|
1679
|
+
else init();
|
|
1611
1680
|
})();
|
|
1612
|
-
// ===== /
|
|
1681
|
+
// ===== /V14.1 =====
|
|
1613
1682
|
|
package/public/style.css
CHANGED
|
@@ -81,11 +81,7 @@
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
|
|
84
|
-
/* =====
|
|
85
|
-
.nodebb-ezoic-
|
|
86
|
-
|
|
87
|
-
top: auto !important;
|
|
88
|
-
transform: none !important;
|
|
89
|
-
}
|
|
90
|
-
/* ===== /V13 ===== */
|
|
84
|
+
/* ===== V14.1 host ===== */
|
|
85
|
+
li.nodebb-ezoic-host { list-style: none; width: 100%; }
|
|
86
|
+
/* ===== /V14.1 ===== */
|
|
91
87
|
|