nodebb-plugin-ezoic-infinite 1.7.84 → 1.7.86
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 +119 -193
- package/public/style.css +16 -34
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -76,16 +76,19 @@
|
|
|
76
76
|
const A_WRAPID = 'data-ezoic-wrapid'; // id Ezoic
|
|
77
77
|
const A_CREATED = 'data-ezoic-created'; // timestamp création ms
|
|
78
78
|
const A_SHOWN = 'data-ezoic-shown'; // timestamp dernier showAds ms
|
|
79
|
-
const A_FILLED = 'data-ezoic-filled';
|
|
79
|
+
const A_FILLED = 'data-ezoic-filled'; // timestamp premier fill réel
|
|
80
|
+
const A_LAST_H = 'data-ezoic-lasth'; // dernière hauteur pub vue
|
|
80
81
|
|
|
81
82
|
const EMPTY_CHECK_MS = 20_000; // délai avant collapse d'un wrap vide post-show
|
|
83
|
+
const MIN_LIVE_AFTER_SHOW_MS = 15_000;
|
|
84
|
+
const MIN_LIVE_AFTER_FILL_MS = 25_000;
|
|
85
|
+
const KEEP_SHELL_AFTER_UNUSED_MS = 90_000;
|
|
86
|
+
const MIN_SHELL_HEIGHT = 120;
|
|
82
87
|
const MIN_PRUNE_AGE_MS = 8_000; // délai de grâce avant pruning (stabilisation DOM)
|
|
83
88
|
const MAX_INSERTS_RUN = 6; // max insertions par appel runCore
|
|
84
89
|
const MAX_INFLIGHT = 4; // max showAds() simultanés
|
|
85
90
|
const SHOW_THROTTLE_MS = 900; // anti-spam showAds() par id
|
|
86
91
|
const BURST_COOLDOWN_MS = 200; // délai min entre deux déclenchements de burst
|
|
87
|
-
const MIN_LIVE_AFTER_SHOW_MS = 15_000; // grâce post-show avant drop/recycle
|
|
88
|
-
const MIN_LIVE_AFTER_FILL_MS = 25_000; // grâce post-fill réel avant drop/recycle
|
|
89
92
|
|
|
90
93
|
// Marges IO larges et fixes — observer créé une seule fois au boot
|
|
91
94
|
const IO_MARGIN_DESKTOP = '2500px 0px 2500px 0px';
|
|
@@ -130,8 +133,8 @@
|
|
|
130
133
|
pending: [], // ids en attente de slot inflight
|
|
131
134
|
pendingSet: new Set(),
|
|
132
135
|
wrapByKey: new Map(), // anchorKey → wrap DOM node
|
|
133
|
-
emptyChecks:
|
|
134
|
-
|
|
136
|
+
emptyChecks: new Map(), // id → [timerIds]
|
|
137
|
+
fillObsById: new Map(), // id → MutationObserver
|
|
135
138
|
runQueued: false,
|
|
136
139
|
burstActive: false,
|
|
137
140
|
burstDeadline: 0,
|
|
@@ -147,153 +150,85 @@
|
|
|
147
150
|
const normBool = v => v === true || v === 'true' || v === 1 || v === '1' || v === 'on';
|
|
148
151
|
const isFilled = n => !!(n?.querySelector?.('iframe, ins, img, video, [data-google-container-id]'));
|
|
149
152
|
|
|
150
|
-
function clearEmptyChecks(id) {
|
|
151
|
-
const timers = S.emptyChecks.get(id);
|
|
152
|
-
if (timers) {
|
|
153
|
-
for (const t of timers) { try { clearTimeout(t); } catch (_) {} }
|
|
154
|
-
S.emptyChecks.delete(id);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function queueEmptyCheck(id, timerId) {
|
|
159
|
-
if (!S.emptyChecks.has(id)) S.emptyChecks.set(id, []);
|
|
160
|
-
S.emptyChecks.get(id).push(timerId);
|
|
161
|
-
}
|
|
162
153
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const kids = Array.from(ph.childNodes).filter(n => {
|
|
219
|
-
if (n.nodeType === 1) return true;
|
|
220
|
-
if (n.nodeType === 3) return (n.textContent || '').trim().length > 0;
|
|
221
|
-
return false;
|
|
222
|
-
});
|
|
223
|
-
if (!kids.length) return null;
|
|
224
|
-
box = document.createElement('div');
|
|
225
|
-
box.className = 'nbb-ez-scale-box';
|
|
226
|
-
while (ph.firstChild) box.appendChild(ph.firstChild);
|
|
227
|
-
ph.appendChild(box);
|
|
228
|
-
return box;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function clearAdScale(ph) {
|
|
154
|
+
function clearEmptyChecks(id) {
|
|
155
|
+
const timers = S.emptyChecks.get(id);
|
|
156
|
+
if (!timers) return;
|
|
157
|
+
for (const t of timers) { try { clearTimeout(t); } catch (_) {} }
|
|
158
|
+
S.emptyChecks.delete(id);
|
|
159
|
+
}
|
|
160
|
+
function queueEmptyCheck(id, timerId) {
|
|
161
|
+
const arr = S.emptyChecks.get(id) || [];
|
|
162
|
+
arr.push(timerId);
|
|
163
|
+
S.emptyChecks.set(id, arr);
|
|
164
|
+
}
|
|
165
|
+
function markFilledOnce(ph) {
|
|
166
|
+
try {
|
|
167
|
+
const wrap = ph?.closest?.(`.${WRAP_CLASS}`);
|
|
168
|
+
if (!wrap || !isFilled(ph)) return;
|
|
169
|
+
if (!wrap.getAttribute(A_FILLED)) wrap.setAttribute(A_FILLED, String(ts()));
|
|
170
|
+
const h = Math.round(ph.getBoundingClientRect?.().height || ph.offsetHeight || 0);
|
|
171
|
+
if (h > 0) wrap.setAttribute(A_LAST_H, String(h));
|
|
172
|
+
} catch (_) {}
|
|
173
|
+
}
|
|
174
|
+
function shouldKeepShellAfterUnused(wrap) {
|
|
175
|
+
try {
|
|
176
|
+
const filledTs = parseInt(wrap?.getAttribute?.(A_FILLED) || '0', 10) || 0;
|
|
177
|
+
return !!filledTs && (ts() - filledTs) < KEEP_SHELL_AFTER_UNUSED_MS;
|
|
178
|
+
} catch (_) { return false; }
|
|
179
|
+
}
|
|
180
|
+
function applyUnusedShell(wrap, ph) {
|
|
181
|
+
try {
|
|
182
|
+
const lastH = parseInt(wrap.getAttribute(A_LAST_H) || '0', 10) || 0;
|
|
183
|
+
const h = Math.max(MIN_SHELL_HEIGHT, lastH || 0);
|
|
184
|
+
wrap.classList.remove('is-empty');
|
|
185
|
+
wrap.classList.add('is-unused-shell');
|
|
186
|
+
wrap.style.minHeight = `${h}px`;
|
|
187
|
+
if (ph) ph.style.minHeight = `${h}px`;
|
|
188
|
+
} catch (_) {}
|
|
189
|
+
}
|
|
190
|
+
function clearUnusedShell(wrap, ph) {
|
|
191
|
+
try {
|
|
192
|
+
wrap?.classList?.remove('is-unused-shell');
|
|
193
|
+
wrap?.style?.removeProperty('min-height');
|
|
194
|
+
ph?.style?.removeProperty('min-height');
|
|
195
|
+
} catch (_) {}
|
|
196
|
+
}
|
|
197
|
+
function isProtectedFromDrop(wrap) {
|
|
198
|
+
try {
|
|
199
|
+
const now = ts();
|
|
200
|
+
const shownTs = parseInt(wrap?.getAttribute?.(A_SHOWN) || '0', 10) || 0;
|
|
201
|
+
const filledTs = parseInt(wrap?.getAttribute?.(A_FILLED) || '0', 10) || 0;
|
|
202
|
+
if (shownTs && (now - shownTs) < MIN_LIVE_AFTER_SHOW_MS) return true;
|
|
203
|
+
if (filledTs && (now - filledTs) < MIN_LIVE_AFTER_FILL_MS) return true;
|
|
204
|
+
return false;
|
|
205
|
+
} catch (_) { return false; }
|
|
206
|
+
}
|
|
207
|
+
function uncollapseIfFilled(ph) {
|
|
208
|
+
try {
|
|
232
209
|
const wrap = ph?.closest?.(`.${WRAP_CLASS}`);
|
|
233
210
|
if (!wrap) return;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
box.style.removeProperty('transform');
|
|
239
|
-
box.style.removeProperty('width');
|
|
240
|
-
box.style.removeProperty('height');
|
|
211
|
+
if (isFilled(ph)) {
|
|
212
|
+
wrap.classList.remove('is-empty');
|
|
213
|
+
clearUnusedShell(wrap, ph);
|
|
214
|
+
markFilledOnce(ph);
|
|
241
215
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
if (size.w <= wrapWidth + 2) { clearAdScale(ph); return; }
|
|
256
|
-
const scale = Math.max(0.1, Math.min(1, wrapWidth / size.w));
|
|
257
|
-
const scaledH = Math.ceil(size.h * scale);
|
|
258
|
-
const box = ensureScaleBox(ph);
|
|
259
|
-
if (!box) return;
|
|
260
|
-
wrap.classList.add('is-scaled');
|
|
261
|
-
box.style.width = `${size.w}px`;
|
|
262
|
-
box.style.height = `${size.h}px`;
|
|
263
|
-
box.style.transform = `scale(${scale})`;
|
|
264
|
-
ph.style.height = `${scaledH}px`;
|
|
265
|
-
wrap.style.height = `${scaledH}px`;
|
|
266
|
-
} catch (_) {}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
function uncollapseIfFilled(ph) {
|
|
270
|
-
try {
|
|
271
|
-
const wrap = ph?.closest?.(`.${WRAP_CLASS}`);
|
|
272
|
-
if (!wrap) return;
|
|
273
|
-
if (isFilled(ph)) {
|
|
274
|
-
wrap.classList.remove('is-empty');
|
|
275
|
-
markFilledOnce(ph);
|
|
276
|
-
fitWideAd(ph);
|
|
277
|
-
}
|
|
278
|
-
} catch (_) {}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
function unwatchPlaceholderFill(phOrId) {
|
|
282
|
-
const id = typeof phOrId === 'number' ? phOrId : parseInt(phOrId?.getAttribute?.('data-ezoic-id'), 10);
|
|
283
|
-
if (!Number.isFinite(id)) return;
|
|
284
|
-
const obs = S.fillObs.get(id);
|
|
285
|
-
if (obs) { try { obs.disconnect(); } catch (_) {} S.fillObs.delete(id); }
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function watchPlaceholderFill(ph) {
|
|
289
|
-
const id = parseInt(ph?.getAttribute?.('data-ezoic-id'), 10);
|
|
290
|
-
if (!ph || !Number.isFinite(id) || S.fillObs.has(id)) { try { if (ph) uncollapseIfFilled(ph); } catch (_) {} return; }
|
|
291
|
-
const obs = new MutationObserver(() => { uncollapseIfFilled(ph); try { fitWideAd(ph); } catch (_) {} });
|
|
292
|
-
try { obs.observe(ph, { childList: true, subtree: true, attributes: true }); } catch (_) { return; }
|
|
293
|
-
S.fillObs.set(id, obs);
|
|
216
|
+
} catch (_) {}
|
|
217
|
+
}
|
|
218
|
+
function unwatchPlaceholderFill(id) {
|
|
219
|
+
const obs = S.fillObsById.get(id);
|
|
220
|
+
if (obs) { try { obs.disconnect(); } catch (_) {} S.fillObsById.delete(id); }
|
|
221
|
+
}
|
|
222
|
+
function watchPlaceholderFill(id) {
|
|
223
|
+
try {
|
|
224
|
+
const ph = document.getElementById(`${PH_PREFIX}${id}`);
|
|
225
|
+
if (!ph || !ph.isConnected || S.fillObsById.has(id)) return;
|
|
226
|
+
const obs = new MutationObserver(() => uncollapseIfFilled(ph));
|
|
227
|
+
obs.observe(ph, { childList: true, subtree: true, attributes: true });
|
|
228
|
+
S.fillObsById.set(id, obs);
|
|
294
229
|
uncollapseIfFilled(ph);
|
|
295
|
-
|
|
296
|
-
|
|
230
|
+
} catch (_) {}
|
|
231
|
+
}
|
|
297
232
|
|
|
298
233
|
function mutate(fn) {
|
|
299
234
|
S.mutGuard++;
|
|
@@ -475,7 +410,6 @@
|
|
|
475
410
|
|
|
476
411
|
document.querySelectorAll(`.${WRAP_CLASS}.${klass}`).forEach(wrap => {
|
|
477
412
|
try {
|
|
478
|
-
if (isProtectedFromDrop(wrap)) return;
|
|
479
413
|
const rect = wrap.getBoundingClientRect();
|
|
480
414
|
if (rect.bottom > threshold) return;
|
|
481
415
|
if (!isFilled(wrap)) {
|
|
@@ -494,16 +428,17 @@
|
|
|
494
428
|
const oldKey = best.getAttribute(A_ANCHOR);
|
|
495
429
|
// Neutraliser l'IO sur ce wrap avant déplacement — évite un showAds
|
|
496
430
|
// parasite si le nœud était encore dans la zone IO_MARGIN.
|
|
497
|
-
try { const ph = best.querySelector(`#${PH_PREFIX}${id}`); if (ph)
|
|
498
|
-
clearEmptyChecks(id);
|
|
431
|
+
try { const ph = best.querySelector(`#${PH_PREFIX}${id}`); if (ph) S.io?.unobserve(ph); } catch (_) {}
|
|
499
432
|
mutate(() => {
|
|
500
433
|
best.setAttribute(A_ANCHOR, newKey);
|
|
501
434
|
best.setAttribute(A_CREATED, String(ts()));
|
|
502
435
|
best.setAttribute(A_SHOWN, '0');
|
|
503
|
-
best.setAttribute(A_FILLED, '0');
|
|
504
436
|
best.classList.remove('is-empty');
|
|
437
|
+
best.classList.remove('is-unused-shell');
|
|
438
|
+
best.removeAttribute(A_FILLED);
|
|
439
|
+
best.removeAttribute(A_LAST_H);
|
|
505
440
|
const ph = best.querySelector(`#${PH_PREFIX}${id}`);
|
|
506
|
-
if (ph) { ph.innerHTML = ''; ph.style.removeProperty('height'); }
|
|
441
|
+
if (ph) { ph.innerHTML = ''; ph.style.removeProperty('min-height'); }
|
|
507
442
|
targetEl.insertAdjacentElement('afterend', best);
|
|
508
443
|
});
|
|
509
444
|
if (oldKey && S.wrapByKey.get(oldKey) === best) S.wrapByKey.delete(oldKey);
|
|
@@ -515,7 +450,6 @@
|
|
|
515
450
|
const doDisplay = () => { try { ez.displayMore([id]); } catch (_) {} };
|
|
516
451
|
try { (typeof ez.cmd?.push === 'function') ? ez.cmd.push(doDestroy) : doDestroy(); } catch (_) {}
|
|
517
452
|
|
|
518
|
-
try { const ph = best.querySelector(`#${PH_PREFIX}${id}`); if (ph) { observePh(id); watchPlaceholderFill(ph); } } catch (_) {}
|
|
519
453
|
return { id, wrap: best };
|
|
520
454
|
}
|
|
521
455
|
|
|
@@ -528,7 +462,6 @@
|
|
|
528
462
|
w.setAttribute(A_WRAPID, String(id));
|
|
529
463
|
w.setAttribute(A_CREATED, String(ts()));
|
|
530
464
|
w.setAttribute(A_SHOWN, '0');
|
|
531
|
-
w.setAttribute(A_FILLED, '0');
|
|
532
465
|
w.style.cssText = 'width:100%;display:block;';
|
|
533
466
|
const ph = document.createElement('div');
|
|
534
467
|
ph.id = `${PH_PREFIX}${id}`;
|
|
@@ -546,17 +479,24 @@
|
|
|
546
479
|
mutate(() => el.insertAdjacentElement('afterend', w));
|
|
547
480
|
S.mountedIds.add(id);
|
|
548
481
|
S.wrapByKey.set(key, w);
|
|
549
|
-
|
|
482
|
+
watchPlaceholderFill(id);
|
|
550
483
|
return w;
|
|
551
484
|
}
|
|
552
485
|
|
|
553
486
|
function dropWrap(w) {
|
|
554
487
|
try {
|
|
555
|
-
if (isProtectedFromDrop(w)) return;
|
|
556
488
|
const ph = w.querySelector(`[id^="${PH_PREFIX}"]`);
|
|
557
|
-
if (ph instanceof Element) { S.io?.unobserve(ph); clearAdScale(ph); unwatchPlaceholderFill(ph); }
|
|
558
489
|
const id = parseInt(w.getAttribute(A_WRAPID), 10);
|
|
559
|
-
if (
|
|
490
|
+
if (isProtectedFromDrop(w) || shouldKeepShellAfterUnused(w)) {
|
|
491
|
+
if (ph) applyUnusedShell(w, ph);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
if (ph instanceof Element) S.io?.unobserve(ph);
|
|
495
|
+
if (Number.isFinite(id)) {
|
|
496
|
+
clearEmptyChecks(id);
|
|
497
|
+
unwatchPlaceholderFill(id);
|
|
498
|
+
S.mountedIds.delete(id);
|
|
499
|
+
}
|
|
560
500
|
const key = w.getAttribute(A_ANCHOR);
|
|
561
501
|
if (key && S.wrapByKey.get(key) === w) S.wrapByKey.delete(key);
|
|
562
502
|
w.remove();
|
|
@@ -664,8 +604,8 @@
|
|
|
664
604
|
function observePh(id) {
|
|
665
605
|
const ph = document.getElementById(`${PH_PREFIX}${id}`);
|
|
666
606
|
if (ph?.isConnected) {
|
|
607
|
+
watchPlaceholderFill(id);
|
|
667
608
|
try { getIO()?.observe(ph); } catch (_) {}
|
|
668
|
-
try { watchPlaceholderFill(ph); } catch (_) {}
|
|
669
609
|
}
|
|
670
610
|
}
|
|
671
611
|
|
|
@@ -704,29 +644,21 @@
|
|
|
704
644
|
try {
|
|
705
645
|
if (isBlocked()) { clearTimeout(timer); return release(); }
|
|
706
646
|
const ph = document.getElementById(`${PH_PREFIX}${id}`);
|
|
707
|
-
if (!ph?.isConnected || isFilled(ph)) {
|
|
647
|
+
if (!ph?.isConnected || isFilled(ph)) { clearTimeout(timer); return release(); }
|
|
648
|
+
clearEmptyChecks(id);
|
|
649
|
+
try { const wrap = ph.closest?.(`.${WRAP_CLASS}`); wrap?.classList?.remove('is-empty'); clearUnusedShell(wrap, ph); } catch (_) {}
|
|
708
650
|
|
|
709
651
|
const t = ts();
|
|
710
652
|
if (t - (S.lastShow.get(id) ?? 0) < SHOW_THROTTLE_MS) { clearTimeout(timer); return release(); }
|
|
711
653
|
S.lastShow.set(id, t);
|
|
712
654
|
|
|
713
|
-
try {
|
|
714
|
-
const wrap = ph.closest?.(`.${WRAP_CLASS}`);
|
|
715
|
-
wrap?.setAttribute(A_SHOWN, String(t));
|
|
716
|
-
wrap?.setAttribute(A_FILLED, '0');
|
|
717
|
-
wrap?.classList.remove('is-empty');
|
|
718
|
-
if (wrap) wrap.style.removeProperty('height');
|
|
719
|
-
ph.style.removeProperty('height');
|
|
720
|
-
} catch (_) {}
|
|
721
|
-
clearEmptyChecks(id);
|
|
655
|
+
try { ph.closest?.(`.${WRAP_CLASS}`)?.setAttribute(A_SHOWN, String(t)); } catch (_) {}
|
|
722
656
|
|
|
723
657
|
window.ezstandalone = window.ezstandalone || {};
|
|
724
658
|
const ez = window.ezstandalone;
|
|
725
659
|
const doShow = () => {
|
|
726
660
|
try { ez.showAds(id); } catch (_) {}
|
|
727
661
|
scheduleEmptyCheck(id, t);
|
|
728
|
-
setTimeout(() => { try { const p = document.getElementById(`${PH_PREFIX}${id}`); if (p) fitWideAd(p); } catch (_) {} }, 500);
|
|
729
|
-
setTimeout(() => { try { const p = document.getElementById(`${PH_PREFIX}${id}`); if (p) fitWideAd(p); } catch (_) {} }, 2500);
|
|
730
662
|
setTimeout(() => { clearTimeout(timer); release(); }, 700);
|
|
731
663
|
};
|
|
732
664
|
Array.isArray(ez.cmd) ? ez.cmd.push(doShow) : doShow();
|
|
@@ -735,22 +667,31 @@
|
|
|
735
667
|
}
|
|
736
668
|
|
|
737
669
|
function scheduleEmptyCheck(id, showTs) {
|
|
738
|
-
clearEmptyChecks(id);
|
|
739
670
|
const runCheck = () => {
|
|
740
671
|
try {
|
|
741
672
|
const ph = document.getElementById(`${PH_PREFIX}${id}`);
|
|
742
673
|
const wrap = ph?.closest?.(`.${WRAP_CLASS}`);
|
|
743
674
|
if (!wrap || !ph?.isConnected) return;
|
|
744
675
|
if (parseInt(wrap.getAttribute(A_SHOWN) || '0', 10) > showTs) return;
|
|
745
|
-
|
|
676
|
+
|
|
677
|
+
if (isFilled(ph)) {
|
|
746
678
|
wrap.classList.remove('is-empty');
|
|
747
|
-
|
|
679
|
+
clearUnusedShell(wrap, ph);
|
|
680
|
+
markFilledOnce(ph);
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
if (shouldKeepShellAfterUnused(wrap)) {
|
|
685
|
+
applyUnusedShell(wrap, ph);
|
|
748
686
|
return;
|
|
749
687
|
}
|
|
750
|
-
|
|
751
|
-
|
|
688
|
+
|
|
689
|
+
clearUnusedShell(wrap, ph);
|
|
690
|
+
wrap.classList.add('is-empty');
|
|
752
691
|
} catch (_) {}
|
|
753
692
|
};
|
|
693
|
+
|
|
694
|
+
clearEmptyChecks(id);
|
|
754
695
|
[EMPTY_CHECK_MS, EMPTY_CHECK_MS + 5000, EMPTY_CHECK_MS + 15000].forEach(delay => {
|
|
755
696
|
const t = setTimeout(runCheck, delay);
|
|
756
697
|
queueEmptyCheck(id, t);
|
|
@@ -869,17 +810,6 @@
|
|
|
869
810
|
step();
|
|
870
811
|
}
|
|
871
812
|
|
|
872
|
-
let fitRaf = 0;
|
|
873
|
-
function scheduleRefitAll() {
|
|
874
|
-
if (fitRaf) return;
|
|
875
|
-
fitRaf = requestAnimationFrame(() => {
|
|
876
|
-
fitRaf = 0;
|
|
877
|
-
document.querySelectorAll(`[id^="${PH_PREFIX}"]`).forEach(ph => {
|
|
878
|
-
try { fitWideAd(ph); } catch (_) {}
|
|
879
|
-
});
|
|
880
|
-
});
|
|
881
|
-
}
|
|
882
|
-
|
|
883
813
|
// ── Cleanup navigation ─────────────────────────────────────────────────────
|
|
884
814
|
|
|
885
815
|
function cleanup() {
|
|
@@ -891,17 +821,14 @@
|
|
|
891
821
|
S.cursors = { topics: 0, posts: 0, categories: 0 };
|
|
892
822
|
S.mountedIds.clear();
|
|
893
823
|
S.lastShow.clear();
|
|
824
|
+
for (const id of Array.from(S.emptyChecks.keys())) clearEmptyChecks(id);
|
|
825
|
+
for (const id of Array.from(S.fillObsById.keys())) unwatchPlaceholderFill(id);
|
|
894
826
|
S.wrapByKey.clear();
|
|
895
|
-
for (const [, timers] of S.emptyChecks) { for (const t of timers) { try { clearTimeout(t); } catch (_) {} } }
|
|
896
|
-
S.emptyChecks.clear();
|
|
897
|
-
for (const [, obs] of S.fillObs) { try { obs.disconnect(); } catch (_) {} }
|
|
898
|
-
S.fillObs.clear();
|
|
899
827
|
S.inflight = 0;
|
|
900
828
|
S.pending = [];
|
|
901
829
|
S.pendingSet.clear();
|
|
902
830
|
S.burstActive = false;
|
|
903
831
|
S.runQueued = false;
|
|
904
|
-
if (fitRaf) { try { cancelAnimationFrame(fitRaf); } catch (_) {} fitRaf = 0; }
|
|
905
832
|
}
|
|
906
833
|
|
|
907
834
|
// ── MutationObserver ───────────────────────────────────────────────────────
|
|
@@ -1039,7 +966,6 @@
|
|
|
1039
966
|
ensureDomObserver();
|
|
1040
967
|
bindNodeBB();
|
|
1041
968
|
bindScroll();
|
|
1042
|
-
window.addEventListener('resize', scheduleRefitAll, { passive: true });
|
|
1043
969
|
blockedUntil = 0;
|
|
1044
970
|
requestBurst();
|
|
1045
971
|
|
package/public/style.css
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
width: 100%;
|
|
9
9
|
margin: 0 !important;
|
|
10
10
|
padding: 0 !important;
|
|
11
|
-
overflow:
|
|
11
|
+
overflow: visible;
|
|
12
12
|
contain: layout style;
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
|
|
81
|
-
/*
|
|
81
|
+
/* Filet de sécurité : si un fill arrive tard alors que .is-empty est resté, ne pas écraser */
|
|
82
82
|
.nodebb-ezoic-wrap.is-empty:has(iframe, ins, img, video, [data-google-container-id]) {
|
|
83
83
|
height: auto !important;
|
|
84
84
|
min-height: 1px !important;
|
|
@@ -86,17 +86,20 @@
|
|
|
86
86
|
overflow: visible !important;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
/*
|
|
90
|
-
.nodebb-ezoic-wrap {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
/* Shell conservé quand Ezoic repasse en "unused" après un affichage initial */
|
|
90
|
+
.nodebb-ezoic-wrap.is-unused-shell {
|
|
91
|
+
overflow: hidden !important;
|
|
92
|
+
}
|
|
93
|
+
.nodebb-ezoic-wrap.is-unused-shell > [id^="ezoic-pub-ad-placeholder-"] {
|
|
94
|
+
display: block;
|
|
95
|
+
width: 100%;
|
|
94
96
|
}
|
|
95
97
|
|
|
98
|
+
/* Responsive hardening conservatif (sans scale JS) */
|
|
99
|
+
.nodebb-ezoic-wrap,
|
|
96
100
|
.nodebb-ezoic-wrap > [id^="ezoic-pub-ad-placeholder-"] {
|
|
97
101
|
max-width: 100%;
|
|
98
102
|
}
|
|
99
|
-
|
|
100
103
|
.nodebb-ezoic-wrap .ezoic-ad,
|
|
101
104
|
.nodebb-ezoic-wrap span.ezoic-ad {
|
|
102
105
|
max-width: 100% !important;
|
|
@@ -104,30 +107,9 @@
|
|
|
104
107
|
box-sizing: border-box !important;
|
|
105
108
|
}
|
|
106
109
|
|
|
107
|
-
|
|
108
|
-
.nodebb-ezoic-wrap
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
overflow: visible !important;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.nodebb-ezoic-wrap iframe {
|
|
116
|
-
display: block !important;
|
|
117
|
-
margin-left: auto !important;
|
|
118
|
-
margin-right: auto !important;
|
|
119
|
-
max-width: none !important;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
.nodebb-ezoic-wrap.is-scaled {
|
|
123
|
-
overflow: hidden !important;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
.nodebb-ezoic-wrap .nbb-ez-scale-box {
|
|
127
|
-
transform-origin: top center;
|
|
128
|
-
will-change: transform;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
@supports not (overflow: clip) {
|
|
132
|
-
.nodebb-ezoic-wrap { overflow-x: hidden; }
|
|
110
|
+
/* Neutralisation sticky plus défensive dans les wraps du plugin */
|
|
111
|
+
.nodebb-ezoic-wrap .ezads-sticky-intradiv,
|
|
112
|
+
.nodebb-ezoic-wrap [style*="position: sticky"] {
|
|
113
|
+
position: static !important;
|
|
114
|
+
top: auto !important;
|
|
133
115
|
}
|