Add Chrome-specific video fallback with play button and lightbox
This commit is contained in:
parent
b714d1a2d6
commit
1fd7b9f9cf
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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">×</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);
|
||||
});
|
||||
});
|
|
@ -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">×</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)})});
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
|
@ -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)})});
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue