Skip to content

Instantly share code, notes, and snippets.

@bohnacker

bohnacker/dropable.js

Last active Feb 11, 2021
Embed
What would you like to do?
Svelte action to turn a node into a file drop area. Demo at: https://svelte.dev/repl/d3af7296998346aeb50d6657b7e31d26?version=3.32.3
// The action "dropable" turns a node into a file drop area and dispatches the custom event "files" when
// on or more files were dropped. You'll get an array of files in event.detail.
// You can provide filetypes as a string or an array of strings, e.g.: "text/html" or ["image/png", "image/jpeg"]
// Matching will be done by searching for the substring, so filetype "image/" will match all images
// or "/svg" will match "image/svg+xml".
export function dropable(node, filetypes) {
if (typeof filetypes === "string") filetypes = [filetypes]
function dragoverHandler(ev) {
ev.preventDefault();
}
async function dropHandler(ev) {
ev.preventDefault();
let files = [];
if (ev.dataTransfer.items) {
// Use DataTransferItemList interface to access the file(s)
for (let i = 0; i < ev.dataTransfer.items.length; i++) {
// If dropped items aren't files, reject them
if (ev.dataTransfer.items[i].kind === 'file') {
files.push(ev.dataTransfer.items[i].getAsFile());
}
}
} else {
// Use DataTransfer interface to access the file(s)
for (let i = 0; i < ev.dataTransfer.files.length; i++) {
files.push(ev.dataTransfer.files[i]);
}
}
// If filetypes are given, check all files if they match with one of the given types.
if (filetypes) {
files = files.filter(file => {
let match = false;
filetypes.forEach(type => {
console.log("check", type, "on", file.type)
if (file.type.indexOf(type) >= 0) match = true;
});
return match;
});
}
node.dispatchEvent( new CustomEvent("files", {detail: files}) );
}
node.addEventListener('dragover', dragoverHandler);
node.addEventListener('drop', dropHandler);
return {
update(newFiletypes) {
filetypes = newFiletypes;
if (typeof filetypes === "string") filetypes = [filetypes]
},
destroy() {
node.removeEventListener('dragover', dragoverHandler);
node.removeEventListener('drop', dropHandler);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment