nodebb-plugin-ezoic-infinite 1.6.30 → 1.6.32

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.6.30",
3
+ "version": "1.6.32",
4
4
  "description": "Production-ready Ezoic infinite ads integration for NodeBB 4.x",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
package/public/client.js CHANGED
@@ -1514,205 +1514,130 @@ function buildOrdinalMap(items) {
1514
1514
 
1515
1515
 
1516
1516
 
1517
- // ===== V17.2: Up-scroll "rehome" by data-ezoic-after (keeps injection intact) =====
1518
- (function () {
1517
+ // ===== V17.4: Hide top pile (supports ul>div OR li hosts), no moving, keeps injection intact =====
1518
+ (function(){
1519
1519
  var TOPIC_LI_SEL = 'li[component="category/topic"]';
1520
1520
  var BETWEEN_WRAP_SEL = 'div.nodebb-ezoic-wrap.ezoic-ad-between';
1521
1521
  var HOST_CLASS = 'nodebb-ezoic-host';
1522
+ var PILED_ATTR = 'data-ezoic-piled';
1522
1523
 
1523
1524
  var lastY = window.pageYOffset || document.documentElement.scrollTop || 0;
1524
1525
  var scheduled = false;
1525
1526
  var lastRun = 0;
1526
- var COOLDOWN = 160;
1527
+ var COOLDOWN = 90;
1527
1528
 
1528
- function getY() {
1529
- return window.pageYOffset || document.documentElement.scrollTop || 0;
1530
- }
1529
+ function getY(){ return window.pageYOffset || document.documentElement.scrollTop || 0; }
1531
1530
 
1532
- function getTopicList() {
1531
+ function getTopicList(){
1533
1532
  try {
1534
1533
  var li = document.querySelector(TOPIC_LI_SEL);
1535
1534
  if (!li) return null;
1536
1535
  return li.closest ? li.closest('ul,ol') : null;
1537
- } catch (e) { return null; }
1536
+ } catch(e){ return null; }
1538
1537
  }
1539
1538
 
1540
- function ensureHostForWrap(wrap, ul) {
1539
+ function isBetweenNode(el){
1541
1540
  try {
1542
- if (!wrap || wrap.nodeType !== 1) return null;
1543
- if (!(wrap.matches && wrap.matches(BETWEEN_WRAP_SEL))) return null;
1544
-
1545
- var host = wrap.closest ? wrap.closest('li.' + HOST_CLASS) : null;
1546
- if (host) return host;
1547
-
1548
- if (!ul) ul = wrap.closest ? wrap.closest('ul,ol') : null;
1549
- if (!ul || !(ul.tagName === 'UL' || ul.tagName === 'OL')) return null;
1550
-
1551
- if (wrap.parentElement === ul) {
1552
- host = document.createElement('li');
1553
- host.className = HOST_CLASS;
1554
- host.setAttribute('role', 'listitem');
1555
- host.style.listStyle = 'none';
1556
- host.style.width = '100%';
1557
- try {
1558
- var after = wrap.getAttribute('data-ezoic-after');
1559
- if (after) host.setAttribute('data-ezoic-after', after);
1560
- } catch (e) {}
1561
- ul.insertBefore(host, wrap);
1562
- host.appendChild(wrap);
1563
- try { wrap.style.width = '100%'; } catch (e) {}
1564
- return host;
1541
+ if (!el || el.nodeType !== 1) return false;
1542
+ if (el.matches && el.matches(BETWEEN_WRAP_SEL)) return true; // ul>div case
1543
+ if (el.tagName === 'LI' && el.classList && el.classList.contains(HOST_CLASS)) {
1544
+ return !!(el.querySelector && el.querySelector(BETWEEN_WRAP_SEL));
1565
1545
  }
1566
- } catch (e) {}
1567
- return null;
1568
- }
1569
-
1570
- function nthTopic(ul, n) {
1571
- try {
1572
- var topics = ul.querySelectorAll(TOPIC_LI_SEL);
1573
- if (!topics || !topics.length) return null;
1574
- if (n < 1) n = 1;
1575
- if (n > topics.length) n = topics.length;
1576
- return topics[n-1] || null;
1577
- } catch (e) {}
1578
- return null;
1546
+ } catch(e){}
1547
+ return false;
1579
1548
  }
1580
1549
 
1581
- function getAfterValue(host) {
1582
- try {
1583
- var v = host.getAttribute('data-ezoic-after');
1584
- if (!v) {
1585
- var wrap = host.querySelector && host.querySelector(BETWEEN_WRAP_SEL);
1586
- if (wrap) v = wrap.getAttribute('data-ezoic-after');
1587
- }
1588
- var n = parseInt(v, 10);
1589
- return isNaN(n) ? null : n;
1590
- } catch (e) {}
1591
- return null;
1550
+ function isTopicNode(el){
1551
+ try { return !!(el && el.nodeType===1 && el.matches && el.matches(TOPIC_LI_SEL)); } catch(e){ return false; }
1592
1552
  }
1593
1553
 
1594
- function isTopPiled(ul) {
1554
+ function clearPiled(ul){
1595
1555
  try {
1596
- var kids = ul.children;
1597
- var limit = Math.min(kids.length, 50);
1598
- var run = 0, maxRun = 0;
1599
- for (var i=0;i<limit;i++){
1600
- var el = kids[i];
1601
- var isAd = false;
1602
- if (el.tagName === 'LI' && el.classList && el.classList.contains(HOST_CLASS)) {
1603
- isAd = !!(el.querySelector && el.querySelector(BETWEEN_WRAP_SEL));
1604
- } else if (el.matches && el.matches(BETWEEN_WRAP_SEL)) {
1605
- isAd = true;
1606
- }
1607
-
1608
- if (isAd) { run++; if (run>maxRun) maxRun=run; }
1609
- else if (el.matches && el.matches(TOPIC_LI_SEL)) { run = 0; }
1610
- else { run = 0; }
1611
- }
1612
- return maxRun >= 2;
1613
- } catch (e) {}
1614
- return false;
1556
+ if (!ul) return;
1557
+ ul.querySelectorAll('['+PILED_ATTR+'="1"]').forEach(function(n){
1558
+ try { n.removeAttribute(PILED_ATTR); } catch(e){}
1559
+ });
1560
+ } catch(e){}
1615
1561
  }
1616
1562
 
1617
- function rehomeByAfter(ul) {
1563
+ function markTopPile(ul){
1564
+ // Mark any consecutive between nodes near top (keep the first, hide the rest until next topic).
1618
1565
  try {
1619
1566
  if (!ul) return;
1620
-
1621
- try {
1622
- ul.querySelectorAll(':scope > ' + BETWEEN_WRAP_SEL).forEach(function(w){ ensureHostForWrap(w, ul); });
1623
- } catch (e) {}
1624
-
1625
- if (!isTopPiled(ul)) return;
1626
-
1627
1567
  var kids = ul.children;
1628
- var limit = Math.min(kids.length, 80);
1629
- var topHosts = [];
1568
+ var limit = Math.min(kids.length, 140);
1569
+ var inRun = 0;
1630
1570
  for (var i=0;i<limit;i++){
1631
1571
  var el = kids[i];
1632
- if (el.tagName === 'LI' && el.classList && el.classList.contains(HOST_CLASS)) {
1633
- var wrap = el.querySelector && el.querySelector(BETWEEN_WRAP_SEL);
1634
- if (wrap) topHosts.push(el);
1572
+ if (isBetweenNode(el)){
1573
+ inRun++;
1574
+ if (inRun >= 2){
1575
+ try { el.setAttribute(PILED_ATTR,'1'); } catch(e){}
1576
+ } else {
1577
+ try { el.removeAttribute(PILED_ATTR); } catch(e){}
1578
+ }
1579
+ } else if (isTopicNode(el)){
1580
+ inRun = 0;
1581
+ } else {
1582
+ // other node breaks run as well
1583
+ inRun = 0;
1635
1584
  }
1636
1585
  }
1637
- if (!topHosts.length) return;
1638
-
1639
- topHosts.sort(function(a,b){
1640
- var aa = getAfterValue(a);
1641
- var bb = getAfterValue(b);
1642
- if (aa == null && bb == null) return 0;
1643
- if (aa == null) return 1;
1644
- if (bb == null) return -1;
1645
- return aa - bb;
1646
- });
1647
-
1648
- topHosts.forEach(function(host){
1649
- try {
1650
- var after = getAfterValue(host);
1651
- var anchor = null;
1652
- if (after != null) anchor = nthTopic(ul, after);
1653
-
1654
- if (!anchor) {
1655
- var prev = host.previousElementSibling;
1656
- while (prev) {
1657
- if (prev.matches && prev.matches(TOPIC_LI_SEL)) { anchor = prev; break; }
1658
- prev = prev.previousElementSibling;
1659
- }
1660
- }
1661
- if (!anchor) return;
1662
-
1663
- if (host.previousElementSibling !== anchor) {
1664
- anchor.insertAdjacentElement('afterend', host);
1665
- }
1666
- } catch (e) {}
1667
- });
1668
- } catch (e) {}
1586
+ } catch(e){}
1669
1587
  }
1670
1588
 
1671
- function schedule() {
1589
+ function schedule(fn){
1672
1590
  var now = Date.now();
1673
- if (now - lastRun < COOLDOWN) return;
1591
+ if (now-lastRun < COOLDOWN) return;
1674
1592
  if (scheduled) return;
1675
1593
  scheduled = true;
1676
1594
  requestAnimationFrame(function(){
1677
1595
  scheduled = false;
1678
1596
  lastRun = Date.now();
1679
- var ul = getTopicList();
1680
- if (!ul) return;
1681
- rehomeByAfter(ul);
1597
+ fn();
1682
1598
  });
1683
1599
  }
1684
1600
 
1685
- function onScroll() {
1601
+ function onScroll(){
1686
1602
  var y = getY();
1687
1603
  var dy = y - lastY;
1688
1604
  lastY = y;
1689
- if (dy < -8 && y < 900) schedule();
1690
- }
1691
1605
 
1692
- function init() {
1693
- try {
1694
- var ul = getTopicList();
1695
- if (ul) ul.querySelectorAll(':scope > ' + BETWEEN_WRAP_SEL).forEach(function(w){ ensureHostForWrap(w, ul); });
1696
- } catch (e) {}
1606
+ var ul = getTopicList();
1607
+ if (!ul) return;
1697
1608
 
1609
+ // Only manage pile visibility when user is near the top area.
1610
+ if (y < 1100 && dy < -6){
1611
+ schedule(function(){ markTopPile(ul); });
1612
+ } else if (y > 1300 || dy > 10){
1613
+ // leaving top area or scrolling down: restore visibility
1614
+ schedule(function(){ clearPiled(ul); });
1615
+ }
1616
+ }
1617
+
1618
+ function init(){
1698
1619
  window.addEventListener('scroll', onScroll, { passive:true });
1699
1620
 
1700
- if (window.jQuery) {
1701
- try {
1621
+ if (window.jQuery){
1622
+ try{
1702
1623
  window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', function(){
1624
+ // if we are near top, re-evaluate pile quickly; otherwise ensure no stale hiding
1703
1625
  setTimeout(function(){
1704
1626
  try {
1705
1627
  var ul = getTopicList();
1706
- if (ul) ul.querySelectorAll(':scope > ' + BETWEEN_WRAP_SEL).forEach(function(w){ ensureHostForWrap(w, ul); });
1628
+ if (!ul) return;
1629
+ var y = getY();
1630
+ if (y < 1100) markTopPile(ul);
1631
+ else clearPiled(ul);
1707
1632
  } catch(e){}
1708
- }, 50);
1633
+ }, 80);
1709
1634
  });
1710
- } catch (e) {}
1635
+ }catch(e){}
1711
1636
  }
1712
1637
  }
1713
1638
 
1714
1639
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
1715
1640
  else init();
1716
1641
  })();
1717
- // ===== /V17.2 =====
1642
+ // ===== /V17.4 =====
1718
1643
 
package/public/style.css CHANGED
@@ -88,8 +88,10 @@ li.nodebb-ezoic-host > .nodebb-ezoic-wrap.ezoic-ad-between { width: 100%; displa
88
88
 
89
89
 
90
90
 
91
- /* ===== V17.2 host styling ===== */
91
+ /* ===== V17.4 pile hide ===== */
92
+ [data-ezoic-piled="1"] { display: none !important; }
93
+ /* keep host stable */
92
94
  li.nodebb-ezoic-host { list-style:none; width:100%; display:block; }
93
95
  li.nodebb-ezoic-host > .nodebb-ezoic-wrap.ezoic-ad-between { width:100%; display:block; }
94
- /* ===== /V17.2 ===== */
96
+ /* ===== /V17.4 ===== */
95
97