@osimatic/helpers-js 1.3.3 → 1.3.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.
package/index.js CHANGED
@@ -31,6 +31,7 @@ const { Pagination, Navigation } = require('./paging');
31
31
  const { DetailsSubArray } = require('./details_sub_array');
32
32
  const { SelectAll } = require('./select_all');
33
33
  const { MultipleActionInTable, MultipleActionInDivList } = require('./multiple_action_in_table');
34
+ const { MultiFilesInput } = require('./multi_files_input');
34
35
  const { FormDate, InputPeriod } = require('./form_date');
35
36
  const { ShoppingCart } = require('./shopping_cart');
36
37
  const { FlashMessage } = require('./flash_message');
@@ -52,7 +53,7 @@ const { WebSocket } = require('./web_socket');
52
53
  module.exports = {
53
54
  Array, Object, Number, String,
54
55
  HTTPClient, Cookie, UrlAndQueryString, IBAN, BankCard, AudioMedia, VideoMedia, UserMedia, PersonName, Email, TelephoneNumber, DateTime, DatePeriod, TimestampUnix, SqlDate, SqlTime, SqlDateTime, Duration, File, CSV, Img, FormHelper, Country, PostalAddress, GeographicCoordinates, HexColor, RgbColor, SocialNetwork, NumberFormatter, Password,
55
- Browser, DataTable, Pagination, Navigation, DetailsSubArray, SelectAll, MultipleActionInTable, MultipleActionInDivList, EditValue, FormDate, InputPeriod, ShoppingCart, FlashMessage, CountDown, ImportFromCsv, JwtToken, JwtSession, ApiTokenSession, ListBox, WebRTC, WebSocket, EventBus,
56
+ Browser, DataTable, Pagination, Navigation, DetailsSubArray, SelectAll, MultipleActionInTable, MultipleActionInDivList, MultiFilesInput, EditValue, FormDate, InputPeriod, ShoppingCart, FlashMessage, CountDown, ImportFromCsv, JwtToken, JwtSession, ApiTokenSession, ListBox, WebRTC, WebSocket, EventBus,
56
57
  sleep, refresh, chr, ord, trim, empty,
57
58
  Chartjs, GoogleCharts, GoogleRecaptcha, GoogleMap, OpenStreetMap
58
59
  };
@@ -0,0 +1,109 @@
1
+ class MultiFilesInput {
2
+ static init(fileInput, setFilesList, nbMaxFiles, maxFileSize) {
3
+ let filesList = [];
4
+ const formGroup = fileInput.closest('.form-group');
5
+
6
+ if (formGroup.find('.multi_files_input_dropzone').length === 0) {
7
+ fileInput.after(`
8
+ <div class="multi_files_input_dropzone border rounded p-3 text-center" style="background:#fafafa; cursor: pointer;">
9
+ <i class="fas fa-cloud-upload-alt fa-2x text-muted mb-1"></i>
10
+ <div class="small text-muted">Glissez-déposez vos fichiers ici ou cliquez pour sélectionner</div>
11
+ </div>
12
+ `);
13
+ }
14
+
15
+ if (formGroup.find('.multi_files_input_files_preview').length === 0) {
16
+ formGroup.append(`
17
+ <div class="multi_files_input_files_preview mt-2 d-flex flex-wrap gap-2 hide"></div>
18
+ `);
19
+ }
20
+
21
+ const dropzone = fileInput.parent().find('.multi_files_input_dropzone');
22
+ const filesPreview = fileInput.parent().find('.multi_files_input_files_preview');
23
+
24
+ fileInput.addClass('hide');
25
+
26
+ // Dropzone interactions
27
+ dropzone.on('click', function (e) {
28
+ e.preventDefault();
29
+ e.stopPropagation();
30
+ fileInput.trigger('click');
31
+ });
32
+ dropzone.on('dragover', function (e) {
33
+ e.preventDefault();
34
+ e.stopPropagation();
35
+ $(this).addClass('border-primary');
36
+ });
37
+ dropzone.on('dragleave', function (e) {
38
+ e.preventDefault();
39
+ e.stopPropagation();
40
+ $(this).removeClass('border-primary');
41
+ });
42
+ dropzone.on('drop', function (e) {
43
+ e.preventDefault();
44
+ e.stopPropagation();
45
+ $(this).removeClass('border-primary');
46
+ const dtFiles = (e.originalEvent.dataTransfer || {}).files || [];
47
+ handleFiles(Array.from(dtFiles));
48
+ });
49
+ fileInput.on('change', (e) => {
50
+ handleFiles(Array.from(e.target.files));
51
+ fileInput.val('');
52
+ });
53
+
54
+ function handleFiles(selected) {
55
+ for (const f of selected) {
56
+ if (filesList.length >= nbMaxFiles) {
57
+ FlashMessage.displayError('Maximum '+nbMaxFiles+' fichiers autorisés.');
58
+ break;
59
+ }
60
+ if (f.size > maxFileSize) {
61
+ FlashMessage.displayError('Le fichier '+f.name+' dépasse la taille maximale.');
62
+ continue;
63
+ }
64
+ filesList.push(f);
65
+ setFilesList(filesList);
66
+ renderPreview(f);
67
+ }
68
+ }
69
+
70
+ function renderPreview(file) {
71
+ const id = 'f_' + Math.random().toString(36).slice(2, 9);
72
+ const wrap = $(`
73
+ <div class="border rounded p-2 d-inline-flex align-items-center" data-file-id="${id}" style="background:white;">
74
+ <div class="me-2 preview-thumb" style="width:64px; height:48px; display:flex; align-items:center; justify-content:center; overflow:hidden;"></div>
75
+ <div class="small text-truncate" style="max-width:160px;">${file.name}</div>
76
+ <button type="button" class="btn-close btn-close-small ms-2" aria-label="Supprimer" style="margin-left:8px;"></button>
77
+ </div>
78
+ `);
79
+ filesPreview.append(wrap);
80
+ filesPreview.removeClass('hide');
81
+
82
+ // thumbnail for images
83
+ if (file.type.startsWith('image/')) {
84
+ const reader = new FileReader();
85
+ reader.onload = function (e) {
86
+ wrap.find('.preview-thumb').html(`<img src="${e.target.result}" alt="" style="max-width:100%; max-height:100%;" />`);
87
+ };
88
+ reader.readAsDataURL(file);
89
+ } else {
90
+ wrap.find('.preview-thumb').html(`<i class="fas fa-file fa-2x text-muted"></i>`);
91
+ }
92
+
93
+ wrap.find('.btn-close').on('click', function () {
94
+ const idx = $(this).closest('[data-file-id]').index();
95
+ // remove by reference: find corresponding file by name+size (best-effort)
96
+ const name = file.name, size = file.size;
97
+ filesList = filesList.filter(f => !(f.name === name && f.size === size));
98
+ setFilesList(filesList);
99
+ $(this).closest('[data-file-id]').remove();
100
+
101
+ if (filesList.length === 0) {
102
+ filesPreview.addClass('hide');
103
+ }
104
+ });
105
+ }
106
+ }
107
+ }
108
+
109
+ module.exports = { MultiFilesInput };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osimatic/helpers-js",
3
- "version": "1.3.3",
3
+ "version": "1.3.5",
4
4
  "main": "main.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
package/visitor.js CHANGED
@@ -21,43 +21,112 @@ class Browser {
21
21
  }
22
22
 
23
23
  class UserAgent {
24
- static getOsDisplay(osName) {
25
- let str = '';
26
- if (osName === 'Windows') {
27
- str += '<i class="fab fa-windows"></i>';
24
+ static getInfosDisplay(userAgentData, separator=' — ') {
25
+ let components = [];
26
+ if (null !== userAgentData['os']) {
27
+ components.push(userAgentData['os']);
28
28
  }
29
- if (osName === 'Linux') {
30
- str += '<i class="fab fa-linux"></i>';
29
+ if (null !== userAgentData['browser']) {
30
+ components.push(userAgentData['browser']);
31
31
  }
32
- if (osName === 'macOS' || osName === 'iOS') {
33
- str += '<i class="fab fa-apple"></i>';
32
+ if (null !== userAgentData['device']) {
33
+ components.push(userAgentData['device']);
34
34
  }
35
- if (osName === 'Android') {
36
- str += '<i class="fab fa-android"></i>';
35
+ return components.join(separator);
36
+ }
37
+
38
+ static getData(userAgent) {
39
+ if (typeof UAParser == 'undefined') {
40
+ return;
37
41
  }
38
- str += ' '+osName;
39
- return str.trim();
42
+
43
+ const parsedData = UAParser(userAgent);
44
+
45
+ let os = null;
46
+ if (typeof parsedData['os']['name'] != 'undefined') {
47
+ os = parsedData['os']['name'];
48
+ if (typeof parsedData['os']['version'] != 'undefined') {
49
+ os += ' '+parsedData['os']['version'];
50
+ }
51
+
52
+ os = os.trim();
53
+ }
54
+
55
+ let browser = null;
56
+ if (typeof parsedData['browser']['name'] != 'undefined') {
57
+ browser = parsedData['browser']['name'];
58
+ if (typeof parsedData['browser']['major'] != 'undefined') {
59
+ browser += ' '+parsedData['browser']['major'];
60
+ }
61
+ else if (typeof parsedData['browser']['version'] != 'undefined') {
62
+ browser += ' '+parsedData['browser']['version'];
63
+ }
64
+
65
+ browser = browser.trim();
66
+ }
67
+
68
+ let device = null;
69
+ if (typeof parsedData['device']['type'] != 'undefined') {
70
+ device = parsedData['device']['type'];
71
+ if (typeof parsedData['device']['vendor'] != 'undefined') {
72
+ device += ' '+parsedData['device']['vendor'];
73
+ }
74
+ if (typeof parsedData['device']['model'] != 'undefined') {
75
+ device += ' '+parsedData['device']['model'];
76
+ }
77
+
78
+ device = device.trim();
79
+ }
80
+
81
+ return {
82
+ os: os !== null && os !== '' ? os : null,
83
+ browser: browser !== null && browser !== '' ? browser : null,
84
+ device: device !== null && device !== '' ? device : null,
85
+ };
86
+ }
87
+
88
+ static getOsIcon(osName) {
89
+ osName = osName.toUpperCase();
90
+ if (osName === 'WINDOWS') {
91
+ return '<i class="fab fa-windows"></i>';
92
+ }
93
+ if (osName === 'LINUX') {
94
+ return '<i class="fab fa-linux"></i>';
95
+ }
96
+ if (osName === 'MACOS' || osName === 'IOS') {
97
+ return '<i class="fab fa-apple"></i>';
98
+ }
99
+ if (osName === 'ANDROID') {
100
+ return '<i class="fab fa-android"></i>';
101
+ }
102
+ return '';
103
+ }
104
+
105
+ static getOsDisplay(osName) {
106
+ return (UserAgent.getOsIcon()+' '+osName).trim();
40
107
  }
41
108
 
42
- static getBrowserDisplay(browserName) {
43
- let str = '';
44
- if (browserName === 'Chrome') {
45
- str += '<i class="fab fa-chrome"></i>';
109
+ static getBrowserIcon(browserName) {
110
+ browserName = browserName.toUpperCase();
111
+ if (browserName === 'CHROME') {
112
+ return '<i class="fab fa-chrome"></i>';
46
113
  }
47
- if (browserName === 'Firefox') {
48
- str += '<i class="fab fa-firefox"></i>';
114
+ if (browserName === 'FIREFOX') {
115
+ return '<i class="fab fa-firefox"></i>';
49
116
  }
50
- if (browserName === 'Edge') {
51
- str += '<i class="fab fa-edge"></i>';
117
+ if (browserName === 'EDGE') {
118
+ return '<i class="fab fa-edge"></i>';
52
119
  }
53
- if (browserName === 'Safari') {
54
- str += '<i class="fab fa-safari"></i>';
120
+ if (browserName === 'SAFARI') {
121
+ return '<i class="fab fa-safari"></i>';
55
122
  }
56
- if (browserName === 'Opera') {
57
- str += '<i class="fab fa-opera"></i>';
123
+ if (browserName === 'OPERA') {
124
+ return '<i class="fab fa-opera"></i>';
58
125
  }
59
- str += ' '+browserName;
60
- return str.trim();
126
+ return '';
127
+ }
128
+ static getBrowserDisplay(browserName) {
129
+ return (UserAgent.getBrowserIcon(browserName)+' '+browserName).trim();
61
130
  }
62
131
 
63
132
  static getDeviceDisplay(device) {