@@ -24,6 +24,51 @@ const VALUE_EMPTY_DEPRECATED_MSG =
24
24
25
25
const isValidValue = value => isFile(value) || (isArray(value) && value.every(v => isValidValue(v)))
26
26
27
+
// Drop handler function to get all files
28
+
/* istanbul ignore next: not supported in JSDOM */
29
+
const getAllFileEntries = async dataTransferItemList => {
30
+
const fileEntries = []
31
+
const queue = []
32
+
// Unfortunately `dataTransferItemList` is not iterable i.e. no `.forEach()`
33
+
for (let i = 0; i < dataTransferItemList.length; i++) {
34
+
queue.push(dataTransferItemList[i].webkitGetAsEntry())
35
+
}
36
+
while (queue.length > 0) {
37
+
const entry = queue.shift()
38
+
if (entry.isFile) {
39
+
fileEntries.push(entry)
40
+
} else if (entry.isDirectory) {
41
+
queue.push(...(await readAllDirectoryEntries(entry.createReader())))
42
+
}
43
+
}
44
+
return fileEntries
45
+
}
46
+
47
+
// Get all the entries (files or sub-directories) in a directory
48
+
// by calling `.readEntries()` until it returns empty array
49
+
/* istanbul ignore next: not supported in JSDOM */
50
+
const readAllDirectoryEntries = async directoryReader => {
51
+
const entries = []
52
+
let readEntries = await readEntriesPromise(directoryReader)
53
+
while (readEntries.length > 0) {
54
+
entries.push(...readEntries)
55
+
readEntries = await readEntriesPromise(directoryReader)
56
+
}
57
+
return entries
58
+
}
59
+
60
+
// Wrap `.readEntries()` in a promise to make working with it easier
61
+
// `.readEntries()` will return only some of the entries in a directory
62
+
// (e.g. Chrome returns at most 100 entries at a time)
63
+
/* istanbul ignore next: not supported in JSDOM */
64
+
const readEntriesPromise = async directoryReader => {
65
+
try {
66
+
return await new Promise((resolve, reject) => {
67
+
directoryReader.readEntries(resolve, reject)
68
+
})
69
+
} catch {}
70
+
}
71
+
27
72
// @vue/component
28
73
export const BFormFile = /*#__PURE__*/ Vue.extend({
29
74
name: NAME,
@@ -202,40 +247,23 @@ export const BFormFile = /*#__PURE__*/ Vue.extend({
202
247
// Always emit original event
203
248
this.$emit('change', evt)
204
249
// Check if special `items` prop is available on event (drop mode)
205
-
// Can be disabled by setting no-traverse
206
-
const items = evt.dataTransfer && evt.dataTransfer.items
250
+
// Can be disabled by setting `no-traverse`
251
+
const { files, items } = evt.dataTransfer || {}
207
252
/* istanbul ignore next: not supported in JSDOM */
208
253
if (items && !this.noTraverse) {
209
-
const queue = []
210
-
for (let i = 0; i < items.length; i++) {
211
-
const item = items[i].webkitGetAsEntry()
212
-
if (item) {
213
-
queue.push(this.traverseFileTree(item))
214
-
}
215
-
}
216
-
Promise.all(queue).then(filesArr => {
217
-
this.setFiles(arrayFrom(filesArr))
254
+
getAllFileEntries(items).then(files => {
255
+
this.setFiles(files)
218
256
})
219
-
return
257
+
} else {
258
+
// Normal handling
259
+
this.setFiles(evt.target.files || files)
220
260
}
221
-
// Normal handling
222
-
this.setFiles(evt.target.files || evt.dataTransfer.files)
223
261
},
224
-
setFiles(files = []) {
225
-
if (!files) {
226
-
/* istanbul ignore next: this will probably not happen */
227
-
this.selectedFile = null
228
-
} else if (this.multiple) {
229
-
// Convert files to array
230
-
const filesArray = []
231
-
for (let i = 0; i < files.length; i++) {
232
-
filesArray.push(files[i])
233
-
}
234
-
// Return file(s) as array
235
-
this.selectedFile = filesArray
262
+
setFiles(files) {
263
+
if (this.multiple) {
264
+
this.selectedFile = arrayFrom(files || [])
236
265
} else {
237
-
// Return single file object
238
-
this.selectedFile = files[0] || null
266
+
this.selectedFile = files ? files[0] || null : null
239
267
}
240
268
},
241
269
onReset() {
@@ -265,39 +293,12 @@ export const BFormFile = /*#__PURE__*/ Vue.extend({
265
293
return
266
294
}
267
295
this.dragging = false
268
-
if (evt.dataTransfer.files && evt.dataTransfer.files.length > 0) {
269
-
this.onFileChange(evt)
270
-
}
271
-
},
272
-
/* istanbul ignore next: not supported in JSDOM */
273
-
traverseFileTree(item, path) /* istanbul ignore next */ {
274
-
// Based on https://stackoverflow.com/questions/3590058
275
-
return new Promise(resolve => {
276
-
path = path || ''
277
-
if (item.isFile) {
278
-
// Get file
279
-
item.file(file => {
280
-
file.$path = path // Inject $path to file obj
281
-
resolve(file)
282
-
})
283
-
} else if (item.isDirectory) {
284
-
// Get folder contents
285
-
item.createReader().readEntries(entries => {
286
-
const queue = []
287
-
for (let i = 0; i < entries.length; i++) {
288
-
queue.push(this.traverseFileTree(entries[i], path + item.name + '/'))
289
-
}
290
-
Promise.all(queue).then(filesArr => {
291
-
resolve(arrayFrom(filesArr))
292
-
})
293
-
})
294
-
}
295
-
})
296
+
this.onFileChange(evt)
296
297
}
297
298
},
298
299
render(h) {
299
300
// Form Input
300
-
const input = h('input', {
301
+
const $input = h('input', {
301
302
ref: 'input',
302
303
class: [
303
304
{
@@ -317,11 +318,11 @@ export const BFormFile = /*#__PURE__*/ Vue.extend({
317
318
})
318
319
319
320
if (this.plain) {
320
-
return input
321
+
return $input
321
322
}
322
323
323
324
// Overlay Labels
324
-
const label = h(
325
+
const $label = h(
325
326
'label',
326
327
{
327
328
staticClass: 'custom-file-label',
@@ -352,7 +353,7 @@ export const BFormFile = /*#__PURE__*/ Vue.extend({
352
353
drop: this.onDrop
353
354
}
354
355
},
355
-
[input, label]
356
+
[$input, $label]
356
357
)
357
358
}
358
359
})
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4