nodebb-plugin-ezoic-infinite 1.6.94 → 1.6.95

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 +73 -73
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-ezoic-infinite",
3
- "version": "1.6.94",
3
+ "version": "1.6.95",
4
4
  "description": "Production-ready Ezoic infinite ads integration for NodeBB 4.x",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
package/public/client.js CHANGED
@@ -5,76 +5,83 @@
5
5
  window.ezInfiniteInjected = true;
6
6
 
7
7
  const WRAP_CLASS = 'nodebb-ezoic-wrap';
8
+ const POOL_ID = 'nodebb-ezoic-placeholder-pool';
8
9
  let config = null;
9
10
  let isInternalChange = false;
10
- let triggerTimer = null;
11
11
 
12
- // On récupère les IDs déjà présents dans la page (générés par ton intégration de base)
13
- // pour éviter de tenter de les redéfinir.
14
- function redistribute() {
15
- if (!config || config.excluded) return;
16
-
17
- const selectors = {
18
- 'home': '.category-item, [component="categories/category"]',
19
- 'topic-list': 'li[component="category/topic"]',
20
- 'message': '[component="post"]'
21
- };
22
-
23
- if (config.enableCategoryAds) {
24
- process(Array.from(document.querySelectorAll(selectors.home)), 'home', config.intervalCategories, config.showFirstCategoryAd);
25
- }
26
- if (config.enableBetweenAds) {
27
- process(Array.from(document.querySelectorAll(selectors['topic-list'])), 'topic-list', config.intervalPosts, config.showFirstTopicAd);
28
- }
29
- if (config.enableMessageAds) {
30
- process(Array.from(document.querySelectorAll(selectors.message)), 'message', config.messageIntervalPosts, config.showFirstMessageAd);
12
+ function getPool() {
13
+ let p = document.getElementById(POOL_ID);
14
+ if (!p) {
15
+ p = document.createElement('div');
16
+ p.id = POOL_ID;
17
+ p.style.display = 'none';
18
+ document.body.appendChild(p);
31
19
  }
20
+ return p;
32
21
  }
33
22
 
34
- function process(items, kind, interval, showFirst) {
35
- const int = parseInt(interval, 10) || 10;
36
- const pool = document.getElementById('nodebb-ezoic-placeholder-pool');
37
- if (!pool) return;
38
-
39
- items.forEach((item, index) => {
40
- const pos = index + 1;
41
- const shouldHaveAd = (pos === 1 && showFirst) || (pos % int === 0);
42
- const next = item.nextElementSibling;
23
+ // Cette fonction force Ezoic à remplir le placeholder
24
+ function forceFillAd(id) {
25
+ if (typeof window.ezstandalone === 'undefined') return;
43
26
 
44
- // Si on doit mettre une pub et qu'il n'y en a pas déjà une après cet élément
45
- if (shouldHaveAd && !(next && next.classList.contains(WRAP_CLASS))) {
46
- const available = pool.querySelector(`.${WRAP_CLASS}[data-kind="${kind}"]`);
47
-
48
- if (available) {
49
- isInternalChange = true;
50
- item.parentNode.insertBefore(available, item.nextSibling);
51
-
52
- const placeholderId = available.getAttribute('data-placeholder-id');
53
- refreshAd(placeholderId);
54
-
55
- setTimeout(() => { isInternalChange = false; }, 50);
27
+ window.ezstandalone.cmd.push(function() {
28
+ // 1. On s'assure que l'ID est bien dans la liste d'Ezoic
29
+ window.ezstandalone.define(parseInt(id, 10));
30
+
31
+ // 2. On attend un micro-délai pour que le DOM soit stable
32
+ setTimeout(() => {
33
+ try {
34
+ // La doc précise que showAds avec IDs est le mode "Dynamic"
35
+ window.ezstandalone.showAds(parseInt(id, 10));
36
+ // On force un rafraîchissement spécifique si showAds ne suffit pas
37
+ if (window.ezstandalone.refresh) {
38
+ window.ezstandalone.refresh(parseInt(id, 10));
39
+ }
40
+ } catch (e) {
41
+ console.warn('[Ezoic] Fill failed for', id, e);
56
42
  }
57
- }
43
+ }, 200);
58
44
  });
59
45
  }
60
46
 
61
- function refreshAd(id) {
62
- if (typeof window.ezstandalone === 'undefined') return;
47
+ function redistribute() {
48
+ if (!config || config.excluded) return;
63
49
 
64
- clearTimeout(triggerTimer);
65
- triggerTimer = setTimeout(() => {
66
- window.ezstandalone.cmd.push(function() {
67
- // Au lieu de define(), on utilise simplement showAds()
68
- // Ezoic va détecter que le div avec cet ID a bougé et va le remplir.
69
- try {
70
- // On force l'affichage de cet ID spécifique
71
- window.ezstandalone.showAds(parseInt(id, 10));
72
- console.debug('[Ezoic] Displaying ID:', id);
73
- } catch (e) {
74
- console.error('[Ezoic] Error showing ID:', id, e);
50
+ const selectors = {
51
+ 'home': '.category-item, [component="categories/category"]',
52
+ 'topic-list': 'li[component="category/topic"]',
53
+ 'message': '[component="post"]'
54
+ };
55
+
56
+ const process = (items, kind, interval, showFirst) => {
57
+ const int = parseInt(interval, 10) || 10;
58
+ const pool = getPool();
59
+
60
+ items.forEach((item, index) => {
61
+ const pos = index + 1;
62
+ const shouldHaveAd = (pos === 1 && showFirst) || (pos % int === 0);
63
+ const next = item.nextElementSibling;
64
+
65
+ if (shouldHaveAd && !(next && next.classList.contains(WRAP_CLASS))) {
66
+ const available = pool.querySelector(`.${WRAP_CLASS}[data-kind="${kind}"]`);
67
+ if (available) {
68
+ isInternalChange = true;
69
+ // On insère l'élément
70
+ item.parentNode.insertBefore(available, item.nextSibling);
71
+
72
+ // On déclenche le remplissage publicitaire
73
+ const pid = available.getAttribute('data-placeholder-id');
74
+ forceFillAd(pid);
75
+
76
+ setTimeout(() => { isInternalChange = false; }, 50);
77
+ }
75
78
  }
76
79
  });
77
- }, 100);
80
+ };
81
+
82
+ if (config.enableCategoryAds) process(Array.from(document.querySelectorAll(selectors.home)), 'home', config.intervalCategories, config.showFirstCategoryAd);
83
+ if (config.enableBetweenAds) process(Array.from(document.querySelectorAll(selectors['topic-list'])), 'topic-list', config.intervalPosts, config.showFirstTopicAd);
84
+ if (config.enableMessageAds) process(Array.from(document.querySelectorAll(selectors.message)), 'message', config.messageIntervalPosts, config.showFirstMessageAd);
78
85
  }
79
86
 
80
87
  function init() {
@@ -82,27 +89,18 @@
82
89
  .then(r => r.json())
83
90
  .then(data => {
84
91
  config = data;
92
+ const pool = getPool();
85
93
 
86
- // On crée un pool CACHÉ qui contient tous les placeholders déclarés dans l'admin
87
- let pool = document.getElementById('nodebb-ezoic-placeholder-pool');
88
- if (!pool) {
89
- pool = document.createElement('div');
90
- pool.id = 'nodebb-ezoic-placeholder-pool';
91
- pool.style.display = 'none';
92
- document.body.appendChild(pool);
93
- }
94
-
95
94
  const setup = (raw, kind) => {
96
95
  if (!raw) return;
97
96
  raw.split(/[\s,]+/).filter(Boolean).forEach(id => {
98
97
  if (!document.getElementById(`ezoic-pub-ad-placeholder-${id}`)) {
99
- const wrap = document.createElement('div');
100
- wrap.className = WRAP_CLASS;
101
- wrap.setAttribute('data-kind', kind);
102
- wrap.setAttribute('data-placeholder-id', id);
103
- // Structure exacte attendue par Ezoic
104
- wrap.innerHTML = `<div id="ezoic-pub-ad-placeholder-${id}"></div>`;
105
- pool.appendChild(wrap);
98
+ const d = document.createElement('div');
99
+ d.className = WRAP_CLASS;
100
+ d.setAttribute('data-kind', kind);
101
+ d.setAttribute('data-placeholder-id', id);
102
+ d.innerHTML = `<div id="ezoic-pub-ad-placeholder-${id}"></div>`;
103
+ pool.appendChild(d);
106
104
  }
107
105
  });
108
106
  };
@@ -120,7 +118,9 @@
120
118
  });
121
119
  }
122
120
 
123
- window.addEventListener('action:ajaxify.end', () => setTimeout(redistribute, 500));
121
+ window.addEventListener('action:ajaxify.end', () => {
122
+ setTimeout(redistribute, 500);
123
+ });
124
124
 
125
125
  if (document.readyState === 'loading') {
126
126
  document.addEventListener('DOMContentLoaded', init);