nodebb-plugin-ezoic-infinite 1.6.18 → 1.6.19
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 -103
- package/public/style.css +2 -2
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -1511,172 +1511,205 @@ function buildOrdinalMap(items) {
|
|
|
1511
1511
|
|
|
1512
1512
|
|
|
1513
1513
|
|
|
1514
|
-
// ===== V14.
|
|
1514
|
+
// ===== V14.2 targeted hook (topic list only) + upscroll reconcile =====
|
|
1515
1515
|
(function () {
|
|
1516
1516
|
var BETWEEN_SEL = 'div.nodebb-ezoic-wrap.ezoic-ad-between';
|
|
1517
1517
|
var HOST_CLASS = 'nodebb-ezoic-host';
|
|
1518
1518
|
var TOKEN_ATTR = 'data-ezoic-anchor-token';
|
|
1519
|
-
var
|
|
1520
|
-
|
|
1521
|
-
var
|
|
1519
|
+
var TOPIC_LI_SEL = 'li[component="category/topic"]';
|
|
1520
|
+
|
|
1521
|
+
var lastY = window.pageYOffset || document.documentElement.scrollTop || 0;
|
|
1522
1522
|
|
|
1523
1523
|
function token() {
|
|
1524
1524
|
try { return String(Date.now()) + '-' + Math.random().toString(16).slice(2); } catch (e) { return String(Date.now()); }
|
|
1525
1525
|
}
|
|
1526
1526
|
|
|
1527
|
-
function
|
|
1528
|
-
|
|
1529
|
-
|
|
1527
|
+
function getScrollY() {
|
|
1528
|
+
return window.pageYOffset || document.documentElement.scrollTop || 0;
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
function isTopicList(ul) {
|
|
1532
|
+
try { return !!(ul && ul.querySelector && ul.querySelector(TOPIC_LI_SEL)); } catch (e) { return false; }
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
function closestTopicList(node) {
|
|
1530
1536
|
try {
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
//
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
if (
|
|
1537
|
+
var ul = node && node.closest ? node.closest('ul,ol') : null;
|
|
1538
|
+
if (ul && isTopicList(ul)) return ul;
|
|
1539
|
+
// sometimes wrap is outside: search up
|
|
1540
|
+
var p = node && node.parentElement;
|
|
1541
|
+
while (p) {
|
|
1542
|
+
if ((p.tagName === 'UL' || p.tagName === 'OL') && isTopicList(p)) return p;
|
|
1543
|
+
p = p.parentElement;
|
|
1537
1544
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
if (!ul) return null;
|
|
1545
|
+
} catch (e) {}
|
|
1546
|
+
return null;
|
|
1547
|
+
}
|
|
1542
1548
|
|
|
1543
|
-
|
|
1549
|
+
function closestAnchorTopicLi(hostOrWrap, ul) {
|
|
1550
|
+
try {
|
|
1551
|
+
var cur = hostOrWrap;
|
|
1552
|
+
if (!cur) return null;
|
|
1553
|
+
// if wrap inside host li, start from host
|
|
1554
|
+
if (cur.closest) {
|
|
1555
|
+
var h = cur.closest('li.' + HOST_CLASS);
|
|
1556
|
+
if (h) cur = h;
|
|
1557
|
+
}
|
|
1544
1558
|
var prev = cur.previousElementSibling;
|
|
1545
1559
|
while (prev) {
|
|
1546
|
-
if (prev.
|
|
1560
|
+
if (prev.matches && prev.matches(TOPIC_LI_SEL)) return prev;
|
|
1547
1561
|
prev = prev.previousElementSibling;
|
|
1548
1562
|
}
|
|
1549
1563
|
} catch (e) {}
|
|
1550
1564
|
return null;
|
|
1551
1565
|
}
|
|
1552
1566
|
|
|
1553
|
-
function
|
|
1567
|
+
function ensureHostAndTokenForWrap(wrap) {
|
|
1554
1568
|
try {
|
|
1555
1569
|
if (!wrap || wrap.nodeType !== 1) return;
|
|
1556
1570
|
if (!(wrap.matches && wrap.matches(BETWEEN_SEL))) return;
|
|
1557
1571
|
|
|
1558
|
-
|
|
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;
|
|
1572
|
+
var ul = closestTopicList(wrap);
|
|
1562
1573
|
if (!ul) return;
|
|
1563
1574
|
|
|
1564
|
-
// Ensure wrap is
|
|
1575
|
+
// Ensure wrap is not direct child of UL/OL
|
|
1576
|
+
var host = wrap.closest ? wrap.closest('li.' + HOST_CLASS) : null;
|
|
1565
1577
|
if (!host) {
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
// move host into correct list container if needed
|
|
1576
|
-
ul.appendChild(host);
|
|
1578
|
+
if (wrap.parentElement === ul) {
|
|
1579
|
+
host = document.createElement('li');
|
|
1580
|
+
host.className = HOST_CLASS;
|
|
1581
|
+
host.setAttribute('role', 'listitem');
|
|
1582
|
+
host.style.listStyle = 'none';
|
|
1583
|
+
host.style.width = '100%';
|
|
1584
|
+
ul.insertBefore(host, wrap);
|
|
1585
|
+
host.appendChild(wrap);
|
|
1586
|
+
}
|
|
1577
1587
|
}
|
|
1578
1588
|
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
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
|
|
1589
|
+
if (!host) return;
|
|
1590
|
+
|
|
1591
|
+
// Anchor = previous topic LI only
|
|
1592
|
+
var anchorLi = closestAnchorTopicLi(host, ul);
|
|
1593
|
+
if (!anchorLi) {
|
|
1594
1594
|
host.setAttribute('data-ezoic-orphan', '1');
|
|
1595
|
+
return;
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
var t = anchorLi.getAttribute(TOKEN_ATTR);
|
|
1599
|
+
if (!t) {
|
|
1600
|
+
t = token();
|
|
1601
|
+
anchorLi.setAttribute(TOKEN_ATTR, t);
|
|
1595
1602
|
}
|
|
1603
|
+
host.setAttribute(TOKEN_ATTR, t);
|
|
1604
|
+
host.removeAttribute('data-ezoic-orphan');
|
|
1596
1605
|
} catch (e) {}
|
|
1597
1606
|
}
|
|
1598
1607
|
|
|
1599
|
-
function
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1608
|
+
function repairInvalidUlChildren(ul) {
|
|
1609
|
+
try {
|
|
1610
|
+
if (!ul) return;
|
|
1611
|
+
// Fix ul>div wraps
|
|
1612
|
+
var bad = ul.querySelectorAll(':scope > ' + BETWEEN_SEL);
|
|
1613
|
+
bad.forEach(function(wrap){ ensureHostAndTokenForWrap(wrap); });
|
|
1614
|
+
} catch (e) {}
|
|
1615
|
+
}
|
|
1603
1616
|
|
|
1617
|
+
function cleanupEmptyHosts(ul) {
|
|
1604
1618
|
try {
|
|
1605
|
-
|
|
1606
|
-
var
|
|
1607
|
-
|
|
1619
|
+
if (!ul) return;
|
|
1620
|
+
var hosts = ul.querySelectorAll('li.' + HOST_CLASS);
|
|
1621
|
+
hosts.forEach(function(host){
|
|
1622
|
+
try {
|
|
1623
|
+
var hasWrap = host.querySelector && host.querySelector(BETWEEN_SEL);
|
|
1624
|
+
if (!hasWrap) host.remove();
|
|
1625
|
+
} catch (e) {}
|
|
1626
|
+
});
|
|
1627
|
+
} catch (e) {}
|
|
1628
|
+
}
|
|
1608
1629
|
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1630
|
+
function reconcileUpScroll(ul) {
|
|
1631
|
+
// Only reconcile (move/drop) on upscroll to avoid breaking infinite scroll load calculations.
|
|
1632
|
+
try {
|
|
1633
|
+
if (!ul) return;
|
|
1634
|
+
var y = getScrollY();
|
|
1635
|
+
var dy = y - lastY;
|
|
1636
|
+
lastY = y;
|
|
1637
|
+
if (dy >= -10) return; // not an upscroll
|
|
1612
1638
|
|
|
1613
|
-
//
|
|
1614
|
-
var hosts =
|
|
1639
|
+
// Reconcile / drop
|
|
1640
|
+
var hosts = ul.querySelectorAll('li.' + HOST_CLASS + '[' + TOKEN_ATTR + '], li.' + HOST_CLASS + '[data-ezoic-orphan="1"]');
|
|
1615
1641
|
hosts.forEach(function(host){
|
|
1616
1642
|
try {
|
|
1617
|
-
|
|
1618
|
-
if (!ul) { host.remove(); return; }
|
|
1643
|
+
if (host.getAttribute('data-ezoic-orphan') === '1') { host.remove(); return; }
|
|
1619
1644
|
var t = host.getAttribute(TOKEN_ATTR);
|
|
1620
1645
|
if (!t) { host.remove(); return; }
|
|
1621
|
-
var anchor = ul.querySelector('
|
|
1622
|
-
if (!anchor) {
|
|
1623
|
-
|
|
1624
|
-
return;
|
|
1625
|
-
}
|
|
1626
|
-
if (host.previousElementSibling !== anchor) {
|
|
1627
|
-
anchor.insertAdjacentElement('afterend', host);
|
|
1628
|
-
}
|
|
1646
|
+
var anchor = ul.querySelector(TOPIC_LI_SEL + '[' + TOKEN_ATTR + '="' + t + '"]');
|
|
1647
|
+
if (!anchor) { host.remove(); return; }
|
|
1648
|
+
if (host.previousElementSibling !== anchor) anchor.insertAdjacentElement('afterend', host);
|
|
1629
1649
|
} catch (e) {}
|
|
1630
1650
|
});
|
|
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) {} });
|
|
1635
1651
|
} catch (e) {}
|
|
1636
1652
|
}
|
|
1637
1653
|
|
|
1638
|
-
function
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1654
|
+
function sweepAll(reasonNode) {
|
|
1655
|
+
try {
|
|
1656
|
+
var ul = closestTopicList(reasonNode || document.querySelector(TOPIC_LI_SEL));
|
|
1657
|
+
if (!ul) return;
|
|
1658
|
+
repairInvalidUlChildren(ul);
|
|
1659
|
+
|
|
1660
|
+
// Tokenize any new wraps within this list
|
|
1661
|
+
ul.querySelectorAll(BETWEEN_SEL).forEach(function(wrap){ ensureHostAndTokenForWrap(wrap); });
|
|
1662
|
+
|
|
1663
|
+
// Don't move on downscroll; only clean empties
|
|
1664
|
+
cleanupEmptyHosts(ul);
|
|
1665
|
+
reconcileUpScroll(ul);
|
|
1666
|
+
} catch (e) {}
|
|
1645
1667
|
}
|
|
1646
1668
|
|
|
1647
|
-
|
|
1648
|
-
|
|
1669
|
+
// Process mutations incrementally (no full-document scan)
|
|
1670
|
+
function installMO() {
|
|
1649
1671
|
try {
|
|
1650
|
-
if (typeof MutationObserver
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1672
|
+
if (typeof MutationObserver === 'undefined') return;
|
|
1673
|
+
var mo = new MutationObserver(function(muts){
|
|
1674
|
+
for (var i=0;i<muts.length;i++){
|
|
1675
|
+
var m = muts[i];
|
|
1676
|
+
if (m.addedNodes && m.addedNodes.length) {
|
|
1677
|
+
for (var j=0;j<m.addedNodes.length;j++){
|
|
1678
|
+
var n = m.addedNodes[j];
|
|
1679
|
+
if (!n || n.nodeType !== 1) continue;
|
|
1680
|
+
if (n.matches && n.matches(BETWEEN_SEL)) {
|
|
1681
|
+
ensureHostAndTokenForWrap(n);
|
|
1682
|
+
} else if (n.querySelector && n.querySelector(BETWEEN_SEL)) {
|
|
1683
|
+
n.querySelectorAll(BETWEEN_SEL).forEach(function(w){ ensureHostAndTokenForWrap(w); });
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
// light sweep on the container only
|
|
1687
|
+
sweepAll(m.target);
|
|
1688
|
+
break;
|
|
1656
1689
|
}
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
}
|
|
1690
|
+
}
|
|
1691
|
+
});
|
|
1692
|
+
mo.observe(document.documentElement || document.body, { childList: true, subtree: true });
|
|
1660
1693
|
} catch (e) {}
|
|
1661
1694
|
}
|
|
1662
1695
|
|
|
1663
1696
|
function init() {
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
window.addEventListener('
|
|
1697
|
+
// initial tokenizing/repair
|
|
1698
|
+
sweepAll(document);
|
|
1699
|
+
window.addEventListener('scroll', function(){ sweepAll(document); }, { passive: true });
|
|
1700
|
+
window.addEventListener('resize', function(){ sweepAll(document); }, { passive: true });
|
|
1667
1701
|
|
|
1668
1702
|
if (window.jQuery) {
|
|
1669
1703
|
window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', function(){
|
|
1670
|
-
setTimeout(
|
|
1671
|
-
setTimeout(
|
|
1672
|
-
setTimeout(scheduleSweep, 900);
|
|
1704
|
+
setTimeout(function(){ sweepAll(document); }, 0);
|
|
1705
|
+
setTimeout(function(){ sweepAll(document); }, 250);
|
|
1673
1706
|
});
|
|
1674
1707
|
}
|
|
1675
|
-
|
|
1708
|
+
installMO();
|
|
1676
1709
|
}
|
|
1677
1710
|
|
|
1678
1711
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
|
|
1679
1712
|
else init();
|
|
1680
1713
|
})();
|
|
1681
|
-
// ===== /V14.
|
|
1714
|
+
// ===== /V14.2 =====
|
|
1682
1715
|
|