vgapp 0.9.3 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -31,6 +31,8 @@ class VGFilesBase extends BaseModule {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
this.template = '<li data-file="" class="file"><div class="file-image"></div><div class="file-info"></div><div class="file-remove"></div></li>';
|
|
34
|
+
this._onNativeInputChange = (e) => this.change(e?.target);
|
|
35
|
+
|
|
34
36
|
this._init();
|
|
35
37
|
}
|
|
36
38
|
|
|
@@ -61,6 +63,17 @@ class VGFilesBase extends BaseModule {
|
|
|
61
63
|
|
|
62
64
|
const filesArray = Array.from(incomingFiles);
|
|
63
65
|
|
|
66
|
+
const shouldReplaceOnSingle =
|
|
67
|
+
Boolean(this._params?.replace) &&
|
|
68
|
+
Number(this._params?.limits?.count) === 1;
|
|
69
|
+
|
|
70
|
+
if (shouldReplaceOnSingle) {
|
|
71
|
+
this.clear();
|
|
72
|
+
this.append(filesArray, true);
|
|
73
|
+
this.build();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
64
77
|
if (!this._params.allowed) {
|
|
65
78
|
this.append(filesArray, false);
|
|
66
79
|
this.build();
|
|
@@ -262,7 +275,7 @@ class VGFilesBase extends BaseModule {
|
|
|
262
275
|
const fragment = document.createDocumentFragment();
|
|
263
276
|
|
|
264
277
|
files.forEach((file) => {
|
|
265
|
-
let classes = $itemsTemplateClasses
|
|
278
|
+
let classes = $itemsTemplateClasses;
|
|
266
279
|
|
|
267
280
|
if (this._params.detach) classes.push('with-remove')
|
|
268
281
|
if (this._params.sortable.enabled) classes.push('with-sortable')
|
|
@@ -415,12 +428,21 @@ class VGFilesBase extends BaseModule {
|
|
|
415
428
|
_generateHiddenInputs(files) {
|
|
416
429
|
this._cleanupFakeInputs();
|
|
417
430
|
const fragment = document.createDocumentFragment();
|
|
418
|
-
const
|
|
431
|
+
const idInput = this._element.querySelector('label').getAttribute('for') || '';
|
|
432
|
+
const name = this._element.querySelector('#' + idInput)?.name || this._element.querySelector('#' + idInput)?.dataset.originalName || 'files[]';
|
|
433
|
+
|
|
434
|
+
// если name уже "files[]" — убираем скобки, чтобы дальше корректно собрать имя
|
|
435
|
+
const baseName = name.endsWith('[]') ? name.slice(0, -2) : name;
|
|
436
|
+
const isSingle = Number(this._params?.limits?.count) === 1;
|
|
419
437
|
|
|
420
438
|
files.forEach((file, index) => {
|
|
421
439
|
const input = document.createElement('input');
|
|
422
440
|
input.type = 'file';
|
|
423
|
-
|
|
441
|
+
|
|
442
|
+
// count=1 => name без массива (без [] и без [0])
|
|
443
|
+
// иначе => name как массив: baseName[index]
|
|
444
|
+
input.name = isSingle ? baseName : `${baseName}[${index}]`;
|
|
445
|
+
|
|
424
446
|
input.dataset.vgFiles = 'generated';
|
|
425
447
|
Manipulator.hide(input);
|
|
426
448
|
|
|
@@ -486,7 +508,8 @@ class VGFilesBase extends BaseModule {
|
|
|
486
508
|
|
|
487
509
|
_addEventListener() {
|
|
488
510
|
Selectors.findAll('[data-vg-toggle="files"]', this._element).forEach(el => {
|
|
489
|
-
el.
|
|
511
|
+
el.removeEventListener('change', this._onNativeInputChange);
|
|
512
|
+
el.addEventListener('change', this._onNativeInputChange);
|
|
490
513
|
});
|
|
491
514
|
}
|
|
492
515
|
|
|
@@ -6,7 +6,7 @@ import { Classes, Manipulator } from "../../../utils/js/dom/manipulator";
|
|
|
6
6
|
class VGFilesTemplateRender {
|
|
7
7
|
constructor(vgFilesInstance, element, params = {}) {
|
|
8
8
|
this.module = vgFilesInstance;
|
|
9
|
-
this.element = isElement(element);
|
|
9
|
+
this.element = isElement(element) ? element : null;
|
|
10
10
|
|
|
11
11
|
if (!this.element) {
|
|
12
12
|
console.error('Invalid element provided:', element);
|
|
@@ -41,6 +41,7 @@ class VGFiles extends VGFilesBase {
|
|
|
41
41
|
types: [],
|
|
42
42
|
ajax: false,
|
|
43
43
|
prepend: true,
|
|
44
|
+
replace: true,
|
|
44
45
|
uploads: {
|
|
45
46
|
mode: 'sequential',
|
|
46
47
|
route: '',
|
|
@@ -98,13 +99,15 @@ class VGFiles extends VGFilesBase {
|
|
|
98
99
|
|
|
99
100
|
if (this._params.ajax) {
|
|
100
101
|
this._params.allowed = false;
|
|
102
|
+
}
|
|
101
103
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
if (this.isRenderNonInit) return;
|
|
105
|
+
this.isRenderNonInit = this._render.init();
|
|
106
|
+
|
|
107
|
+
if (this._render.parsedFiles.length) {
|
|
108
|
+
this._addExternalFiles(this._render.parsedFiles);
|
|
107
109
|
}
|
|
110
|
+
|
|
108
111
|
if (this._params.allowed && !this._params.ajax) this._params.detach = false;
|
|
109
112
|
if (this._nodes.drop) {
|
|
110
113
|
this._params.image = true;
|
|
@@ -179,15 +182,24 @@ class VGFiles extends VGFilesBase {
|
|
|
179
182
|
|
|
180
183
|
_addEventListenerExtended() {
|
|
181
184
|
Selectors.findAll(SELECTOR_DATA_TOGGLE, this._element).forEach(el => {
|
|
182
|
-
|
|
183
|
-
|
|
185
|
+
if (this._onNativeInputChange) {
|
|
186
|
+
el.removeEventListener('change', this._onNativeInputChange);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
el.addEventListener('change', (e) => this._handleChange(e));
|
|
184
190
|
});
|
|
185
191
|
}
|
|
186
192
|
|
|
187
193
|
_handleChange(e) {
|
|
194
|
+
const input = e?.target;
|
|
195
|
+
this.change(input);
|
|
196
|
+
|
|
188
197
|
if (this._params.ajax) this.uploadAll(this._files);
|
|
189
|
-
|
|
190
|
-
|
|
198
|
+
|
|
199
|
+
const payload = { files: this._files, input: e?.target || e?.src || '' };
|
|
200
|
+
|
|
201
|
+
this._triggerCallback('onChange', payload);
|
|
202
|
+
this._triggerEvent('change', { files: this._files, input: payload.input });
|
|
191
203
|
}
|
|
192
204
|
|
|
193
205
|
async uploadAll(files) {
|
|
@@ -232,6 +244,10 @@ class VGFiles extends VGFilesBase {
|
|
|
232
244
|
files: notUploadedFiles,
|
|
233
245
|
total: notUploadedFiles.length
|
|
234
246
|
});
|
|
247
|
+
this._triggerEvent('upload.start', {
|
|
248
|
+
files: notUploadedFiles,
|
|
249
|
+
total: notUploadedFiles.length
|
|
250
|
+
});
|
|
235
251
|
|
|
236
252
|
try {
|
|
237
253
|
await this._uploader.uploadFiles(notUploadedFiles, this._params.uploads.route, uploadParams);
|
|
@@ -322,12 +338,15 @@ class VGFiles extends VGFilesBase {
|
|
|
322
338
|
}
|
|
323
339
|
}
|
|
324
340
|
|
|
325
|
-
|
|
341
|
+
const payload = {
|
|
326
342
|
file: uploadData.file,
|
|
327
343
|
progress: uploadData.progress,
|
|
328
344
|
bytesSent: uploadData.bytesSent,
|
|
329
345
|
totalBytes: uploadData.totalBytes
|
|
330
|
-
}
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
this._triggerCallback('onUploadProgress', payload);
|
|
349
|
+
this._triggerEvent('upload.progress', payload);
|
|
331
350
|
});
|
|
332
351
|
|
|
333
352
|
this._uploader.onComplete((uploadData) => {
|
|
@@ -372,12 +391,15 @@ class VGFiles extends VGFilesBase {
|
|
|
372
391
|
this._setStatItem('completed', this._uploadedKeys.size);
|
|
373
392
|
this._setStatItem('pending', this._pendingUploadedKeys.size);
|
|
374
393
|
|
|
375
|
-
|
|
394
|
+
const payload = {
|
|
376
395
|
file: uploadData.file,
|
|
377
396
|
response: uploadData.result?.response,
|
|
378
397
|
status: uploadData.result?.status,
|
|
379
398
|
id: file.id
|
|
380
|
-
}
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
this._triggerCallback('onUploadComplete', payload);
|
|
402
|
+
this._triggerEvent('upload.complete', payload);
|
|
381
403
|
});
|
|
382
404
|
|
|
383
405
|
this._uploader.onError((uploadData) => {
|
|
@@ -413,13 +435,14 @@ class VGFiles extends VGFilesBase {
|
|
|
413
435
|
}
|
|
414
436
|
}
|
|
415
437
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
438
|
+
const payload = { file: uploadData.file };
|
|
439
|
+
|
|
440
|
+
this._triggerCallback('onUploadError', payload);
|
|
441
|
+
this._triggerEvent('upload.error', payload);
|
|
419
442
|
});
|
|
420
443
|
|
|
421
444
|
this._uploader.onAllComplete(() => {
|
|
422
|
-
|
|
445
|
+
this._triggerEvent('upload.allComplete');
|
|
423
446
|
this._updateStat(false);
|
|
424
447
|
|
|
425
448
|
if (!this._failingUploadedKeys.size) {
|
|
@@ -436,11 +459,13 @@ class VGFiles extends VGFilesBase {
|
|
|
436
459
|
}
|
|
437
460
|
}
|
|
438
461
|
|
|
439
|
-
|
|
462
|
+
const payload = {
|
|
440
463
|
uploaded: this._uploadedKeys.size,
|
|
441
464
|
failed: this._failingUploadedKeys.size,
|
|
442
465
|
total: this._files.length
|
|
443
|
-
}
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
this._triggerCallback('onUploadAllComplete', payload);
|
|
444
469
|
});
|
|
445
470
|
}
|
|
446
471
|
|
|
@@ -467,10 +492,13 @@ class VGFiles extends VGFilesBase {
|
|
|
467
492
|
this._setStatItem('failing', this._failingUploadedKeys.size);
|
|
468
493
|
this._setStatItem('pending', this._pendingUploadedKeys.size);
|
|
469
494
|
|
|
470
|
-
|
|
495
|
+
const payload = {
|
|
471
496
|
button: button,
|
|
472
497
|
file: fileToRetry
|
|
473
|
-
}
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
this._triggerCallback('onReload', payload);
|
|
501
|
+
this._triggerEvent('reload', payload);
|
|
474
502
|
|
|
475
503
|
this.upload(fileToRetry);
|
|
476
504
|
}
|
|
@@ -567,13 +595,16 @@ class VGFiles extends VGFilesBase {
|
|
|
567
595
|
|
|
568
596
|
this._resetFileInput();
|
|
569
597
|
|
|
570
|
-
|
|
598
|
+
const payload = {
|
|
571
599
|
button: button,
|
|
572
600
|
name: name,
|
|
573
601
|
size: size,
|
|
574
602
|
id: id,
|
|
575
603
|
remaining: this._files.length
|
|
576
|
-
}
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
this._triggerCallback('onRemoveFile', payload);
|
|
607
|
+
this._triggerEvent('remove', payload);
|
|
577
608
|
}
|
|
578
609
|
|
|
579
610
|
_updateStatsAfterRemove() {
|
|
@@ -707,6 +738,10 @@ class VGFiles extends VGFilesBase {
|
|
|
707
738
|
}
|
|
708
739
|
}
|
|
709
740
|
|
|
741
|
+
_triggerEvent(suffix, payload = {}) {
|
|
742
|
+
EventHandler.trigger(this._element, `${NAME_KEY}.${suffix}`, payload);
|
|
743
|
+
}
|
|
744
|
+
|
|
710
745
|
_getUploadedIds() {
|
|
711
746
|
return Array.from(this._uploadedKeys).map(key => {
|
|
712
747
|
const file = this._files.find(f => this._getFileKey(f) === key);
|