/**
* Drag and drop
*/
const drop = document.getElementById("drop");
drop.addEventListener('dragover', e => {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
drop.style.background = "rgba(12,99,250,0.3)";
});
drop.addEventListener('dragleave', () =>
drop.style.background = "white"
);
drop.addEventListener('drop', e => {
e.stopPropagation();
e.preventDefault();
drop.style.background = "white";
const items = e.dataTransfer.items;
const uploadedFiles = [];
for (let i = 0; i < items.length; i++) {
const item = items[i].webkitGetAsEntry();
const file = items[i].getAsFile();
// TODO: Consider using current date due to updated lastModified state at upload
const date = new Date(file.lastModified);
const row = document.getElementById("table").insertRow(-1);
row.setAttribute("data-href", file.name);
// TODO: Differentiate between file and directory upload in frontend
row.insertCell(0).innerHTML = "
| ";
row.insertCell(1).innerHTML = file.name;
row.insertCell(2).innerHTML = bytesToSize(file.size);
row.insertCell(3).innerHTML = `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
row.insertCell(4).innerHTML = " | ";
row.insertCell(5).innerHTML = "";
row.insertCell(6).innerHTML = " | ";
setListeners();
// TODO: Add empty directory upload support
const iterateFiles = subItem => {
if (subItem.isDirectory) {
let directoryReader = subItem.createReader();
directoryReader.readEntries(entries => {
entries.forEach(entry => {
iterateFiles(entry);
});
});
} else {
subItem.file(subFile => {
// TODO: Add support for nested directory upload with more than 1 layer - via webkitRelativePath on firefox?
if (!uploadedFiles.includes(`/${path}/${file.name}/${subFile.name}`.clean())) {
const formData = new FormData();
const request = new XMLHttpRequest();
request.upload.onprogress = e => {
if (e.lengthComputable) {
console.log(`${subFile.name}: ${e.loaded / e.total * 100}%`)
}
};
uploadedFiles.push(`/${path}/${file.name}/${subFile.name}`.clean());
formData.append("file", subFile);
if (subFile.webkitRelativePath === "") request.open("POST", `/upload/${path}/${file.name}`.clean());
else request.open("POST", `/upload/${path}`.clean());
request.send(formData);
}
})
}
};
if (item.isDirectory) {
iterateFiles(item);
} else {
if (!uploadedFiles.includes(`/${path}/${file.name}`.clean())) {
const formData = new FormData();
const request = new XMLHttpRequest();
request.upload.onprogress = e => {
if (e.lengthComputable) {
console.log(`${file.name}: ${e.loaded / e.total * 100}%`)
}
};
formData.append("file", file);
request.open("POST", `/upload/${path}`.clean());
request.send(formData);
}
}
}
function bytesToSize(bytes) {
const sizes = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
if (bytes === 0) return '0 Byte';
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
}
}, false);
/**
* Set up listeners
*/
function setListeners() {
if (isShared) {
const accessId = location.pathname === '/shared' ? location.search.split('=')[1] : undefined;
document.querySelectorAll('[data-path], [data-href]').forEach(element => {
element.addEventListener('click', () => {
const request = new XMLHttpRequest();
const formData = new FormData();
formData.append('accessId', accessId);
formData.append('fileName', element.getAttribute('data-path') || element.getAttribute('data-href'));
request.open('POST', '/shared', true);
request.onload = () => {
if (request.status === 200 && request.readyState === 4) {
if (request.responseText)
window.location = `/shared?id=${request.responseText}`;
else alert('File not found!');
}
};
request.send(formData)
});
});
} else {
document.querySelectorAll("[data-path]").forEach(element => {
const images = ["jpg", "jpeg", "png", "gif", "bmp", "webp", "svg", "tiff"];
const videos = ["mp4", "m4v", "mov", "webm", "avi", "wmv", "mpg", "mpv", "mpeg", "ogv"];
const audio = ["mp3", "m4a", "wav", "ogg"];
const filename = element.getAttribute("data-path");
const extension = /(?:\.([^.]+))?$/.exec(filename)[1].toLowerCase();
if (images.includes(extension)) {
element.setAttribute("data-bp", filename);
element.setAttribute("data-image", "");
} else if (videos.includes(extension)) {
element.setAttribute("data-src", filename);
element.setAttribute("data-video", "");
} else if (audio.includes(extension)) {
element.setAttribute("data-src", filename);
element.setAttribute("data-audio", "");
}
element.addEventListener("click", () => {
if (images.indexOf(extension) === -1 && videos.indexOf(extension) === -1 && audio.indexOf(extension) === -1)
window.location = `/files/${path}/${filename}`.clean(); // download binary files
});
});
// images
document.querySelectorAll("[data-image]").forEach(element => {
element.addEventListener("click", image => {
BigPicture({
el: image.currentTarget,
gallery: document.querySelectorAll("[data-image]")
})
});
});
// videos // TODO: Fix timeout exception and scrubbing issues with chromium based browsers
document.querySelectorAll("[data-video]").forEach(element => {
element.addEventListener("click", video => {
BigPicture({
el: video.currentTarget,
vidSrc: video.currentTarget.getAttribute("data-src")
})
});
});
// audio // TODO: Fix IOException and scrubbing issues with chromium based browsers
document.querySelectorAll("[data-audio]").forEach(element => {
element.addEventListener("click", audio => {
BigPicture({
el: audio.currentTarget,
audio: audio.currentTarget.getAttribute("data-src")
});
});
});
// normal files
document.querySelectorAll("[data-href]").forEach(element => {
element.addEventListener("click", () => {
window.location = `/files/${path}/${element.getAttribute("data-href")}`.clean();
})
});
}
// deletion button
document.querySelectorAll(".delete").forEach(element => {
element.addEventListener("click", e => {
e.stopPropagation();
const request = new XMLHttpRequest();
const parent = e.target.closest("tr");
const fileName = parent.getAttribute("data-href") || parent.getAttribute("data-path");
if (confirm(`Do you really want to delete: ${fileName}?`)) {
request.open("POST", `/delete/${path}/${fileName}`.clean(), true);
request.send();
parent.remove();
} else console.log("File not deleted!")
})
});
// download button
document.querySelectorAll(".download").forEach(element => {
element.addEventListener("click", e => {
e.stopPropagation();
})
});
document.querySelectorAll(".downloadButton").forEach(element => {
element.addEventListener("click", e => {
console.log(e);
e.stopPropagation();
e.target.children[0].click()
})
});
// share button
document.querySelectorAll(".share").forEach(element => {
element.addEventListener("click", e => {
e.stopPropagation();
const request = new XMLHttpRequest();
const parent = e.target.closest("tr");
const fileName = parent.getAttribute("data-href") || parent.getAttribute("data-path");
const type = fileName.endsWith('/') ? 'dir' : 'file';
request.open("POST", `/share/${path}/${fileName}?type=${type}`.clean());
request.onload = () => {
if (request.readyState === 4) {
if (request.status === 200) { // TODO: fix clipboard in Firefox
const input = document.createElement('input');
input.setAttribute('value', request.responseText);
document.body.appendChild(input);
input.select();
document.execCommand('copy');
document.body.removeChild(input);
alert(`Copied url to clipboard!\n${request.responseText}`);
} else {
alert("Something went wrong.");
}
}
};
request.send();
})
});
}
setListeners();
/**
* Set up sort features
*/
function sortTable(table, col, ascending) {
const tb = table.tBodies[0];
let tr = Array.prototype.slice.call(tb.rows, 0);
ascending = -((+ascending) || -1);
tr = tr.sort((a, b) => {
if (a.cells[col].getAttribute("data-size") !== null)
return ascending * (Number(a.cells[col].getAttribute("data-size")) > Number(b.cells[col].getAttribute("data-size")) ? 1 : -1);
else if (a.cells[col].getAttribute("data-date") !== null)
return ascending * (Number(a.cells[col].getAttribute("data-date")) > Number(b.cells[col].getAttribute("data-date")) ? 1 : -1);
else
return ascending * (a.cells[col].textContent.trim().localeCompare(b.cells[col].textContent.trim()))
});
for (let i = 0; i < tr.length; ++i) tb.appendChild(tr[i]);
}
document.querySelectorAll("thead tr > th").forEach((header, index) => {
header.addEventListener("click", () => {
const ascending = header.getAttribute("data-asc");
sortTable(document.querySelector("table"), index, (ascending === "true"));
header.setAttribute("data-asc", (ascending === "false").toString())
})
});
/**
* Cleans the string (in this case the url)
* @returns {String}
*/
String.prototype.clean = function () {
return this.replace(/\/\/+/g, '/')
};