@massimo-cassandro/minimo 0.11.0 → 0.11.2
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/design-tokens-utilities/build-tokens.mjs +0 -0
- package/design-tokens-utilities/check-unresolved-custom-props.mjs +0 -0
- package/index.js +10 -0
- package/package.json +2 -11
- package/src/components/dismiss-alerts.js +7 -6
- package/src/components/form-reset-submit.js +38 -0
- package/src/components/inner-nav/inner-nav.js +11 -8
- package/src/web-components/s-datatable-component/docs.md +149 -80
- package/src/web-components/s-datatable-component/s-datatable-component.js +58 -1
- package/src/components/forms.js +0 -36
|
File without changes
|
|
File without changes
|
package/index.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
// utilities
|
|
1
3
|
export { classnames } from './src/utilities/classnames.js';
|
|
2
4
|
export { domBuilder } from './src/utilities/dom-builder/dom-builder.js';
|
|
3
5
|
export { enableSubmitBtns } from './src/utilities/enable-submit-btns.js';
|
|
6
|
+
|
|
7
|
+
// components
|
|
4
8
|
export { default as modalAlert } from './src/components/modal-alert/modal-alert.js';
|
|
9
|
+
export { dismissAlerts } from './src/components/dismiss-alerts.js';
|
|
10
|
+
export { formResetSubmit } from './src/components/form-reset-submit.js';
|
|
11
|
+
export { innerNav } from './src/components/inner-nav/inner-nav.js';
|
|
12
|
+
export { overlay, removeOverlay } from './src/components/overlay/overlay.js';
|
|
13
|
+
export { sf_macro } from './src/components/sf-macro/sf-macro.js';
|
|
14
|
+
export { snackbar } from './src/components/snackbar/snackbar.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@massimo-cassandro/minimo",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "Light css framework & utilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://github.com/massimo-cassandro/minimo#readme",
|
|
@@ -30,16 +30,7 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"main": "./index.js",
|
|
33
|
-
"sideEffects":
|
|
34
|
-
"*.css",
|
|
35
|
-
"*.js",
|
|
36
|
-
"*.svg",
|
|
37
|
-
"*.jpg",
|
|
38
|
-
"*.jpeg",
|
|
39
|
-
"*.png",
|
|
40
|
-
"*.webp",
|
|
41
|
-
"*.avif"
|
|
42
|
-
],
|
|
33
|
+
"sideEffects": false,
|
|
43
34
|
"files": [
|
|
44
35
|
"./index.js",
|
|
45
36
|
"src/**/*.{js,mjs,css,svg,md}",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
document.querySelectorAll('[data-dismiss]').forEach(item => {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
});
|
|
1
|
+
export function dismissAlerts(){
|
|
2
|
+
document.querySelectorAll('[data-dismiss]').forEach(item => {
|
|
3
|
+
item.addEventListener('click', () => {
|
|
4
|
+
item.closest('.' + item.dataset.dismiss).remove();
|
|
5
|
+
}, false);
|
|
6
|
+
});
|
|
7
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// import './form.css'; //incorporato nel css principale
|
|
2
|
+
import { enableSubmitBtns } from '../../index.js';
|
|
3
|
+
|
|
4
|
+
export function formResetSubmit(){
|
|
5
|
+
|
|
6
|
+
document.querySelectorAll('form').forEach( form => {
|
|
7
|
+
|
|
8
|
+
// form.querySelectorAll('[type="submit"]').forEach(btn =>{
|
|
9
|
+
// btn.addEventListener('click', () => {
|
|
10
|
+
// form.classList.add('was-validated');
|
|
11
|
+
// }, false);
|
|
12
|
+
// });
|
|
13
|
+
|
|
14
|
+
form.addEventListener('submit', e => {
|
|
15
|
+
|
|
16
|
+
if(!form.hasAttribute('data-no-was-validated')) {
|
|
17
|
+
form.classList.add('was-validated');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
form.querySelectorAll('.is-invalid, .is-valid').forEach(item => {
|
|
21
|
+
item.classList.remove('is-invalid', 'is-valid');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
if(!form.checkValidity()) {
|
|
25
|
+
e.preventDefault();
|
|
26
|
+
enableSubmitBtns();
|
|
27
|
+
|
|
28
|
+
} else {
|
|
29
|
+
if(!form.hasAttribute('data-no-disabling') && !form.hasAttribute('data-disable-submit')) { /* 'data-disable-submit' per compatibilitò con verioni precedenti */
|
|
30
|
+
form.querySelectorAll('[type="submit"]').forEach(btn => {
|
|
31
|
+
btn.disabled = true;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}, false);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
@@ -7,13 +7,16 @@
|
|
|
7
7
|
|
|
8
8
|
import './inner-nav.css';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
if (nav_primary) {
|
|
12
|
-
// nav_primary.classList.add('text-right', 'd-print-none');
|
|
13
|
-
let nav = nav_primary.innerHTML;
|
|
10
|
+
export function innerNav(){
|
|
14
11
|
|
|
15
|
-
document.
|
|
16
|
-
|
|
17
|
-
//
|
|
18
|
-
|
|
12
|
+
const nav_primary = document.querySelector('.inner-nav-main');
|
|
13
|
+
if (nav_primary) {
|
|
14
|
+
// nav_primary.classList.add('text-right', 'd-print-none');
|
|
15
|
+
let nav = nav_primary.innerHTML;
|
|
16
|
+
|
|
17
|
+
document.querySelectorAll('.inner-nav').forEach(item => {
|
|
18
|
+
item.innerHTML = nav;
|
|
19
|
+
// item.classList.add('text-right', 'd-print-none');
|
|
20
|
+
});
|
|
21
|
+
}
|
|
19
22
|
}
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
# `s-datatable` web-component
|
|
1
|
+
# `s-datatable` web-component per simple-datatables
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<https://fiduswriter.github.io/simple-datatables/documentation/>
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
## Utilizzo da markup
|
|
7
7
|
|
|
8
8
|
```html
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
##
|
|
9
|
+
<s-datatable
|
|
10
|
+
json="/api/data.json"
|
|
11
|
+
cols='[{"_heading":"Nome","_field":"name"}, ...]'
|
|
12
|
+
perPage="10"
|
|
13
|
+
></s-datatable>
|
|
14
|
+
|
|
15
|
+
<!-- Alternativa: dati inline via attributo (utile per SSR/Twig/Blade).
|
|
16
|
+
Se presenti entrambi, `data` ha la precedenza su `json`. -->
|
|
17
|
+
<s-datatable
|
|
18
|
+
data='[{"name":"Mario","city":"Roma"}, ...]'
|
|
19
|
+
cols='[{"_heading":"Nome","_field":"name"}, ...]'
|
|
20
|
+
perPage="10"
|
|
21
|
+
></s-datatable>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Utilizzo da script
|
|
25
25
|
|
|
26
26
|
```javascript
|
|
27
27
|
const el = document.querySelector('s-datatable');
|
|
@@ -43,23 +43,25 @@ el.init({
|
|
|
43
43
|
// Se appena creato, appendere dopo init():
|
|
44
44
|
document.body.appendChild(el);
|
|
45
45
|
```
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
## Utilizzo misto – attributi HTML + script
|
|
48
48
|
|
|
49
|
-
I parametri non inclusi in init() vengono letti dall'attributo HTML corrispondente.
|
|
49
|
+
I parametri non inclusi in `init()` vengono letti dall'attributo HTML corrispondente.
|
|
50
|
+
Si possono quindi separare configurazione statica (`cols`, `perPage`) nel markup
|
|
51
|
+
e dati dinamici (`json`) nello script:
|
|
50
52
|
|
|
51
|
-
```html
|
|
53
|
+
```html
|
|
52
54
|
<s-datatable
|
|
53
55
|
id="table-utenti"
|
|
54
56
|
cols='[{"_heading":"Nome","_field":"name"},{"_heading":"Città","_field":"city"}]'
|
|
55
57
|
perPage="20"
|
|
56
58
|
></s-datatable>
|
|
57
59
|
```
|
|
58
|
-
|
|
60
|
+
|
|
59
61
|
```javascript
|
|
60
62
|
el.init({ json: '/api/utenti.json' }); // → json da script, cols e perPage da attributo
|
|
61
63
|
```
|
|
62
|
-
|
|
64
|
+
|
|
63
65
|
Ordine di precedenza: config (script) > attributo HTML > default interno.
|
|
64
66
|
|
|
65
67
|
Per ignorare esplicitamente un attributo e ricadere sul default, passare `null` nel config:
|
|
@@ -67,121 +69,188 @@ Per ignorare esplicitamente un attributo e ricadere sul default, passare `null`
|
|
|
67
69
|
```javascript
|
|
68
70
|
el.init({ json: '/api/data.json', cols: null }); // → cols = null, l'attributo viene saltato
|
|
69
71
|
```
|
|
70
|
-
|
|
72
|
+
|
|
71
73
|
## Reazione ad eventi esterni
|
|
72
74
|
|
|
73
|
-
Il componente ascolta tre CustomEvent che altri componenti possono emettere
|
|
74
|
-
|
|
75
|
+
Il componente ascolta tre CustomEvent che altri componenti possono emettere
|
|
76
|
+
sul `document` (o su qualsiasi antenato del componente nel DOM):
|
|
77
|
+
|
|
75
78
|
### `datatable:search`
|
|
76
79
|
|
|
77
80
|
Applica una ricerca su una o più colonne.
|
|
78
81
|
|
|
79
82
|
`detail: { term: string, columns?: number[] }`
|
|
80
83
|
|
|
81
|
-
Esempio – ricerca globale:
|
|
82
|
-
|
|
83
84
|
```javascript
|
|
85
|
+
// Ricerca globale
|
|
84
86
|
document.dispatchEvent(new CustomEvent('datatable:search', {
|
|
85
87
|
detail: { term: 'mario' }
|
|
86
88
|
}));
|
|
87
|
-
```
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
detail: { term: 'mario', columns: [0, 2] }
|
|
94
|
-
}));
|
|
90
|
+
// Ricerca su colonna 0 e 2
|
|
91
|
+
document.dispatchEvent(new CustomEvent('datatable:search', {
|
|
92
|
+
detail: { term: 'mario', columns: [0, 2] }
|
|
93
|
+
}));
|
|
95
94
|
```
|
|
96
95
|
|
|
97
96
|
### `datatable:multisearch`
|
|
98
|
-
|
|
97
|
+
|
|
99
98
|
Applica più filtri contemporaneamente (uno per colonna).
|
|
100
99
|
|
|
101
100
|
`detail: { queries: Array<{ terms: string[], columns?: number[] }> }`
|
|
102
|
-
|
|
103
|
-
Esempio – filtra colonna 1 per "mario" E colonna 3 per "roma":
|
|
104
101
|
|
|
105
102
|
```javascript
|
|
103
|
+
// Filtra colonna 1 per "mario" E colonna 3 per "roma"
|
|
106
104
|
document.dispatchEvent(new CustomEvent('datatable:multisearch', {
|
|
107
105
|
detail: {
|
|
108
106
|
queries: [
|
|
109
|
-
{ terms: ['
|
|
107
|
+
{ terms: ['mario'], columns: [1] },
|
|
110
108
|
{ terms: ['roma'], columns: [3] }
|
|
111
109
|
]
|
|
112
110
|
}
|
|
113
111
|
}));
|
|
114
112
|
```
|
|
115
|
-
|
|
113
|
+
|
|
116
114
|
### `datatable:reload`
|
|
117
115
|
|
|
118
|
-
Ricarica i dati da un nuovo URL JSON (o dallo stesso URL originale se json è omesso),
|
|
116
|
+
Ricarica i dati da un nuovo URL JSON (o dallo stesso URL originale se `json` è omesso),
|
|
117
|
+
opzionalmente con nuove colonne, dati inline e/o un filtro da applicare al termine del
|
|
118
|
+
caricamento.
|
|
119
119
|
|
|
120
|
-
`detail: { json?: string, data?: Array, cols?: Array }`
|
|
120
|
+
`detail: { json?: string, data?: Array, cols?: Array, search?: object }`
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
```javascript
|
|
125
|
-
document.dispatchEvent(new CustomEvent('datatable:reload', {
|
|
126
|
-
detail: {}
|
|
127
|
-
}));
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
Esempio – nuovo endpoint + nuove colonne:
|
|
122
|
+
Il campo `search` permette di combinare reload e filtro in un unico evento, evitando
|
|
123
|
+
race condition tra il fetch e la ricerca. Formati supportati:
|
|
131
124
|
|
|
125
|
+
- `{ term, columns? }` → ricerca semplice
|
|
126
|
+
- `{ queries: [{terms, columns?}] }` → ricerca multipla
|
|
132
127
|
|
|
133
128
|
```javascript
|
|
129
|
+
// Reload stesso URL
|
|
130
|
+
document.dispatchEvent(new CustomEvent('datatable:reload', { detail: {} }));
|
|
131
|
+
|
|
132
|
+
// Nuovo endpoint + nuove colonne
|
|
134
133
|
document.dispatchEvent(new CustomEvent('datatable:reload', {
|
|
135
134
|
detail: {
|
|
136
135
|
json: '/api/data-filtered.json',
|
|
137
136
|
cols: [{ _heading: 'Nome', _field: 'name' }]
|
|
138
137
|
}
|
|
139
138
|
}));
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Esempio – dati inline (senza fetch):
|
|
143
139
|
|
|
144
|
-
|
|
140
|
+
// Dati inline (senza fetch)
|
|
145
141
|
document.dispatchEvent(new CustomEvent('datatable:reload', {
|
|
146
142
|
detail: {
|
|
147
143
|
data: [{ name: 'Mario', city: 'Roma' }],
|
|
148
|
-
|
|
144
|
+
}
|
|
145
|
+
}));
|
|
146
|
+
|
|
147
|
+
// Reload + filtro contestuale applicato dopo il render
|
|
148
|
+
document.dispatchEvent(new CustomEvent('datatable:reload', {
|
|
149
|
+
detail: {
|
|
150
|
+
json: '/api/utenti?anno=2024',
|
|
151
|
+
search: { term: 'mario', columns: [0] }
|
|
149
152
|
}
|
|
150
153
|
}));
|
|
151
154
|
```
|
|
152
|
-
|
|
153
155
|
|
|
154
|
-
## Targeting –
|
|
156
|
+
## Targeting – più istanze nella stessa pagina
|
|
157
|
+
|
|
158
|
+
Aggiungere `id` al componente e `target` nel detail. Se `target` è assente,
|
|
159
|
+
l'evento viene raccolto da **tutte** le istanze.
|
|
155
160
|
|
|
161
|
+
```html
|
|
162
|
+
<s-datatable id="table-utenti" ...></s-datatable>
|
|
163
|
+
```
|
|
156
164
|
|
|
157
|
-
Aggiungere l'attributo `id` al componente e includere `target` nel detail:
|
|
158
|
-
|
|
159
|
-
`<s-datatable id="table-utenti" ...></s-datatable>`
|
|
160
|
-
|
|
161
165
|
```javascript
|
|
162
166
|
document.dispatchEvent(new CustomEvent('datatable:search', {
|
|
163
167
|
detail: { term: 'mario', target: 'table-utenti' }
|
|
164
168
|
}));
|
|
165
169
|
```
|
|
166
170
|
|
|
167
|
-
|
|
171
|
+
## Parametro `cols`
|
|
168
172
|
|
|
169
|
-
|
|
173
|
+
Array di oggetti di configurazione delle colonne. Le chiavi con prefisso `_` sono
|
|
174
|
+
proprietà del componente; le restanti vengono passate direttamente a simple-datatables
|
|
175
|
+
(es. `sortable`, `searchable`, `type`, `hidden`, …).
|
|
170
176
|
|
|
171
177
|
```javascript
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
178
|
+
cols: [
|
|
179
|
+
{
|
|
180
|
+
// ── Proprietà del componente (prefisso _) ─────────────────────────────
|
|
181
|
+
|
|
182
|
+
_field, // Chiave del campo JSON. Obbligatorio.
|
|
183
|
+
// Supporta notazione punto per valori annidati: 'owner.cognome'
|
|
184
|
+
|
|
185
|
+
_heading, // Testo dell'intestazione di colonna (contenuto del <th>). Obbligatorio.
|
|
186
|
+
|
|
187
|
+
_title, // Testo del tooltip sull'intestazione (attributo `title` dell'<abbr>).
|
|
188
|
+
|
|
189
|
+
_renderTpl, // Template HTML per il contenuto della cella.
|
|
190
|
+
// I segnaposto [[chiave]] vengono sostituiti con i valori della riga.
|
|
191
|
+
// Supporta notazione punto: [[owner.nome]] [[owner.cognome]]
|
|
192
|
+
// Se un valore è null (es. oggetto padre assente da Symfony),
|
|
193
|
+
// il segnaposto viene sostituito con stringa vuota senza errori.
|
|
194
|
+
|
|
195
|
+
_renderMode, // Preset di visualizzazione predefiniti. Valori disponibili:
|
|
196
|
+
// 'id' – colonna numerica, non ricercabile, allineata a destra
|
|
197
|
+
// 'email' – va a capo prima e dopo la @
|
|
198
|
+
// 'boolean' – icona spunta/croce con colore semantico
|
|
199
|
+
// 'sf_datetime' – data/ora da oggetto Symfony ({ date, timezone })
|
|
200
|
+
|
|
201
|
+
_sortValue, // Percorso del campo da usare per l'ORDINAMENTO al posto del contenuto
|
|
202
|
+
// visualizzato. Utile quando la cella contiene HTML composto (_renderTpl).
|
|
203
|
+
// Supporta notazione punto.
|
|
204
|
+
// Implementato tramite l'attributo data-order sulla cella, letto
|
|
205
|
+
// nativamente da simple-datatables.
|
|
206
|
+
//
|
|
207
|
+
// Esempio: cella con '[[owner.nome]] [[owner.cognome]]'
|
|
208
|
+
// _sortValue: 'owner.cognome' → ordina per cognome
|
|
209
|
+
|
|
210
|
+
_searchValue, // Percorso/i del campo da usare per la RICERCA al posto del contenuto
|
|
211
|
+
// visualizzato. Accetta uno o più percorsi separati da spazio.
|
|
212
|
+
// Supporta notazione punto.
|
|
213
|
+
// Implementato tramite searchMethod di colonna (API simple-datatables)
|
|
214
|
+
// e attributo data-search sulla cella.
|
|
215
|
+
// La ricerca è di tipo AND: tutti i termini digitati devono essere
|
|
216
|
+
// presenti nel valore del campo (o dei campi) indicati.
|
|
217
|
+
//
|
|
218
|
+
// Esempio: _searchValue: 'owner.cognome owner.nome'
|
|
219
|
+
// cerca su entrambi i campi concatenati; "rossi mario" trova solo
|
|
220
|
+
// le righe che contengono entrambe le parole, in qualsiasi ordine.
|
|
221
|
+
|
|
222
|
+
// ── Proprietà native simple-datatables (senza prefisso _) ────────────
|
|
223
|
+
|
|
224
|
+
type, // Tipo di dato: 'string' | 'number' | 'date' | 'boolean' | 'html' | 'other'
|
|
225
|
+
sortable, // false per disabilitare l'ordinamento sulla colonna
|
|
226
|
+
searchable, // false per escludere la colonna dalla ricerca globale
|
|
227
|
+
hidden, // true per nascondere la colonna (esclusa anche dalla ricerca)
|
|
228
|
+
sort, // 'asc' | 'desc' per ordinamento iniziale (solo su colonna singola)
|
|
229
|
+
// ... tutte le altre opzioni columns di simple-datatables
|
|
230
|
+
}
|
|
231
|
+
]
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Esempio completo con valori annidati
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
const cols = [
|
|
238
|
+
{
|
|
239
|
+
_field: 'commessa',
|
|
240
|
+
_heading: 'Commessa / fornitore',
|
|
241
|
+
_renderTpl: '[[commessa]]<br><small class="text-muted">[[fornitore]]</small>',
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
_field: 'owner.cognome',
|
|
245
|
+
_heading: 'Owner',
|
|
246
|
+
_renderTpl: '[[owner.nome]] [[owner.cognome]]',
|
|
247
|
+
_sortValue: 'owner.cognome', // ordina per cognome
|
|
248
|
+
_searchValue: 'owner.cognome owner.nome', // cerca su cognome e nome (AND)
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
_field: 'importi.0.importo', // valore annidato con indice array
|
|
252
|
+
_heading: 'Importo',
|
|
253
|
+
type: 'number',
|
|
254
|
+
}
|
|
255
|
+
];
|
|
256
|
+
```
|
|
@@ -25,6 +25,15 @@ import caretRightIcon from '../../icons/caret-right.svg?inline';
|
|
|
25
25
|
* @property {string} [_renderTpl] Template HTML per il contenuto della cella.
|
|
26
26
|
* I segnaposto `[[key]]` vengono sostituiti con i
|
|
27
27
|
* valori corrispondenti dell'oggetto riga.
|
|
28
|
+
* @property {string} [_sortValue] Percorso del campo da usare per l'ordinamento al posto
|
|
29
|
+
* del contenuto visualizzato (es. 'owner.cognome').
|
|
30
|
+
* Supporta valori annidati con la notazione punto.
|
|
31
|
+
* Implementato tramite `data-order` sull'attributo della cella.
|
|
32
|
+
* @property {string} [_searchValue] Percorso del campo da usare per la ricerca al posto
|
|
33
|
+
* del contenuto visualizzato (es. 'owner.cognome owner.nome').
|
|
34
|
+
* Supporta valori annidati con la notazione punto.
|
|
35
|
+
* Implementato tramite una funzione `search` personalizzata
|
|
36
|
+
* sulla colonna (API simple-datatables).
|
|
28
37
|
* @property {'id'|'email'|'boolean'|'sf_datetime'} [_renderMode]
|
|
29
38
|
* Modalità di visualizzazione predefinita:
|
|
30
39
|
* - `id` – colonna numerica, non ricercabile, allineata a destra
|
|
@@ -332,6 +341,12 @@ class SimpleDatatableAdapter extends HTMLElement {
|
|
|
332
341
|
cells: cols.map((col_item, col_idx) => {
|
|
333
342
|
let value = getNestedValue(row, col_item._field);
|
|
334
343
|
|
|
344
|
+
// _sortValue: valore alternativo per l'ordinamento
|
|
345
|
+
// simple-datatables lo legge da cell.attributes['data-order']
|
|
346
|
+
const sortValue = col_item._sortValue
|
|
347
|
+
? (getNestedValue(row, col_item._sortValue) ?? '')
|
|
348
|
+
: null;
|
|
349
|
+
|
|
335
350
|
if (col_item._renderTpl) {
|
|
336
351
|
value = decodeURIComponent(col_item._renderTpl).replace(
|
|
337
352
|
/\[\[(.*?)\]\]/g,
|
|
@@ -358,6 +373,29 @@ class SimpleDatatableAdapter extends HTMLElement {
|
|
|
358
373
|
(value.timezone === 'UTC' ? 'Z' : '');
|
|
359
374
|
}
|
|
360
375
|
|
|
376
|
+
// _searchValue: valore alternativo per la ricerca
|
|
377
|
+
// Viene scritto come testo nascosto nella cella così la funzione
|
|
378
|
+
// search personalizzata della colonna può leggerlo direttamente
|
|
379
|
+
// dal contenuto, senza dipendere da attributi non supportati.
|
|
380
|
+
const searchValue = col_item._searchValue
|
|
381
|
+
? col_item._searchValue.split(' ')
|
|
382
|
+
.map(path => getNestedValue(row, path.trim()) ?? '')
|
|
383
|
+
.filter(Boolean)
|
|
384
|
+
.join(' ')
|
|
385
|
+
: null;
|
|
386
|
+
|
|
387
|
+
// Se sono definiti _sortValue o _searchValue, restituisce un
|
|
388
|
+
// oggetto cella strutturato; altrimenti il valore grezzo.
|
|
389
|
+
// Se sono definiti _sortValue o _searchValue, restituisce un
|
|
390
|
+
// oggetto cella strutturato con attributi data-order / data-search
|
|
391
|
+
// che simple-datatables può leggere in modo affidabile.
|
|
392
|
+
if (sortValue !== null || searchValue !== null) {
|
|
393
|
+
const attrs = {};
|
|
394
|
+
if (sortValue !== null) attrs['data-order'] = sortValue;
|
|
395
|
+
if (searchValue !== null) attrs['data-search'] = searchValue;
|
|
396
|
+
return { text: value ?? '', attributes: attrs };
|
|
397
|
+
}
|
|
398
|
+
|
|
361
399
|
return value;
|
|
362
400
|
})
|
|
363
401
|
}));
|
|
@@ -365,7 +403,7 @@ class SimpleDatatableAdapter extends HTMLElement {
|
|
|
365
403
|
this.columns = cols.map((col_settings, idx) => {
|
|
366
404
|
col_settings = parseCols(col_settings);
|
|
367
405
|
|
|
368
|
-
|
|
406
|
+
const colObj = {
|
|
369
407
|
...(Object.fromEntries(
|
|
370
408
|
Object.entries(col_settings).filter(([key]) => !key.startsWith('_'))
|
|
371
409
|
)),
|
|
@@ -374,6 +412,25 @@ class SimpleDatatableAdapter extends HTMLElement {
|
|
|
374
412
|
searchable: col_settings.searchable ?? true,
|
|
375
413
|
sortable: col_settings.sortable ?? true,
|
|
376
414
|
};
|
|
415
|
+
|
|
416
|
+
// _searchValue: funzione searchMethod personalizzata che opera su
|
|
417
|
+
// cell.attributes['data-search'] invece che sul testo visualizzato.
|
|
418
|
+
// L'API simple-datatables prevede: (terms, cell, row, colIdx, source)
|
|
419
|
+
// - terms: array di stringhe (uno per parola cercata)
|
|
420
|
+
// - cell: oggetto cella dai dati originali (con .text e .attributes)
|
|
421
|
+
// La funzione deve restituire true se la riga è da includere.
|
|
422
|
+
// Comportamento AND: tutti i termini devono essere presenti (come
|
|
423
|
+
// nella demo https://fiduswriter.github.io/simple-datatables/demos/22-and-search/).
|
|
424
|
+
if (col_settings._searchValue) {
|
|
425
|
+
colObj.searchMethod = (terms, cell) => {
|
|
426
|
+
const haystack = (
|
|
427
|
+
cell.attributes?.['data-search'] ?? cell.text ?? ''
|
|
428
|
+
).toLowerCase();
|
|
429
|
+
return terms.every(term => haystack.includes(term.toLowerCase()));
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return colObj;
|
|
377
434
|
});
|
|
378
435
|
|
|
379
436
|
} catch (err) {
|
package/src/components/forms.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
// import './form.css'; //incorporato nel css principale
|
|
2
|
-
|
|
3
|
-
import { enableSubmitBtns } from '../../index.js';
|
|
4
|
-
|
|
5
|
-
document.querySelectorAll('form').forEach( form => {
|
|
6
|
-
|
|
7
|
-
// form.querySelectorAll('[type="submit"]').forEach(btn =>{
|
|
8
|
-
// btn.addEventListener('click', () => {
|
|
9
|
-
// form.classList.add('was-validated');
|
|
10
|
-
// }, false);
|
|
11
|
-
// });
|
|
12
|
-
|
|
13
|
-
form.querySelectorAll('.is-invalid, .is-valid').forEach(item => {
|
|
14
|
-
item.classList.remove('is-invalid', 'is-valid');
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
form.addEventListener('submit', e => {
|
|
18
|
-
|
|
19
|
-
if(!form.hasAttribute('data-no-was-validated')) {
|
|
20
|
-
form.classList.add('was-validated');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if(!form.checkValidity()) {
|
|
24
|
-
e.preventDefault();
|
|
25
|
-
enableSubmitBtns();
|
|
26
|
-
|
|
27
|
-
} else {
|
|
28
|
-
if(!form.hasAttribute('data-no-disabling') && !form.hasAttribute('data-disable-submit')) { /* 'data-disable-submit' per compatibilitò con verioni precedenti */
|
|
29
|
-
form.querySelectorAll('[type="submit"]').forEach(btn => {
|
|
30
|
-
btn.disabled = true;
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}, false);
|
|
35
|
-
});
|
|
36
|
-
|