fix: added onerror log

This commit is contained in:
lacni 2025-02-27 19:15:58 -05:00
parent db60f355b2
commit ae4bbc8baa

View file

@ -1,261 +1,265 @@
const webroot = document.querySelector("meta[name='webroot']").content; const webroot = document.querySelector("meta[name='webroot']").content;
const fileInput = document.querySelector('input[type="file"]'); const fileInput = document.querySelector('input[type="file"]');
const dropZone = document.getElementById("dropzone"); const dropZone = document.getElementById("dropzone");
const convertButton = document.querySelector("input[type='submit']"); const convertButton = document.querySelector("input[type='submit']");
const fileNames = []; const fileNames = [];
let fileType; let fileType;
let pendingFiles = 0; let pendingFiles = 0;
let formatSelected = false; let formatSelected = false;
dropZone.addEventListener("dragover", () => { dropZone.addEventListener("dragover", () => {
dropZone.classList.add("dragover"); dropZone.classList.add("dragover");
}); });
dropZone.addEventListener("dragleave", () => { dropZone.addEventListener("dragleave", () => {
dropZone.classList.remove("dragover"); dropZone.classList.remove("dragover");
}); });
dropZone.addEventListener("drop", () => { dropZone.addEventListener("drop", () => {
dropZone.classList.remove("dragover"); dropZone.classList.remove("dragover");
}); });
const selectContainer = document.querySelector("form .select_container"); const selectContainer = document.querySelector("form .select_container");
const updateSearchBar = () => { const updateSearchBar = () => {
const convertToInput = document.querySelector( const convertToInput = document.querySelector(
"input[name='convert_to_search']", "input[name='convert_to_search']",
); );
const convertToPopup = document.querySelector(".convert_to_popup"); const convertToPopup = document.querySelector(".convert_to_popup");
const convertToGroupElements = document.querySelectorAll(".convert_to_group"); const convertToGroupElements = document.querySelectorAll(".convert_to_group");
const convertToGroups = {}; const convertToGroups = {};
const convertToElement = document.querySelector("select[name='convert_to']"); const convertToElement = document.querySelector("select[name='convert_to']");
const showMatching = (search) => { const showMatching = (search) => {
for (const [targets, groupElement] of Object.values(convertToGroups)) { for (const [targets, groupElement] of Object.values(convertToGroups)) {
let matchingTargetsFound = 0; let matchingTargetsFound = 0;
for (const target of targets) { for (const target of targets) {
if (target.dataset.target.includes(search)) { if (target.dataset.target.includes(search)) {
matchingTargetsFound++; matchingTargetsFound++;
target.classList.remove("hidden"); target.classList.remove("hidden");
target.classList.add("flex"); target.classList.add("flex");
} else { } else {
target.classList.add("hidden"); target.classList.add("hidden");
target.classList.remove("flex"); target.classList.remove("flex");
} }
} }
if (matchingTargetsFound === 0) { if (matchingTargetsFound === 0) {
groupElement.classList.add("hidden"); groupElement.classList.add("hidden");
groupElement.classList.remove("flex"); groupElement.classList.remove("flex");
} else { } else {
groupElement.classList.remove("hidden"); groupElement.classList.remove("hidden");
groupElement.classList.add("flex"); groupElement.classList.add("flex");
} }
} }
}; };
for (const groupElement of convertToGroupElements) { for (const groupElement of convertToGroupElements) {
const groupName = groupElement.dataset.converter; const groupName = groupElement.dataset.converter;
const targetElements = groupElement.querySelectorAll(".target"); const targetElements = groupElement.querySelectorAll(".target");
const targets = Array.from(targetElements); const targets = Array.from(targetElements);
for (const target of targets) { for (const target of targets) {
target.onmousedown = () => { target.onmousedown = () => {
convertToElement.value = target.dataset.value; convertToElement.value = target.dataset.value;
convertToInput.value = `${target.dataset.target} using ${target.dataset.converter}`; convertToInput.value = `${target.dataset.target} using ${target.dataset.converter}`;
formatSelected = true; formatSelected = true;
if (pendingFiles === 0 && fileNames.length > 0) { if (pendingFiles === 0 && fileNames.length > 0) {
convertButton.disabled = false; convertButton.disabled = false;
} }
showMatching(""); showMatching("");
}; };
} }
convertToGroups[groupName] = [targets, groupElement]; convertToGroups[groupName] = [targets, groupElement];
} }
convertToInput.addEventListener("input", (e) => { convertToInput.addEventListener("input", (e) => {
showMatching(e.target.value.toLowerCase()); showMatching(e.target.value.toLowerCase());
}); });
convertToInput.addEventListener("search", () => { convertToInput.addEventListener("search", () => {
// when the user clears the search bar using the 'x' button // when the user clears the search bar using the 'x' button
convertButton.disabled = true; convertButton.disabled = true;
formatSelected = false; formatSelected = false;
}); });
convertToInput.addEventListener("blur", (e) => { convertToInput.addEventListener("blur", (e) => {
// Keep the popup open even when clicking on a target button // Keep the popup open even when clicking on a target button
// for a split second to allow the click to go through // for a split second to allow the click to go through
if (e?.relatedTarget?.classList?.contains("target")) { if (e?.relatedTarget?.classList?.contains("target")) {
convertToPopup.classList.add("hidden"); convertToPopup.classList.add("hidden");
convertToPopup.classList.remove("flex"); convertToPopup.classList.remove("flex");
return; return;
} }
convertToPopup.classList.add("hidden"); convertToPopup.classList.add("hidden");
convertToPopup.classList.remove("flex"); convertToPopup.classList.remove("flex");
}); });
convertToInput.addEventListener("focus", () => { convertToInput.addEventListener("focus", () => {
convertToPopup.classList.remove("hidden"); convertToPopup.classList.remove("hidden");
convertToPopup.classList.add("flex"); convertToPopup.classList.add("flex");
}); });
}; };
// Add a 'change' event listener to the file input element // Add a 'change' event listener to the file input element
fileInput.addEventListener("change", (e) => { fileInput.addEventListener("change", (e) => {
// Get the selected files from the event target // Get the selected files from the event target
const files = e.target.files; const files = e.target.files;
// Select the file-list table // Select the file-list table
const fileList = document.querySelector("#file-list"); const fileList = document.querySelector("#file-list");
// Loop through the selected files // Loop through the selected files
for (const file of files) { for (const file of files) {
// Create a new table row for each file // Create a new table row for each file
const row = document.createElement("tr"); const row = document.createElement("tr");
row.innerHTML = ` row.innerHTML = `
<td>${file.name}</td> <td>${file.name}</td>
<td><progress max="100"></progress></td> <td><progress max="100"></progress></td>
<td>${(file.size / 1024).toFixed(2)} kB</td> <td>${(file.size / 1024).toFixed(2)} kB</td>
<td><a onclick="deleteRow(this)">Remove</a></td> <td><a onclick="deleteRow(this)">Remove</a></td>
`; `;
if (!fileType) { if (!fileType) {
fileType = file.name.split(".").pop(); fileType = file.name.split(".").pop();
fileInput.setAttribute("accept", `.${fileType}`); fileInput.setAttribute("accept", `.${fileType}`);
setTitle(); setTitle();
// choose the option that matches the file type // choose the option that matches the file type
// for (const option of convertFromSelect.children) { // for (const option of convertFromSelect.children) {
// console.log(option.value); // console.log(option.value);
// if (option.value === fileType) { // if (option.value === fileType) {
// option.selected = true; // option.selected = true;
// } // }
// } // }
fetch(`${webroot}/conversions`, { fetch(`${webroot}/conversions`, {
method: "POST", method: "POST",
body: JSON.stringify({ fileType: fileType }), body: JSON.stringify({ fileType: fileType }),
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
}) })
.then((res) => res.text()) .then((res) => res.text())
.then((html) => { .then((html) => {
selectContainer.innerHTML = html; selectContainer.innerHTML = html;
updateSearchBar(); updateSearchBar();
}) })
.catch((err) => console.log(err)); .catch((err) => console.log(err));
} }
// Append the row to the file-list table // Append the row to the file-list table
fileList.appendChild(row); fileList.appendChild(row);
//Imbed row into the file to reference later //Imbed row into the file to reference later
file.htmlRow = row; file.htmlRow = row;
// Append the file to the hidden input // Append the file to the hidden input
fileNames.push(file.name); fileNames.push(file.name);
} }
uploadFiles(files); uploadFiles(files);
}); });
const setTitle = () => { const setTitle = () => {
const title = document.querySelector("h1"); const title = document.querySelector("h1");
title.textContent = `Convert ${fileType ? `.${fileType}` : ""}`; title.textContent = `Convert ${fileType ? `.${fileType}` : ""}`;
}; };
// Add a onclick for the delete button // Add a onclick for the delete button
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const deleteRow = (target) => { const deleteRow = (target) => {
const filename = target.parentElement.parentElement.children[0].textContent; const filename = target.parentElement.parentElement.children[0].textContent;
const row = target.parentElement.parentElement; const row = target.parentElement.parentElement;
row.remove(); row.remove();
// remove from fileNames // remove from fileNames
const index = fileNames.indexOf(filename); const index = fileNames.indexOf(filename);
fileNames.splice(index, 1); fileNames.splice(index, 1);
// reset fileInput // reset fileInput
fileInput.value = ""; fileInput.value = "";
// if fileNames is empty, reset fileType // if fileNames is empty, reset fileType
if (fileNames.length === 0) { if (fileNames.length === 0) {
fileType = null; fileType = null;
fileInput.removeAttribute("accept"); fileInput.removeAttribute("accept");
convertButton.disabled = true; convertButton.disabled = true;
setTitle(); setTitle();
} }
fetch(`${webroot}/delete`, { fetch(`${webroot}/delete`, {
method: "POST", method: "POST",
body: JSON.stringify({ filename: filename }), body: JSON.stringify({ filename: filename }),
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
}) })
.catch((err) => console.log(err)); .catch((err) => console.log(err));
}; };
const uploadFiles = (files) => { const uploadFiles = (files) => {
convertButton.disabled = true; convertButton.disabled = true;
convertButton.textContent = "Uploading..."; convertButton.textContent = "Uploading...";
pendingFiles += 1; pendingFiles += 1;
const formData = new FormData(); const formData = new FormData();
for (const file of files) { for (const file of files) {
formData.append("file", file, file.name); formData.append("file", file, file.name);
} }
let xhr = new XMLHttpRequest(); let xhr = new XMLHttpRequest();
xhr.open("POST", `${webroot}/upload`, true); xhr.open("POST", `${webroot}/upload`, true);
xhr.onload = (e) => { xhr.onload = (e) => {
let data = JSON.parse(xhr.responseText); let data = JSON.parse(xhr.responseText);
pendingFiles -= 1; pendingFiles -= 1;
if (pendingFiles === 0) { if (pendingFiles === 0) {
if (formatSelected) { if (formatSelected) {
convertButton.disabled = false; convertButton.disabled = false;
} }
convertButton.textContent = "Convert"; convertButton.textContent = "Convert";
} }
//Remove the progress bar when upload is done //Remove the progress bar when upload is done
for (const file of files) { for (const file of files) {
let progressbar = file.htmlRow.getElementsByTagName("progress"); let progressbar = file.htmlRow.getElementsByTagName("progress");
progressbar[0].parentElement.remove(); progressbar[0].parentElement.remove();
} }
console.log(data); console.log(data);
}; };
xhr.upload.onprogress = (e) => { xhr.upload.onprogress = (e) => {
//All files upload together are binded by the same progress. The loop should probably be on the call to this function to track each upload individually. //All files upload together are binded by the same progress. The loop should probably be on the call to this function to track each upload individually.
let sent = e.loaded; let sent = e.loaded;
let total = e.total; let total = e.total;
console.log("upload progress:", (100 * sent) / total); console.log("upload progress:", (100 * sent) / total);
for (const file of files) { for (const file of files) {
let progressbar = file.htmlRow.getElementsByTagName("progress"); let progressbar = file.htmlRow.getElementsByTagName("progress");
progressbar[0].value = ((100 * sent) / total); progressbar[0].value = ((100 * sent) / total);
} }
}; };
xhr.send(formData); xhr.onerror = (e) => {
}; console.log(e);
};
const formConvert = document.querySelector(`form[action='${webroot}/convert']`);
xhr.send(formData);
formConvert.addEventListener("submit", () => { };
const hiddenInput = document.querySelector("input[name='file_names']");
hiddenInput.value = JSON.stringify(fileNames); const formConvert = document.querySelector(`form[action='${webroot}/convert']`);
});
formConvert.addEventListener("submit", () => {
updateSearchBar(); const hiddenInput = document.querySelector("input[name='file_names']");
hiddenInput.value = JSON.stringify(fileNames);
});
updateSearchBar();