fix(jeu): src injecté au clic (about:blank initial) + event delegation
- jeu.php : iframe démarre sur about:blank, URL stockée dans data-src - Article.svelte : event delegation sur document (plus de timeout/querySelector) → le src de l'iframe est injecté seulement quand l'user clique (évite l'iframe noir) → supprime l'ancien $effect avec setTimeout au profit d'une délégation propre Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ddfcf4de70
commit
b4dfc4480e
2 changed files with 44 additions and 38 deletions
|
|
@ -1,14 +1,12 @@
|
||||||
<?php if ($block->url()->isNotEmpty()):
|
<?php if ($block->url()->isNotEmpty()):
|
||||||
$iframeUrl = preg_replace('/\s+/', '', $block->url()->value());
|
$iframeUrl = preg_replace('/\s+/', '', $block->url()->value());
|
||||||
?>
|
?>
|
||||||
<div class="iframe-game-container">
|
<div class="iframe-game-container" data-src="<?= htmlspecialchars($iframeUrl, ENT_QUOTES, 'UTF-8') ?>">
|
||||||
<iframe
|
<iframe
|
||||||
loading="eager"
|
|
||||||
importance="high"
|
|
||||||
width="400"
|
width="400"
|
||||||
height="650"
|
height="650"
|
||||||
style="border: none; overflow: hidden; pointer-events: none; display: block; width: 100%;"
|
style="border: none; overflow: hidden; pointer-events: none; display: block; width: 100%;"
|
||||||
src="<?= htmlspecialchars($iframeUrl, ENT_QUOTES, 'UTF-8') ?>"
|
src="about:blank"
|
||||||
></iframe>
|
></iframe>
|
||||||
<div class="iframe-click-overlay" data-state="initial">
|
<div class="iframe-click-overlay" data-state="initial">
|
||||||
<div class="overlay-content">
|
<div class="overlay-content">
|
||||||
|
|
|
||||||
|
|
@ -13,40 +13,6 @@
|
||||||
let copySuccess = $state(false)
|
let copySuccess = $state(false)
|
||||||
let copyTimer = null
|
let copyTimer = null
|
||||||
|
|
||||||
// Setup click-to-play iframes après le rendu du body HTML
|
|
||||||
$effect(() => {
|
|
||||||
if (!data.body) return
|
|
||||||
|
|
||||||
const timer = setTimeout(() => {
|
|
||||||
document.querySelectorAll('.iframe-game-container').forEach(container => {
|
|
||||||
if (container.dataset.initialized) return
|
|
||||||
container.dataset.initialized = 'true'
|
|
||||||
|
|
||||||
const overlay = container.querySelector('.iframe-click-overlay')
|
|
||||||
const iframe = container.querySelector('iframe')
|
|
||||||
const deactivateBtn = container.querySelector('.iframe-deactivate-btn')
|
|
||||||
|
|
||||||
overlay?.addEventListener('click', () => {
|
|
||||||
if (overlay.getAttribute('data-state') === 'ended') return
|
|
||||||
overlay.style.display = 'none'
|
|
||||||
iframe.style.pointerEvents = 'auto'
|
|
||||||
container.classList.add('game-active')
|
|
||||||
overlay.setAttribute('data-state', 'played')
|
|
||||||
})
|
|
||||||
|
|
||||||
deactivateBtn?.addEventListener('click', (e) => {
|
|
||||||
e.stopPropagation()
|
|
||||||
overlay.style.display = 'flex'
|
|
||||||
overlay.setAttribute('data-state', 'initial')
|
|
||||||
iframe.style.pointerEvents = 'none'
|
|
||||||
container.classList.remove('game-active')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}, 300)
|
|
||||||
|
|
||||||
return () => clearTimeout(timer)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Écoute les messages postMessage depuis l'iframe du jeu
|
// Écoute les messages postMessage depuis l'iframe du jeu
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
const handleIframeMessage = (event) => {
|
const handleIframeMessage = (event) => {
|
||||||
|
|
@ -73,6 +39,48 @@
|
||||||
return () => window.removeEventListener('message', handleIframeMessage)
|
return () => window.removeEventListener('message', handleIframeMessage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Event delegation sur le body de l'article pour les blocs jeu
|
||||||
|
$effect(() => {
|
||||||
|
if (!data.body) return
|
||||||
|
|
||||||
|
const handleClick = (e) => {
|
||||||
|
// Clic sur l'overlay → lancer le jeu
|
||||||
|
const overlay = e.target.closest('.iframe-click-overlay')
|
||||||
|
if (overlay && overlay.getAttribute('data-state') !== 'ended') {
|
||||||
|
const container = overlay.closest('.iframe-game-container')
|
||||||
|
const iframe = container?.querySelector('iframe')
|
||||||
|
if (!iframe) return
|
||||||
|
|
||||||
|
// Injecter le src seulement au premier clic
|
||||||
|
if (iframe.src === 'about:blank' || !iframe.src) {
|
||||||
|
iframe.src = container.dataset.src
|
||||||
|
}
|
||||||
|
overlay.style.display = 'none'
|
||||||
|
iframe.style.pointerEvents = 'auto'
|
||||||
|
container.classList.add('game-active')
|
||||||
|
overlay.setAttribute('data-state', 'played')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clic sur le bouton désactiver
|
||||||
|
const btn = e.target.closest('.iframe-deactivate-btn')
|
||||||
|
if (btn) {
|
||||||
|
e.stopPropagation()
|
||||||
|
const container = btn.closest('.iframe-game-container')
|
||||||
|
const iframe = container?.querySelector('iframe')
|
||||||
|
const ov = container?.querySelector('.iframe-click-overlay')
|
||||||
|
if (!iframe || !ov) return
|
||||||
|
ov.style.display = 'flex'
|
||||||
|
ov.setAttribute('data-state', 'initial')
|
||||||
|
iframe.style.pointerEvents = 'none'
|
||||||
|
container.classList.remove('game-active')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('click', handleClick)
|
||||||
|
return () => document.removeEventListener('click', handleClick)
|
||||||
|
})
|
||||||
|
|
||||||
function copyLink() {
|
function copyLink() {
|
||||||
navigator.clipboard.writeText(window.location.href)
|
navigator.clipboard.writeText(window.location.href)
|
||||||
copySuccess = true
|
copySuccess = true
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue