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.svg" type="image/svg+xml">
|
||||||
<link rel="icon" href="/static/favicon.ico" type="image/x-icon">
|
<link rel="icon" href="/static/favicon.ico" type="image/x-icon">
|
||||||
|
|
||||||
<!-- HLS Video Support -->
|
<!-- VideoJS for HLS -->
|
||||||
<script src="/static/js/vendor/hls.min.js" defer></script>
|
<link rel="stylesheet" href="/static/css/video-js.min.css">
|
||||||
<script src="/static/js/hls-player.min.js" defer></script>
|
<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>
|
</head>
|
||||||
|
|
Loading…
Reference in New Issue