nodebb-plugin-ezoic-infinite 0.5.3 → 0.5.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
CHANGED
package/public/client.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/* globals ajaxify */
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
window.ezoicInfiniteLoaded = true;
|
|
5
|
+
|
|
4
6
|
let cachedConfig;
|
|
5
7
|
let lastFetch = 0;
|
|
6
8
|
let debounceTimer;
|
|
@@ -23,17 +25,27 @@ function parsePool(raw) {
|
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
function getTopicPosts() {
|
|
26
|
-
const $
|
|
27
|
-
if ($
|
|
28
|
+
const $primary = $('[component="post"][data-pid]');
|
|
29
|
+
if ($primary.length) return $primary.not('.ezoic-ad-post');
|
|
30
|
+
|
|
31
|
+
const $top = $('[data-pid]').filter(function () {
|
|
32
|
+
const $el = $(this);
|
|
33
|
+
const hasContent = $el.find('[component="post/content"]').length > 0;
|
|
34
|
+
const nested = $el.parents('[data-pid]').length > 0;
|
|
35
|
+
return hasContent && !nested;
|
|
36
|
+
});
|
|
37
|
+
if ($top.length) return $top.not('.ezoic-ad-post');
|
|
38
|
+
|
|
28
39
|
return $('.posts .post').not('.ezoic-ad-post');
|
|
29
40
|
}
|
|
30
41
|
|
|
31
|
-
function
|
|
32
|
-
return ($el && $el.length
|
|
42
|
+
function tagName($el) {
|
|
43
|
+
return ($el && $el.length ? (($el.prop('tagName') || '').toUpperCase()) : '');
|
|
33
44
|
}
|
|
34
45
|
|
|
46
|
+
// Remove *all* nodes with a given id (duplicates are possible if misconfigured)
|
|
35
47
|
function removePlaceholdersByPool(pool) {
|
|
36
|
-
pool.forEach(id => $('
|
|
48
|
+
pool.forEach(id => $('[id="ezoic-pub-ad-placeholder-' + id + '"]').remove());
|
|
37
49
|
}
|
|
38
50
|
|
|
39
51
|
function removeAdWrappers() {
|
|
@@ -50,77 +62,70 @@ function computeWindowSlots(totalItems, interval, poolSize) {
|
|
|
50
62
|
return out;
|
|
51
63
|
}
|
|
52
64
|
|
|
53
|
-
function
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
'<div id="ezoic-pub-ad-placeholder-' + placeholderId + '"></div>' +
|
|
58
|
-
'</li>'
|
|
59
|
-
);
|
|
65
|
+
function makeWrapperLike($target, classes, innerHtml) {
|
|
66
|
+
const t = tagName($target);
|
|
67
|
+
if (t === 'LI') {
|
|
68
|
+
return '<li class="' + classes + ' list-unstyled" data-ezoic-ad="1">' + innerHtml + '</li>';
|
|
60
69
|
}
|
|
61
|
-
return '<div class="ezoic-ad
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function makeAdMessageWrapper($targetPost, placeholderId) {
|
|
65
|
-
if (isLi($targetPost)) {
|
|
66
|
-
return (
|
|
67
|
-
'<li class="post ezoic-ad-post" data-ezoic-ad="1">' +
|
|
68
|
-
'<div class="content">' +
|
|
69
|
-
'<div id="ezoic-pub-ad-placeholder-' + placeholderId + '"></div>' +
|
|
70
|
-
'</div>' +
|
|
71
|
-
'</li>'
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return (
|
|
76
|
-
'<div class="post ezoic-ad-post" data-ezoic-ad="1">' +
|
|
77
|
-
'<div class="content">' +
|
|
78
|
-
'<div id="ezoic-pub-ad-placeholder-' + placeholderId + '"></div>' +
|
|
79
|
-
'</div>' +
|
|
80
|
-
'</div>'
|
|
81
|
-
);
|
|
70
|
+
return '<div class="' + classes + '" data-ezoic-ad="1">' + innerHtml + '</div>';
|
|
82
71
|
}
|
|
83
72
|
|
|
84
|
-
function insertBetweenPosts($posts,
|
|
73
|
+
function insertBetweenPosts($posts, ids, interval) {
|
|
85
74
|
const total = $posts.length;
|
|
86
|
-
const slotsToRender = computeWindowSlots(total, interval,
|
|
75
|
+
const slotsToRender = computeWindowSlots(total, interval, ids.length);
|
|
87
76
|
if (!slotsToRender.length) return [];
|
|
88
77
|
|
|
89
78
|
const activeIds = [];
|
|
90
79
|
for (let i = 0; i < slotsToRender.length; i++) {
|
|
91
80
|
const slotNumber = slotsToRender[i];
|
|
92
|
-
const id =
|
|
81
|
+
const id = ids[i];
|
|
93
82
|
const index = slotNumber * interval - 1;
|
|
94
83
|
const $target = $posts.eq(index);
|
|
95
84
|
if (!$target.length) continue;
|
|
96
85
|
|
|
97
|
-
|
|
86
|
+
const html = makeWrapperLike($target, 'ezoic-ad-between', '<div id="ezoic-pub-ad-placeholder-' + id + '"></div>');
|
|
87
|
+
$target.after(html);
|
|
98
88
|
activeIds.push(id);
|
|
99
89
|
}
|
|
100
90
|
return activeIds;
|
|
101
91
|
}
|
|
102
92
|
|
|
103
|
-
function insertAdMessagesBetweenReplies($posts,
|
|
93
|
+
function insertAdMessagesBetweenReplies($posts, ids, interval) {
|
|
104
94
|
const total = $posts.length;
|
|
105
|
-
const slotsToRender = computeWindowSlots(total, interval,
|
|
95
|
+
const slotsToRender = computeWindowSlots(total, interval, ids.length);
|
|
106
96
|
if (!slotsToRender.length) return [];
|
|
107
97
|
|
|
108
98
|
const activeIds = [];
|
|
109
99
|
for (let i = 0; i < slotsToRender.length; i++) {
|
|
110
100
|
const slotNumber = slotsToRender[i];
|
|
111
|
-
const id =
|
|
101
|
+
const id = ids[i];
|
|
112
102
|
const index = slotNumber * interval - 1;
|
|
113
103
|
const $target = $posts.eq(index);
|
|
114
104
|
if (!$target.length) continue;
|
|
115
105
|
|
|
116
|
-
|
|
106
|
+
const inner = '<div class="content"><div id="ezoic-pub-ad-placeholder-' + id + '"></div></div>';
|
|
107
|
+
const html = makeWrapperLike($target, 'post ezoic-ad-post', inner);
|
|
108
|
+
$target.after(html);
|
|
117
109
|
activeIds.push(id);
|
|
118
110
|
}
|
|
119
111
|
return activeIds;
|
|
120
112
|
}
|
|
121
113
|
|
|
114
|
+
function uniqueConcat(a, b) {
|
|
115
|
+
const seen = new Set();
|
|
116
|
+
const out = [];
|
|
117
|
+
[...a, ...b].forEach((x) => {
|
|
118
|
+
if (!seen.has(x)) {
|
|
119
|
+
seen.add(x);
|
|
120
|
+
out.push(x);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
|
|
122
126
|
async function refreshAds() {
|
|
123
|
-
|
|
127
|
+
let cfg;
|
|
128
|
+
try { cfg = await fetchConfig(); } catch (e) { return; }
|
|
124
129
|
if (!cfg || cfg.excluded) return;
|
|
125
130
|
|
|
126
131
|
const betweenPool = parsePool(cfg.placeholderIds);
|
|
@@ -132,32 +137,48 @@ async function refreshAds() {
|
|
|
132
137
|
const $posts = getTopicPosts();
|
|
133
138
|
if (!$posts.length) return;
|
|
134
139
|
|
|
140
|
+
// Clean first (remove wrappers + any placeholders, even duplicates)
|
|
135
141
|
removeAdWrappers();
|
|
136
|
-
removePlaceholdersByPool(betweenPool);
|
|
137
|
-
|
|
142
|
+
removePlaceholdersByPool(uniqueConcat(betweenPool, messagePool));
|
|
143
|
+
|
|
144
|
+
// IMPORTANT:
|
|
145
|
+
// IDs must be UNIQUE on the page. If admin reuses the same IDs for both pools,
|
|
146
|
+
// we allocate unique IDs across "between posts" and "message ads" to avoid duplicates.
|
|
147
|
+
const combinedUnique = uniqueConcat(betweenPool, messagePool);
|
|
138
148
|
|
|
139
149
|
const activeIds = [];
|
|
150
|
+
let cursor = 0;
|
|
140
151
|
|
|
141
152
|
if (cfg.enableBetweenAds && betweenPool.length) {
|
|
142
|
-
|
|
153
|
+
const idsForBetween = combinedUnique.slice(cursor, cursor + betweenPool.length);
|
|
154
|
+
cursor += idsForBetween.length;
|
|
155
|
+
activeIds.push(...insertBetweenPosts($posts, idsForBetween, betweenInterval));
|
|
143
156
|
}
|
|
144
157
|
|
|
145
158
|
if (cfg.enableMessageAds && messagePool.length) {
|
|
146
|
-
|
|
159
|
+
const idsForMessage = combinedUnique.slice(cursor, cursor + messagePool.length);
|
|
160
|
+
cursor += idsForMessage.length;
|
|
161
|
+
activeIds.push(...insertAdMessagesBetweenReplies($posts, idsForMessage, messageInterval));
|
|
147
162
|
}
|
|
148
163
|
|
|
164
|
+
// Ezoic render
|
|
149
165
|
if (activeIds.length && window.ezstandalone && typeof window.ezstandalone.destroyPlaceholders === 'function') {
|
|
150
166
|
try { window.ezstandalone.destroyPlaceholders(); } catch (e) {}
|
|
151
167
|
}
|
|
152
168
|
activeIds.forEach(id => {
|
|
153
|
-
try {
|
|
169
|
+
try {
|
|
170
|
+
if (window.ezstandalone && typeof window.ezstandalone.showAds === 'function') {
|
|
171
|
+
window.ezstandalone.showAds(id);
|
|
172
|
+
}
|
|
173
|
+
} catch (e) {}
|
|
154
174
|
});
|
|
155
175
|
}
|
|
156
176
|
|
|
157
177
|
function debounceRefresh() {
|
|
158
178
|
clearTimeout(debounceTimer);
|
|
159
|
-
debounceTimer = setTimeout(refreshAds,
|
|
179
|
+
debounceTimer = setTimeout(refreshAds, 150);
|
|
160
180
|
}
|
|
161
181
|
|
|
182
|
+
$(document).ready(debounceRefresh);
|
|
162
183
|
$(window).on('action:ajaxify.end action:posts.loaded action:topic.loaded', debounceRefresh);
|
|
163
|
-
setTimeout(debounceRefresh,
|
|
184
|
+
setTimeout(debounceRefresh, 1500);
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
<div class="mb-3">
|
|
34
34
|
<label class="form-label" for="messagePlaceholderIds">Pool d’IDs Ezoic (message)</label>
|
|
35
35
|
<textarea id="messagePlaceholderIds" name="messagePlaceholderIds" class="form-control" rows="4">{messagePlaceholderIds}</textarea>
|
|
36
|
-
<p class="form-text">Pool séparé recommandé pour éviter la réutilisation d’IDs.</p>
|
|
36
|
+
<p class="form-text">Pool séparé recommandé pour éviter la réutilisation d’IDs. IMPORTANT : ne réutilise pas les mêmes IDs dans les deux pools.</p>
|
|
37
37
|
</div>
|
|
38
38
|
|
|
39
39
|
<div class="mb-3">
|