nodebb-plugin-ezoic-infinite 1.6.26 → 1.6.27

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.26",
3
+ "version": "1.6.27",
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
@@ -1,40 +1,90 @@
1
1
  (function () {
2
2
  'use strict';
3
3
 
4
- function ezoicInsertAfterTopicHost(target, wrap, kindClass) {
4
+ function ezoicEnsureBetweenHost(anchorLi, wrap) {
5
5
  try {
6
- if (!target || !wrap) return false;
7
- if (kindClass !== 'ezoic-ad-between') return false;
8
-
9
- // Ensure we insert a LI host that looks like a topic item so NodeBB list virtualization keeps ordering.
10
- var anchorLi = target.closest ? (target.closest('li[component="category/topic"]') || target.closest('li')) : null;
11
- if (!anchorLi && target.tagName === 'LI') anchorLi = target;
12
- if (!anchorLi) return false;
13
-
6
+ if (!anchorLi || !wrap) return null;
14
7
  var ul = anchorLi.parentElement;
15
- if (!ul || !(ul.tagName === 'UL' || ul.tagName === 'OL')) return false;
8
+ if (!ul || !(ul.tagName === 'UL' || ul.tagName === 'OL')) return null;
16
9
 
17
- // If wrap already hosted, do nothing
18
- var existingHost = wrap.closest ? wrap.closest('li.nodebb-ezoic-host') : null;
19
- if (existingHost) return true;
10
+ // already hosted?
11
+ var host = wrap.closest ? wrap.closest('li.nodebb-ezoic-host') : null;
12
+ if (host) return host;
20
13
 
21
- var host = document.createElement('li');
14
+ host = document.createElement('li');
22
15
  host.className = 'nodebb-ezoic-host';
23
- // mimic topic list item so NodeBB doesn't relocate it
24
- host.setAttribute('component', 'category/topic');
25
- host.setAttribute('data-ezoic-host', 'between');
16
+ host.setAttribute('role', 'listitem');
26
17
  host.style.listStyle = 'none';
27
18
  host.style.width = '100%';
28
19
 
29
- // Insert host after anchorLi
30
- if (anchorLi.insertAdjacentElement) anchorLi.insertAdjacentElement('afterend', host);
31
- else ul.insertBefore(host, anchorLi.nextSibling);
20
+ // copy after position for later repairs
21
+ try {
22
+ var after = wrap.getAttribute && wrap.getAttribute('data-ezoic-after');
23
+ if (after) host.setAttribute('data-ezoic-after', after);
24
+ } catch (e) {}
32
25
 
26
+ anchorLi.insertAdjacentElement('afterend', host);
33
27
  host.appendChild(wrap);
34
28
  try { wrap.style.width = '100%'; } catch (e) {}
35
- return true;
29
+ return host;
30
+ } catch (e) {}
31
+ return null;
32
+ }
33
+
34
+ function ezoicDesiredAnchorForAfter(ul, afterNum) {
35
+ try {
36
+ var n = parseInt(afterNum, 10);
37
+ if (!n || n < 1) return null;
38
+ var topics = ul.querySelectorAll('li[component="category/topic"]');
39
+ if (!topics || !topics.length) return null;
40
+ if (n > topics.length) n = topics.length;
41
+ return topics[n-1] || null;
42
+ } catch (e) {}
43
+ return null;
44
+ }
45
+
46
+ function ezoicRepairBetweenHosts() {
47
+ // Reposition between hosts if NodeBB moved them (e.g., to the top/bottom) after virtualized rerender.
48
+ try {
49
+ var ul = document.querySelector('li[component="category/topic"]')?.closest('ul,ol');
50
+ if (!ul) return;
51
+
52
+ // 1) fix invalid ul>div wraps
53
+ ul.querySelectorAll(':scope > div.nodebb-ezoic-wrap.ezoic-ad-between').forEach(function(wrap){
54
+ try {
55
+ var prev = wrap.previousElementSibling;
56
+ if (prev && prev.tagName === 'LI') {
57
+ ezoicEnsureBetweenHost(prev, wrap);
58
+ }
59
+ } catch(e){}
60
+ });
61
+
62
+ // 2) ensure every between wrap is hosted (but don't scan whole document)
63
+ ul.querySelectorAll('div.nodebb-ezoic-wrap.ezoic-ad-between').forEach(function(wrap){
64
+ try {
65
+ var host = wrap.closest ? wrap.closest('li.nodebb-ezoic-host') : null;
66
+ if (!host) {
67
+ var prev = wrap.closest ? wrap.closest('li') : null;
68
+ if (prev) ezoicEnsureBetweenHost(prev, wrap);
69
+ }
70
+ } catch(e){}
71
+ });
72
+
73
+ // 3) reposition hosts based on data-ezoic-after (stable intent)
74
+ ul.querySelectorAll('li.nodebb-ezoic-host').forEach(function(host){
75
+ try {
76
+ var wrap = host.querySelector && host.querySelector('div.nodebb-ezoic-wrap.ezoic-ad-between');
77
+ if (!wrap) { host.remove(); return; }
78
+ var after = host.getAttribute('data-ezoic-after') || wrap.getAttribute('data-ezoic-after');
79
+ if (!after) return;
80
+ var anchor = ezoicDesiredAnchorForAfter(ul, after);
81
+ if (!anchor) return;
82
+ if (host.previousElementSibling !== anchor) {
83
+ anchor.insertAdjacentElement('afterend', host);
84
+ }
85
+ } catch(e){}
86
+ });
36
87
  } catch (e) {}
37
- return false;
38
88
  }
39
89
 
40
90
 
@@ -705,7 +755,10 @@ function globalGapFixInit() {
705
755
  insertingIds.add(id);
706
756
  try {
707
757
  const wrap = buildWrap(id, kindClass, afterPos, !existingPh);
708
- if (ezoicInsertAfterTopicHost(target, wrap, kindClass)) return;
758
+ if (kindClass === 'ezoic-ad-between') {
759
+ var aLi = (target.closest ? (target.closest('li[component="category/topic"]') || target.closest('li')) : null) || (target.tagName==='LI'?target:null);
760
+ if (aLi) { ezoicEnsureBetweenHost(aLi, wrap); return; }
761
+ }
709
762
  target.insertAdjacentElement('afterend', wrap);
710
763
 
711
764
  // If placeholder exists elsewhere (including pool), move it into the wrapper.
@@ -1198,7 +1251,10 @@ function buildOrdinalMap(items) {
1198
1251
  if (!anchorEl || !wrap || !wrap.isConnected) return null;
1199
1252
 
1200
1253
  wrap.setAttribute('data-ezoic-after', String(afterPos));
1201
- if (ezoicInsertAfterTopicHost(anchorEl, wrap, kindClass)) return;
1254
+ if (kindClass === 'ezoic-ad-between') {
1255
+ var aLi = (anchorEl.closest ? (anchorEl.closest('li[component="category/topic"]') || anchorEl.closest('li')) : null) || (anchorEl.tagName==='LI'?anchorEl:null);
1256
+ if (aLi) { ezoicEnsureBetweenHost(aLi, wrap); return; }
1257
+ }
1202
1258
  anchorEl.insertAdjacentElement('afterend', wrap);
1203
1259
 
1204
1260
  // Ensure minimal layout impact.
@@ -1550,27 +1606,16 @@ function buildOrdinalMap(items) {
1550
1606
 
1551
1607
 
1552
1608
 
1553
- // ===== V16 repair invalid UL children (between) =====
1554
- function ezoicRepairBetweenHosts() {
1555
- try {
1556
- var bad = document.querySelectorAll('ul > div.nodebb-ezoic-wrap.ezoic-ad-between, ol > div.nodebb-ezoic-wrap.ezoic-ad-between');
1557
- bad.forEach(function(wrap){
1558
- try {
1559
- var prev = wrap.previousElementSibling;
1560
- if (!prev) return;
1561
- ezoicInsertAfterTopicHost(prev, wrap, 'ezoic-ad-between');
1562
- } catch (e) {}
1563
- });
1564
- } catch (e) {}
1565
- }
1566
- try { ezoicRepairBetweenHosts(); } catch (e) {}
1609
+ // ===== V16.1 event-based repair (no scroll, no heavy observers) =====
1610
+ try { ezoicRepairBetweenHosts(); } catch(e) {}
1567
1611
  if (window.jQuery) {
1568
1612
  try {
1569
1613
  window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', function(){
1570
- setTimeout(function(){ try { ezoicRepairBetweenHosts(); } catch(e) {} }, 0);
1571
- setTimeout(function(){ try { ezoicRepairBetweenHosts(); } catch(e) {} }, 250);
1614
+ // Let NodeBB settle before repositioning
1615
+ setTimeout(function(){ try { ezoicRepairBetweenHosts(); } catch(e) {} }, 150);
1616
+ setTimeout(function(){ try { ezoicRepairBetweenHosts(); } catch(e) {} }, 700);
1572
1617
  });
1573
- } catch (e) {}
1618
+ } catch(e) {}
1574
1619
  }
1575
- // ===== /V16 =====
1620
+ // ===== /V16.1 =====
1576
1621
 
package/public/style.css CHANGED
@@ -81,14 +81,8 @@
81
81
  }
82
82
 
83
83
 
84
- /* ===== V16 host topic li ===== */
85
- li.nodebb-ezoic-host[component="category/topic"]{
86
- list-style:none;
87
- width:100%;
88
- }
89
- /* ensure host doesn't inherit topic card layout */
90
- li.nodebb-ezoic-host[component="category/topic"] > .nodebb-ezoic-wrap.ezoic-ad-between{
91
- width:100%;
92
- }
93
- /* ===== /V16 ===== */
84
+ /* ===== V16.1 host li ===== */
85
+ li.nodebb-ezoic-host { list-style: none; width: 100%; display:block; }
86
+ li.nodebb-ezoic-host > .nodebb-ezoic-wrap.ezoic-ad-between { width: 100%; display:block; }
87
+ /* ===== /V16.1 ===== */
94
88