nodebb-plugin-ezoic-infinite 1.6.25 → 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.25",
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,39 +1,90 @@
1
1
  (function () {
2
2
  'use strict';
3
3
 
4
- function ezoicClosestTopicLi(el) {
4
+ function ezoicEnsureBetweenHost(anchorLi, wrap) {
5
5
  try {
6
- if (!el) return null;
7
- if (el.closest) {
8
- return el.closest('li[component="category/topic"]') || el.closest('li');
9
- }
6
+ if (!anchorLi || !wrap) return null;
7
+ var ul = anchorLi.parentElement;
8
+ if (!ul || !(ul.tagName === 'UL' || ul.tagName === 'OL')) return null;
9
+
10
+ // already hosted?
11
+ var host = wrap.closest ? wrap.closest('li.nodebb-ezoic-host') : null;
12
+ if (host) return host;
13
+
14
+ host = document.createElement('li');
15
+ host.className = 'nodebb-ezoic-host';
16
+ host.setAttribute('role', 'listitem');
17
+ host.style.listStyle = 'none';
18
+ host.style.width = '100%';
19
+
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) {}
25
+
26
+ anchorLi.insertAdjacentElement('afterend', host);
27
+ host.appendChild(wrap);
28
+ try { wrap.style.width = '100%'; } catch (e) {}
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;
10
42
  } catch (e) {}
11
43
  return null;
12
44
  }
13
45
 
14
- function ezoicPlaceBetweenInLi(target, wrap) {
15
- // Place between-ad WRAP inside the previous topic <li>, not as a sibling in the <ul>.
46
+ function ezoicRepairBetweenHosts() {
47
+ // Reposition between hosts if NodeBB moved them (e.g., to the top/bottom) after virtualized rerender.
16
48
  try {
17
- var li = ezoicClosestTopicLi(target) || target;
18
- if (!li || !wrap) return false;
49
+ var ul = document.querySelector('li[component="category/topic"]')?.closest('ul,ol');
50
+ if (!ul) return;
19
51
 
20
- // avoid duplicates per anchor+after
21
- try {
22
- var after = wrap.getAttribute && wrap.getAttribute('data-ezoic-after');
23
- if (after && li.querySelector) {
24
- var existing = li.querySelector('.nodebb-ezoic-wrap.ezoic-ad-between[data-ezoic-after="' + after + '"]');
25
- if (existing && existing !== wrap) {
26
- try { wrap.remove(); } catch(e) {}
27
- return true;
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);
28
58
  }
29
- }
30
- } catch (e) {}
59
+ } catch(e){}
60
+ });
31
61
 
32
- try { wrap.setAttribute('data-ezoic-in-li', '1'); } catch (e) {}
33
- li.appendChild(wrap);
34
- return true;
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
+ });
35
87
  } catch (e) {}
36
- return false;
37
88
  }
38
89
 
39
90
 
@@ -705,7 +756,8 @@ function globalGapFixInit() {
705
756
  try {
706
757
  const wrap = buildWrap(id, kindClass, afterPos, !existingPh);
707
758
  if (kindClass === 'ezoic-ad-between') {
708
- if (ezoicPlaceBetweenInLi(target, wrap)) return;
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; }
709
761
  }
710
762
  target.insertAdjacentElement('afterend', wrap);
711
763
 
@@ -1200,7 +1252,8 @@ function buildOrdinalMap(items) {
1200
1252
 
1201
1253
  wrap.setAttribute('data-ezoic-after', String(afterPos));
1202
1254
  if (kindClass === 'ezoic-ad-between') {
1203
- if (ezoicPlaceBetweenInLi(anchorEl, wrap)) return;
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; }
1204
1257
  }
1205
1258
  anchorEl.insertAdjacentElement('afterend', wrap);
1206
1259
 
@@ -1553,26 +1606,16 @@ function buildOrdinalMap(items) {
1553
1606
 
1554
1607
 
1555
1608
 
1556
- // ===== V15 one-shot repair (no heavy observers) =====
1557
- function ezoicRepairBetweenPlacement() {
1558
- try {
1559
- var bad = document.querySelectorAll('ul > div.nodebb-ezoic-wrap.ezoic-ad-between, ol > div.nodebb-ezoic-wrap.ezoic-ad-between');
1560
- bad.forEach(function(wrap){
1561
- try {
1562
- var prev = wrap.previousElementSibling;
1563
- if (prev) ezoicPlaceBetweenInLi(prev, wrap);
1564
- } catch (e) {}
1565
- });
1566
- } catch (e) {}
1567
- }
1568
- try { ezoicRepairBetweenPlacement(); } catch (e) {}
1609
+ // ===== V16.1 event-based repair (no scroll, no heavy observers) =====
1610
+ try { ezoicRepairBetweenHosts(); } catch(e) {}
1569
1611
  if (window.jQuery) {
1570
1612
  try {
1571
1613
  window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', function(){
1572
- setTimeout(function(){ try { ezoicRepairBetweenPlacement(); } catch(e) {} }, 0);
1573
- setTimeout(function(){ try { ezoicRepairBetweenPlacement(); } 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);
1574
1617
  });
1575
- } catch (e) {}
1618
+ } catch(e) {}
1576
1619
  }
1577
- // ===== /V15 =====
1620
+ // ===== /V16.1 =====
1578
1621
 
package/public/style.css CHANGED
@@ -81,15 +81,8 @@
81
81
  }
82
82
 
83
83
 
84
- /* ===== V15 between in li ===== */
85
- li[component="category/topic"] > .nodebb-ezoic-wrap.ezoic-ad-between[data-ezoic-in-li="1"] {
86
- display: block;
87
- width: 100%;
88
- margin-top: 12px;
89
- margin-bottom: 12px;
90
- }
91
- li[component="category/topic"] > .nodebb-ezoic-wrap.ezoic-ad-between[data-ezoic-in-li="1"] * {
92
- max-width: 100%;
93
- }
94
- /* ===== /V15 ===== */
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 ===== */
95
88