htmx is so cool
This commit is contained in:
parent
e04ef78a42
commit
3ed7b0b5c7
11 changed files with 557 additions and 400 deletions
|
@ -21,6 +21,60 @@
|
|||
line-height: 40px;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
/* Positioning and Sizing */
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
position: relative;
|
||||
margin: 50px auto;
|
||||
/* Centering the spinner */
|
||||
|
||||
/* Text Styling */
|
||||
color: #555;
|
||||
text-align: center;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
padding-top: 80px;
|
||||
/* Adjust as needed for text position */
|
||||
|
||||
/* Adding a background to the spinner for better visibility */
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Keyframes for the spinner animation */
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Spinner Animation */
|
||||
.spinner::before {
|
||||
content: '';
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 40px;
|
||||
/* Spinner Size */
|
||||
height: 40px;
|
||||
margin-top: -20px;
|
||||
/* Half of height */
|
||||
margin-left: -20px;
|
||||
/* Half of width */
|
||||
border-radius: 50%;
|
||||
border: 2px solid transparent;
|
||||
border-top-color: #007bff;
|
||||
/* Spinner Color */
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
#search {
|
||||
padding: 6px 12px;
|
||||
background: rgb(31, 32, 35);
|
||||
|
|
|
@ -1,59 +1,74 @@
|
|||
/* eslint-disable no-undef */
|
||||
/* eslint-env browser: true */
|
||||
|
||||
let files;
|
||||
|
||||
function copyURI(evt) {
|
||||
evt.preventDefault();
|
||||
navigator.clipboard.writeText(absolutePath(evt.target.getAttribute("src"))).then(() => {
|
||||
/* clipboard successfully set */
|
||||
console.log("copied");
|
||||
}, () => {
|
||||
/* clipboard write failed */
|
||||
console.log("failed");
|
||||
});
|
||||
navigator.clipboard
|
||||
.writeText(absolutePath(evt.target.getAttribute("src")))
|
||||
.then(
|
||||
() => {
|
||||
/* clipboard successfully set */
|
||||
console.log("copied");
|
||||
},
|
||||
() => {
|
||||
/* clipboard write failed */
|
||||
console.log("failed");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function copyA(evt) {
|
||||
evt.preventDefault();
|
||||
navigator.clipboard.writeText(absolutePath(evt.target.getAttribute("href"))).then(() => {
|
||||
console.log("copied");
|
||||
}, () => {
|
||||
console.log("failed");
|
||||
});
|
||||
navigator.clipboard
|
||||
.writeText(absolutePath(evt.target.getAttribute("href")))
|
||||
.then(
|
||||
() => {
|
||||
console.log("copied");
|
||||
},
|
||||
() => {
|
||||
console.log("failed");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function copyPath(evt) {
|
||||
navigator.clipboard.writeText(absolutePath(evt)).then(() => {
|
||||
console.log("copied");
|
||||
}, () => {
|
||||
console.log("failed");
|
||||
});
|
||||
navigator.clipboard.writeText(absolutePath(evt)).then(
|
||||
() => {
|
||||
console.log("copied");
|
||||
},
|
||||
() => {
|
||||
console.log("failed");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function absolutePath (href) {
|
||||
function absolutePath(href) {
|
||||
let link = document.createElement("a");
|
||||
link.href = href;
|
||||
return link.href;
|
||||
}
|
||||
|
||||
function extension(string) {
|
||||
return string.slice((string.lastIndexOf(".") - 2 >>> 0) + 2);
|
||||
return string.slice(((string.lastIndexOf(".") - 2) >>> 0) + 2);
|
||||
}
|
||||
|
||||
let dropArea = document.getElementById("dropArea");
|
||||
|
||||
["dragenter", "dragover", "dragleave", "drop"].forEach(eventName => {
|
||||
["dragenter", "dragover", "dragleave", "drop"].forEach((eventName) => {
|
||||
dropArea.addEventListener(eventName, preventDefaults, false);
|
||||
});
|
||||
|
||||
function preventDefaults (e) {
|
||||
function preventDefaults(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
["dragenter", "dragover"].forEach(eventName => {
|
||||
["dragenter", "dragover"].forEach((eventName) => {
|
||||
dropArea.addEventListener(eventName, highlight, false);
|
||||
})
|
||||
|
||||
;["dragleave", "drop"].forEach(eventName => {
|
||||
});
|
||||
["dragleave", "drop"].forEach((eventName) => {
|
||||
dropArea.addEventListener(eventName, unhighlight, false);
|
||||
});
|
||||
|
||||
|
@ -100,16 +115,14 @@ function handleFiles(files) {
|
|||
files.forEach(previewFile);
|
||||
}
|
||||
|
||||
|
||||
function previewFile(file) {
|
||||
let reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onloadend = function() {
|
||||
reader.onloadend = function () {
|
||||
let img = document.createElement("img");
|
||||
img.src = reader.result;
|
||||
img.className = "image";
|
||||
document.getElementById("gallery").appendChild(img);
|
||||
console.log(document.getElementById("fileupload"));
|
||||
document.getElementById("fileupload").src = img.src;
|
||||
};
|
||||
}
|
||||
|
@ -118,15 +131,20 @@ function uploadFile(file) {
|
|||
let xhr = new XMLHttpRequest();
|
||||
let formData = new FormData();
|
||||
let reader = new FileReader();
|
||||
|
||||
|
||||
xhr.open("POST", "/", true);
|
||||
|
||||
xhr.addEventListener("readystatechange", function(e) {
|
||||
if (xhr.readyState == 4 && xhr.status == 200) {
|
||||
location.reload();
|
||||
}
|
||||
else if (xhr.readyState == 4 && xhr.status != 200) {
|
||||
alert(`Upload failed, error code: ${xhr.status}`)
|
||||
xhr.addEventListener("readystatechange", function (e) {
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status == 200) {
|
||||
let response = xhr.responseText;
|
||||
//document.getElementById("embedder-list").innerHTML = response;
|
||||
htmx.ajax("GET", "/media-list", {target: "#embedder-list", swap: "innerHTML"});
|
||||
document.getElementById("gallery").innerHTML = "";
|
||||
htmx.process(document.body);
|
||||
} else {
|
||||
alert(`Upload failed, error code: ${xhr.status}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -136,7 +154,6 @@ function uploadFile(file) {
|
|||
|
||||
formData.append("fileupload", file);
|
||||
formData.append("expire", document.getElementById("expire").value);
|
||||
console.log(formData);
|
||||
xhr.send(formData);
|
||||
}
|
||||
|
||||
|
@ -149,18 +166,27 @@ function openFullSize(imageUrl) {
|
|||
video.src = imageUrl;
|
||||
video.controls = true;
|
||||
|
||||
if (extension(imageUrl) == ".jpg" || extension(imageUrl) == ".png" || extension(imageUrl) == ".gif" || extension(imageUrl) == ".jpeg" || extension(imageUrl) == ".webp") {
|
||||
if (
|
||||
extension(imageUrl) == ".jpg" ||
|
||||
extension(imageUrl) == ".png" ||
|
||||
extension(imageUrl) == ".gif" ||
|
||||
extension(imageUrl) == ".jpeg" ||
|
||||
extension(imageUrl) == ".webp"
|
||||
) {
|
||||
modal.appendChild(img);
|
||||
}
|
||||
else if (extension(imageUrl) == ".mp4" || extension(imageUrl) == ".webm" || extension(imageUrl) == ".mov") {
|
||||
} else if (
|
||||
extension(imageUrl) == ".mp4" ||
|
||||
extension(imageUrl) == ".webm" ||
|
||||
extension(imageUrl) == ".mov"
|
||||
) {
|
||||
modal.appendChild(video);
|
||||
}
|
||||
|
||||
|
||||
// Add the modal to the page
|
||||
document.body.appendChild(modal);
|
||||
|
||||
|
||||
// Add an event listener to close the modal when the user clicks on it
|
||||
modal.addEventListener("click", function() {
|
||||
modal.addEventListener("click", function () {
|
||||
modal.remove();
|
||||
});
|
||||
}
|
||||
|
@ -172,20 +198,112 @@ searchInput.addEventListener("input", () => {
|
|||
let mediaList = document.querySelectorAll("ul.embedder-list li");
|
||||
|
||||
mediaList.forEach((li) => {
|
||||
if (!li.id.toLowerCase().includes(searchValue)) { //make lowercase to allow case insensitivity
|
||||
if (!li.id.toLowerCase().includes(searchValue)) {
|
||||
//make lowercase to allow case insensitivity
|
||||
li.classList.add("hide");
|
||||
li.classList.remove("show");
|
||||
li.addEventListener("animationend", function() {
|
||||
if (searchInput.value !== "") {
|
||||
this.style.display = "none";
|
||||
}
|
||||
}, {once: true}); // The {once: true} option automatically removes the event listener after it has been called
|
||||
li.addEventListener(
|
||||
"animationend",
|
||||
function () {
|
||||
if (searchInput.value !== "") {
|
||||
this.style.display = "none";
|
||||
}
|
||||
},
|
||||
{ once: true }
|
||||
); // The {once: true} option automatically removes the event listener after it has been called
|
||||
} else {
|
||||
li.style.display = "";
|
||||
li.style.display = "";
|
||||
li.classList.remove("hide");
|
||||
if (searchValue === "" && !li.classList.contains("show")) {
|
||||
if (searchValue === "" && !li.classList.contains("show")) {
|
||||
li.classList.add("show");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function checkFileAvailability(filePath) {
|
||||
const checkFile = () => {
|
||||
console.log(`Checking if ${filePath} is processed...`);
|
||||
fetch(`/uploads/${filePath}-progress.json`)
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
console.log(`${filePath} still processing`);
|
||||
return response.json();
|
||||
} else {
|
||||
console.log(`${filePath} finished processing`);
|
||||
console.log(`/uploads/720p-${filePath}-progress.json finished`);
|
||||
clearInterval(interval);
|
||||
createVideoElement(filePath);
|
||||
return;
|
||||
}
|
||||
})
|
||||
.then((jsonData) => {
|
||||
// Handle your JSON data here
|
||||
console.log(jsonData);
|
||||
})
|
||||
.catch((error) => console.error("Error:", error));
|
||||
};
|
||||
|
||||
checkFile();
|
||||
const interval = setInterval(checkFile, 5000);
|
||||
}
|
||||
|
||||
function createVideoElement(filePath) {
|
||||
const videoContainer = document.getElementById(`video-${filePath}`);
|
||||
videoContainer.outerHTML = `
|
||||
<video id='video-${filePath}' class="image" autoplay loop muted playsinline loading="lazy">
|
||||
<source src="/uploads/720p-${filePath}" loading="lazy">
|
||||
</video>
|
||||
`;
|
||||
videoContainer.style.display = "block";
|
||||
document.getElementById(`spinner-${filePath}`).style.display = "none";
|
||||
}
|
||||
|
||||
async function updateMediaList() {
|
||||
try {
|
||||
const response = await fetch("/media-list");
|
||||
if (!response.ok) {
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
|
||||
const data = await response.text();
|
||||
|
||||
document.getElementById("embedder-list").innerHTML = data;
|
||||
htmx.process(document.body);
|
||||
} catch (error) {
|
||||
console.error("There was a problem with the fetch operation:", error);
|
||||
}
|
||||
}
|
||||
|
||||
function refreshMediaList(files) {
|
||||
files.forEach(file => {
|
||||
console.log(`Checking ${file.path}...`);
|
||||
if (videoExtensions.includes(extension(file.path))) {
|
||||
const progressFileName = `uploads/${file.path}-progress.json`;
|
||||
console.log(`Fetching ${progressFileName}...`);
|
||||
checkFileAvailability(file.path);
|
||||
} else {
|
||||
console.log(`File ${file.path} is not a video, displaying...`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const videoExtensions = [
|
||||
".mp4",
|
||||
".mov",
|
||||
".avi",
|
||||
".flv",
|
||||
".mkv",
|
||||
".wmv",
|
||||
".webm",
|
||||
];
|
||||
const imageExtensions = [
|
||||
".jpg",
|
||||
".jpeg",
|
||||
".png",
|
||||
".gif",
|
||||
".bmp",
|
||||
".svg",
|
||||
".tiff",
|
||||
".webp",
|
||||
];
|
Loading…
Add table
Add a link
Reference in a new issue