Add Chrome-specific video fallback with play button and lightbox

This commit is contained in:
Leopere 2025-03-09 17:09:33 -04:00
parent b714d1a2d6
commit 1fd7b9f9cf
7 changed files with 281 additions and 3 deletions

View File

@ -0,0 +1,98 @@
/* Chrome-specific video fallback styles */
/* Poster image styling */
.chrome-poster-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
z-index: 1;
border-radius: 4px;
}
/* Play button overlay */
.chrome-play-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
z-index: 2;
}
.chrome-play-button {
width: 68px;
height: 48px;
transition: transform 0.2s;
filter: drop-shadow(0 0 5px rgba(0,0,0,0.5));
}
.chrome-play-overlay:hover .chrome-play-button {
transform: scale(1.1);
}
/* Video lightbox */
.video-lightbox {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.85);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}
.video-lightbox-content {
position: relative;
width: 90%;
max-width: 960px;
}
.video-lightbox video {
width: 100%;
max-height: 90vh;
border-radius: 4px;
}
.close-lightbox {
position: absolute;
top: -40px;
right: 0;
background: none;
border: none;
color: white;
font-size: 30px;
cursor: pointer;
z-index: 10;
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
.close-lightbox:hover {
color: #f00;
}
/* Mobile optimizations */
@media (max-width: 768px) {
.video-lightbox-content {
width: 95%;
}
.close-lightbox {
top: -35px;
right: 0;
}
}

View File

@ -0,0 +1,35 @@
/* Custom VideoJS styling */
.video-container {
position: relative;
width: 100%;
/* Add some bottom padding to ensure controls are visible */
margin-bottom: 10px;
}
/* Ensure the video-js player is properly contained */
.video-js {
width: 100%;
height: auto;
/* Ensure controls are within the container */
position: relative;
}
/* Fix control bar positioning */
.video-js .vjs-control-bar {
/* Ensure the control bar stays within the player's dimensions */
bottom: 0;
width: 100%;
}
/* Additional responsive adjustments */
@media (max-width: 768px) {
.video-js {
/* Ensure the video fits on smaller screens */
max-height: 300px;
}
.video-container {
/* More bottom space on mobile */
margin-bottom: 15px;
}
}

View File

@ -0,0 +1,93 @@
/**
* Chrome-specific video fallback
* Since Chrome has issues with VideoJS/HLS, this script provides a fallback
* that replaces video players with play buttons that open videos in a new page.
*/
document.addEventListener('DOMContentLoaded', function() {
// Only run this script for Chrome browsers
const isChrome = /Chrome/.test(navigator.userAgent) && !/Edge/.test(navigator.userAgent) && !/OPR/.test(navigator.userAgent);
if (!isChrome) {
return; // Exit if not Chrome
}
// Videos to handle with IDs and their mp4 sources
const videoMappings = {
'video-hero': '/static/videos/video1.mp4',
'video2': '/static/videos/video2.mp4',
'video3': '/static/videos/video3.mp4'
};
// Process each video
Object.keys(videoMappings).forEach(function(videoId) {
const videoElement = document.getElementById(videoId);
if (!videoElement) return;
const videoContainer = videoElement.closest('.video-container');
if (!videoContainer) return;
// Get poster image
const posterUrl = videoElement.getAttribute('poster');
// Create play button overlay
const playButtonOverlay = document.createElement('div');
playButtonOverlay.className = 'chrome-play-overlay';
playButtonOverlay.innerHTML = `
<div class="chrome-play-button">
<svg xmlns="http://www.w3.org/2000/svg" width="68" height="48" viewBox="0 0 68 48">
<path fill="#f00" d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z"></path>
<path fill="#fff" d="M 45,24 27,14 27,34"></path>
</svg>
</div>
`;
// Style the container for positioning
videoContainer.style.position = 'relative';
// Create a poster image as background
if (posterUrl) {
const posterImage = document.createElement('div');
posterImage.className = 'chrome-poster-image';
posterImage.style.backgroundImage = `url(${posterUrl})`;
videoContainer.appendChild(posterImage);
}
// Add click event to open the video in a new page/overlay
playButtonOverlay.addEventListener('click', function() {
// Create the lightbox overlay
const lightbox = document.createElement('div');
lightbox.className = 'video-lightbox';
lightbox.innerHTML = `
<div class="video-lightbox-content">
<button class="close-lightbox">&times;</button>
<video controls autoplay>
<source src="${videoMappings[videoId]}" type="video/mp4">
Your browser does not support the video tag.
</video>
</div>
`;
// Add the lightbox to the body
document.body.appendChild(lightbox);
// Add close functionality
const closeButton = lightbox.querySelector('.close-lightbox');
closeButton.addEventListener('click', function() {
document.body.removeChild(lightbox);
});
// Close when clicking outside the video
lightbox.addEventListener('click', function(e) {
if (e.target === lightbox) {
document.body.removeChild(lightbox);
}
});
});
// Hide the original video element
videoElement.style.display = 'none';
// Add the play button to the container
videoContainer.appendChild(playButtonOverlay);
});
});

View File

@ -0,0 +1 @@
document.addEventListener("DOMContentLoaded",function(){const e=/Chrome/.test(navigator.userAgent)&&!/Edge/.test(navigator.userAgent)&&!/OPR/.test(navigator.userAgent);if(!e)return;const t={"video-hero":"/static/videos/video1.mp4",video2:"/static/videos/video2.mp4",video3:"/static/videos/video3.mp4"};Object.keys(t).forEach(function(e){const o=document.getElementById(e);if(!o)return;const n=o.closest(".video-container");if(!n)return;const i=o.getAttribute("poster"),r=document.createElement("div");if(r.className="chrome-play-overlay",r.innerHTML='\n <div class="chrome-play-button">\n <svg xmlns="http://www.w3.org/2000/svg" width="68" height="48" viewBox="0 0 68 48">\n <path fill="#f00" d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z"></path>\n <path fill="#fff" d="M 45,24 27,14 27,34"></path>\n </svg>\n </div>\n ',n.style.position="relative",i){const e=document.createElement("div");e.className="chrome-poster-image",e.style.backgroundImage=`url(${i})`,n.appendChild(e)}r.addEventListener("click",function(){const o=document.createElement("div");o.className="video-lightbox",o.innerHTML=`\n <div class="video-lightbox-content">\n <button class="close-lightbox">&times;</button>\n <video controls autoplay>\n <source src="${t[e]}" type="video/mp4">\n Your browser does not support the video tag.\n </video>\n </div>\n `,document.body.appendChild(o);const n=o.querySelector(".close-lightbox");n.addEventListener("click",function(){document.body.removeChild(o)}),o.addEventListener("click",function(e){e.target===o&&document.body.removeChild(o)})}),o.style.display="none",n.appendChild(r)})});

View File

@ -0,0 +1,45 @@
/**
* VideoJS Player initialization
* This script initializes VideoJS for all video elements, handling both
* videos with data-setup attribute and regular videos.
*/
document.addEventListener('DOMContentLoaded', function() {
// First, initialize all videos with the data-setup attribute
// VideoJS will automatically process these
// Then find any remaining videos (without video-js class) that need to be initialized
const regularVideos = document.querySelectorAll('video:not(.video-js)');
if (regularVideos.length) {
regularVideos.forEach(function(video) {
// Ensure the video has an ID
const id = video.id || 'video-' + Math.floor(Math.random() * 1000000);
video.id = id;
// Add VideoJS class
video.classList.add('video-js');
video.classList.add('vjs-big-play-centered');
// Initialize with default options
videojs(id, {
controls: true,
autoplay: false,
preload: 'auto'
});
});
}
// Additional check to ensure all video.video-js elements are initialized
// This helps with videos that have the class but weren't auto-initialized
const videojsElements = document.querySelectorAll('video.video-js');
videojsElements.forEach(function(videoElement) {
const id = videoElement.id;
if (id) {
// Check if this element already has a VideoJS instance
if (!videojs.getPlayers()[id]) {
// Initialize VideoJS for this element
videojs(id);
}
}
});
});

View File

@ -0,0 +1 @@
document.addEventListener("DOMContentLoaded",function(){const e=document.querySelectorAll("video:not(.video-js)");e.length&&e.forEach(function(e){const t=e.id||"video-"+Math.floor(1e6*Math.random());e.id=t,e.classList.add("video-js"),e.classList.add("vjs-big-play-centered"),videojs(t,{controls:!0,autoplay:!1,preload:"auto"})});const t=document.querySelectorAll("video.video-js");t.forEach(function(e){const t=e.id;t&&!videojs.getPlayers()[t]&&videojs(t)})});

View File

@ -163,7 +163,12 @@
<link rel="icon" href="/static/favicon.svg" type="image/svg+xml">
<link rel="icon" href="/static/favicon.ico" type="image/x-icon">
<!-- HLS Video Support -->
<script src="/static/js/vendor/hls.min.js" defer></script>
<script src="/static/js/hls-player.min.js" defer></script>
<!-- VideoJS for HLS -->
<link rel="stylesheet" href="/static/css/video-js.min.css">
<link rel="stylesheet" href="/static/css/custom-video.css">
<link rel="stylesheet" href="/static/css/chrome-video-fallback.css">
<script src="/static/js/vendor/video.min.js"></script>
<script src="/static/js/vendor/videojs-http-streaming.min.js"></script>
<script src="/static/js/videojs-player.min.js"></script>
<script src="/static/js/chrome-video-fallback.min.js"></script>
</head>