vgapp 1.5.6 → 1.5.8
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.
- package/app/langs/en/buttons.json +17 -17
- package/app/langs/en/messages.json +36 -36
- package/app/langs/ru/buttons.json +17 -17
- package/app/langs/ru/messages.json +1 -1
- package/app/modules/vgalert/js/vgalert.js +6 -3
- package/app/modules/vgalert/scss/_variables.scss +16 -16
- package/app/modules/vgcollapse/scss/_variables.scss +7 -7
- package/app/modules/vgcollapse/scss/vgcollapse.scss +5 -5
- package/app/modules/vgdropdown/scss/_variables.scss +14 -14
- package/app/modules/vgdropdown/scss/vgdropdown.scss +5 -5
- package/app/modules/vgfilepreview/js/i18n.js +56 -56
- package/app/modules/vgfilepreview/js/renderers/image-modal.js +145 -145
- package/app/modules/vgfilepreview/js/renderers/image.js +92 -92
- package/app/modules/vgfilepreview/js/renderers/index.js +19 -19
- package/app/modules/vgfilepreview/js/renderers/office-modal.js +168 -168
- package/app/modules/vgfilepreview/js/renderers/office.js +79 -79
- package/app/modules/vgfilepreview/js/renderers/pdf-modal.js +260 -260
- package/app/modules/vgfilepreview/js/renderers/pdf.js +76 -76
- package/app/modules/vgfilepreview/js/renderers/playlist.js +71 -71
- package/app/modules/vgfilepreview/js/renderers/text-modal.js +343 -343
- package/app/modules/vgfilepreview/js/renderers/text.js +83 -83
- package/app/modules/vgfilepreview/js/renderers/zip-modal.js +522 -522
- package/app/modules/vgfilepreview/js/renderers/zip.js +89 -89
- package/app/modules/vgfilepreview/readme.md +68 -68
- package/app/modules/vgfiles/js/base.js +189 -194
- package/app/modules/vgfiles/js/droppable.js +17 -17
- package/app/modules/vgfiles/js/render.js +153 -153
- package/app/modules/vgfiles/js/sortable.js +52 -52
- package/app/modules/vgfiles/js/vgfiles.js +43 -43
- package/app/modules/vgfiles/readme.md +123 -123
- package/app/modules/vgfiles/scss/_mixins.scss +13 -13
- package/app/modules/vgfiles/scss/_variables.scss +10 -10
- package/app/modules/vgfiles/scss/vgfiles.scss +28 -28
- package/app/modules/vgformsender/js/hideshowpass.js +22 -22
- package/app/modules/vgformsender/readme.md +1 -1
- package/app/modules/vgformsender/scss/_variables.scss +5 -5
- package/app/modules/vgformsender/scss/vgformsender.scss +42 -42
- package/app/modules/vglawcookie/js/vglawcookie.js +19 -19
- package/app/modules/vglawcookie/scss/_variables.scss +13 -13
- package/app/modules/vglawcookie/scss/vglawcookie.scss +5 -5
- package/app/modules/vgmodal/js/vgmodal.interaction.js +216 -216
- package/app/modules/vgmodal/js/vgmodal.js +6 -0
- package/app/modules/vgmodal/js/vgmodal.minimized.js +227 -227
- package/app/modules/vgmodal/scss/_variables.scss +17 -17
- package/app/modules/vgmodal/scss/vgmodal.scss +77 -77
- package/app/modules/vgnav/js/vgnav.js +62 -62
- package/app/modules/vgnav/scss/_breakpoints.scss +36 -36
- package/app/modules/vgnav/scss/_hamburger.scss +5 -5
- package/app/modules/vgnav/scss/_placement.scss +5 -5
- package/app/modules/vgnav/scss/_toggle.scss +5 -5
- package/app/modules/vgnav/scss/_variables.scss +26 -26
- package/app/modules/vgnav/scss/vgnav.scss +41 -41
- package/app/modules/vgnestable/README.md +39 -39
- package/app/modules/vgrangeslider/js/skins.js +8 -8
- package/app/modules/vgrangeslider/js/vgrangeslider.js +29 -29
- package/app/modules/vgrangeslider/scss/_variables.scss +55 -55
- package/app/modules/vgrangeslider/scss/vgrangeslider.scss +239 -239
- package/app/modules/vgrollup/js/vgrollup.js +15 -15
- package/app/modules/vgrollup/scss/_variables.scss +15 -15
- package/app/modules/vgrollup/scss/vgrollup.scss +6 -6
- package/app/modules/vgselect/js/handlers.js +5 -52
- package/app/modules/vgselect/js/vgselect.js +128 -40
- package/app/modules/vgselect/readme.md +11 -11
- package/app/modules/vgselect/scss/_variables.scss +51 -51
- package/app/modules/vgselect/scss/vgselect.scss +1 -1
- package/app/modules/vgsidebar/js/vgsidebar.js +16 -5
- package/app/modules/vgsidebar/scss/_variables.scss +10 -10
- package/app/modules/vgsidebar/scss/vgsidebar.scss +5 -5
- package/app/modules/vgspy/js/vgspy.js +28 -7
- package/app/modules/vgtable/js/_filters.js +10 -6
- package/app/modules/vgtable/js/_options.js +16 -16
- package/app/modules/vgtable/js/_pagination.js +118 -118
- package/app/modules/vgtable/js/_responsive.js +79 -79
- package/app/modules/vgtable/js/_sticky-header.js +349 -280
- package/app/modules/vgtable/js/vgtable.js +98 -98
- package/app/modules/vgtable/scss/_sorting.scss +6 -6
- package/app/modules/vgtable/scss/_sticky-header.scss +31 -31
- package/app/modules/vgtable/scss/_variables.scss +6 -4
- package/app/modules/vgtable/scss/vgtable.scss +8 -4
- package/app/modules/vgtabs/js/vgtabs.js +82 -57
- package/app/modules/vgtabs/scss/_variables.scss +23 -23
- package/app/modules/vgtabs/scss/vgtabs.scss +5 -5
- package/app/modules/vgtoast/js/vgtoast.js +11 -5
- package/app/modules/vgtoast/scss/_variables.scss +13 -13
- package/app/modules/vgtoast/scss/vgtoast.scss +5 -5
- package/app/modules/vgtooltip/js/vgtooltip.js +121 -111
- package/app/modules/vgtooltip/scss/_variables.scss +10 -10
- package/app/modules/vgtooltip/scss/vgtooltip.scss +5 -5
- package/app/utils/js/components/audio-metadata.js +240 -240
- package/app/utils/js/components/backdrop.js +116 -116
- package/app/utils/js/components/file-icon.js +5 -0
- package/app/utils/js/components/file-preview.js +304 -304
- package/app/utils/js/components/responsive.js +165 -165
- package/app/utils/js/components/sanitize.js +150 -150
- package/app/utils/js/components/video-metadata.js +140 -140
- package/app/utils/scss/_backdrop.scss +5 -5
- package/app/utils/scss/_theme-default.scss +12 -12
- package/app/utils/scss/_theme.scss +7 -7
- package/app/utils/scss/default.scss +9 -9
- package/app/utils/scss/functions.scss +21 -21
- package/app/utils/scss/index.scss +4 -4
- package/app/utils/scss/mixin.scss +16 -16
- package/app/utils/scss/variables.scss +147 -147
- package/build/vgapp.css +1 -1
- package/build/vgapp.css.map +1 -1
- package/build/vgapp.js +1 -1
- package/build/vgapp.js.map +1 -1
- package/index.js +7 -7
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Описание: базовая логика выбора, валидации и отображения файлов VGFiles.
|
|
3
|
-
* Возможности: управляет
|
|
2
|
+
* Описание: базовая логика выбора, валидации и отображения файлов VGFiles.
|
|
3
|
+
* Возможности: управляет файлами, валидацией, списками, миниатюрами и иконками, действиями, статистикой и скрытыми полями.
|
|
4
4
|
*/
|
|
5
5
|
import BaseModule from "../../base-module";
|
|
6
6
|
import {mergeDeepObject} from "../../../utils/js/functions";
|
|
@@ -9,6 +9,7 @@ import {lang_messages} from "../../../utils/js/components/lang";
|
|
|
9
9
|
import {Classes, Manipulator} from "../../../utils/js/dom/manipulator";
|
|
10
10
|
import Selectors from "../../../utils/js/dom/selectors";
|
|
11
11
|
import {getSVG} from "../../module-fn";
|
|
12
|
+
import {resolveFileIconName} from "../../../utils/js/components/file-icon";
|
|
12
13
|
import VGFilePreview from "../../vgfilepreview";
|
|
13
14
|
import {extractAudioMetadata} from "../../../utils/js/components/audio-metadata";
|
|
14
15
|
|
|
@@ -26,10 +27,10 @@ class VGFilesBase extends BaseModule {
|
|
|
26
27
|
this._isInitialized = true;
|
|
27
28
|
|
|
28
29
|
this._tpl = Html('dom');
|
|
29
|
-
this._files = [];
|
|
30
|
-
this._errors = new Set();
|
|
31
|
-
this._validationErrorsByKey = new Map();
|
|
32
|
-
this._fileObjectUrls = new Map();
|
|
30
|
+
this._files = [];
|
|
31
|
+
this._errors = new Set();
|
|
32
|
+
this._validationErrorsByKey = new Map();
|
|
33
|
+
this._fileObjectUrls = new Map();
|
|
33
34
|
this._audioMetaPromises = new Map();
|
|
34
35
|
|
|
35
36
|
this._nodes = {
|
|
@@ -198,10 +199,10 @@ class VGFilesBase extends BaseModule {
|
|
|
198
199
|
filesToProcess = this._mergeFilesByOrder(incoming, this._files, Boolean(this._params.prepend));
|
|
199
200
|
}
|
|
200
201
|
|
|
201
|
-
this._files = this._filterFiles(filesToProcess);
|
|
202
|
-
this._syncSingleInputSubmission();
|
|
203
|
-
|
|
204
|
-
this._renderErrors();
|
|
202
|
+
this._files = this._filterFiles(filesToProcess);
|
|
203
|
+
this._syncSingleInputSubmission();
|
|
204
|
+
|
|
205
|
+
this._renderErrors();
|
|
205
206
|
this._enrichAudioMetadata(this._files);
|
|
206
207
|
|
|
207
208
|
return this._files;
|
|
@@ -282,119 +283,119 @@ class VGFilesBase extends BaseModule {
|
|
|
282
283
|
return attrs;
|
|
283
284
|
}
|
|
284
285
|
|
|
285
|
-
_filterFiles(files) {
|
|
286
|
-
this._errors.clear();
|
|
287
|
-
this._validationErrorsByKey.clear();
|
|
288
|
-
const { count, sizes, total } = this._params.limits;
|
|
289
|
-
const maxSize = sizes * 1024 * 1024;
|
|
290
|
-
const maxTotalSize = total * 1024 * 1024;
|
|
291
|
-
|
|
292
|
-
let currentTotalSize = 0;
|
|
293
|
-
let validCount = 0;
|
|
294
|
-
const visibleFiles = [];
|
|
295
|
-
|
|
296
|
-
for (const file of files) {
|
|
297
|
-
const fileErrors = new Set();
|
|
298
|
-
|
|
299
|
-
if (count > 0 && validCount >= count) {
|
|
300
|
-
this._errors.add('is-count');
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (this._params.types.length && !this._params.types.includes(file.type)) {
|
|
305
|
-
fileErrors.add('is-types');
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
if (file.size > maxSize) {
|
|
309
|
-
fileErrors.add('is-sizes');
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (!fileErrors.size && maxTotalSize > 0 && currentTotalSize + file.size > maxTotalSize) {
|
|
313
|
-
fileErrors.add('is-total-size');
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
visibleFiles.push(file);
|
|
317
|
-
|
|
318
|
-
if (fileErrors.size) {
|
|
319
|
-
fileErrors.forEach(error => this._errors.add(error));
|
|
320
|
-
this._validationErrorsByKey.set(this._getFileKey(file), fileErrors);
|
|
321
|
-
continue;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
validCount += 1;
|
|
325
|
-
currentTotalSize += file.size;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return visibleFiles;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
_isFileValid(file) {
|
|
332
|
-
return !this._validationErrorsByKey.has(this._getFileKey(file));
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
_syncSingleInputSubmission() {
|
|
336
|
-
if (Number(this._params?.limits?.count) !== 1) return;
|
|
337
|
-
|
|
338
|
-
const selectedFile = this._files[0];
|
|
339
|
-
const canSubmit = !this._params.ajax && (!selectedFile || this._isFileValid(selectedFile));
|
|
340
|
-
this._preventOriginalInputFromSubmit(canSubmit);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
_getFileValidationMessages(file) {
|
|
344
|
-
const errors = this._validationErrorsByKey.get(this._getFileKey(file));
|
|
345
|
-
if (!errors?.size) return [];
|
|
346
|
-
|
|
347
|
-
const messages = lang_messages(this._params.lang, 'files') || this._getFallbackErrors();
|
|
348
|
-
return Array.from(errors, error => messages[error] || error);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
_getFileValidationLabel(file) {
|
|
352
|
-
const messages = this._getFileValidationMessages(file);
|
|
353
|
-
if (!messages.length) return '';
|
|
354
|
-
|
|
355
|
-
const fileName = this._getShortValidationFileName(file?.name);
|
|
356
|
-
return [fileName, messages.join('. ')].filter(Boolean).join(' — ');
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
_getFullFileValidationLabel(file) {
|
|
360
|
-
const messages = this._getFileValidationMessages(file);
|
|
361
|
-
if (!messages.length) return '';
|
|
362
|
-
|
|
363
|
-
const fileName = String(file?.name || '').trim();
|
|
364
|
-
return [fileName, messages.join('. ')].filter(Boolean).join(' — ');
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
_getShortValidationFileName(fileName) {
|
|
368
|
-
const name = String(fileName || '').trim();
|
|
369
|
-
if (name.length <= 24) return name;
|
|
370
|
-
|
|
371
|
-
const dotIndex = name.lastIndexOf('.');
|
|
372
|
-
const hasExtension = dotIndex > 0 && name.length - dotIndex <= 10;
|
|
373
|
-
const baseName = hasExtension ? name.slice(0, dotIndex) : name;
|
|
374
|
-
const extension = hasExtension ? name.slice(dotIndex) : '';
|
|
375
|
-
|
|
376
|
-
return `${baseName.slice(0, 5)}...${extension}`;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
_decorateValidationItem(item, file) {
|
|
380
|
-
if (this._isFileValid(file)) return item;
|
|
381
|
-
|
|
382
|
-
Classes.add(item, 'failing');
|
|
383
|
-
Classes.add(item, 'validation-error');
|
|
384
|
-
|
|
385
|
-
return item;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
_forgetFileValidation(file) {
|
|
389
|
-
if (!file) return;
|
|
390
|
-
|
|
391
|
-
this._validationErrorsByKey.delete(this._getFileKey(file));
|
|
392
|
-
this._errors.clear();
|
|
393
|
-
this._validationErrorsByKey.forEach(errors => {
|
|
394
|
-
errors.forEach(error => this._errors.add(error));
|
|
395
|
-
});
|
|
396
|
-
this._renderErrors();
|
|
397
|
-
}
|
|
286
|
+
_filterFiles(files) {
|
|
287
|
+
this._errors.clear();
|
|
288
|
+
this._validationErrorsByKey.clear();
|
|
289
|
+
const { count, sizes, total } = this._params.limits;
|
|
290
|
+
const maxSize = sizes * 1024 * 1024;
|
|
291
|
+
const maxTotalSize = total * 1024 * 1024;
|
|
292
|
+
|
|
293
|
+
let currentTotalSize = 0;
|
|
294
|
+
let validCount = 0;
|
|
295
|
+
const visibleFiles = [];
|
|
296
|
+
|
|
297
|
+
for (const file of files) {
|
|
298
|
+
const fileErrors = new Set();
|
|
299
|
+
|
|
300
|
+
if (count > 0 && validCount >= count) {
|
|
301
|
+
this._errors.add('is-count');
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (this._params.types.length && !this._params.types.includes(file.type)) {
|
|
306
|
+
fileErrors.add('is-types');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (file.size > maxSize) {
|
|
310
|
+
fileErrors.add('is-sizes');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (!fileErrors.size && maxTotalSize > 0 && currentTotalSize + file.size > maxTotalSize) {
|
|
314
|
+
fileErrors.add('is-total-size');
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
visibleFiles.push(file);
|
|
318
|
+
|
|
319
|
+
if (fileErrors.size) {
|
|
320
|
+
fileErrors.forEach(error => this._errors.add(error));
|
|
321
|
+
this._validationErrorsByKey.set(this._getFileKey(file), fileErrors);
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
validCount += 1;
|
|
326
|
+
currentTotalSize += file.size;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return visibleFiles;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
_isFileValid(file) {
|
|
333
|
+
return !this._validationErrorsByKey.has(this._getFileKey(file));
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
_syncSingleInputSubmission() {
|
|
337
|
+
if (Number(this._params?.limits?.count) !== 1) return;
|
|
338
|
+
|
|
339
|
+
const selectedFile = this._files[0];
|
|
340
|
+
const canSubmit = !this._params.ajax && (!selectedFile || this._isFileValid(selectedFile));
|
|
341
|
+
this._preventOriginalInputFromSubmit(canSubmit);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
_getFileValidationMessages(file) {
|
|
345
|
+
const errors = this._validationErrorsByKey.get(this._getFileKey(file));
|
|
346
|
+
if (!errors?.size) return [];
|
|
347
|
+
|
|
348
|
+
const messages = lang_messages(this._params.lang, 'files') || this._getFallbackErrors();
|
|
349
|
+
return Array.from(errors, error => messages[error] || error);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
_getFileValidationLabel(file) {
|
|
353
|
+
const messages = this._getFileValidationMessages(file);
|
|
354
|
+
if (!messages.length) return '';
|
|
355
|
+
|
|
356
|
+
const fileName = this._getShortValidationFileName(file?.name);
|
|
357
|
+
return [fileName, messages.join('. ')].filter(Boolean).join(' — ');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
_getFullFileValidationLabel(file) {
|
|
361
|
+
const messages = this._getFileValidationMessages(file);
|
|
362
|
+
if (!messages.length) return '';
|
|
363
|
+
|
|
364
|
+
const fileName = String(file?.name || '').trim();
|
|
365
|
+
return [fileName, messages.join('. ')].filter(Boolean).join(' — ');
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
_getShortValidationFileName(fileName) {
|
|
369
|
+
const name = String(fileName || '').trim();
|
|
370
|
+
if (name.length <= 24) return name;
|
|
371
|
+
|
|
372
|
+
const dotIndex = name.lastIndexOf('.');
|
|
373
|
+
const hasExtension = dotIndex > 0 && name.length - dotIndex <= 10;
|
|
374
|
+
const baseName = hasExtension ? name.slice(0, dotIndex) : name;
|
|
375
|
+
const extension = hasExtension ? name.slice(dotIndex) : '';
|
|
376
|
+
|
|
377
|
+
return `${baseName.slice(0, 5)}...${extension}`;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
_decorateValidationItem(item, file) {
|
|
381
|
+
if (this._isFileValid(file)) return item;
|
|
382
|
+
|
|
383
|
+
Classes.add(item, 'failing');
|
|
384
|
+
Classes.add(item, 'validation-error');
|
|
385
|
+
|
|
386
|
+
return item;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
_forgetFileValidation(file) {
|
|
390
|
+
if (!file) return;
|
|
391
|
+
|
|
392
|
+
this._validationErrorsByKey.delete(this._getFileKey(file));
|
|
393
|
+
this._errors.clear();
|
|
394
|
+
this._validationErrorsByKey.forEach(errors => {
|
|
395
|
+
errors.forEach(error => this._errors.add(error));
|
|
396
|
+
});
|
|
397
|
+
this._renderErrors();
|
|
398
|
+
}
|
|
398
399
|
|
|
399
400
|
_getSizes(size, isArray = false) {
|
|
400
401
|
const totalSize = isArray ? this._files.reduce((acc, f) => acc + f.size, 0) : size;
|
|
@@ -418,12 +419,12 @@ class VGFilesBase extends BaseModule {
|
|
|
418
419
|
}
|
|
419
420
|
}
|
|
420
421
|
|
|
421
|
-
_renderErrors() {
|
|
422
|
-
if (!this._errors.size) {
|
|
423
|
-
const $errorCont = Selectors.find(`.${this._getClass('errors')}`, this._element);
|
|
424
|
-
if ($errorCont) $errorCont.remove();
|
|
425
|
-
return;
|
|
426
|
-
}
|
|
422
|
+
_renderErrors() {
|
|
423
|
+
if (!this._errors.size) {
|
|
424
|
+
const $errorCont = Selectors.find(`.${this._getClass('errors')}`, this._element);
|
|
425
|
+
if ($errorCont) $errorCont.remove();
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
427
428
|
|
|
428
429
|
const messages = lang_messages(this._params.lang, 'files') || this._getFallbackErrors();
|
|
429
430
|
let $errorCont = Selectors.find(`.${this._getClass('errors')}`, this._element);
|
|
@@ -435,32 +436,32 @@ class VGFilesBase extends BaseModule {
|
|
|
435
436
|
$errorCont.innerHTML = '';
|
|
436
437
|
}
|
|
437
438
|
|
|
438
|
-
if (this._validationErrorsByKey.size) {
|
|
439
|
-
const renderedErrors = new Set();
|
|
440
|
-
this._files.forEach(file => {
|
|
441
|
-
const msg = this._getFileValidationLabel(file);
|
|
442
|
-
if (!msg) return;
|
|
443
|
-
|
|
444
|
-
const fileErrors = this._validationErrorsByKey.get(this._getFileKey(file));
|
|
445
|
-
fileErrors?.forEach(error => renderedErrors.add(error));
|
|
446
|
-
const fullMsg = this._getFullFileValidationLabel(file);
|
|
447
|
-
const attrs = { class: 'error-item' };
|
|
448
|
-
if (fullMsg && fullMsg !== msg) attrs.title = fullMsg;
|
|
449
|
-
$errorCont.append(this._tpl.span(attrs, msg));
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
this._errors.forEach(errKey => {
|
|
453
|
-
if (renderedErrors.has(errKey)) return;
|
|
454
|
-
const msg = messages[errKey] || errKey;
|
|
455
|
-
$errorCont.append(this._tpl.span({ class: 'error-item' }, msg));
|
|
456
|
-
});
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
this._errors.forEach(errKey => {
|
|
461
|
-
const msg = messages[errKey] || errKey;
|
|
462
|
-
$errorCont.append(this._tpl.span({ class: 'error-item' }, msg));
|
|
463
|
-
});
|
|
439
|
+
if (this._validationErrorsByKey.size) {
|
|
440
|
+
const renderedErrors = new Set();
|
|
441
|
+
this._files.forEach(file => {
|
|
442
|
+
const msg = this._getFileValidationLabel(file);
|
|
443
|
+
if (!msg) return;
|
|
444
|
+
|
|
445
|
+
const fileErrors = this._validationErrorsByKey.get(this._getFileKey(file));
|
|
446
|
+
fileErrors?.forEach(error => renderedErrors.add(error));
|
|
447
|
+
const fullMsg = this._getFullFileValidationLabel(file);
|
|
448
|
+
const attrs = { class: 'error-item' };
|
|
449
|
+
if (fullMsg && fullMsg !== msg) attrs.title = fullMsg;
|
|
450
|
+
$errorCont.append(this._tpl.span(attrs, msg));
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
this._errors.forEach(errKey => {
|
|
454
|
+
if (renderedErrors.has(errKey)) return;
|
|
455
|
+
const msg = messages[errKey] || errKey;
|
|
456
|
+
$errorCont.append(this._tpl.span({ class: 'error-item' }, msg));
|
|
457
|
+
});
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
this._errors.forEach(errKey => {
|
|
462
|
+
const msg = messages[errKey] || errKey;
|
|
463
|
+
$errorCont.append(this._tpl.span({ class: 'error-item' }, msg));
|
|
464
|
+
});
|
|
464
465
|
}
|
|
465
466
|
|
|
466
467
|
_getFallbackErrors() {
|
|
@@ -522,7 +523,7 @@ class VGFilesBase extends BaseModule {
|
|
|
522
523
|
};
|
|
523
524
|
}
|
|
524
525
|
|
|
525
|
-
_renderUIDropList(files) {
|
|
526
|
+
_renderUIDropList(files) {
|
|
526
527
|
if (!this._nodes.drop) return;
|
|
527
528
|
|
|
528
529
|
let $list = Selectors.find(`.${this._getClass('drop-list')}`, this._nodes.drop);
|
|
@@ -535,10 +536,10 @@ class VGFilesBase extends BaseModule {
|
|
|
535
536
|
const fragment = document.createDocumentFragment();
|
|
536
537
|
|
|
537
538
|
files.forEach((file) => {
|
|
538
|
-
let classes = [...$itemsTemplateClasses];
|
|
539
|
+
let classes = [...$itemsTemplateClasses];
|
|
539
540
|
|
|
540
|
-
if (this._params.detach) classes.push('with-remove')
|
|
541
|
-
if (this._params.customButtons?.hideOnUploadState) classes.push('hide-custom-buttons-on-upload-state')
|
|
541
|
+
if (this._params.detach) classes.push('with-remove')
|
|
542
|
+
if (this._params.customButtons?.hideOnUploadState) classes.push('hide-custom-buttons-on-upload-state')
|
|
542
543
|
if (this._params.sortable.enabled) classes.push('with-sortable')
|
|
543
544
|
if (this._params.limits.count === 1) {
|
|
544
545
|
classes.push('single');
|
|
@@ -566,7 +567,7 @@ class VGFilesBase extends BaseModule {
|
|
|
566
567
|
parts
|
|
567
568
|
);
|
|
568
569
|
|
|
569
|
-
fragment.appendChild(this._decorateValidationItem($li, file));
|
|
570
|
+
fragment.appendChild(this._decorateValidationItem($li, file));
|
|
570
571
|
});
|
|
571
572
|
|
|
572
573
|
$list.innerHTML = '';
|
|
@@ -707,13 +708,13 @@ class VGFilesBase extends BaseModule {
|
|
|
707
708
|
return '';
|
|
708
709
|
}
|
|
709
710
|
|
|
710
|
-
_createInfoListItem(file, i, itemsTemplate, itemTemplateClasses, fileKey, signature) {
|
|
711
|
+
_createInfoListItem(file, i, itemsTemplate, itemTemplateClasses, fileKey, signature) {
|
|
711
712
|
let classes = [...itemTemplateClasses];
|
|
712
713
|
|
|
713
714
|
if (this._params.image) classes.push('with-image');
|
|
714
715
|
if (this._params.info) classes.push('with-info');
|
|
715
|
-
if (this._params.detach) classes.push('with-remove')
|
|
716
|
-
if (this._params.customButtons?.hideOnUploadState) classes.push('hide-custom-buttons-on-upload-state')
|
|
716
|
+
if (this._params.detach) classes.push('with-remove')
|
|
717
|
+
if (this._params.customButtons?.hideOnUploadState) classes.push('hide-custom-buttons-on-upload-state')
|
|
717
718
|
if (this._params.sortable.enabled) classes.push('with-sortable');
|
|
718
719
|
const previewPath = this._resolveFilePreviewPath(file);
|
|
719
720
|
const displayName = this._resolveDisplayName(file);
|
|
@@ -741,12 +742,12 @@ class VGFilesBase extends BaseModule {
|
|
|
741
742
|
liAttrs['data-vg-filepreview-display-name'] = displayName || file.name || '';
|
|
742
743
|
}
|
|
743
744
|
|
|
744
|
-
const item = this._tpl.li(
|
|
745
|
-
this._buildFileDataAttributes(file, liAttrs),
|
|
746
|
-
parts
|
|
747
|
-
);
|
|
748
|
-
|
|
749
|
-
return this._decorateValidationItem(item, file);
|
|
745
|
+
const item = this._tpl.li(
|
|
746
|
+
this._buildFileDataAttributes(file, liAttrs),
|
|
747
|
+
parts
|
|
748
|
+
);
|
|
749
|
+
|
|
750
|
+
return this._decorateValidationItem(item, file);
|
|
750
751
|
}
|
|
751
752
|
|
|
752
753
|
_renderTemplatePart(element, file, index = null, options = {}) {
|
|
@@ -815,31 +816,25 @@ class VGFilesBase extends BaseModule {
|
|
|
815
816
|
|
|
816
817
|
_renderUIImage(file) {
|
|
817
818
|
const $container = this._tpl.div({ class: 'file-image' });
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
return $container;
|
|
823
|
-
}
|
|
824
|
-
|
|
819
|
+
const renderIcon = () => {
|
|
820
|
+
const icon = this._getIconByFileType(file);
|
|
821
|
+
$container.replaceChildren(this._tpl.i({}, icon, { isHTML: true }));
|
|
822
|
+
};
|
|
825
823
|
const customData = this._getFileCustomData(file);
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
824
|
+
let imageSrc = String(file?.image || '').trim() || String(customData.audioCover || '').trim();
|
|
825
|
+
|
|
826
|
+
if (!imageSrc && resolveFileIconName({ type: file?.type, name: file?.name || file?.src }) === 'file-image') {
|
|
827
|
+
imageSrc = String(file?.src || '').trim() || this._getFileObjectUrl(file);
|
|
830
828
|
}
|
|
831
829
|
|
|
832
|
-
if (
|
|
833
|
-
const
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
return $container;
|
|
830
|
+
if (imageSrc) {
|
|
831
|
+
const image = this._tpl.img(imageSrc, this._resolveDisplayName(file), { class: 'file-preview' });
|
|
832
|
+
image.addEventListener('error', renderIcon, { once: true });
|
|
833
|
+
$container.appendChild(image);
|
|
834
|
+
} else {
|
|
835
|
+
renderIcon();
|
|
839
836
|
}
|
|
840
837
|
|
|
841
|
-
const icon = this._getIconByFileType(file);
|
|
842
|
-
$container.appendChild(this._tpl.i({}, icon, { isHTML: true }));
|
|
843
838
|
return $container;
|
|
844
839
|
}
|
|
845
840
|
|
|
@@ -1028,7 +1023,7 @@ class VGFilesBase extends BaseModule {
|
|
|
1028
1023
|
|
|
1029
1024
|
if (isSingle) return;
|
|
1030
1025
|
|
|
1031
|
-
files.filter(file => this._isFileValid(file)).forEach((file, index) => {
|
|
1026
|
+
files.filter(file => this._isFileValid(file)).forEach((file, index) => {
|
|
1032
1027
|
const input = document.createElement('input');
|
|
1033
1028
|
input.type = 'file';
|
|
1034
1029
|
input.name = `${baseName}[${index}]`;
|
|
@@ -1070,10 +1065,10 @@ class VGFilesBase extends BaseModule {
|
|
|
1070
1065
|
if (resetInput) {
|
|
1071
1066
|
this._resetFileInput();
|
|
1072
1067
|
}
|
|
1073
|
-
this._cleanupFakeInputs();
|
|
1074
|
-
this._cleanupErrors();
|
|
1075
|
-
this._validationErrorsByKey.clear();
|
|
1076
|
-
this._files = [];
|
|
1068
|
+
this._cleanupFakeInputs();
|
|
1069
|
+
this._cleanupErrors();
|
|
1070
|
+
this._validationErrorsByKey.clear();
|
|
1071
|
+
this._files = [];
|
|
1077
1072
|
|
|
1078
1073
|
if (this._nodes.info) {
|
|
1079
1074
|
Classes.remove(this._nodes.info, 'show');
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
import { isElement } from "../../../utils/js/functions";
|
|
6
6
|
import EventHandler from "../../../utils/js/dom/event";
|
|
7
7
|
import Selectors from "../../../utils/js/dom/selectors";
|
|
8
|
-
import { Classes } from "../../../utils/js/dom/manipulator";
|
|
9
|
-
import BaseModule from "../../base-module";
|
|
10
|
-
import {isVGFilesSortableDragActive, VG_FILES_SORTABLE_DATA_TYPE} from "./sortable";
|
|
8
|
+
import { Classes } from "../../../utils/js/dom/manipulator";
|
|
9
|
+
import BaseModule from "../../base-module";
|
|
10
|
+
import {isVGFilesSortableDragActive, VG_FILES_SORTABLE_DATA_TYPE} from "./sortable";
|
|
11
11
|
|
|
12
12
|
const CLASS_NAME_CONTAINER = 'vg-files';
|
|
13
13
|
const CLASS_NAME_DROP = `${CLASS_NAME_CONTAINER}-drop`;
|
|
@@ -254,20 +254,20 @@ class VGFilesDroppable extends BaseModule {
|
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
_isSortableDrag(e) {
|
|
258
|
-
if (isVGFilesSortableDragActive()) return true;
|
|
259
|
-
if (document.querySelector('.dragging')) return true;
|
|
260
|
-
|
|
261
|
-
try {
|
|
262
|
-
const dataTransfer = e?.dataTransfer;
|
|
263
|
-
const types = Array.from(dataTransfer?.types || []);
|
|
264
|
-
if (types.includes(VG_FILES_SORTABLE_DATA_TYPE)) return true;
|
|
265
|
-
|
|
266
|
-
return (dataTransfer?.getData?.(VG_FILES_SORTABLE_DATA_TYPE) || '') === '1' ||
|
|
267
|
-
(dataTransfer?.getData?.('text/plain') || '') === 'vgsortable';
|
|
268
|
-
} catch (_) {
|
|
269
|
-
return false;
|
|
270
|
-
}
|
|
257
|
+
_isSortableDrag(e) {
|
|
258
|
+
if (isVGFilesSortableDragActive()) return true;
|
|
259
|
+
if (document.querySelector('.dragging')) return true;
|
|
260
|
+
|
|
261
|
+
try {
|
|
262
|
+
const dataTransfer = e?.dataTransfer;
|
|
263
|
+
const types = Array.from(dataTransfer?.types || []);
|
|
264
|
+
if (types.includes(VG_FILES_SORTABLE_DATA_TYPE)) return true;
|
|
265
|
+
|
|
266
|
+
return (dataTransfer?.getData?.(VG_FILES_SORTABLE_DATA_TYPE) || '') === '1' ||
|
|
267
|
+
(dataTransfer?.getData?.('text/plain') || '') === 'vgsortable';
|
|
268
|
+
} catch (_) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
_getVisibleDropZonesInViewport() {
|