nodebb-plugin-ezoic-infinite 1.6.3 → 1.6.5
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 +101 -102
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -1346,54 +1346,60 @@ function buildOrdinalMap(items) {
|
|
|
1346
1346
|
|
|
1347
1347
|
|
|
1348
1348
|
|
|
1349
|
+
|
|
1350
|
+
|
|
1349
1351
|
// ===== CLEAN REFRACTOR: visibility manager for Ezoic wraps =====
|
|
1350
1352
|
(function () {
|
|
1351
|
-
// v2.
|
|
1352
|
-
//
|
|
1353
|
-
// -
|
|
1354
|
-
// -
|
|
1355
|
-
//
|
|
1353
|
+
// v2.3 (no-redefine):
|
|
1354
|
+
// Your logs show:
|
|
1355
|
+
// - "Placeholder Id XXX has already been defined"
|
|
1356
|
+
// - "No valid placeholders for loadMore"
|
|
1357
|
+
//
|
|
1358
|
+
// Root cause: calling showAds repeatedly for the same placeholder id and/or
|
|
1359
|
+
// removing/recreating wrappers with the same IDs causes Ezoic to treat them as re-defined.
|
|
1360
|
+
//
|
|
1361
|
+
// Fix:
|
|
1362
|
+
// - NEVER remove wraps/placeholders here (no DOM deletion of ads).
|
|
1363
|
+
// - Only call showAds ONCE per placeholder per page lifetime (unless the placeholder is truly empty).
|
|
1364
|
+
// - De-duplicate placeholders in DOM: if the same data-ezoic-id appears multiple times, keep the first.
|
|
1356
1365
|
|
|
1357
1366
|
var BETWEEN_SELECTOR = '.nodebb-ezoic-wrap.ezoic-ad-between';
|
|
1358
1367
|
var MESSAGE_SELECTOR = '.nodebb-ezoic-wrap.ezoic-ad-message';
|
|
1359
1368
|
var WRAP_SELECTOR = BETWEEN_SELECTOR + ', ' + MESSAGE_SELECTOR;
|
|
1360
1369
|
|
|
1361
|
-
|
|
1362
|
-
var
|
|
1363
|
-
|
|
1364
|
-
// Show tuning (moderate)
|
|
1365
|
-
var SHOW_COOLDOWN_MS = 900;
|
|
1366
|
-
var MAX_SHOW_PER_TICK = 6;
|
|
1367
|
-
|
|
1368
|
-
// Up-scroll helper: only check near-viewport wraps, bounded
|
|
1369
|
-
var SCAN_COOLDOWN_MS = 220;
|
|
1370
|
-
var lastScan = 0;
|
|
1371
|
-
var SCAN_BUDGET = 10;
|
|
1372
|
-
|
|
1373
|
-
function isMobile() {
|
|
1374
|
-
try { return window.matchMedia && window.matchMedia('(max-width: 767px)').matches; } catch (e) { return false; }
|
|
1375
|
-
}
|
|
1376
|
-
function keepMarginBetween() { return isMobile() ? KEEP_MARGIN_BETWEEN_MOBILE : KEEP_MARGIN_BETWEEN_DESKTOP; }
|
|
1370
|
+
// show tuning (safe)
|
|
1371
|
+
var MAX_SHOW_PER_TICK = 4;
|
|
1377
1372
|
|
|
1378
|
-
|
|
1373
|
+
// internal state
|
|
1374
|
+
var activatedById = Object.create(null); // id -> ts
|
|
1379
1375
|
var showQueue = [];
|
|
1380
1376
|
var showTicking = false;
|
|
1381
1377
|
|
|
1382
|
-
function
|
|
1378
|
+
function getIdFromWrap(w) {
|
|
1383
1379
|
try { return w.getAttribute('data-ezoic-wrapid'); } catch (e) { return null; }
|
|
1384
1380
|
}
|
|
1385
|
-
function
|
|
1381
|
+
function getIdFromPlaceholder(w) {
|
|
1386
1382
|
try {
|
|
1387
1383
|
var ph = w.querySelector('[data-ezoic-id]');
|
|
1388
1384
|
return ph ? ph.getAttribute('data-ezoic-id') : null;
|
|
1389
1385
|
} catch (e) { return null; }
|
|
1390
1386
|
}
|
|
1387
|
+
function getId(w) { return getIdFromWrap(w) || getIdFromPlaceholder(w); }
|
|
1388
|
+
|
|
1389
|
+
function isFilled(w) {
|
|
1390
|
+
try {
|
|
1391
|
+
// if Ezoic/Google already injected, there will be an iframe or an element with id starting google_ads_iframe
|
|
1392
|
+
if (w.querySelector('iframe')) return true;
|
|
1393
|
+
if (w.querySelector('[id^="google_ads_iframe"]')) return true;
|
|
1394
|
+
if (w.querySelector('.ezoic-ad')) return true;
|
|
1395
|
+
} catch (e) {}
|
|
1396
|
+
return false;
|
|
1397
|
+
}
|
|
1391
1398
|
|
|
1392
1399
|
function enqueueShow(id) {
|
|
1393
1400
|
if (!id) return;
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
if (now - last < SHOW_COOLDOWN_MS) return;
|
|
1401
|
+
// show only once (avoid "already defined")
|
|
1402
|
+
if (activatedById[id]) return;
|
|
1397
1403
|
|
|
1398
1404
|
for (var i = 0; i < showQueue.length; i++) if (showQueue[i] === id) return;
|
|
1399
1405
|
showQueue.push(id);
|
|
@@ -1409,9 +1415,9 @@ function buildOrdinalMap(items) {
|
|
|
1409
1415
|
while (showQueue.length && n < MAX_SHOW_PER_TICK) {
|
|
1410
1416
|
var id = showQueue.shift();
|
|
1411
1417
|
try {
|
|
1412
|
-
if (window.ezstandalone && typeof window.ezstandalone.showAds === 'function') {
|
|
1418
|
+
if (!activatedById[id] && window.ezstandalone && typeof window.ezstandalone.showAds === 'function') {
|
|
1413
1419
|
window.ezstandalone.showAds(String(id));
|
|
1414
|
-
|
|
1420
|
+
activatedById[id] = Date.now();
|
|
1415
1421
|
}
|
|
1416
1422
|
} catch (e) {}
|
|
1417
1423
|
n++;
|
|
@@ -1420,28 +1426,27 @@ function buildOrdinalMap(items) {
|
|
|
1420
1426
|
});
|
|
1421
1427
|
}
|
|
1422
1428
|
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
var
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
});
|
|
1429
|
+
// De-duplicate placeholders to avoid Ezoic warnings.
|
|
1430
|
+
function dedupePlaceholders() {
|
|
1431
|
+
var seen = Object.create(null);
|
|
1432
|
+
try {
|
|
1433
|
+
document.querySelectorAll('.nodebb-ezoic-wrap [data-ezoic-id]').forEach(function (ph) {
|
|
1434
|
+
try {
|
|
1435
|
+
var id = ph.getAttribute('data-ezoic-id');
|
|
1436
|
+
if (!id) return;
|
|
1437
|
+
if (seen[id]) {
|
|
1438
|
+
// remove duplicate wrapper entirely (keep first occurrence)
|
|
1439
|
+
var wrap = ph.closest('.nodebb-ezoic-wrap');
|
|
1440
|
+
if (wrap) wrap.remove();
|
|
1441
|
+
} else {
|
|
1442
|
+
seen[id] = true;
|
|
1443
|
+
}
|
|
1444
|
+
} catch (e) {}
|
|
1445
|
+
});
|
|
1446
|
+
} catch (e) {}
|
|
1442
1447
|
}
|
|
1443
1448
|
|
|
1444
|
-
//
|
|
1449
|
+
// Track visibility: when a wrap comes near viewport, trigger show once if empty.
|
|
1445
1450
|
var io = null;
|
|
1446
1451
|
function installIO() {
|
|
1447
1452
|
if (io || typeof IntersectionObserver === 'undefined') return;
|
|
@@ -1451,9 +1456,15 @@ function buildOrdinalMap(items) {
|
|
|
1451
1456
|
entries.forEach(function (e) {
|
|
1452
1457
|
if (!e || !e.target) return;
|
|
1453
1458
|
if (e.isIntersecting) {
|
|
1454
|
-
|
|
1455
|
-
var id =
|
|
1456
|
-
if (id)
|
|
1459
|
+
// If the slot is already filled, mark it as activated to prevent re-define attempts.
|
|
1460
|
+
var id = getId(e.target);
|
|
1461
|
+
if (!id) return;
|
|
1462
|
+
|
|
1463
|
+
if (isFilled(e.target)) {
|
|
1464
|
+
activatedById[id] = activatedById[id] || Date.now();
|
|
1465
|
+
return;
|
|
1466
|
+
}
|
|
1467
|
+
enqueueShow(id);
|
|
1457
1468
|
}
|
|
1458
1469
|
});
|
|
1459
1470
|
} catch (e) {}
|
|
@@ -1462,12 +1473,16 @@ function buildOrdinalMap(items) {
|
|
|
1462
1473
|
try { document.querySelectorAll(WRAP_SELECTOR).forEach(function (w) { try { io.observe(w); } catch(e) {} }); } catch (e) {}
|
|
1463
1474
|
}
|
|
1464
1475
|
|
|
1476
|
+
// Observe newly added wraps and observe them + dedupe
|
|
1465
1477
|
var moInstalled = false;
|
|
1466
1478
|
function installMO() {
|
|
1467
1479
|
if (moInstalled || typeof MutationObserver === 'undefined') return;
|
|
1468
1480
|
moInstalled = true;
|
|
1469
1481
|
|
|
1470
1482
|
var mo = new MutationObserver(function (muts) {
|
|
1483
|
+
// dedupe quickly, then observe new wraps
|
|
1484
|
+
try { dedupePlaceholders(); } catch (e) {}
|
|
1485
|
+
|
|
1471
1486
|
if (!io) return;
|
|
1472
1487
|
try {
|
|
1473
1488
|
for (var i = 0; i < muts.length; i++) {
|
|
@@ -1479,8 +1494,10 @@ function buildOrdinalMap(items) {
|
|
|
1479
1494
|
|
|
1480
1495
|
if (n.matches && n.matches(WRAP_SELECTOR)) {
|
|
1481
1496
|
try { io.observe(n); } catch (e) {}
|
|
1482
|
-
|
|
1483
|
-
|
|
1497
|
+
// eager show if empty
|
|
1498
|
+
var id = getId(n);
|
|
1499
|
+
if (id && !isFilled(n)) enqueueShow(id);
|
|
1500
|
+
else if (id) activatedById[id] = activatedById[id] || Date.now();
|
|
1484
1501
|
} else if (n.querySelectorAll) {
|
|
1485
1502
|
var inner = n.querySelectorAll(WRAP_SELECTOR);
|
|
1486
1503
|
for (var k = 0; k < inner.length; k++) {
|
|
@@ -1495,67 +1512,47 @@ function buildOrdinalMap(items) {
|
|
|
1495
1512
|
try { mo.observe(document.documentElement || document.body, { childList: true, subtree: true }); } catch (e) {}
|
|
1496
1513
|
}
|
|
1497
1514
|
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
if (now - lastScan < SCAN_COOLDOWN_MS) return;
|
|
1502
|
-
lastScan = now;
|
|
1515
|
+
function init() {
|
|
1516
|
+
// 1) dedupe existing
|
|
1517
|
+
dedupePlaceholders();
|
|
1503
1518
|
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
try { wraps = document.querySelectorAll(WRAP_SELECTOR); } catch (e) { return; }
|
|
1519
|
+
// 2) install observers
|
|
1520
|
+
installIO();
|
|
1521
|
+
installMO();
|
|
1508
1522
|
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
var
|
|
1512
|
-
|
|
1523
|
+
// 3) initial eager show for empty visible-ish wraps (bounded)
|
|
1524
|
+
try {
|
|
1525
|
+
var vh = window.innerHeight || document.documentElement.clientHeight || 0;
|
|
1526
|
+
var margin = 900;
|
|
1527
|
+
var wraps = document.querySelectorAll(WRAP_SELECTOR);
|
|
1528
|
+
var budget = 12;
|
|
1529
|
+
for (var i = 0; i < wraps.length && budget > 0; i++) {
|
|
1530
|
+
var w = wraps[i];
|
|
1513
1531
|
var r = w.getBoundingClientRect();
|
|
1514
1532
|
if (r.bottom >= -margin && r.top <= (vh + margin)) {
|
|
1515
|
-
var id =
|
|
1516
|
-
if (id)
|
|
1533
|
+
var id = getId(w);
|
|
1534
|
+
if (id) {
|
|
1535
|
+
if (isFilled(w)) activatedById[id] = activatedById[id] || Date.now();
|
|
1536
|
+
else enqueueShow(id);
|
|
1537
|
+
}
|
|
1517
1538
|
budget--;
|
|
1518
1539
|
}
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
var sweepPending = false;
|
|
1524
|
-
var lastSweep = 0;
|
|
1525
|
-
var SWEEP_COOLDOWN_MS = 600;
|
|
1526
|
-
|
|
1527
|
-
function scheduleSweep() {
|
|
1528
|
-
var now = Date.now();
|
|
1529
|
-
if (now - lastSweep < SWEEP_COOLDOWN_MS) return;
|
|
1530
|
-
if (sweepPending) return;
|
|
1531
|
-
sweepPending = true;
|
|
1532
|
-
requestAnimationFrame(function () {
|
|
1533
|
-
sweepPending = false;
|
|
1534
|
-
lastSweep = Date.now();
|
|
1535
|
-
removeFarBetweenWraps();
|
|
1536
|
-
});
|
|
1537
|
-
}
|
|
1538
|
-
|
|
1539
|
-
function onScroll() {
|
|
1540
|
-
scheduleSweep();
|
|
1541
|
-
scanNearViewport();
|
|
1542
|
-
scheduleShowTick();
|
|
1543
|
-
}
|
|
1544
|
-
|
|
1545
|
-
function init() {
|
|
1546
|
-
installIO();
|
|
1547
|
-
installMO();
|
|
1540
|
+
}
|
|
1541
|
+
} catch (e) {}
|
|
1548
1542
|
|
|
1549
|
-
window.addEventListener('scroll',
|
|
1550
|
-
window.addEventListener('resize',
|
|
1543
|
+
window.addEventListener('scroll', scheduleShowTick, { passive: true });
|
|
1544
|
+
window.addEventListener('resize', scheduleShowTick, { passive: true });
|
|
1551
1545
|
|
|
1552
1546
|
if (window.jQuery) {
|
|
1553
1547
|
window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', function () {
|
|
1554
|
-
setTimeout(function () {
|
|
1548
|
+
setTimeout(function () {
|
|
1549
|
+
dedupePlaceholders();
|
|
1550
|
+
scheduleShowTick();
|
|
1551
|
+
}, 0);
|
|
1555
1552
|
});
|
|
1556
1553
|
}
|
|
1557
1554
|
|
|
1558
|
-
setTimeout(
|
|
1555
|
+
setTimeout(scheduleShowTick, 0);
|
|
1559
1556
|
}
|
|
1560
1557
|
|
|
1561
1558
|
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
|
|
@@ -1565,3 +1562,5 @@ function buildOrdinalMap(items) {
|
|
|
1565
1562
|
|
|
1566
1563
|
|
|
1567
1564
|
|
|
1565
|
+
|
|
1566
|
+
|