nodebb-plugin-ezoic-infinite 1.6.9 → 1.6.10
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 +153 -263
- package/public/style.css +3 -3
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
function createWrapElement(kindClass, targetEl) {
|
|
5
|
+
try {
|
|
6
|
+
if (kindClass === 'ezoic-ad-between') {
|
|
7
|
+
var p = targetEl && targetEl.parentElement;
|
|
8
|
+
if (p && (p.tagName === 'UL' || p.tagName === 'OL')) {
|
|
9
|
+
var li = document.createElement('li');
|
|
10
|
+
li.className = 'nodebb-ezoic-wrap ' + kindClass;
|
|
11
|
+
li.setAttribute('role', 'listitem');
|
|
12
|
+
return li;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
} catch (e) {}
|
|
16
|
+
var div = document.createElement('div');
|
|
17
|
+
div.className = 'nodebb-ezoic-wrap ' + kindClass;
|
|
18
|
+
return div;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
4
22
|
// Track scroll direction to avoid aggressive recycling when the user scrolls upward.
|
|
5
23
|
// Recycling while scrolling up is a common cause of ads "bunching" and a "disappearing too fast" feeling.
|
|
6
24
|
let lastScrollY = 0;
|
|
@@ -637,7 +655,7 @@ function globalGapFixInit() {
|
|
|
637
655
|
// ---------------- insertion primitives ----------------
|
|
638
656
|
|
|
639
657
|
function buildWrap(id, kindClass, afterPos, createPlaceholder) {
|
|
640
|
-
const wrap =
|
|
658
|
+
const wrap = createWrapElement(kindClass, el);
|
|
641
659
|
wrap.className = `${WRAP_CLASS} ${kindClass}`;
|
|
642
660
|
wrap.setAttribute('data-ezoic-after', String(afterPos));
|
|
643
661
|
wrap.setAttribute('data-ezoic-wrapid', String(id));
|
|
@@ -647,6 +665,7 @@ function globalGapFixInit() {
|
|
|
647
665
|
wrap.setAttribute('data-ezoic-pin', '1');
|
|
648
666
|
}
|
|
649
667
|
wrap.style.width = '100%';
|
|
668
|
+
try { if (wrap.tagName === 'LI') { wrap.style.listStyle = 'none'; wrap.setAttribute('data-ezoic-li','1'); } } catch(e) {}
|
|
650
669
|
|
|
651
670
|
if (createPlaceholder) {
|
|
652
671
|
const ph = document.createElement('div');
|
|
@@ -704,13 +723,144 @@ function globalGapFixInit() {
|
|
|
704
723
|
}
|
|
705
724
|
|
|
706
725
|
function pruneOrphanWraps(kindClass, items) {
|
|
726
|
+
// Topic pages can be virtualized (posts removed from DOM as you scroll).
|
|
727
|
+
// When that happens, previously-inserted ad wraps may become "orphan" nodes with no
|
|
728
|
+
// nearby post containers, which leads to ads clustering together when scrolling back up.
|
|
729
|
+
// We prune only *true* orphans that are far offscreen to keep the UI stable.
|
|
730
|
+
if (!items || !items.length) return 0;
|
|
731
|
+
const itemSet = new Set(items);
|
|
732
|
+
const wraps = document.querySelectorAll(`.${WRAP_CLASS}.${kindClass}`);
|
|
733
|
+
let removed = 0;
|
|
734
|
+
|
|
735
|
+
const isFilled = (wrap) => {
|
|
736
|
+
return !!(wrap.querySelector('iframe, ins, img, video, [data-google-container-id]'));
|
|
737
|
+
};
|
|
738
|
+
|
|
739
|
+
const hasNearbyItem = (wrap) => {
|
|
740
|
+
// NodeBB/skins can inject separators/spacers; be tolerant.
|
|
741
|
+
let prev = wrap.previousElementSibling;
|
|
742
|
+
for (let i = 0; i < 14 && prev; i++) {
|
|
743
|
+
if (itemSet.has(prev)) return true;
|
|
744
|
+
prev = prev.previousElementSibling;
|
|
745
|
+
}
|
|
746
|
+
let next = wrap.nextElementSibling;
|
|
747
|
+
for (let i = 0; i < 14 && next; i++) {
|
|
748
|
+
if (itemSet.has(next)) return true;
|
|
749
|
+
next = next.nextElementSibling;
|
|
750
|
+
}
|
|
751
|
+
return false;
|
|
752
|
+
};
|
|
753
|
+
|
|
754
|
+
wraps.forEach((wrap) => {
|
|
755
|
+
// Never prune pinned placements.
|
|
756
|
+
try {
|
|
757
|
+
if (wrap.getAttribute('data-ezoic-pin') === '1') return;
|
|
758
|
+
} catch (e) {}
|
|
759
|
+
|
|
760
|
+
// For message/topic pages we may prune filled or empty orphans if they are far away,
|
|
761
|
+
// otherwise consecutive "stacks" can appear when posts are virtualized.
|
|
762
|
+
const isMessage = (kindClass === 'ezoic-ad-message');
|
|
763
|
+
if (!isMessage && isFilled(wrap)) return; // never prune filled ads for non-message lists
|
|
764
|
+
|
|
765
|
+
// Never prune a fresh wrap: it may fill late.
|
|
766
|
+
try {
|
|
767
|
+
const created = parseInt(wrap.getAttribute('data-created') || '0', 10);
|
|
768
|
+
if (created && (now() - created) < keepEmptyWrapMs()) return;
|
|
769
|
+
} catch (e) {}
|
|
770
|
+
|
|
771
|
+
if (hasNearbyItem(wrap)) {
|
|
772
|
+
try { wrap.classList && wrap.classList.remove('ez-orphan-hidden'); wrap.style && (wrap.style.display = ''); } catch (e) {}
|
|
707
773
|
return;
|
|
708
774
|
}
|
|
709
775
|
|
|
710
|
-
|
|
711
|
-
|
|
776
|
+
// If the anchor item is no longer in the DOM (virtualized), hide the wrap so ads never "stack"
|
|
777
|
+
// back-to-back while scrolling. We'll recycle it when its anchor comes back.
|
|
778
|
+
try { wrap.classList && wrap.classList.add('ez-orphan-hidden'); wrap.style && (wrap.style.display = 'none'); } catch (e) {}
|
|
779
|
+
|
|
780
|
+
// For message ads: only release if far offscreen to avoid perceived "vanishing" during fast scroll.
|
|
781
|
+
if (isMessage) {
|
|
782
|
+
try {
|
|
783
|
+
const r = wrap.getBoundingClientRect();
|
|
784
|
+
const vh = Math.max(1, window.innerHeight || 1);
|
|
785
|
+
const farAbove = r.bottom < -vh * 2;
|
|
786
|
+
const farBelow = r.top > vh * 4;
|
|
787
|
+
if (!farAbove && !farBelow) return;
|
|
788
|
+
} catch (e) {
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
712
791
|
}
|
|
713
792
|
|
|
793
|
+
withInternalDomChange(() => releaseWrapNode(wrap));
|
|
794
|
+
removed++;
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
return removed;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
function decluster(kindClass) {
|
|
801
|
+
// Remove "near-consecutive" wraps (keep the first). Be tolerant of spacer nodes.
|
|
802
|
+
const wraps = Array.from(document.querySelectorAll(`.${WRAP_CLASS}.${kindClass}`));
|
|
803
|
+
if (wraps.length < 2) return 0;
|
|
804
|
+
|
|
805
|
+
const isWrap = (el) => !!(el && el.classList && el.classList.contains(WRAP_CLASS));
|
|
806
|
+
|
|
807
|
+
const isFilled = (wrap) => {
|
|
808
|
+
return !!(wrap && wrap.querySelector && wrap.querySelector('iframe, ins, img, video, [data-google-container-id]'));
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
const isFresh = (wrap) => {
|
|
812
|
+
try {
|
|
813
|
+
const created = parseInt(wrap.getAttribute('data-created') || '0', 10);
|
|
814
|
+
return created && (now() - created) < keepEmptyWrapMs();
|
|
815
|
+
} catch (e) {
|
|
816
|
+
return false;
|
|
817
|
+
}
|
|
818
|
+
};
|
|
819
|
+
|
|
820
|
+
let removed = 0;
|
|
821
|
+
for (const w of wraps) {
|
|
822
|
+
// Never decluster pinned placements.
|
|
823
|
+
try {
|
|
824
|
+
if (w.getAttribute && w.getAttribute('data-ezoic-pin') === '1') continue;
|
|
825
|
+
} catch (e) {}
|
|
826
|
+
|
|
827
|
+
let prev = w.previousElementSibling;
|
|
828
|
+
for (let i = 0; i < 3 && prev; i++) {
|
|
829
|
+
if (isWrap(prev)) {
|
|
830
|
+
// If the previous wrap is pinned, keep this one (spacing is intentional).
|
|
831
|
+
try {
|
|
832
|
+
if (prev.getAttribute && prev.getAttribute('data-ezoic-pin') === '1') break;
|
|
833
|
+
} catch (e) {}
|
|
834
|
+
|
|
835
|
+
// Never remove a wrap that is already filled; otherwise it looks like
|
|
836
|
+
// ads "disappear" while scrolling. Only remove the empty neighbour.
|
|
837
|
+
const prevFilled = isFilled(prev);
|
|
838
|
+
const curFilled = isFilled(w);
|
|
839
|
+
|
|
840
|
+
if (curFilled) {
|
|
841
|
+
// If the previous one is empty (and not fresh), drop the previous instead.
|
|
842
|
+
if (!prevFilled && !isFresh(prev)) {
|
|
843
|
+
withInternalDomChange(() => releaseWrapNode(prev));
|
|
844
|
+
removed++;
|
|
845
|
+
}
|
|
846
|
+
break;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
// Current is empty.
|
|
850
|
+
// Don't decluster two "fresh" empty wraps — it can reduce fill on slow auctions.
|
|
851
|
+
// Only decluster when previous is filled, or when current is stale.
|
|
852
|
+
if (prevFilled || !isFresh(w)) {
|
|
853
|
+
withInternalDomChange(() => releaseWrapNode(w));
|
|
854
|
+
removed++;
|
|
855
|
+
}
|
|
856
|
+
break;
|
|
857
|
+
}
|
|
858
|
+
prev = prev.previousElementSibling;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
return removed;
|
|
862
|
+
}
|
|
863
|
+
|
|
714
864
|
// ---------------- show (preload / fast fill) ----------------
|
|
715
865
|
|
|
716
866
|
function ensurePreloadObserver() {
|
|
@@ -1341,263 +1491,3 @@ function buildOrdinalMap(items) {
|
|
|
1341
1491
|
insertHeroAdEarly().catch(() => {});
|
|
1342
1492
|
requestBurst();
|
|
1343
1493
|
})();
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
// ===== CLEAN REFRACTOR: visibility manager for Ezoic wraps =====
|
|
1353
|
-
(function () {
|
|
1354
|
-
// v2.6 (slot-recycler):
|
|
1355
|
-
// Observed:
|
|
1356
|
-
// - When scrolling up, ad wraps accumulate before first post.
|
|
1357
|
-
// - Ezoic logs: "Placeholder Id X already defined" + "No valid placeholders for loadMore"
|
|
1358
|
-
//
|
|
1359
|
-
// Root cause:
|
|
1360
|
-
// - Infinite scroll / templating introduces MULTIPLE instances of the SAME placeholder id in DOM.
|
|
1361
|
-
// - Ezoic expects each placeholder id to be unique on the page. Duplicates cause warnings and loadMore failure.
|
|
1362
|
-
// - Some scripts then "re-home" the active slot near the top, causing pile-up.
|
|
1363
|
-
//
|
|
1364
|
-
// Fix strategy:
|
|
1365
|
-
// - Keep EXACTLY ONE DOM node per placeholder id ("canonical wrap").
|
|
1366
|
-
// - Replace any duplicate wraps with lightweight SLOT ANCHORS left in place.
|
|
1367
|
-
// - As user scrolls, MOVE the canonical wrap to the closest visible anchor for that id.
|
|
1368
|
-
// (Move, not recreate => no re-define; prevents pile-up; ad follows the viewport.)
|
|
1369
|
-
//
|
|
1370
|
-
// We only handle .nodebb-ezoic-wrap.* nodes; we do not change post markup.
|
|
1371
|
-
|
|
1372
|
-
var WRAP_SELECTOR = '.nodebb-ezoic-wrap';
|
|
1373
|
-
var PLACEHOLDER_SELECTOR = '[data-ezoic-id]';
|
|
1374
|
-
|
|
1375
|
-
// show tuning
|
|
1376
|
-
var MAX_SHOW_PER_TICK = 3;
|
|
1377
|
-
|
|
1378
|
-
// recycler tuning
|
|
1379
|
-
var ROOT_MARGIN = 1400; // how far from viewport we consider an anchor "active"
|
|
1380
|
-
var MOVE_COOLDOWN_MS = 120; // avoid moving too often
|
|
1381
|
-
var SCAN_COOLDOWN_MS = 150; // throttle scroll scans
|
|
1382
|
-
var lastScan = 0;
|
|
1383
|
-
var lastMove = 0;
|
|
1384
|
-
|
|
1385
|
-
// state
|
|
1386
|
-
var canonicalById = Object.create(null); // id -> element
|
|
1387
|
-
var activatedById = Object.create(null); // id -> ts
|
|
1388
|
-
var showQueue = [];
|
|
1389
|
-
var showTicking = false;
|
|
1390
|
-
|
|
1391
|
-
function getId(w) {
|
|
1392
|
-
try {
|
|
1393
|
-
var id = w.getAttribute('data-ezoic-wrapid');
|
|
1394
|
-
if (id) return id;
|
|
1395
|
-
var ph = w.querySelector(PLACEHOLDER_SELECTOR);
|
|
1396
|
-
if (ph) return ph.getAttribute('data-ezoic-id');
|
|
1397
|
-
} catch (e) {}
|
|
1398
|
-
return null;
|
|
1399
|
-
}
|
|
1400
|
-
|
|
1401
|
-
function isFilled(w) {
|
|
1402
|
-
try {
|
|
1403
|
-
if (w.querySelector('iframe')) return true;
|
|
1404
|
-
if (w.querySelector('[id^="google_ads_iframe"]')) return true;
|
|
1405
|
-
if (w.querySelector('.ezoic-ad')) return true;
|
|
1406
|
-
} catch (e) {}
|
|
1407
|
-
return false;
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
|
-
function enqueueShow(id) {
|
|
1411
|
-
if (!id) return;
|
|
1412
|
-
if (activatedById[id]) return;
|
|
1413
|
-
for (var i = 0; i < showQueue.length; i++) if (showQueue[i] === id) return;
|
|
1414
|
-
showQueue.push(id);
|
|
1415
|
-
scheduleShowTick();
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
function scheduleShowTick() {
|
|
1419
|
-
if (showTicking) return;
|
|
1420
|
-
showTicking = true;
|
|
1421
|
-
requestAnimationFrame(function () {
|
|
1422
|
-
showTicking = false;
|
|
1423
|
-
var n = 0;
|
|
1424
|
-
while (showQueue.length && n < MAX_SHOW_PER_TICK) {
|
|
1425
|
-
var id = showQueue.shift();
|
|
1426
|
-
try {
|
|
1427
|
-
if (!activatedById[id] && window.ezstandalone && typeof window.ezstandalone.showAds === 'function') {
|
|
1428
|
-
window.ezstandalone.showAds(String(id));
|
|
1429
|
-
activatedById[id] = Date.now();
|
|
1430
|
-
}
|
|
1431
|
-
} catch (e) {}
|
|
1432
|
-
n++;
|
|
1433
|
-
}
|
|
1434
|
-
if (showQueue.length) scheduleShowTick();
|
|
1435
|
-
});
|
|
1436
|
-
}
|
|
1437
|
-
|
|
1438
|
-
function createAnchorForDuplicate(w, id) {
|
|
1439
|
-
try {
|
|
1440
|
-
var a = document.createElement('span');
|
|
1441
|
-
a.className = 'nodebb-ezoic-slot-anchor';
|
|
1442
|
-
a.setAttribute('data-slot-for', String(id));
|
|
1443
|
-
// keep after/index metadata if present
|
|
1444
|
-
var after = w.getAttribute('data-ezoic-after');
|
|
1445
|
-
if (after) a.setAttribute('data-ezoic-after', after);
|
|
1446
|
-
a.style.display = 'block';
|
|
1447
|
-
a.style.width = '100%';
|
|
1448
|
-
// leave minimal height to keep spacing similar without large blank
|
|
1449
|
-
a.style.minHeight = '1px';
|
|
1450
|
-
w.parentNode.insertBefore(a, w);
|
|
1451
|
-
w.remove();
|
|
1452
|
-
} catch (e) {}
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1455
|
-
function normalizeDomOnce() {
|
|
1456
|
-
// Build canonical map; convert duplicates to anchors.
|
|
1457
|
-
try {
|
|
1458
|
-
var wraps = document.querySelectorAll(WRAP_SELECTOR);
|
|
1459
|
-
for (var i = 0; i < wraps.length; i++) {
|
|
1460
|
-
var w = wraps[i];
|
|
1461
|
-
var id = getId(w);
|
|
1462
|
-
if (!id) continue;
|
|
1463
|
-
|
|
1464
|
-
if (!canonicalById[id]) {
|
|
1465
|
-
canonicalById[id] = w;
|
|
1466
|
-
// if already filled, mark activated
|
|
1467
|
-
if (isFilled(w)) activatedById[id] = activatedById[id] || Date.now();
|
|
1468
|
-
} else if (canonicalById[id] !== w) {
|
|
1469
|
-
createAnchorForDuplicate(w, id);
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
} catch (e) {}
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
function getCandidateAnchors(id) {
|
|
1476
|
-
try {
|
|
1477
|
-
return document.querySelectorAll('.nodebb-ezoic-slot-anchor[data-slot-for="' + String(id) + '"]');
|
|
1478
|
-
} catch (e) {
|
|
1479
|
-
return [];
|
|
1480
|
-
}
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1483
|
-
function anchorDistanceToViewport(a, vh) {
|
|
1484
|
-
try {
|
|
1485
|
-
var r = a.getBoundingClientRect();
|
|
1486
|
-
// distance 0 if overlaps extended viewport, else min distance
|
|
1487
|
-
if (r.bottom >= -ROOT_MARGIN && r.top <= (vh + ROOT_MARGIN)) return 0;
|
|
1488
|
-
if (r.top > (vh + ROOT_MARGIN)) return r.top - (vh + ROOT_MARGIN);
|
|
1489
|
-
if (r.bottom < -ROOT_MARGIN) return (-ROOT_MARGIN) - r.bottom;
|
|
1490
|
-
} catch (e) {}
|
|
1491
|
-
return 1e12;
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
|
-
function moveCanonicalToAnchor(id, anchor) {
|
|
1495
|
-
var now = Date.now();
|
|
1496
|
-
if (now - lastMove < MOVE_COOLDOWN_MS) return;
|
|
1497
|
-
lastMove = now;
|
|
1498
|
-
|
|
1499
|
-
try {
|
|
1500
|
-
var w = canonicalById[id];
|
|
1501
|
-
if (!w || !anchor || !anchor.parentNode) return;
|
|
1502
|
-
|
|
1503
|
-
// If already directly after anchor, nothing to do.
|
|
1504
|
-
if (w.parentNode === anchor.parentNode && w.previousSibling === anchor) return;
|
|
1505
|
-
|
|
1506
|
-
// Insert canonical wrap right after anchor.
|
|
1507
|
-
if (anchor.nextSibling) anchor.parentNode.insertBefore(w, anchor.nextSibling);
|
|
1508
|
-
else anchor.parentNode.appendChild(w);
|
|
1509
|
-
} catch (e) {}
|
|
1510
|
-
}
|
|
1511
|
-
|
|
1512
|
-
function recycleTick() {
|
|
1513
|
-
var now = Date.now();
|
|
1514
|
-
if (now - lastScan < SCAN_COOLDOWN_MS) return;
|
|
1515
|
-
lastScan = now;
|
|
1516
|
-
|
|
1517
|
-
// ensure dom normalized before recycling
|
|
1518
|
-
normalizeDomOnce();
|
|
1519
|
-
|
|
1520
|
-
var vh = window.innerHeight || document.documentElement.clientHeight || 0;
|
|
1521
|
-
if (!vh) return;
|
|
1522
|
-
|
|
1523
|
-
try {
|
|
1524
|
-
for (var id in canonicalById) {
|
|
1525
|
-
if (!canonicalById[id]) continue;
|
|
1526
|
-
var anchors = getCandidateAnchors(id);
|
|
1527
|
-
if (!anchors || !anchors.length) continue;
|
|
1528
|
-
|
|
1529
|
-
// choose the first anchor that intersects extended viewport, otherwise closest
|
|
1530
|
-
var best = null;
|
|
1531
|
-
var bestDist = 1e12;
|
|
1532
|
-
for (var i = 0; i < anchors.length; i++) {
|
|
1533
|
-
var a = anchors[i];
|
|
1534
|
-
var d = anchorDistanceToViewport(a, vh);
|
|
1535
|
-
if (d === 0) { best = a; bestDist = 0; break; }
|
|
1536
|
-
if (d < bestDist) { bestDist = d; best = a; }
|
|
1537
|
-
}
|
|
1538
|
-
if (best) {
|
|
1539
|
-
moveCanonicalToAnchor(id, best);
|
|
1540
|
-
|
|
1541
|
-
// trigger show when canonical is near viewport and still empty
|
|
1542
|
-
var w = canonicalById[id];
|
|
1543
|
-
if (w) {
|
|
1544
|
-
try {
|
|
1545
|
-
var r = w.getBoundingClientRect();
|
|
1546
|
-
if (r.bottom >= -ROOT_MARGIN && r.top <= (vh + ROOT_MARGIN)) {
|
|
1547
|
-
if (isFilled(w)) activatedById[id] = activatedById[id] || Date.now();
|
|
1548
|
-
else enqueueShow(id);
|
|
1549
|
-
}
|
|
1550
|
-
} catch (e) {}
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
} catch (e) {}
|
|
1555
|
-
|
|
1556
|
-
scheduleShowTick();
|
|
1557
|
-
}
|
|
1558
|
-
|
|
1559
|
-
// Observe new content; normalize duplicates immediately
|
|
1560
|
-
var moInstalled = false;
|
|
1561
|
-
function installMO() {
|
|
1562
|
-
if (moInstalled || typeof MutationObserver === 'undefined') return;
|
|
1563
|
-
moInstalled = true;
|
|
1564
|
-
|
|
1565
|
-
var mo = new MutationObserver(function (muts) {
|
|
1566
|
-
// When new nodes arrive, normalize and run one recycle tick.
|
|
1567
|
-
normalizeDomOnce();
|
|
1568
|
-
recycleTick();
|
|
1569
|
-
});
|
|
1570
|
-
|
|
1571
|
-
try { mo.observe(document.documentElement || document.body, { childList: true, subtree: true }); } catch (e) {}
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
|
-
function init() {
|
|
1575
|
-
normalizeDomOnce();
|
|
1576
|
-
installMO();
|
|
1577
|
-
|
|
1578
|
-
window.addEventListener('scroll', recycleTick, { passive: true });
|
|
1579
|
-
window.addEventListener('resize', recycleTick, { passive: true });
|
|
1580
|
-
|
|
1581
|
-
if (window.jQuery) {
|
|
1582
|
-
window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', function () {
|
|
1583
|
-
setTimeout(function () {
|
|
1584
|
-
normalizeDomOnce();
|
|
1585
|
-
recycleTick();
|
|
1586
|
-
}, 0);
|
|
1587
|
-
});
|
|
1588
|
-
}
|
|
1589
|
-
|
|
1590
|
-
setInterval(recycleTick, 900);
|
|
1591
|
-
setTimeout(recycleTick, 0);
|
|
1592
|
-
}
|
|
1593
|
-
|
|
1594
|
-
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
|
|
1595
|
-
else init();
|
|
1596
|
-
})();
|
|
1597
|
-
// ===== /CLEAN REFRACTOR =====
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
package/public/style.css
CHANGED
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
|
|
84
|
-
/* =====
|
|
85
|
-
.nodebb-ezoic-wrap {
|
|
86
|
-
/* ===== /
|
|
84
|
+
/* ===== V12 between-as-li ===== */
|
|
85
|
+
li.nodebb-ezoic-wrap.ezoic-ad-between { list-style: none; width: 100%; }
|
|
86
|
+
/* ===== /V12 ===== */
|
|
87
87
|
|