Skip to content

Commit

Permalink
Support multiple files
Browse files Browse the repository at this point in the history
  • Loading branch information
KamilDev committed Dec 7, 2024
1 parent 267abe3 commit 4d685da
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 31 deletions.
5 changes: 3 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@ <h1>File Download Simulator</h1>
without the delay of a real network transfer.
</p>
<div class="upload-area">
<input type="file" id="fileInput" class="file-input" />
<input type="file" id="fileInput" class="file-input" multiple />
<label
for="fileInput"
class="file-label"
role="button"
tabindex="0"
autofocus
>
Choose any file
Choose any files
</label>
</div>
<div id="fileInfo" class="file-info"></div>
<div id="downloadList" class="download-list"></div>
</div>
<script src="script.js"></script>
</body>
Expand Down
81 changes: 58 additions & 23 deletions script.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,73 @@
document.addEventListener("DOMContentLoaded", () => {
const fileInput = document.getElementById("fileInput");
const fileInfo = document.getElementById("fileInfo");
const downloadList = document.getElementById("downloadList");
const fileLabel = document.querySelector(".file-label");

function handleFile(file) {
if (!file) return;
function formatFileSize(bytes) {
if (bytes === 0) return "0 B";
const k = 1024;
const sizes = ["B", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
}

function handleFiles(files) {
if (!files || files.length === 0) return;

// Clear previous downloads
downloadList.innerHTML = "";

// Start downloads
Array.from(files).forEach((file) => {
const blobUrl = URL.createObjectURL(file);
const link = document.createElement("a");
link.href = blobUrl;
link.download = file.name;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(blobUrl);
});

// Display summary
const totalSize = Array.from(files).reduce(
(acc, file) => acc + file.size,
0
);
fileInfo.textContent = `Downloaded ${files.length} file${
files.length === 1 ? "" : "s"
} (${formatFileSize(totalSize)} total)`;

// Display file information
const fileSizeMB = (file.size / (1024 * 1024)).toFixed(2);
fileInfo.textContent = `Selected: ${file.name} (${fileSizeMB} MB)`;
// Update UI for each file
Array.from(files).forEach((file) => {
const downloadItem = document.createElement("div");
downloadItem.className = "download-item";

// Create a blob URL and trigger download immediately
const blobUrl = URL.createObjectURL(file);
const link = document.createElement("a");
link.href = blobUrl;
link.download = file.name;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
const nameSpan = document.createElement("span");
nameSpan.className = "download-item-name";
nameSpan.textContent = file.name;

const sizeSpan = document.createElement("span");
sizeSpan.className = "download-item-size";
sizeSpan.textContent = formatFileSize(file.size);

downloadItem.appendChild(nameSpan);
downloadItem.appendChild(sizeSpan);
downloadList.insertBefore(downloadItem, downloadList.firstChild);
});

// Clean up
URL.revokeObjectURL(blobUrl);
fileInput.value = ""; // Reset file input
}

function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}

// Handle file input change
fileInput.addEventListener("change", (e) => {
handleFile(e.target.files[0]);
handleFiles(e.target.files);
});

// Make file input keyboard accessible
Expand All @@ -42,11 +83,6 @@ document.addEventListener("DOMContentLoaded", () => {
document.body.addEventListener(eventName, preventDefaults, false);
});

function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}

// Handle drag and drop
document.body.addEventListener("dragenter", () => {
document.body.classList.add("dragging");
Expand All @@ -60,7 +96,6 @@ document.addEventListener("DOMContentLoaded", () => {

document.body.addEventListener("drop", (e) => {
document.body.classList.remove("dragging");
const file = e.dataTransfer.files[0];
handleFile(file);
handleFiles(e.dataTransfer.files);
});
});
40 changes: 34 additions & 6 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ body {
display: flex;
justify-content: center;
align-items: center;
transition: background-color 0.3s ease;
margin: 0;
position: relative;
}
Expand All @@ -52,7 +51,7 @@ body.dragging::before {
}

body.dragging::after {
content: 'Drop file here';
content: '';
position: fixed;
top: 50%;
left: 50%;
Expand All @@ -71,7 +70,6 @@ body.dragging::after {
box-shadow: 0 2px 10px var(--shadow);
width: 90%;
max-width: 600px;
transition: background-color 0.3s ease, box-shadow 0.3s ease;
}

h1 {
Expand All @@ -82,7 +80,7 @@ h1 {

.upload-area {
text-align: center;
margin-bottom: 2rem;
margin-bottom: 0;
}

.file-input {
Expand All @@ -96,7 +94,7 @@ h1 {
color: white;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
transition: background-color 0.2s ease;
}

.file-label:hover {
Expand All @@ -105,8 +103,38 @@ h1 {

.file-info {
text-align: center;
margin: 1rem 0;
margin: 1.5rem 0 1rem;
color: var(--text-secondary);
font-weight: 500;
}

.download-list {
max-height: 300px;
overflow-y: auto;
margin: 1rem 0 0.5rem;
}

.download-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75rem 1rem;
margin: 0.5rem 0;
background-color: var(--background);
border-radius: 6px;
}

.download-item-name {
color: var(--text);
font-weight: 500;
margin-right: 1rem;
word-break: break-all;
}

.download-item-size {
color: var(--text-secondary);
font-size: 0.9rem;
white-space: nowrap;
}

.description {
Expand Down

0 comments on commit 4d685da

Please sign in to comment.