Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="en"> <!-- specify the language of the document -->
- <head>
- <meta charset="UTF-8"> <!-- specify the character encoding of the document -->
- <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- specify the viewport settings for responsive design -->
- <meta name="description" content="The Sports Watcher is a web app that lets you watch live streams of various sports games."> <!-- provide a brief summary of the web page for search engines and users -->
- <title>The Sports Watcher</title>
- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
- <link href="https://vjs.zencdn.net/8.5.2/video-js.css" rel="stylesheet" />
- <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;700&display=swap" rel="stylesheet">
- <style>
- :root {
- --bg-color: linear-gradient(to right, #000000, #3c3d5b, #000000); /* define a CSS variable for background color */
- --text-color: #fff; /* define a CSS variable for text color */
- --shadow-color: rgba(0,0,0,0.3); /* define a CSS variable for shadow color */
- --accent-color: #ffcc00; /* define a CSS variable for accent color */
- --rotation-degree: 5deg;
- --scale-value: 1.1;
- }
- body {
- font-family: 'Montserrat', sans-serif;
- background: var(--bg-color); /* use the CSS variable for background color */
- margin: 0;
- color: var(--text-color); /* use the CSS variable for text color */
- }
- .container {
- margin: 0 auto;
- max-width: 1200px;
- padding: 2%;
- }
- header {
- /* use a semantic element for the header */
- text-align: center;
- margin-top: 2%;
- }
- h1 {
- font-weight: 700;
- color: var(--text-color);
- text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
- transition: all 0.3s ease;
- }
- h1:hover {
- transform: scale(1.1);
- }
- nav {
- /* use a semantic element for the navigation */
- display: flex;
- justify-content: center;
- align-items: center;
- }
- #gamesDropdown {
- display: block;
- width: 100%;
- padding: 0.4em 1em;
- font-size: 1em;
- margin-bottom: 2%;
- border: none;
- border-radius: 20px;
- background-color: var(--text-color);
- color: #333;
- box-shadow: 0 10px 10px var(--shadow-color); /* use the CSS variable for shadow color */
- transition: all 0.3s ease;
- }
- #gamesDropdown:hover {
- box-shadow: 0 15px 15px var(--shadow-color);
- }
- #gamesDropdown:focus {
- outline: none;
- border-color: var(--accent-color); /* use the CSS variable for accent color */
- box-shadow: 0 0 0 0.2rem rgba(255,204,0,.25);
- }
- main {
- /* use a semantic element for the main content */
- margin-top: 5%;
- }
- .video-container {
- position: relative;
- width: 100%;
- padding-top: 56.25%;
- border-radius: 20px;
- overflow: hidden;
- box-shadow: 0 10px 10px var(--shadow-color);
- perspective: 3000x; /* Add perspective for 3D transformations */
- transition: transform 3s; /* Add smooth transition for the transform property */
- }
- .video-container:hover{
- /* Scale the video on hover to create a 3D depth effect */
- transform: scale(var(--scale-value));
- }
- .video-container__player {
- /* use BEM methodology to name CSS classes and avoid specificity issues and conflicts */
- position:absolute;
- top :0;
- left :0;
- width :100%;
- height :100%;
- transform-style: preserve-3d; /* Make sure the 3D transformations are applied to child elements too */
- }
- @media screen and (max-width :768px) {
- /* use a media query to apply different styles for smaller screens */
- header {
- margin-top :5%;
- }
- nav {
- flex-direction : column; /* stack the nav items vertically */
- }
- #gamesDropdown {
- width :80%; /* reduce the width of the dropdown */
- }
- main {
- margin-top :10%; /* increase the margin-top of the main content */
- }
- .video-container {
- border-radius :10px; /* reduce the border-radius of the video container */
- }
- }
- @media (orientation : portrait) {
- /* use a media query to apply different styles for portrait mode */
- .video-container__player {
- object-fit : cover; /* fit the video to the container */
- }
- }
- </style>
- </head>
- <body>
- <div class="container">
- <header>
- <!-- use a semantic element for the header -->
- <h1>The Sports Watcher</h1>
- </header>
- <nav>
- <!-- use a semantic element for the navigation -->
- <select id="gamesDropdown" onchange="loadGame()" class="form-control"></select>
- </nav>
- <main>
- <!-- use a semantic element for the main content -->
- <div class="video-container mt-5">
- <video-js id="player" class="video-js vjs-default-skin video-container__player" controls preload="none" data-setup='{}'>
- <!-- use BEM methodology to name CSS classes and avoid specificity issues and conflicts -->
- <p class="vjs-no-js">
- To view this video please enable JavaScript, and consider upgrading to a web browser that
- <a href="http://videojs.com/html5-video-support/" target="_blank" style="color:var(--accent-color);">supports HTML5 video</a> <!-- use the CSS variable for accent color -->
- </p>
- </video-js>
- </div>
- </main>
- </div>
- <script src="https://vjs.zencdn.net/8.5.2/video.js"></script>
- <script>
- let player = videojs('player');
- // Listen for fullscreen changes and adjust control bar visibility
- player.on('fullscreenchange', function() {
- if (player.isFullscreen()) {
- player.controls(false); // hides the control bar
- } else {
- player.controls(true); // shows the control bar
- }
- });
- let gamesDropdown = document.getElementById('gamesDropdown');
- let games = {};
- const apiUrl = '/games';
- fetch(apiUrl)
- .then(response => response.json())
- .then(gamesData => {
- gamesData.forEach(game => {
- if (!games[game.sport]) {
- games[game.sport] = [];
- }
- games[game.sport].push(game);
- });
- for (let sport in games) {
- let optgroup = document.createElement('optgroup');
- optgroup.label = sport;
- games[sport].forEach(game => {
- let option = document.createElement('option');
- option.text = game.title;
- option.value = game.streamLink;
- optgroup.appendChild(option);
- });
- gamesDropdown.appendChild(optgroup);
- }
- loadGame();
- })
- .catch(error => {
- console.error('Error fetching games:', error);
- });
- function loadGame() {
- let streamLink = gamesDropdown.value;
- if (streamLink) {
- streamLink = streamLink.replace('https://', ''); // remove 'https://'
- streamLink = streamLink.replace('http://', ''); // remove 'http://'
- // Fetch headers from the proxy URL
- fetch('/proxy/' + streamLink, { method: 'HEAD' })
- .then(response => {
- if (response.ok) {
- let type = response.headers.get('content-type');
- // Setup the player with the obtained type
- player.src({ src: '/proxy/' + streamLink, type: type });
- } else {
- console.error("Error fetching video type:", response.statusText);
- }
- })
- .catch(error => {
- console.error("Failed to fetch video type:", error);
- });
- }
- }
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment