-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathupload.js
More file actions
121 lines (95 loc) · 3.44 KB
/
upload.js
File metadata and controls
121 lines (95 loc) · 3.44 KB
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
121
function formatBytes(bytes, decimals = 2) {
if (!bytes) {
return '0 Bytes';
}
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + 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
}
const noop = function(){}
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'], ['Open'])
const upload = element('button', ['btn', 'primary'], ['Upload'])
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-block'
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}</span>
${formatBytes(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 = '0px';
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);
}