nodebb-plugin-ezoic-infinite 1.6.74 → 1.6.76

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 +37 -29
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.6.74",
3
+ "version": "1.6.76",
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
@@ -770,40 +770,42 @@ function globalGapFixInit() {
770
770
  // when orphaned, but we still avoid fully releasing them (so they can come back
771
771
  // when anchors reappear).
772
772
 
773
- // Never prune a fresh wrap: it may fill late.
773
+ // If the wrap is anchored to current items, ensure it is visible.
774
+ if (hasNearbyItem(wrap)) {
775
+ try { wrap.classList && wrap.classList.remove('ez-orphan-hidden'); wrap.style && (wrap.style.display = ''); } catch (e) {}
776
+ return;
777
+ }
778
+
779
+ // If the anchor item is no longer in the DOM (virtualized), hide the wrap so ads never 'stack'
780
+ // back-to-back while scrolling. We'll restore it when its anchor comes back.
781
+ try { wrap.classList && wrap.classList.add('ez-orphan-hidden'); wrap.style && (wrap.style.display = 'none'); } catch (e) {}
782
+
783
+ // On topic/category lists, never release orphan wraps. Releasing moves placeholders around and makes
784
+ // ads appear to 'travel' from top to bottom as you scroll. Parking (hiding) keeps DOM order stable.
785
+ const isList = (kindClass === 'ezoic-ad-between' || kindClass === 'ezoic-ad-categories');
786
+ if (isList) return;
787
+
788
+ // Never release a fresh wrap: it may fill late (auction/CMP). Keep it hidden for a while.
774
789
  try {
775
790
  const created = parseInt(wrap.getAttribute('data-created') || '0', 10);
776
791
  if (created && (now() - created) < keepEmptyWrapMs()) return;
777
792
  } catch (e) {}
778
793
 
779
- if (hasNearbyItem(wrap)) {
780
- try { wrap.classList && wrap.classList.remove('ez-orphan-hidden'); wrap.style && (wrap.style.display = ''); } catch (e) {}
781
- return;
782
- }
783
-
784
- // If the anchor item is no longer in the DOM (virtualized), hide the wrap so ads never "stack"
785
- // back-to-back while scrolling. We'll recycle it when its anchor comes back.
786
- try { wrap.classList && wrap.classList.add('ez-orphan-hidden'); wrap.style && (wrap.style.display = 'none'); } catch (e) {}
787
-
788
- // For message ads: only release if far offscreen to avoid perceived "vanishing" during fast scroll.
789
- // For non-message lists (topics/categories): do not release filled wraps at all; only hide.
790
- if (isMessage) {
791
- try {
792
- const r = wrap.getBoundingClientRect();
793
- const vh = Math.max(1, window.innerHeight || 1);
794
- const farAbove = r.bottom < -vh * 2;
795
- const farBelow = r.top > vh * 4;
796
- if (!farAbove && !farBelow) return;
797
- } catch (e) {
798
- return;
799
- }
800
- }
801
-
802
- // Never release filled wraps on non-message lists; hiding is enough to prevent stacks.
803
- if (!isMessage && isFilled(wrap)) return;
794
+ // For message ads: only release if far offscreen to avoid perceived 'vanishing' during fast scroll.
795
+ if (isMessage) {
796
+ try {
797
+ const r = wrap.getBoundingClientRect();
798
+ const vh = Math.max(1, window.innerHeight || 1);
799
+ const farAbove = r.bottom < -vh * 2;
800
+ const farBelow = r.top > vh * 4;
801
+ if (!farAbove && !farBelow) return;
802
+ } catch (e) {
803
+ return;
804
+ }
805
+ }
804
806
 
805
- withInternalDomChange(() => releaseWrapNode(wrap));
806
- removed++;
807
+ withInternalDomChange(() => releaseWrapNode(wrap));
808
+ removed++;
807
809
  });
808
810
 
809
811
  return removed;
@@ -849,6 +851,12 @@ removed++;
849
851
  const prevFilled = isFilled(prev);
850
852
  const curFilled = isFilled(w);
851
853
 
854
+ // On topic/category lists, prevent visible stacking by hiding the later wrap immediately.
855
+ if ((kindClass === 'ezoic-ad-between' || kindClass === 'ezoic-ad-categories') && prevFilled && curFilled) {
856
+ try { w.classList && w.classList.add('ez-stack-hidden'); w.style && (w.style.display = 'none'); } catch (e) {}
857
+ break;
858
+ }
859
+
852
860
  if (curFilled) {
853
861
  // If the previous one is empty (and not fresh), drop the previous instead.
854
862
  if (!prevFilled && !isFresh(prev)) {
@@ -1137,7 +1145,7 @@ function buildOrdinalMap(items) {
1137
1145
  if (!id) {
1138
1146
  // Safe mode: disable recycling for topic message ads to prevent visual "jumping"
1139
1147
  // (ads seemingly moving back under the first post during virtualized scroll).
1140
- const allowRecycle = kindClass !== 'ezoic-ad-message';
1148
+ const allowRecycle = kindClass !== 'ezoic-ad-message' && kindClass !== 'ezoic-ad-between' && kindClass !== 'ezoic-ad-categories';
1141
1149
  recycledWrap = (allowRecycle && scrollDir > 0) ? pickRecyclableWrap(kindClass) : null;
1142
1150
  if (recycledWrap) {
1143
1151
  id = recycledWrap.getAttribute('data-ezoic-wrapid') || '';