nodebb-plugin-ezoic-infinite 1.0.8 → 1.0.11

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 +65 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.0.8",
3
+ "version": "1.0.11",
4
4
  "description": "Ezoic ads with infinite scroll using a pool of placeholder IDs",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
package/public/client.js CHANGED
@@ -111,21 +111,48 @@
111
111
  destroyPlaceholder(id);
112
112
  }
113
113
 
114
+ function showAdsOnceForElement(wrapperEl, id) {
115
+ if (!wrapperEl || !id) return;
116
+ if (wrapperEl.getAttribute('data-ezoic-shown') === '1') return;
117
+ wrapperEl.setAttribute('data-ezoic-shown', '1');
118
+ callShowAdsSingle(id);
119
+ }
120
+
114
121
  function callShowAdsSingle(id) {
115
122
  if (!id) return;
116
123
 
124
+ // Normalize id key
125
+ const key = String(id);
126
+
127
+ // Ensure we never call showAds twice for the same id within a short window
117
128
  const now = Date.now();
118
129
  window.__ezoicLastSingle = window.__ezoicLastSingle || {};
119
- const last = window.__ezoicLastSingle[id] || 0;
120
- if (now - last < 1200) return;
121
- window.__ezoicLastSingle[id] = now;
130
+ const last = window.__ezoicLastSingle[key] || 0;
131
+ if (now - last < 4000) return;
132
+
133
+ // If showAds is ready now, call once and exit (no cmd + no retry)
134
+ try {
135
+ window.ezstandalone = window.ezstandalone || {};
136
+ if (typeof window.ezstandalone.showAds === 'function') {
137
+ window.__ezoicLastSingle[key] = now;
138
+ window.ezstandalone.showAds(id);
139
+ return;
140
+ }
141
+ } catch (e) {}
142
+
143
+ // Otherwise: schedule a single pending call via cmd + retries until it succeeds
144
+ window.__ezoicPending = window.__ezoicPending || {};
145
+ if (window.__ezoicPending[key]) return;
146
+ window.__ezoicPending[key] = true;
122
147
 
123
148
  window.ezstandalone = window.ezstandalone || {};
124
149
  window.ezstandalone.cmd = window.ezstandalone.cmd || [];
125
150
 
126
- const run = function () {
151
+ const tryRun = function () {
127
152
  try {
128
153
  if (typeof window.ezstandalone.showAds === 'function') {
154
+ window.__ezoicLastSingle[key] = Date.now();
155
+ delete window.__ezoicPending[key];
129
156
  window.ezstandalone.showAds(id);
130
157
  return true;
131
158
  }
@@ -133,12 +160,17 @@
133
160
  return false;
134
161
  };
135
162
 
136
- window.ezstandalone.cmd.push(function () { run(); });
163
+ // When Ezoic finishes loading, it will drain cmd; run once there
164
+ window.ezstandalone.cmd.push(function () { tryRun(); });
137
165
 
166
+ // Retry a few times in case cmd doesn't fire (race conditions)
138
167
  let tries = 0;
139
168
  (function tick() {
140
169
  tries++;
141
- if (run() || tries >= 8) return;
170
+ if (tryRun() || tries >= 8) {
171
+ if (tries >= 8) delete window.__ezoicPending[key];
172
+ return;
173
+ }
142
174
  setTimeout(tick, 800);
143
175
  })();
144
176
  }
@@ -170,6 +202,7 @@
170
202
  wrap.setAttribute('data-ezoic-after', String(afterVal));
171
203
  wrap.innerHTML = '<div class="ezoic-ad-inner"><div id="ezoic-pub-ad-placeholder-' + id + '"></div></div>';
172
204
  targetEl.insertAdjacentElement('afterend', wrap);
205
+ return wrap;
173
206
  }
174
207
 
175
208
  function injectBetweenTopics(cfg) {
@@ -198,8 +231,8 @@
198
231
  usedBetween.add(id);
199
232
  fifoBetween.push({ id, after: pos });
200
233
 
201
- insertAfter(li, id, 'ezoic-ad-between', pos);
202
- callShowAdsSingle(id);
234
+ const wrap = insertAfter(li, id, 'ezoic-ad-between', pos);
235
+ showAdsOnceForElement(wrap, id);
203
236
  });
204
237
  }
205
238
 
@@ -229,8 +262,8 @@
229
262
  usedMessage.add(id);
230
263
  fifoMessage.push({ id, after: no });
231
264
 
232
- insertAfter(post, id, 'ezoic-ad-message', no);
233
- callShowAdsSingle(id);
265
+ const wrap = insertAfter(post, id, 'ezoic-ad-message', no);
266
+ showAdsOnceForElement(wrap, id);
234
267
  });
235
268
  }
236
269
 
@@ -243,13 +276,27 @@
243
276
  if (pageKey !== key) {
244
277
  pageKey = key;
245
278
  cleanupForNewPage();
279
+ window.__ezoicCatRetry = 0;
246
280
  }
247
281
 
248
282
  const cfg = await fetchConfig();
249
283
  if (!cfg || cfg.excluded) return;
250
284
 
251
- if (isTopicPage()) injectBetweenMessages(cfg);
252
- else if (isCategoryTopicList()) injectBetweenTopics(cfg);
285
+ if (isTopicPage()) {
286
+ injectBetweenMessages(cfg);
287
+ } else {
288
+ // category/topic list pages may render after ajaxify end; retry a few times
289
+ const hasList = document.querySelectorAll('li[component="category/topic"]').length > 0;
290
+ if (hasList) {
291
+ injectBetweenTopics(cfg);
292
+ } else {
293
+ window.__ezoicCatRetry = window.__ezoicCatRetry || 0;
294
+ if (window.__ezoicCatRetry < 20) {
295
+ window.__ezoicCatRetry++;
296
+ setTimeout(run, 250);
297
+ }
298
+ }
299
+ }
253
300
  } catch (e) {
254
301
  // silent
255
302
  } finally {
@@ -271,7 +318,7 @@ function bindNodeBBEvents() {
271
318
  if (window.jQuery) {
272
319
  const $w = window.jQuery(window);
273
320
  $w.off('.ezoicInfinite');
274
- $w.on('action:ajaxify.end.ezoicInfinite', scheduleRun);
321
+ $w.on('action:ajaxify.end.ezoicInfinite', function(){ scheduleRun(); setTimeout(scheduleRun, 600); });
275
322
  $w.on('action:posts.loaded.ezoicInfinite', scheduleRun);
276
323
  $w.on('action:topic.loaded.ezoicInfinite', scheduleRun);
277
324
  $w.on('action:topics.loaded.ezoicInfinite', scheduleRun);
@@ -279,6 +326,7 @@ function bindNodeBBEvents() {
279
326
  $w.on('action:ajaxify.start.ezoicInfinite', function () {
280
327
  pageKey = null;
281
328
  cleanupForNewPage();
329
+ window.__ezoicCatRetry = 0;
282
330
  });
283
331
  }
284
332
  }
@@ -287,7 +335,10 @@ function bindNodeBBEvents() {
287
335
 
288
336
  // Run immediately, so it works on first ajaxify navigation too
289
337
  run();
290
- setTimeout(run, 1200);
338
+ setTimeout(function(){
339
+ // only retry if nothing was injected yet
340
+ if (!document.querySelector('.ezoic-ad')) run();
341
+ }, 1400);
291
342
 
292
343
  // Also run on hard-refresh initial load
293
344
  if (document.readyState === 'loading') {