-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
304 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<link rel="stylesheet" href="styles.css"> | ||
<link rel="shortcut icon" href="./favicon-light.png" type="image/x-icon"> | ||
<title>Thumbnailed</title> | ||
<script defer src="script.js"></script> | ||
</head> | ||
|
||
<body> | ||
<header> | ||
<div class="site-id"> | ||
<a href="./" ><h2>Thumbnailed</h2></a> | ||
</div> | ||
<div class="input-container"> | ||
<input id="url-input" name="url-input" type="url" placeholder="YouTube video URL" required pattern=""> | ||
<button id="input-btn" type="submit">Get Thumbnail</button> | ||
</div> | ||
</header> | ||
<main> | ||
<div id="display" class="image-display hidden"> | ||
<div class="image-container"> | ||
<div class="img-description"><span>Maximum</span></div> | ||
<img id="img-0" class="thumbnail" | ||
src="" | ||
width="1280" | ||
height="720" | ||
loading="lazy" | ||
alt="Maximum Resolution"> | ||
</div> | ||
<div class="image-container"> | ||
<div class="img-description"><span>Large</span></div> | ||
<img id="img-1" class="thumbnail" | ||
src="" | ||
width="640" | ||
height="480" | ||
loading="lazy" | ||
alt="High Resolution"> | ||
</div> | ||
<div class="image-container"> | ||
<div class="img-description"><span>Medium</span></div> | ||
<img id="img-2" class="thumbnail" | ||
src="" | ||
width="480" | ||
height="360" | ||
loading="lazy" | ||
alt="Standard Quality"> | ||
</div> | ||
<div class="image-container"> | ||
<div class="img-description"><span>Small</span></div> | ||
<img id="img-3" class="thumbnail" | ||
src="" | ||
width="320" | ||
height="180" | ||
loading="lazy" | ||
alt="Medium Quality"> | ||
</div> | ||
</div> | ||
</main> | ||
<footer></footer> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/** | ||
* @type {HTMLInputElement} | ||
*/ | ||
let input = document.getElementById('url-input'); | ||
/** | ||
* @type {NodeListOf<HTMLImageElement>} Nodelist of images | ||
*/ | ||
let images = document.querySelectorAll('.thumbnail'); | ||
/** | ||
* @type {HTMLButtonElement} button | ||
*/ | ||
let button = document.getElementById('input-btn'); | ||
/** | ||
* @type {HTMLDivElement} div | ||
*/ | ||
let display = document.getElementById('display'); | ||
/** | ||
* @type {HTMLLinkElement} favicon | ||
*/ | ||
let link = document.querySelector("link[rel~='icon']"); | ||
|
||
|
||
input.addEventListener('focus', () => {input.select()}); | ||
input.addEventListener('change', processThumbnail); | ||
input.addEventListener('input', processThumbnail); | ||
button.addEventListener('click', processThumbnail); | ||
|
||
processThumbnail(); | ||
if (!link) { | ||
link = document.createElement('link'); | ||
link.rel = 'icon'; | ||
document.head.appendChild(link); | ||
} | ||
|
||
if (matchMedia && matchMedia('(prefers-color-scheme: dark)').matches) { | ||
link.href = "./favicon-dark.png"; | ||
} | ||
|
||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { | ||
if (e.matches) { | ||
link.href = "./favicon-dark.png"; | ||
} else { | ||
link.href = "./favicon-light.png"; | ||
} | ||
}); | ||
|
||
function processThumbnail() { | ||
let url = input.value.trim(); | ||
let id = parseID(url); | ||
if (id === undefined) return; | ||
let thumbURLS = [ | ||
`https://i.ytimg.com/vi_webp/${id}/maxresdefault.webp`, | ||
`https://i.ytimg.com/vi_webp/${id}/sddefault.webp`, | ||
`https://i.ytimg.com/vi_webp/${id}/hqdefault.webp`, | ||
`https://i.ytimg.com/vi_webp/${id}/mqdefault.webp`, | ||
]; | ||
for (let i = 0; i < images.length; i++) { | ||
images[i].src = thumbURLS[i]; | ||
} | ||
display.classList.remove("hidden"); | ||
} | ||
|
||
/** | ||
* Parses video ID from YouTube URL | ||
* @param {string} url YouTube video URL | ||
* @return {string | undefined} YouTube video ID | ||
*/ | ||
function parseID(url) { | ||
let matches = url.match(/[/=]([0-9a-zA-Z-_]{11})[?&]?/); | ||
if (matches && matches.length) { | ||
return matches[1]; | ||
} | ||
return; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
:root { | ||
--background-color: #fff; | ||
--secondary-background-color: #f5f5f5; | ||
--text-color: #000; | ||
--accent-color: #172554; | ||
} | ||
|
||
|
||
@media (prefers-color-scheme: dark) { | ||
:root { | ||
--background-color: #111; | ||
--secondary-background-color: #1a1a1a; | ||
--text-color: #eee; | ||
--accent-color: #fca5a5; | ||
} | ||
} | ||
|
||
::-moz-focus-inner { | ||
outline: none; | ||
} | ||
|
||
* { | ||
padding: 0; | ||
margin: 0; | ||
box-sizing: border-box; | ||
} | ||
|
||
html { | ||
color-scheme: light dark; | ||
} | ||
|
||
body { | ||
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; | ||
background-color: var(--secondary-background-color); | ||
color: var(--text-color); | ||
min-height: 100svh; | ||
} | ||
|
||
*::selection { | ||
background-color: var(--accent-color); | ||
color: var(--background-color); | ||
} | ||
|
||
input:not(:focus)::selection { | ||
background-color: var(--text-color); | ||
color: var(--background-color); | ||
} | ||
|
||
header { | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
padding: 15px 50px; | ||
background-color: var(--background-color); | ||
color: var(--text-color); | ||
position: fixed; | ||
width: 100%; | ||
top: 0; | ||
left: 0; | ||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 4px rgba(0, 0, 0, 0.2); | ||
} | ||
|
||
.site-id a { | ||
text-decoration: none; | ||
color: var(--text-color); | ||
transition: outline 100ms linear, color 100ms ease-out; | ||
user-select: none; | ||
} | ||
|
||
.site-id a:hover { | ||
color: var(--accent-color); | ||
} | ||
|
||
.site-id a:focus-visible { | ||
outline: 2px solid var(--accent-color); | ||
outline-offset: 5px; | ||
} | ||
|
||
main { | ||
padding-top: 70px; | ||
} | ||
|
||
.input-container input, .input-container button { | ||
padding: 10px; | ||
margin: 5px; | ||
border: 1px solid var(--text-color); | ||
border-radius: 5px; | ||
background-color: var(--background-color); | ||
font-weight: 600; | ||
color: var(--text-color); | ||
transition: outline 100ms linear; | ||
} | ||
|
||
.input-container button{ | ||
transition: outline 100ms linear, background-color 200ms ease-out, transition-color 200ms ease-out; | ||
} | ||
|
||
.input-container input { | ||
min-width: 48ch; | ||
} | ||
|
||
.input-container button:hover, .input-container button:active{ | ||
color: var(--background-color); | ||
background-color: var(--accent-color); | ||
border: 1px solid var(--accent-color); | ||
} | ||
|
||
.input-container button:focus-visible { | ||
border-color: var(--accent-color); | ||
outline: 2px solid var(--accent-color) !important; | ||
} | ||
|
||
.input-container input:focus-visible { | ||
outline: 2px solid var(--accent-color); | ||
} | ||
|
||
|
||
.input-container input:focus { | ||
color: var(--text-color); | ||
background-color: var(--secondary-background-color); | ||
border: 1px solid var(--accent-color); | ||
} | ||
|
||
.img-description { | ||
padding: 10px; | ||
font-size: large; | ||
font-weight: 500; | ||
} | ||
|
||
.image-display { | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
flex-direction: column; | ||
max-width: 1020px; | ||
padding: 10px; | ||
margin: auto; | ||
} | ||
|
||
.image-container { | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
flex-direction: column; | ||
margin: 15px 0; | ||
} | ||
|
||
.image-container img { | ||
width: 100%; | ||
height: auto; | ||
border-radius: 10px; | ||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); | ||
transition: box-shadow 0.25s ease-out, border-radius 0.25s ease-in; | ||
/* border: 10px solid var(--background-color); */ | ||
} | ||
|
||
.image-container img:hover { | ||
box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22); | ||
border-radius: 2px; | ||
} | ||
|
||
.hidden { | ||
display: none; | ||
} |