-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupload.js
120 lines (100 loc) · 3.17 KB
/
upload.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
function bytesToSize(bytes) {
var sizes = ["Bytes", "KB", "MB", "GB", "TB"];
if (!bytes) {
return "0 Byte";
}
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return Math.round(bytes / Math.pow(1024, i), 2) + " " + sizes[i];
}
const element = (tag, classes = [], content) => {
const node = document.createElement(tag);
if (classes.length) {
node.classList.add(...classes);
}
if (content) {
node.textContent = content;
}
return node;
};
function noop() {}
export function upload(selector, options = {}) {
let files = [];
const onUpload = options.onUpload ?? noop;
const input = document.querySelector(selector);
const preview = element("div", ["preview"]);
const open = element("button", ["btn"], "Открыть");
const upload = element("button", ["btn", "primary"], "Загрузить");
upload.style.display = "none";
if (options.multi) {
input.setAttribute("multiple", true);
}
if (options.accept && Array.isArray(options.accept)) {
input.setAttribute("accept", options.accept.join(","));
}
input.insertAdjacentElement("afterend", preview);
input.insertAdjacentElement("afterend", upload);
input.insertAdjacentElement("afterend", open);
const triggerInput = () => {
input.click();
};
const changeHandler = (event) => {
if (!event.target.files.length) {
return;
}
files = Array.from(event.target.files);
preview.innerHTML = "";
upload.style.display = "inline";
files.forEach((file) => {
if (!file.type.match("image")) {
return;
}
const reader = new FileReader();
reader.onload = (ev) => {
const src = ev.target.result;
preview.insertAdjacentHTML(
"afterbegin",
`
<div class="preview-image">
<div class="preview-remove" data-name="${file.name}">×</div>
<img src="${src}" alt="${file.name}" />
<div class="preview-info">
<span>${file.name.substr(0, 15) + `...`}</span>
${bytesToSize(file.size)}
</div>
</div>
`
);
};
reader.readAsDataURL(file);
});
};
const removeHandler = (event) => {
if (!event.target.dataset.name) {
return;
}
const { name } = event.target.dataset;
files = files.filter((file) => file.name !== name);
if (!files.length) {
upload.style.display = "none";
}
const block = preview
.querySelector(`[data-name="${name}"]`)
.closest(".preview-image");
block.classList.add("removing");
setTimeout(() => block.remove(), 300);
};
const clearPreview = (el) => {
el.style.bottom = "4px";
el.innerHTML = '<div class="preview-info-progress"></div>';
};
const uploadHandler = () => {
preview.querySelectorAll(".preview-remove").forEach((e) => e.remove());
const previewInfo = preview.querySelectorAll(".preview-info");
previewInfo.forEach(clearPreview);
onUpload(files, previewInfo);
};
open.addEventListener("click", triggerInput);
input.addEventListener("change", changeHandler);
preview.addEventListener("click", removeHandler);
upload.addEventListener("click", uploadHandler);
}