nodebb-plugin-ezoic-infinite 1.6.75 → 1.6.77

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/public/client.js +25 -75
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.6.75",
3
+ "version": "1.6.77",
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
@@ -220,42 +220,6 @@ function tightenEzoicMinHeight(wrap) {
220
220
  } catch (e) {}
221
221
  }
222
222
 
223
- // If a placement never fills, Ezoic may still leave an inline `min-height:400px !important`
224
- // on nested containers, creating large "blank" blocks. On SPA/infinite scroll, some
225
- // auctions can fail (network/CMP/adblock). We collapse those gaps after a grace period.
226
- function collapseEmptyGap(wrap) {
227
- try {
228
- if (!wrap || !wrap.isConnected) return;
229
- if (isFilledNode(wrap)) return;
230
-
231
- const created = parseInt(wrap.getAttribute('data-created') || '0', 10);
232
- if (!created) return;
233
- // Give plenty of time for late fill (CMP / header bidding).
234
- if ((now() - created) < 12000) return;
235
-
236
- // Find the nested node that carries the 400px min-height.
237
- const nodes = wrap.querySelectorAll('.ezoic-ad, .ezoic-ad-adaptive');
238
- nodes.forEach((n) => {
239
- const st = (n.getAttribute('style') || '').toLowerCase();
240
- if (st.includes('min-height:400')) {
241
- try { n.style.setProperty('min-height', '1px', 'important'); } catch (e) { n.style.minHeight = '1px'; }
242
- try { n.style.setProperty('height', 'auto', 'important'); } catch (e) {}
243
- }
244
- });
245
-
246
- // Also collapse our wrapper's reserved height.
247
- try { wrap.style.setProperty('min-height', '1px', 'important'); } catch (e) { wrap.style.minHeight = '1px'; }
248
- try { wrap.style.setProperty('height', 'auto', 'important'); } catch (e) {}
249
- } catch (e) {}
250
- }
251
-
252
- function collapseEmptyGaps(kindClass) {
253
- try {
254
- const wraps = document.querySelectorAll(`.${WRAP_CLASS}.${kindClass}`);
255
- wraps.forEach((w) => collapseEmptyGap(w));
256
- } catch (e) {}
257
- }
258
-
259
223
  function watchWrapForFill(wrap) {
260
224
  try {
261
225
  if (!wrap || wrap.__ezFillObs) return;
@@ -774,16 +738,10 @@ function globalGapFixInit() {
774
738
  if (wrap.getAttribute('data-ezoic-pin') === '1') return;
775
739
  } catch (e) {}
776
740
 
777
- // Virtualized lists can remove anchors from the DOM while keeping our wraps.
778
- // If we keep *filled* wraps alive when their anchors disappear, they will visually
779
- // "stack" (back-to-back) when the user scrolls back up.
780
- //
781
- // Topic list pages (categoryTopics) are also virtualized in some themes/plugins,
782
- // so we must treat between-ads similarly to message-ads.
741
+ // For message/topic pages we may prune filled or empty orphans if they are far away,
742
+ // otherwise consecutive "stacks" can appear when posts are virtualized.
783
743
  const isMessage = (kindClass === 'ezoic-ad-message');
784
- const isBetween = (kindClass === 'ezoic-ad-between');
785
- const isVirtualizedList = isMessage || isBetween;
786
- if (!isVirtualizedList && isFilled(wrap)) return; // keep filled ads for non-virtualized lists
744
+ if (!isMessage && isFilled(wrap)) return; // never prune filled ads for non-message lists
787
745
 
788
746
  // Never prune a fresh wrap: it may fill late.
789
747
  try {
@@ -791,34 +749,30 @@ function globalGapFixInit() {
791
749
  if (created && (now() - created) < keepEmptyWrapMs()) return;
792
750
  } catch (e) {}
793
751
 
794
- if (hasNearbyItem(wrap)) {
795
- try {
796
- wrap.classList && wrap.classList.remove('ez-orphan-hidden');
797
- wrap.style && (wrap.style.display = '');
798
- } catch (e) {}
799
- return;
800
- }
752
+ if (hasNearbyItem(wrap)) {
753
+ try { wrap.classList && wrap.classList.remove('ez-orphan-hidden'); wrap.style && (wrap.style.display = ''); } catch (e) {}
754
+ return;
755
+ }
801
756
 
802
- // If the anchor item is no longer in the DOM (virtualized), hide the wrap so ads never "stack"
803
- // back-to-back while scrolling. When the anchor comes back, the wrap can be shown again.
804
- try {
805
- wrap.classList && wrap.classList.add('ez-orphan-hidden');
806
- wrap.style && (wrap.style.display = 'none');
807
- } catch (e) {}
757
+ // If the anchor item is no longer in the DOM (virtualized), hide the wrap so ads never "stack"
758
+ // back-to-back while scrolling. We'll recycle it when its anchor comes back.
759
+ try { wrap.classList && wrap.classList.add('ez-orphan-hidden'); wrap.style && (wrap.style.display = 'none'); } catch (e) {}
808
760
 
809
- // Release only if far offscreen (keep UX stable). Use looser thresholds for topic lists.
810
- try {
811
- const r = wrap.getBoundingClientRect();
812
- const vh = Math.max(1, window.innerHeight || 1);
813
- const farAbove = r.bottom < -vh * (isBetween ? 4 : 2);
814
- const farBelow = r.top > vh * (isBetween ? 8 : 4);
815
- if (!farAbove && !farBelow) return;
816
- } catch (e) {
817
- return;
818
- }
761
+ // For message ads: only release if far offscreen to avoid perceived "vanishing" during fast scroll.
762
+ if (isMessage) {
763
+ try {
764
+ const r = wrap.getBoundingClientRect();
765
+ const vh = Math.max(1, window.innerHeight || 1);
766
+ const farAbove = r.bottom < -vh * 2;
767
+ const farBelow = r.top > vh * 4;
768
+ if (!farAbove && !farBelow) return;
769
+ } catch (e) {
770
+ return;
771
+ }
772
+ }
819
773
 
820
- withInternalDomChange(() => releaseWrapNode(wrap));
821
- removed++;
774
+ withInternalDomChange(() => releaseWrapNode(wrap));
775
+ removed++;
822
776
  });
823
777
 
824
778
  return removed;
@@ -844,7 +798,6 @@ function globalGapFixInit() {
844
798
  }
845
799
  };
846
800
 
847
- const lookback = (kindClass === 'ezoic-ad-between') ? 12 : 3;
848
801
  let removed = 0;
849
802
  for (const w of wraps) {
850
803
  // Never decluster pinned placements.
@@ -853,7 +806,7 @@ function globalGapFixInit() {
853
806
  } catch (e) {}
854
807
 
855
808
  let prev = w.previousElementSibling;
856
- for (let i = 0; i < lookback && prev; i++) {
809
+ for (let i = 0; i < 3 && prev; i++) {
857
810
  if (isWrap(prev)) {
858
811
  // If the previous wrap is pinned, keep this one (spacing is intentional).
859
812
  try {
@@ -1243,7 +1196,6 @@ function buildOrdinalMap(items) {
1243
1196
  'curPosts'
1244
1197
  );
1245
1198
  decluster('ezoic-ad-message');
1246
- collapseEmptyGaps('ezoic-ad-message');
1247
1199
  }
1248
1200
  } else if (kind === 'categoryTopics') {
1249
1201
  if (normalizeBool(cfg.enableBetweenAds)) {
@@ -1258,7 +1210,6 @@ function buildOrdinalMap(items) {
1258
1210
  'curTopics'
1259
1211
  );
1260
1212
  decluster('ezoic-ad-between');
1261
- collapseEmptyGaps('ezoic-ad-between');
1262
1213
  }
1263
1214
  } else if (kind === 'categories') {
1264
1215
  if (normalizeBool(cfg.enableCategoryAds)) {
@@ -1273,7 +1224,6 @@ function buildOrdinalMap(items) {
1273
1224
  'curCategories'
1274
1225
  );
1275
1226
  decluster('ezoic-ad-categories');
1276
- collapseEmptyGaps('ezoic-ad-categories');
1277
1227
  }
1278
1228
  }
1279
1229