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 name = this._element.querySelector('[data-vg-toggle]')?.name || 'files[]';
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
- input.name = `${name.replace('[]', '')}[${index}]`;
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.addEventListener('change', () => this.change(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
- if (this.isRenderNonInit) return;
103
- this.isRenderNonInit = this._render.init();
104
- if (this._render.parsedFiles.length) {
105
- this._addExternalFiles(this._render.parsedFiles);
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
- el.removeEventListener('change', this.change.bind(this));
183
- el.addEventListener('change', e => this._handleChange(e));
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
- this._triggerCallback('onChange', { files: this._files, input: e?.target || e?.src || '' });
190
- EventHandler.trigger(this._element, `${NAME_KEY}.change`, { files: this._files });
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
- this._triggerCallback('onUploadProgress', {
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
- this._triggerCallback('onUploadComplete', {
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
- this._triggerCallback('onUploadError', {
417
- file: uploadData.file
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
- EventHandler.trigger(this._element, `${NAME_KEY}.upload.allComplete`);
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
- this._triggerCallback('onUploadAllComplete', {
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
- this._triggerCallback('onReload', {
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
- this._triggerCallback('onRemoveFile', {
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vgapp",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "",
5
5
  "author": {
6
6
  "name": "Vegas Studio",