From c8b6798f9b4698e81e07cb562c864a76851c6b6d Mon Sep 17 00:00:00 2001 From: Sebastiaan de Schaetzen Date: Tue, 17 Jun 2025 10:01:08 +0200 Subject: [PATCH] Refactor javascript code a little --- static/index.html | 286 +++++++++++++++++++++++++--------------------- 1 file changed, 154 insertions(+), 132 deletions(-) diff --git a/static/index.html b/static/index.html index 320b500..f1cd3d6 100644 --- a/static/index.html +++ b/static/index.html @@ -158,12 +158,104 @@ $(".video-container").css("display", "flex"); } + let currentVideo = null; + let videoElement = null; + let overlayContainer = null; + let inactivityTimer = null; + let backButton = null; + let customControls = null; + let playPauseButton = null; + let seekBar = null; + + function exitVideoPlayback() { + if (videoElement && videoElement.pause) { + videoElement.pause(); + } + clearTimeout(inactivityTimer); + if (overlayContainer) { + overlayContainer.css('cursor', 'default'); + overlayContainer.off('mousemove.inactivityControls'); + // Detach document-level fullscreen listener specific to this playback + $(document).off('fullscreenchange.videoPlayback webkitfullscreenchange.videoPlayback mozfullscreenchange.videoPlayback MSFullscreenChange.videoPlayback', handleFullscreenChange); + overlayContainer.remove(); + } + // Attempt to exit fullscreen if the document is still in fullscreen mode + // and our container was likely the one in fullscreen. + if (document.fullscreenElement || document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement) { + if (document.exitFullscreen) { + document.exitFullscreen().catch(() => {}); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); + } + } + } + + function showControlsAndResetTimer() { + backButton.removeClass('button-hidden'); + customControls.removeClass('controls-hidden'); + overlayContainer.css('cursor', 'default'); // Show cursor + clearTimeout(inactivityTimer); + inactivityTimer = setTimeout(function() { + backButton.addClass('button-hidden'); + customControls.addClass('controls-hidden'); + overlayContainer.css('cursor', 'none'); // Hide cursor + }, 3000); // 3 seconds + } + + // --- Moved Helper Function Definitions --- + function handlePlayPauseClick() { + if (videoElement.paused) { + videoElement.play(); + } else { + videoElement.pause(); + } + } + + function updatePlayPauseButtonState() { + if (!playPauseButton) return; // Ensure button exists + if (videoElement.paused) { + playPauseButton.text('►'); // Play icon + } else { + playPauseButton.text('❚❚'); // Pause icon + } + } + + function handleVideoLoadedMetadata() { + if (!seekBar) return; // Ensure seekbar exists + seekBar.attr('max', videoElement.duration); + } + + function handleVideoTimeUpdate() { + if (!seekBar) return; // Ensure seekbar exists + seekBar.val(videoElement.currentTime); + const percentage = (videoElement.currentTime / videoElement.duration) * 100; + seekBar.css('background', `linear-gradient(to right, #3498db ${percentage}%, #555 ${percentage}%)`); + } + + function handleSeekBarInput() { + if (!seekBar) return; // Ensure seekbar exists + videoElement.currentTime = seekBar.val(); + } + + function handleFullscreenChange() { + const isActuallyFullscreen = document.fullscreenElement || document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement; + if (!isActuallyFullscreen && overlayContainer && overlayContainer.length && !overlayContainer.is(document.fullscreenElement)) { + if (overlayContainer.is(':visible')) { + exitVideoPlayback(); + } + } + } + $(document).ready(function() { // Pre-set all thumbnails to a placeholder state $(".video-thumbnail").attr("src", "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100%25' height='100%25' viewBox='0 0 16 9'%3E%3C/svg%3E"); $.getJSON("/api/homepage", function(data) { - let currentVideo = data.currentVideo; + currentVideo = data.currentVideo; // previousVideo = data.previousVideo; // nextVideo = data.nextVideo; // @@ -174,138 +266,68 @@ // Hide loader and show videos hideLoader(); - - $("#play-button").click(function() { - if (currentVideo && currentVideo.url) { - // Create the overlay container - let overlayContainer = $("
").appendTo("body"); - - // Create video element and append to container - let videoElement = $("") // Removed 'controls' attribute - .attr("src", currentVideo.url) - .appendTo(overlayContainer)[0]; - - // Create back button and append to container - let backButton = $("") - .appendTo(overlayContainer); - - // Create custom video controls container - let customControls = $("
").appendTo(overlayContainer); - let playPauseButton = $("").appendTo(customControls); // Initial state: Pause icon - let seekBar = $("").appendTo(customControls); - - - // Mouse inactivity logic for back button, controls, and cursor - let inactivityTimer; - function showControlsAndResetTimer() { - backButton.removeClass('button-hidden'); - customControls.removeClass('controls-hidden'); - overlayContainer.css('cursor', 'default'); // Show cursor - clearTimeout(inactivityTimer); - inactivityTimer = setTimeout(function() { - backButton.addClass('button-hidden'); - customControls.addClass('controls-hidden'); - overlayContainer.css('cursor', 'none'); // Hide cursor - }, 3000); // 3 seconds - } - - overlayContainer.on('mousemove.inactivityControls', function() { - showControlsAndResetTimer(); - }); - showControlsAndResetTimer(); // Initial call - - // Custom Controls Logic - // Play/Pause Button - playPauseButton.click(function() { - if (videoElement.paused) { - videoElement.play(); - } else { - videoElement.pause(); - } - }); - $(videoElement).on('play', function() { - playPauseButton.text('❚❚'); // Pause icon - }); - $(videoElement).on('pause', function() { - playPauseButton.text('►'); // Play icon - }); - - // Seek Bar - $(videoElement).on('loadedmetadata', function() { - seekBar.attr('max', videoElement.duration); - }); - $(videoElement).on('timeupdate', function() { - seekBar.val(videoElement.currentTime); - // Optional: Update seek bar background to show progress - const percentage = (videoElement.currentTime / videoElement.duration) * 100; - seekBar.css('background', `linear-gradient(to right, #3498db ${percentage}%, #555 ${percentage}%)`); - }); - seekBar.on('input', function() { - videoElement.currentTime = $(this).val(); - }); - - - // Request fullscreen on the container - const containerEl = overlayContainer[0]; - if (containerEl.requestFullscreen) { - containerEl.requestFullscreen(); - } else if (containerEl.mozRequestFullScreen) { /* Firefox */ - containerEl.mozRequestFullScreen(); - } else if (containerEl.webkitRequestFullscreen) { /* Chrome, Safari & Opera */ - containerEl.webkitRequestFullscreen(); - } else if (containerEl.msRequestFullscreen) { /* IE/Edge */ - containerEl.msRequestFullscreen(); - } - - function exitVideoPlayback() { - if (videoElement && videoElement.pause) { - videoElement.pause(); - } - clearTimeout(inactivityTimer); // Clear inactivity timer - if (overlayContainer) { // Ensure overlayContainer exists before trying to modify it - overlayContainer.css('cursor', 'default'); // Always reset cursor on exit - } - // Exit fullscreen if active - if (document.fullscreenElement || document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement) { - if (document.exitFullscreen) { - document.exitFullscreen().catch(() => {}); - } else if (document.mozCancelFullScreen) { - document.mozCancelFullScreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } else if (document.msExitFullscreen) { - document.msExitFullscreen(); - } - } - if (overlayContainer) { - overlayContainer.off('mousemove.inactivityControls'); // Remove specific listener - overlayContainer.remove(); - } - } - - // Handle video ending - videoElement.onended = function() { - exitVideoPlayback(); - }; - - // Handle back button click - backButton.click(function() { - exitVideoPlayback(); - }); - - // Detach previous fullscreen change listeners to avoid multiple triggers - $(document).off('fullscreenchange.videoPlayback webkitfullscreenchange.videoPlayback mozfullscreenchange.videoPlayback MSFullscreenChange.videoPlayback'); - // Handle fullscreen change (e.g., user pressing Esc) - $(document).on('fullscreenchange.videoPlayback webkitfullscreenchange.videoPlayback mozfullscreenchange.videoPlayback MSFullscreenChange.videoPlayback', function() { - const isActuallyFullscreen = document.fullscreenElement || document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement; - // Check if fullscreen was exited AND if our container was the one in fullscreen or is still around - if (!isActuallyFullscreen && overlayContainer && overlayContainer.length && overlayContainer.is(':visible')) { - exitVideoPlayback(); - } - }); - } - }); }) + + $("#play-button").click(function() { + if (currentVideo && currentVideo.url) { + // Create the overlay container + overlayContainer = $("
").appendTo("body"); + + // Create video element and append to container + videoElement = $("") // Removed 'controls' attribute + .attr("src", currentVideo.url) + .appendTo(overlayContainer)[0]; + + // Create back button and append to container + backButton = $("") + .appendTo(overlayContainer); + + // Create custom video controls container + customControls = $("
").appendTo(overlayContainer); + playPauseButton = $("").appendTo(customControls); // Assign to global var + seekBar = $("").appendTo(customControls); // Assign to global var + + // Remove local inactivityTimer declaration, it's global now + // let inactivityTimer; + + // --- Setup Inactivity Controls --- + overlayContainer.on('mousemove.inactivityControls', showControlsAndResetTimer); + showControlsAndResetTimer(); // Initial call + + // --- Setup Custom Video Controls --- + playPauseButton.click(handlePlayPauseClick); + $(videoElement).on('play', updatePlayPauseButtonState); + $(videoElement).on('pause', updatePlayPauseButtonState); + $(videoElement).on('loadedmetadata', handleVideoLoadedMetadata); + $(videoElement).on('timeupdate', handleVideoTimeUpdate); + seekBar.on('input', handleSeekBarInput); + // Initial call to set play/pause button state, especially if autoplay is effective + updatePlayPauseButtonState(); + + // --- Setup Video End and Back Button --- + $(videoElement).on('ended', exitVideoPlayback); + backButton.click(exitVideoPlayback); + + // --- Setup Fullscreen Change Listener --- + // Detach any previous listeners first (using the specific named handler for accuracy if needed, but general works too) + $(document).off('fullscreenchange.videoPlayback webkitfullscreenchange.videoPlayback mozfullscreenchange.videoPlayback MSFullscreenChange.videoPlayback'); + $(document).on('fullscreenchange.videoPlayback webkitfullscreenchange.videoPlayback mozfullscreenchange.videoPlayback MSFullscreenChange.videoPlayback', handleFullscreenChange); + + // --- Request Fullscreen --- + const containerEl = overlayContainer[0]; + if (containerEl.requestFullscreen) { + containerEl.requestFullscreen(); + } else if (containerEl.mozRequestFullScreen) { /* Firefox */ + containerEl.mozRequestFullScreen(); + } else if (containerEl.webkitRequestFullscreen) { /* Chrome, Safari & Opera */ + containerEl.webkitRequestFullscreen(); + } else if (containerEl.msRequestFullscreen) { /* IE/Edge */ + containerEl.msRequestFullscreen(); + } + // NOTE: exitVideoPlayback was defined above. + // The original snippet showed its definition here, it's now grouped with other helpers. + } + }); })