It only happens on mobile devices.
Situation on mobile:
- The user plays a video.
- The user scrolls to another carousel video, and the intersection observer triggers, playing the second video.
- The user navigates back to the first video via intersection, but the
play button is missing. - The user touches the mobile screen and
swipes slightly forward or backward, and the play button appears.
The user releases their finger, and the play button disappears.
Expected: The play button should always be visible if the video is stopped. This behavior works on desktop but not on touchscreens.
window.addEventListener("DOMContentLoaded", () => {
const iframesWrappers = document.getElementsByClassName("video-wrapper");
let currentPlayingIndex = null;
const players = [];
const videoStates = {};
const isMultiplePlayback = document.getElementById("dataBlock").getAttribute("data-allow-multiple-playback");
const observerOptions = {
root: document.getElementById("swiperCarousel"),
rootMargin: "0px",
threshold: 0.3,
};
const intersectionCallback = (entries, observer) => {
entries.forEach((entry) => {
const index = entry.target.dataset.index;
const videoElement = document.getElementById(`video-${index}`);
const playButton = document.getElementById(`playButton-${index}`);
const overlay = videoElement.querySelector(".overlay");
const iframe = videoElement.querySelector("iframe");
if (!entry.isIntersecting) {
if (iframe.src.includes("autoplay=true")) {
playButton.style.display = "none";
overlay.style.display = "block";
}
} else {
if (videoStates[index] === "stopped") {
let src = iframe.src;
if (src.includes("autoplay=true")) {
src = src.replace("autoplay=true", "");
iframe.src = src;
}
playButton.style.display = "block";
overlay.style.display = "none";
Stream(iframe).pause();
} else if (iframe.src.includes("autoplay=true")) {
playButton.style.display = "none";
overlay.style.display = "block";
Stream(iframe).pause();
} else if (videoStates[index] === "playing") {
playButton.style.display = "none";
overlay.style.display = "block";
Stream(iframe).play();
} else {
playButton.style.display = "block";
overlay.style.display = "none";
Stream(iframe).pause();
console.log("pause");
}
}
});
};
const observer = new IntersectionObserver(intersectionCallback, observerOptions);
Array.from(iframesWrappers).forEach((videoElement, index) => {
videoElement.dataset.index = index;
const videoUrl = videoElement.dataset.url;
const iframe = document.createElement("iframe");
iframe.src = videoUrl;
iframe.style.transform = "scale(1.02)";
iframe.style.width = "100%";
iframe.style.height = "100%";
iframe.style.border = "none";
iframe.style.pointerEvents = "none";
iframe.style.position = "absolute";
iframe.style.top = "0";
iframe.allow =
"accelerometer; autoplay; clipboard-write; encrypted-media; fullscreen; gyroscope; picture-in-picture; web-share";
videoElement.style.position = "relative";
videoElement.style.borderRadius = "10px";
videoElement.style.overflow = "hidden";
videoElement.appendChild(iframe);
const overlay = document.createElement("div");
overlay.classList.add("overlay");
overlay.style.position = "absolute";
overlay.style.top = "0";
overlay.style.left = "0";
overlay.style.width = "100%";
overlay.style.height = "100%";
overlay.style.cursor = "pointer";
overlay.style.zIndex = "1";
const playButton = document.getElementById(`playButton-${index}`);
if (videoUrl.includes("autoplay=true")) {
overlay.style.display = "block";
playButton.style.display = "none";
currentPlayingIndex = index;
videoStates[index] = "playing";
} else {
overlay.style.display = "none";
playButton.style.display = "block";
videoStates[index] = "stopped";
}
videoElement.appendChild(overlay);
Stream(iframe).addEventListener("ended", () => {
playButton.style.display = "block";
overlay.style.display = "none";
videoStates[index] = "stopped";
});
const player = Stream(iframe);
players[index] = player;
observer.observe(videoElement);
playButton.addEventListener("click", () => {
if (isMultiplePlayback === "false") {
if (currentPlayingIndex !== index && currentPlayingIndex !== null) {
const prevPlayer = players[currentPlayingIndex];
const prevVideoElement = document.getElementById(`video-${currentPlayingIndex}`);
const prevPlayButton = document.getElementById(`playButton-${currentPlayingIndex}`);
const prevOverlay = prevVideoElement.querySelector(".overlay");
prevPlayButton.style.display = "block";
prevOverlay.style.display = "none";
if (prevPlayer) {
prevPlayer.pause();
videoStates[currentPlayingIndex] = "stopped";
}
}
}
currentPlayingIndex = index;
player.play();
iframe.style.display = "block";
overlay.style.display = "block";
playButton.style.display = "none";
videoStates[index] = "playing";
});
overlay.addEventListener("click", () => {
player.pause();
playButton.style.display = "block";
overlay.style.display = "none";
videoStates[index] = "stopped";
currentPlayingIndex = null;
});
});
});
I also have swiper settings:
const swiperElement = document.querySelector("#swiperCarousel");
if (swiperElement) {
const totalSlides = swiperElement.querySelectorAll(".swiper-slide").length;
let slidesPerView = null;
let loop = true;
if (totalSlides == 3) {
slidesPerView = 2.3;
} else if (totalSlides == 2) {
slidesPerView = 1.9;
loop = false;
}
let breakpoints = {
481: { slidesPerView: totalSlides >= 4 ? 3.125 : slidesPerView },
320: { slidesPerView: 1.1 },
};
new Swiper("#swiperCarousel", {
loop: loop,
slidesPerView: slidesPerView,
centeredSlides: false,
spaceBetween: 8,
observer: true,
observeParents: true,
pagination: {
el: ".swiper-pagination",
clickable: true,
},
breakpoints: breakpoints,
});
}
I’m using HTML:
import { useBlockProps } from "@wordpress/block-editor";
import PlayButtonSvg from "../assets/PlayButtonSvg";
import PlayButton from "../assets/Vector.png";
const Save = ({ attributes }) => {
const blockProps = useBlockProps.save();
return (
<>
<script src="https://embed.cloudflarestream.com/embed/sdk.latest.js"></script>
<div {...blockProps} id="dataBlock" data-allow-multiple-playback={attributes.allowMultiplePlayback}>
<div id="swiperCarousel" className="swiper">
<div className="swiper-wrapper">
{attributes.videos.map((video, index) => (
<div className="swiper-slide" key={index}>
<div className="video-wrapper" id={`video-${index}`} data-url={video.videoUrl}>
<img className="playButtonFull" id={`playButton-${index}`} src={PlayButton} alt="play button" />
</div>
</div>
))}
</div>
<div className="swiper-pagination"></div>
</div>
</div>
</>
);
};
export default Save;
I checked on the dev tools it has display: block, but not visible.



