nodebb-plugin-ezoic-infinite 1.5.34 → 1.5.35

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 +52 -18
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.5.34",
3
+ "version": "1.5.35",
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
@@ -383,7 +383,33 @@ function withInternalDomChange(fn) {
383
383
  } catch (e) {}
384
384
  }
385
385
 
386
- function pruneOrphanWraps(kindClass, items) {
386
+
387
+ function findWrapById(id) {
388
+ try {
389
+ return document.querySelector(`.${WRAP_CLASS}[data-ezoic-wrapid="${id}"]`);
390
+ } catch (e) {}
391
+ return null;
392
+ }
393
+
394
+ function armPlaceholder(wrap, id) {
395
+ try {
396
+ if (!wrap || !wrap.isConnected) return null;
397
+ const domId = `${PLACEHOLDER_PREFIX}${id}`;
398
+
399
+ // If the id is already present somewhere, do not reassign it.
400
+ const existing = document.getElementById(domId);
401
+ if (existing && existing.isConnected) return existing;
402
+
403
+ const ph = wrap.querySelector('[data-ezoic-ph="1"]');
404
+ if (!ph) return null;
405
+
406
+ if (!ph.id) ph.id = domId;
407
+ return ph;
408
+ } catch (e) {}
409
+ return null;
410
+ }
411
+
412
+ function pruneOrphanWraps(kindClass, items) {
387
413
  if (!items || !items.length) return 0;
388
414
  const itemSet = new Set(items);
389
415
  const wraps = document.querySelectorAll(`.${WRAP_CLASS}.${kindClass}`);
@@ -421,8 +447,10 @@ function buildWrap(id, kindClass, afterPos) {
421
447
  wrap.style.width = '100%';
422
448
 
423
449
  const ph = document.createElement('div');
424
- ph.id = `${PLACEHOLDER_PREFIX}${id}`;
450
+ // Do not assign the Ezoic placeholder id until we actually want to load the ad.
451
+ // This avoids Ezoic defining placeholders too early during DOM churn/infinite scroll.
425
452
  ph.setAttribute('data-ezoic-id', String(id));
453
+ ph.setAttribute('data-ezoic-ph', '1');
426
454
  wrap.appendChild(ph);
427
455
 
428
456
  return wrap;
@@ -437,8 +465,8 @@ function buildWrap(id, kindClass, afterPos) {
437
465
  if (findWrap(kindClass, afterPos)) return null;
438
466
  if (insertingIds.has(id)) return null;
439
467
 
440
- const existingPh = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
441
- if (existingPh && existingPh.isConnected) return null;
468
+ const existingWrap = findWrapById(id);
469
+ if (existingWrap && existingWrap.isConnected) return null;
442
470
 
443
471
  insertingIds.add(id);
444
472
  try {
@@ -460,8 +488,8 @@ function buildWrap(id, kindClass, afterPos) {
460
488
  state[cursorKey] = (state[cursorKey] + 1) % n;
461
489
 
462
490
  const id = allIds[idx];
463
- const ph = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
464
- if (ph && ph.isConnected) continue;
491
+ const w = findWrapById(id);
492
+ if (w && w.isConnected) continue;
465
493
 
466
494
  return id;
467
495
  }
@@ -488,8 +516,8 @@ function buildWrap(id, kindClass, afterPos) {
488
516
  withInternalDomChange(() => {
489
517
  // Unobserve placeholder if still observed
490
518
  try {
491
- const ph = victim.querySelector && victim.querySelector(`[id^="${PLACEHOLDER_PREFIX}"]`);
492
- if (ph && state.io) state.io.unobserve(ph);
519
+ const t = victim;
520
+ if (t && state.io) state.io.unobserve(t);
493
521
  } catch (e) {}
494
522
 
495
523
  try { if (id) safeDestroyById(id); } catch (e) {}
@@ -604,9 +632,12 @@ function startShow(id) {
604
632
  const el = ent.target;
605
633
  try { state.io && state.io.unobserve(el); } catch (e) {}
606
634
 
607
- const idAttr = el && el.getAttribute && el.getAttribute('data-ezoic-id');
635
+ const idAttr = el && el.getAttribute && el.getAttribute('data-ezoic-wrapid');
608
636
  const id = parseInt(idAttr, 10);
609
- if (Number.isFinite(id) && id > 0) enqueueShow(id);
637
+ if (Number.isFinite(id) && id > 0) {
638
+ armPlaceholder(el, id);
639
+ enqueueShow(id);
640
+ }
610
641
  }
611
642
  }, { root: null, rootMargin: desiredMargin, threshold: 0 });
612
643
  state.ioMargin = desiredMargin;
@@ -618,7 +649,7 @@ function startShow(id) {
618
649
  // If we rebuilt the observer, re-observe existing placeholders so we don't miss them.
619
650
  try {
620
651
  if (state.io) {
621
- const nodes = document.querySelectorAll(`[id^="${PLACEHOLDER_PREFIX}"]`);
652
+ const nodes = document.querySelectorAll(`.${WRAP_CLASS}[data-ezoic-wrapid]`);
622
653
  nodes.forEach((n) => { try { state.io.observe(n); } catch (e) {} });
623
654
  }
624
655
  } catch (e) {}
@@ -626,17 +657,20 @@ function startShow(id) {
626
657
  }
627
658
 
628
659
  function observePlaceholder(id) {
629
- const ph = document.getElementById(`${PLACEHOLDER_PREFIX}${id}`);
630
- if (!ph || !ph.isConnected) return;
660
+ const wrap = findWrapById(id);
661
+ if (!wrap || !wrap.isConnected) return;
631
662
  const io = ensurePreloadObserver();
632
- try { io && io.observe(ph); } catch (e) {}
663
+ try { io && io.observe(wrap); } catch (e) {}
633
664
 
634
- // If already above fold, fire immediately
665
+ // If already near the fold, arm & fire immediately
635
666
  try {
636
- const r = ph.getBoundingClientRect();
667
+ const r = wrap.getBoundingClientRect();
637
668
  const screens = isBoosted() ? 5.0 : 3.0;
638
- const minBottom = isBoosted() ? -1500 : -800;
639
- if (r.top < window.innerHeight * screens && r.bottom > minBottom) enqueueShow(id);
669
+ const h = (window.innerHeight || 800);
670
+ if (r.top < screens * h && r.bottom > -screens * h) {
671
+ armPlaceholder(wrap, id);
672
+ enqueueShow(id);
673
+ }
640
674
  } catch (e) {}
641
675
  }
642
676