Add image + noDelay
This commit is contained in:
@@ -19,6 +19,17 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
transition: opacity 0.5s ease-out;
|
transition: opacity 0.5s ease-out;
|
||||||
}
|
}
|
||||||
|
#popupContainer .overlay-popup .overlay-popup-image {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
transform: translate(50%, -50%);
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
border: 2px solid #444;
|
||||||
|
}
|
||||||
#popupContainer .overlay-popup.fade-out {
|
#popupContainer .overlay-popup.fade-out {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,17 @@
|
|||||||
max-width: 20%;
|
max-width: 20%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
transition: opacity 0.5s ease-out;
|
transition: opacity 0.5s ease-out;
|
||||||
|
.overlay-popup-image {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
transform: translate(50%, -50%);
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
border: 2px solid #444;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay-popup.fade-out {
|
.overlay-popup.fade-out {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
const moduleUrl = window.getModuleUrl();
|
const moduleUrl = window.getModuleUrl();
|
||||||
loadCSSModule('overlay-popup-css', moduleUrl + '/css/popup.css');
|
loadCSSModule('overlay-popup-css', moduleUrl + '/css/popup.css');
|
||||||
|
|
||||||
|
const FADE_OUT_MS = 500;
|
||||||
|
|
||||||
function initModule() {
|
function initModule() {
|
||||||
const container = document.getElementById('mainContainer') || document.body;
|
const container = document.getElementById('mainContainer') || document.body;
|
||||||
if (!document.getElementById('popupContainer')) {
|
if (!document.getElementById('popupContainer')) {
|
||||||
@@ -12,18 +14,10 @@
|
|||||||
}
|
}
|
||||||
initModule();
|
initModule();
|
||||||
|
|
||||||
if (window.SBdispatcher) {
|
// Tableau global des popups actifs pour éviter le chevauchement
|
||||||
SBdispatcher.on('stream-popup', data => {
|
window._activePopups = window._activePopups || [];
|
||||||
showPopup(
|
|
||||||
data.param1,
|
|
||||||
data.param2,
|
|
||||||
parseFloat(data.param3) || 3,
|
|
||||||
data.param4 != null ? parseFloat(data.param4) : -1,
|
|
||||||
data.param5 != null ? parseFloat(data.param5) : -1
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// ===== Helpers =====
|
||||||
function randomPercent(min = 0, max = 100) {
|
function randomPercent(min = 0, max = 100) {
|
||||||
const minClamped = Math.ceil(min);
|
const minClamped = Math.ceil(min);
|
||||||
const maxClamped = Math.floor(max);
|
const maxClamped = Math.floor(max);
|
||||||
@@ -34,46 +28,96 @@
|
|||||||
return !(r1.right < r2.left || r1.left > r2.right || r1.bottom < r2.top || r1.top > r2.bottom);
|
return !(r1.right < r2.left || r1.left > r2.right || r1.bottom < r2.top || r1.top > r2.bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tableau global des popups actifs pour éviter le chevauchement
|
function findPopupByRef(ref) {
|
||||||
window._activePopups = window._activePopups || [];
|
if (!ref) return null;
|
||||||
|
return window._activePopups.find(el => el.dataset && el.dataset.ref === String(ref)) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removePopupElement(popupEl) {
|
||||||
|
if (!popupEl || !popupEl.isConnected) return;
|
||||||
|
if (popupEl._timeoutId) {
|
||||||
|
clearTimeout(popupEl._timeoutId);
|
||||||
|
popupEl._timeoutId = null;
|
||||||
|
}
|
||||||
|
popupEl.classList.add('fade-out');
|
||||||
|
setTimeout(() => {
|
||||||
|
if (popupEl && popupEl.remove) popupEl.remove();
|
||||||
|
const idx = window._activePopups.indexOf(popupEl);
|
||||||
|
if (idx !== -1) window._activePopups.splice(idx, 1);
|
||||||
|
}, FADE_OUT_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== API =====
|
||||||
|
/**
|
||||||
|
* Supprime manuellement un popup par sa référence.
|
||||||
|
* @param {string} reference
|
||||||
|
* @returns {boolean} true si supprimé, false sinon
|
||||||
|
*/
|
||||||
|
function deletePopup(reference) {
|
||||||
|
const target = findPopupByRef(reference);
|
||||||
|
if (target) {
|
||||||
|
removePopupElement(target);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Expose globalement
|
||||||
|
window.deletePopup = deletePopup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Affiche un popup dans #mainContainer (ou body si absent).
|
* Affiche un popup dans #mainContainer (ou body si absent).
|
||||||
* @param {string} title Titre du popup
|
* @param {string} title Titre du popup
|
||||||
* @param {string} message Contenu HTML du message
|
* @param {string} message Contenu HTML du message
|
||||||
* @param {number} delaySeconds Durée d'affichage en secondes
|
* @param {number} delaySeconds Durée d'affichage en secondes. -1 = ne pas auto-supprimer
|
||||||
* @param {number|null} posX Position horizontale en %, -1 ou null = aléatoire
|
* @param {number|null} posX Position horizontale en %, -1 ou null = aléatoire
|
||||||
* @param {number|null} posY Position verticale en %, -1 ou null = aléatoire
|
* @param {number|null} posY Position verticale en %, -1 ou null = aléatoire
|
||||||
|
* @param {string|null} reference Identifiant unique pour ce popup (permet deletePopup)
|
||||||
|
* @param {string|null} image URL d'une image à afficher dans le popup
|
||||||
*/
|
*/
|
||||||
function showPopup(title, message, delaySeconds, posX = -1, posY = -1) {
|
function showPopup(title, message, delaySeconds, posX = -1, posY = -1, reference = null, image = null) {
|
||||||
const container = document.getElementById('popupContainer') || document.body;
|
const container = document.getElementById('popupContainer') || document.body;
|
||||||
const activePopups = window._activePopups;
|
const activePopups = window._activePopups;
|
||||||
const maxAttempts = 10;
|
const maxAttempts = 10;
|
||||||
|
|
||||||
|
// Remplacer un popup existant de même référence
|
||||||
|
if (reference) {
|
||||||
|
const existing = findPopupByRef(reference);
|
||||||
|
if (existing) removePopupElement(existing);
|
||||||
|
}
|
||||||
|
|
||||||
let attempt = 0;
|
let attempt = 0;
|
||||||
let popup, rect;
|
let popup, rect;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (popup) {
|
if (popup) popup.remove();
|
||||||
popup.remove();
|
|
||||||
}
|
|
||||||
// Calcul position (entre 10% et 90% si aléatoire)
|
|
||||||
const x = (posX == null || posX < 0) ? randomPercent(10, 90) : posX;
|
const x = (posX == null || posX < 0) ? randomPercent(10, 90) : posX;
|
||||||
const y = (posY == null || posY < 0) ? randomPercent(10, 90) : posY;
|
const y = (posY == null || posY < 0) ? randomPercent(10, 90) : posY;
|
||||||
|
|
||||||
// Création de l'élément popup
|
|
||||||
popup = document.createElement('div');
|
popup = document.createElement('div');
|
||||||
popup.classList.add('overlay-popup');
|
popup.classList.add('overlay-popup');
|
||||||
popup.style.position = 'absolute';
|
popup.style.position = 'absolute';
|
||||||
popup.style.left = `${x}%`;
|
popup.style.left = `${x}%`;
|
||||||
popup.style.top = `${y}%`;
|
popup.style.top = `${y}%`;
|
||||||
|
|
||||||
// Contenu
|
if (reference) popup.dataset.ref = String(reference);
|
||||||
|
|
||||||
const header = document.createElement('h3');
|
const header = document.createElement('h3');
|
||||||
header.innerText = title;
|
header.innerText = title;
|
||||||
|
|
||||||
const body = document.createElement('div');
|
const body = document.createElement('div');
|
||||||
body.innerHTML = message;
|
body.innerHTML = message;
|
||||||
|
|
||||||
popup.append(header, body);
|
popup.append(header, body);
|
||||||
|
|
||||||
|
if (image) {
|
||||||
|
const img = document.createElement('img');
|
||||||
|
img.src = image;
|
||||||
|
img.alt = title || 'image';
|
||||||
|
img.classList.add('overlay-popup-image');
|
||||||
|
popup.append(img);
|
||||||
|
}
|
||||||
|
|
||||||
container.appendChild(popup);
|
container.appendChild(popup);
|
||||||
rect = popup.getBoundingClientRect();
|
rect = popup.getBoundingClientRect();
|
||||||
attempt++;
|
attempt++;
|
||||||
@@ -82,17 +126,31 @@
|
|||||||
activePopups.some(other => isOverlapping(rect, other.getBoundingClientRect()))
|
activePopups.some(other => isOverlapping(rect, other.getBoundingClientRect()))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Conserve ce popup dans la liste des actifs
|
|
||||||
activePopups.push(popup);
|
activePopups.push(popup);
|
||||||
|
|
||||||
// Suppression après délai et retrait de la liste
|
if (delaySeconds !== -1) {
|
||||||
setTimeout(() => {
|
popup._timeoutId = setTimeout(() => removePopupElement(popup), delaySeconds * 1000);
|
||||||
popup.classList.add('fade-out');
|
}
|
||||||
setTimeout(() => {
|
}
|
||||||
popup.remove();
|
|
||||||
const idx = activePopups.indexOf(popup);
|
// ===== Events =====
|
||||||
if (idx !== -1) activePopups.splice(idx, 1);
|
if (window.SBdispatcher) {
|
||||||
}, 500);
|
SBdispatcher.on('stream-popup', data => {
|
||||||
}, delaySeconds * 1000);
|
showPopup(
|
||||||
|
data.param1, // title
|
||||||
|
data.param2, // message (HTML)
|
||||||
|
parseFloat(data.param3) || 3, // delaySeconds
|
||||||
|
data.param4 != null ? parseFloat(data.param4) : -1, // posX
|
||||||
|
data.param5 != null ? parseFloat(data.param5) : -1, // posY
|
||||||
|
data.param6 != null ? String(data.param6) : null, // reference
|
||||||
|
data.param7 != null ? String(data.param7) : null // image URL
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// >>> Nouveau : suppression par event
|
||||||
|
SBdispatcher.on('stream-popup-delete', data => {
|
||||||
|
// data.param1 = reference
|
||||||
|
deletePopup(data?.param1 != null ? String(data.param1) : null);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -17,5 +17,4 @@
|
|||||||
<script type="text/javascript" src="modules/alert-banner/alert-banner.js"></script>
|
<script type="text/javascript" src="modules/alert-banner/alert-banner.js"></script>
|
||||||
<script type="text/javascript" src="modules/big-emote/big-emote.js"></script>
|
<script type="text/javascript" src="modules/big-emote/big-emote.js"></script>
|
||||||
<script type="text/javascript" src="modules/alert-video/alert-video.js"></script>
|
<script type="text/javascript" src="modules/alert-video/alert-video.js"></script>
|
||||||
<script type="text/javascript" src="modules/apple-music/apple-music.js"></script>
|
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user