nodebb-plugin-ezoic-infinite 1.6.74 → 1.6.75
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 +1 -1
- package/public/client.js +76 -59
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -133,29 +133,7 @@ function tightenEzoicMinHeight(wrap) {
|
|
|
133
133
|
if (!wrap || !wrap.querySelector) return;
|
|
134
134
|
|
|
135
135
|
const iframes = wrap.querySelectorAll('iframe');
|
|
136
|
-
|
|
137
|
-
// If the wrap is still empty, Ezoic often leaves inline `min-height:400px !important` on
|
|
138
|
-
// nested `.ezoic-ad` containers, which creates large blank gaps. We can't remove it with CSS.
|
|
139
|
-
// We collapse those gaps after a short grace period, while still allowing late fill.
|
|
140
|
-
if (!iframes || !iframes.length) {
|
|
141
|
-
try {
|
|
142
|
-
const created = parseInt(wrap.getAttribute('data-created') || '0', 10);
|
|
143
|
-
const age = created ? (now() - created) : 0;
|
|
144
|
-
// Give auctions/CMP a bit of time; then collapse the notorious 400px gap.
|
|
145
|
-
if (age >= 12000) {
|
|
146
|
-
const nodes = wrap.querySelectorAll('.ezoic-ad, .ezoic-ad-adaptive');
|
|
147
|
-
nodes.forEach((n) => {
|
|
148
|
-
const st = (n.getAttribute('style') || '').toLowerCase();
|
|
149
|
-
if (st.includes('min-height:400') || st.includes('min-height: 400') || st.includes('min-height:400px')) {
|
|
150
|
-
try { n.style.setProperty('min-height', '1px', 'important'); } catch (e) { n.style.minHeight = '1px'; }
|
|
151
|
-
try { n.style.setProperty('height', 'auto', 'important'); } catch (e) {}
|
|
152
|
-
try { n.style.setProperty('line-height', '0', 'important'); } catch (e) {}
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
} catch (e) {}
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
136
|
+
if (!iframes || !iframes.length) return;
|
|
159
137
|
|
|
160
138
|
// Find the closest "big" ezoic container that carries the 400px min-height.
|
|
161
139
|
const firstIframe = iframes[0];
|
|
@@ -242,6 +220,42 @@ function tightenEzoicMinHeight(wrap) {
|
|
|
242
220
|
} catch (e) {}
|
|
243
221
|
}
|
|
244
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
|
+
|
|
245
259
|
function watchWrapForFill(wrap) {
|
|
246
260
|
try {
|
|
247
261
|
if (!wrap || wrap.__ezFillObs) return;
|
|
@@ -760,15 +774,16 @@ function globalGapFixInit() {
|
|
|
760
774
|
if (wrap.getAttribute('data-ezoic-pin') === '1') return;
|
|
761
775
|
} catch (e) {}
|
|
762
776
|
|
|
763
|
-
//
|
|
764
|
-
//
|
|
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.
|
|
765
783
|
const isMessage = (kindClass === 'ezoic-ad-message');
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
// "stack" together on upward scroll. We therefore allow filled wraps to be hidden
|
|
770
|
-
// when orphaned, but we still avoid fully releasing them (so they can come back
|
|
771
|
-
// when anchors reappear).
|
|
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
|
|
772
787
|
|
|
773
788
|
// Never prune a fresh wrap: it may fill late.
|
|
774
789
|
try {
|
|
@@ -776,34 +791,34 @@ function globalGapFixInit() {
|
|
|
776
791
|
if (created && (now() - created) < keepEmptyWrapMs()) return;
|
|
777
792
|
} catch (e) {}
|
|
778
793
|
|
|
779
|
-
if (hasNearbyItem(wrap)) {
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
try { wrap.classList && wrap.classList.add('ez-orphan-hidden'); wrap.style && (wrap.style.display = 'none'); } catch (e) {}
|
|
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
|
+
}
|
|
787
801
|
|
|
788
|
-
//
|
|
789
|
-
//
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
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
|
-
}
|
|
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) {}
|
|
801
808
|
|
|
802
|
-
//
|
|
803
|
-
|
|
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
|
+
}
|
|
804
819
|
|
|
805
|
-
withInternalDomChange(() => releaseWrapNode(wrap));
|
|
806
|
-
removed++;
|
|
820
|
+
withInternalDomChange(() => releaseWrapNode(wrap));
|
|
821
|
+
removed++;
|
|
807
822
|
});
|
|
808
823
|
|
|
809
824
|
return removed;
|
|
@@ -829,6 +844,7 @@ removed++;
|
|
|
829
844
|
}
|
|
830
845
|
};
|
|
831
846
|
|
|
847
|
+
const lookback = (kindClass === 'ezoic-ad-between') ? 12 : 3;
|
|
832
848
|
let removed = 0;
|
|
833
849
|
for (const w of wraps) {
|
|
834
850
|
// Never decluster pinned placements.
|
|
@@ -837,7 +853,7 @@ removed++;
|
|
|
837
853
|
} catch (e) {}
|
|
838
854
|
|
|
839
855
|
let prev = w.previousElementSibling;
|
|
840
|
-
for (let i = 0; i <
|
|
856
|
+
for (let i = 0; i < lookback && prev; i++) {
|
|
841
857
|
if (isWrap(prev)) {
|
|
842
858
|
// If the previous wrap is pinned, keep this one (spacing is intentional).
|
|
843
859
|
try {
|
|
@@ -1050,8 +1066,6 @@ removed++;
|
|
|
1050
1066
|
watchWrapForFill(ww);
|
|
1051
1067
|
setTimeout(() => { try { tightenEzoicMinHeight(ww); } catch (e) {} }, 900);
|
|
1052
1068
|
setTimeout(() => { try { tightenEzoicMinHeight(ww); } catch (e) {} }, 2200);
|
|
1053
|
-
// Collapse the notorious 400px inline min-height if the slot stays empty.
|
|
1054
|
-
setTimeout(() => { try { tightenEzoicMinHeight(ww); } catch (e) {} }, 12500);
|
|
1055
1069
|
}
|
|
1056
1070
|
} catch (e) {}
|
|
1057
1071
|
setTimeout(() => { clearTimeout(hardTimer); release(); }, 650);
|
|
@@ -1229,6 +1243,7 @@ function buildOrdinalMap(items) {
|
|
|
1229
1243
|
'curPosts'
|
|
1230
1244
|
);
|
|
1231
1245
|
decluster('ezoic-ad-message');
|
|
1246
|
+
collapseEmptyGaps('ezoic-ad-message');
|
|
1232
1247
|
}
|
|
1233
1248
|
} else if (kind === 'categoryTopics') {
|
|
1234
1249
|
if (normalizeBool(cfg.enableBetweenAds)) {
|
|
@@ -1243,6 +1258,7 @@ function buildOrdinalMap(items) {
|
|
|
1243
1258
|
'curTopics'
|
|
1244
1259
|
);
|
|
1245
1260
|
decluster('ezoic-ad-between');
|
|
1261
|
+
collapseEmptyGaps('ezoic-ad-between');
|
|
1246
1262
|
}
|
|
1247
1263
|
} else if (kind === 'categories') {
|
|
1248
1264
|
if (normalizeBool(cfg.enableCategoryAds)) {
|
|
@@ -1257,6 +1273,7 @@ function buildOrdinalMap(items) {
|
|
|
1257
1273
|
'curCategories'
|
|
1258
1274
|
);
|
|
1259
1275
|
decluster('ezoic-ad-categories');
|
|
1276
|
+
collapseEmptyGaps('ezoic-ad-categories');
|
|
1260
1277
|
}
|
|
1261
1278
|
}
|
|
1262
1279
|
|