nodebb-plugin-ezoic-infinite 1.6.53 → 1.6.55
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 +59 -66
- package/public/style.css +12 -0
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -1,30 +1,16 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
// --- 1.
|
|
5
|
-
let lastScrollY = 0;
|
|
6
|
-
let scrollDir = 1;
|
|
7
|
-
try {
|
|
8
|
-
lastScrollY = window.scrollY || 0;
|
|
9
|
-
window.addEventListener('scroll', () => {
|
|
10
|
-
const y = window.scrollY || 0;
|
|
11
|
-
const d = y - lastScrollY;
|
|
12
|
-
if (Math.abs(d) > 4) {
|
|
13
|
-
scrollDir = d > 0 ? 1 : -1;
|
|
14
|
-
lastScrollY = y;
|
|
15
|
-
}
|
|
16
|
-
}, { passive: true });
|
|
17
|
-
} catch (e) {}
|
|
18
|
-
|
|
4
|
+
// --- 1. VARIABLES ET CONFIG ---
|
|
19
5
|
const WRAP_CLASS = 'nodebb-ezoic-wrap';
|
|
20
|
-
const PLACEHOLDER_PREFIX = 'ezoic-pub-ad-placeholder-';
|
|
21
6
|
const PINNED_ATTR = 'data-ezoic-pinned';
|
|
22
|
-
|
|
7
|
+
const PLACEHOLDER_PREFIX = 'ezoic-pub-ad-placeholder-';
|
|
8
|
+
|
|
23
9
|
let config = null;
|
|
24
10
|
let usedIds = new Set();
|
|
25
11
|
let scheduleTimer = null;
|
|
26
12
|
|
|
27
|
-
// --- 2. SÉLECTEURS DE THÈMES
|
|
13
|
+
// --- 2. SÉLECTEURS DE THÈMES ---
|
|
28
14
|
function getTopicList() {
|
|
29
15
|
return document.querySelector('.category [component="category"], .categories [component="categories"], [component="topic/list"], .topic-list');
|
|
30
16
|
}
|
|
@@ -33,28 +19,7 @@
|
|
|
33
19
|
return document.querySelector('[component="topic"], [component="post/list"]');
|
|
34
20
|
}
|
|
35
21
|
|
|
36
|
-
// --- 3.
|
|
37
|
-
function pruneOrphans(ul) {
|
|
38
|
-
if (!ul) return;
|
|
39
|
-
const wraps = ul.querySelectorAll('.' + WRAP_CLASS);
|
|
40
|
-
wraps.forEach(wrap => {
|
|
41
|
-
// Si c'est la pub après le 1er sujet, on la force à rester collée au 1er LI
|
|
42
|
-
if (wrap.getAttribute(PINNED_ATTR) === 'true') {
|
|
43
|
-
const firstLi = ul.querySelector('li[data-tid], li:first-child');
|
|
44
|
-
if (firstLi && wrap.previousElementSibling !== firstLi) {
|
|
45
|
-
firstLi.after(wrap);
|
|
46
|
-
}
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
// Si on remonte, on supprime les pubs qui perdent leur "ancre" (le LI précédent)
|
|
50
|
-
// NodeBB détruit les LI du haut pour la performance, on doit suivre le mouvement
|
|
51
|
-
if (scrollDir === -1 && (!wrap.previousElementSibling || wrap.previousElementSibling.tagName !== 'LI')) {
|
|
52
|
-
wrap.remove();
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// --- 4. LOGIQUE EZOIC (Pools & Refresh) ---
|
|
22
|
+
// --- 3. LOGIQUE DES POOLS D'ID ---
|
|
58
23
|
function getNextId(poolStr) {
|
|
59
24
|
if (!poolStr) return null;
|
|
60
25
|
const ids = poolStr.split(/[\s,]+/).filter(Boolean);
|
|
@@ -68,6 +33,7 @@
|
|
|
68
33
|
return null;
|
|
69
34
|
}
|
|
70
35
|
|
|
36
|
+
// --- 4. APPEL EZOIC (REFRESH & SHOW) ---
|
|
71
37
|
function callEzoic(id) {
|
|
72
38
|
if (window.ezstandalone) {
|
|
73
39
|
try {
|
|
@@ -83,27 +49,34 @@
|
|
|
83
49
|
}
|
|
84
50
|
}
|
|
85
51
|
|
|
86
|
-
// --- 5. INJECTION ---
|
|
52
|
+
// --- 5. INJECTION SÉCURISÉE (ANTI-PILEUP) ---
|
|
87
53
|
function inject() {
|
|
88
54
|
if (!config || config.excluded) return;
|
|
89
55
|
|
|
90
|
-
// A.
|
|
56
|
+
// A. LISTE DES SUJETS (Topics)
|
|
91
57
|
const ul = getTopicList();
|
|
92
58
|
if (ul && config.enableBetweenAds) {
|
|
93
|
-
|
|
59
|
+
// Nettoyage des pubs orphelines (celles qui n'ont plus de LI au dessus à cause du scroll up)
|
|
60
|
+
const wraps = ul.querySelectorAll('.' + WRAP_CLASS);
|
|
61
|
+
wraps.forEach(w => {
|
|
62
|
+
if (!w.previousElementSibling || w.previousElementSibling.tagName !== 'LI') w.remove();
|
|
63
|
+
});
|
|
64
|
+
|
|
94
65
|
const items = Array.from(ul.children).filter(c => c.tagName === 'LI' && !c.classList.contains(WRAP_CLASS));
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
66
|
+
if (items.length > 0) {
|
|
67
|
+
// Pub n°1 (Pinned)
|
|
68
|
+
if (config.showFirstTopicAd && !ul.querySelector(`[${PINNED_ATTR}="true"]`)) {
|
|
69
|
+
insertAd(items[0], getNextId(config.placeholderIds), true);
|
|
70
|
+
}
|
|
100
71
|
|
|
101
|
-
|
|
102
|
-
if (scrollDir === 1) {
|
|
72
|
+
// Pubs d'intervalles
|
|
103
73
|
const interval = parseInt(config.intervalPosts, 10) || 5;
|
|
104
74
|
items.forEach((li, idx) => {
|
|
105
|
-
|
|
106
|
-
|
|
75
|
+
const pos = idx + 1;
|
|
76
|
+
if (pos > 1 && pos % interval === 0) {
|
|
77
|
+
// Vérifie si ce LI a déjà une pub juste après lui pour éviter les doublons
|
|
78
|
+
const next = li.nextElementSibling;
|
|
79
|
+
if (!next || !next.classList.contains(WRAP_CLASS)) {
|
|
107
80
|
insertAd(li, getNextId(config.placeholderIds), false);
|
|
108
81
|
}
|
|
109
82
|
}
|
|
@@ -111,14 +84,25 @@
|
|
|
111
84
|
}
|
|
112
85
|
}
|
|
113
86
|
|
|
114
|
-
// B.
|
|
87
|
+
// B. LISTE DES MESSAGES (Posts)
|
|
115
88
|
const postList = getPostList();
|
|
116
89
|
if (postList && config.enableMessageAds) {
|
|
117
|
-
const posts = Array.from(postList.querySelectorAll('[component="post"]'))
|
|
90
|
+
const posts = Array.from(postList.querySelectorAll('[component="post"]'));
|
|
118
91
|
if (config.showFirstMessageAd && posts.length > 0 && !postList.querySelector('.ezoic-msg-first')) {
|
|
119
92
|
insertAd(posts[0], getNextId(config.messagePlaceholderIds), false, 'ezoic-msg-first');
|
|
120
93
|
}
|
|
121
|
-
|
|
94
|
+
|
|
95
|
+
const msgInterval = parseInt(config.messageIntervalPosts, 10) || 5;
|
|
96
|
+
if (msgInterval > 0) {
|
|
97
|
+
posts.forEach((post, idx) => {
|
|
98
|
+
const pPos = idx + 1;
|
|
99
|
+
if (pPos > 1 && pPos % msgInterval === 0) {
|
|
100
|
+
if (!post.nextElementSibling || !post.nextElementSibling.classList.contains(WRAP_CLASS)) {
|
|
101
|
+
insertAd(post, getNextId(config.messagePlaceholderIds), false);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
122
106
|
}
|
|
123
107
|
}
|
|
124
108
|
|
|
@@ -133,36 +117,45 @@
|
|
|
133
117
|
wrap.appendChild(placeholder);
|
|
134
118
|
|
|
135
119
|
target.after(wrap);
|
|
136
|
-
|
|
120
|
+
|
|
121
|
+
// On laisse le DOM respirer 50ms avant d'appeler Ezoic
|
|
122
|
+
setTimeout(() => callEzoic(id), 50);
|
|
137
123
|
}
|
|
138
124
|
|
|
139
|
-
// --- 6. INITIALISATION ---
|
|
125
|
+
// --- 6. INITIALISATION ET HOOKS ---
|
|
140
126
|
async function fetchConfig() {
|
|
141
127
|
try {
|
|
142
128
|
const res = await fetch('/api/plugins/ezoic-infinite/config');
|
|
143
129
|
config = await res.json();
|
|
144
|
-
} catch (e) {}
|
|
130
|
+
} catch (e) { console.error('[ezoic] config fetch failed'); }
|
|
145
131
|
}
|
|
146
132
|
|
|
147
133
|
function schedule() {
|
|
148
134
|
if (scheduleTimer) clearTimeout(scheduleTimer);
|
|
149
|
-
scheduleTimer = setTimeout(inject,
|
|
135
|
+
scheduleTimer = setTimeout(inject, 250);
|
|
150
136
|
}
|
|
151
137
|
|
|
152
138
|
function init() {
|
|
153
139
|
fetchConfig().then(() => {
|
|
154
140
|
schedule();
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
141
|
+
|
|
142
|
+
// MutationObserver pour le scroll infini
|
|
143
|
+
const body = document.body;
|
|
144
|
+
const mo = new MutationObserver((mutations) => {
|
|
145
|
+
for (let m of mutations) {
|
|
146
|
+
if (m.addedNodes.length > 0) {
|
|
147
|
+
schedule();
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
mo.observe(body, { childList: true, subtree: true });
|
|
161
153
|
});
|
|
162
154
|
|
|
155
|
+
// Compatibilité jQuery/NodeBB Events
|
|
163
156
|
if (window.jQuery) {
|
|
164
157
|
window.jQuery(window).on('action:ajaxify.end action:infiniteScroll.loaded', () => {
|
|
165
|
-
setTimeout(schedule,
|
|
158
|
+
setTimeout(schedule, 500);
|
|
166
159
|
});
|
|
167
160
|
}
|
|
168
161
|
}
|
package/public/style.css
CHANGED
|
@@ -86,3 +86,15 @@ li.nodebb-ezoic-host { list-style: none; width: 100%; display: block; }
|
|
|
86
86
|
li.nodebb-ezoic-host > .nodebb-ezoic-wrap.ezoic-ad-between { width: 100%; display: block; }
|
|
87
87
|
/* ===== /V17 ===== */
|
|
88
88
|
|
|
89
|
+
.nodebb-ezoic-wrap {
|
|
90
|
+
display: block;
|
|
91
|
+
width: 100%;
|
|
92
|
+
clear: both;
|
|
93
|
+
margin: 20px 0 !important; /* Ajoute un peu d'espace pour le visuel */
|
|
94
|
+
min-height: 50px; /* Évite que le bloc ne soit écrasé à 0px */
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Si la pub est vide, on garde un petit espace pour éviter le saut au scroll up */
|
|
98
|
+
.nodebb-ezoic-wrap:empty {
|
|
99
|
+
min-height: 1px;
|
|
100
|
+
}
|