@appius-fr/apx 2.5.2 → 2.6.0
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/APX.mjs +121 -118
- package/README.md +55 -22
- package/dist/APX.dev.mjs +765 -119
- package/dist/APX.mjs +1 -1
- package/dist/APX.prod.mjs +1 -1
- package/dist/APX.standalone.js +732 -36
- package/dist/APX.standalone.js.map +1 -1
- package/modules/listen/README.md +235 -0
- package/modules/tools/README.md +165 -0
- package/modules/tools/exports.mjs +16 -0
- package/modules/tools/form-packer/README.md +315 -0
- package/modules/tools/form-packer/augment-apx.mjs +30 -0
- package/modules/tools/form-packer/packToJson.mjs +549 -0
- package/package.json +1 -1
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# APX Tools: Form Packer
|
|
2
|
+
|
|
3
|
+
The `form-packer` module provides utilities for converting HTML forms into structured JSON objects. It handles complex form structures including nested objects, arrays, numeric indices, and mixed structures.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
The `form-packer` module is automatically included when you import APX. It provides both a direct API and an APX object method.
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
import APX from './APX.mjs';
|
|
13
|
+
// APX.tools.packFormToJSON() and APX('form').pack() are now available
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
### Method 1: Direct API
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
const form = document.querySelector('#myForm');
|
|
24
|
+
const data = APX.tools.packFormToJSON(form);
|
|
25
|
+
console.log(data);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Method 2: APX Object Method (Recommended)
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
// Using APX selector
|
|
32
|
+
const data = APX('form#myForm').pack();
|
|
33
|
+
const data2 = APX('form.myformclass').pack();
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
### Nested Objects
|
|
41
|
+
|
|
42
|
+
Use bracket notation to create nested objects:
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<input name="user[name]" value="John">
|
|
46
|
+
<input name="user[email]" value="john@example.com">
|
|
47
|
+
<input name="user[profile][age]" value="30">
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Result:**
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"user": {
|
|
54
|
+
"name": "John",
|
|
55
|
+
"email": "john@example.com",
|
|
56
|
+
"profile": {
|
|
57
|
+
"age": "30"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Arrays
|
|
64
|
+
|
|
65
|
+
Use `[]` notation to create arrays:
|
|
66
|
+
|
|
67
|
+
```html
|
|
68
|
+
<input name="tags[]" value="javascript">
|
|
69
|
+
<input name="tags[]" value="html">
|
|
70
|
+
<input name="tags[]" value="css">
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Result:**
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"tags": ["javascript", "html", "css"]
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Numeric Indices
|
|
81
|
+
|
|
82
|
+
Use numeric indices to create arrays with specific positions:
|
|
83
|
+
|
|
84
|
+
```html
|
|
85
|
+
<input name="items[0][name]" value="Item 1">
|
|
86
|
+
<input name="items[0][price]" value="10">
|
|
87
|
+
<input name="items[1][name]" value="Item 2">
|
|
88
|
+
<input name="items[1][price]" value="20">
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Result:**
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"items": [
|
|
95
|
+
{ "name": "Item 1", "price": "10" },
|
|
96
|
+
{ "name": "Item 2", "price": "20" }
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Mixed Structures
|
|
102
|
+
|
|
103
|
+
The module intelligently handles mixed structures (objects with both numeric and string keys):
|
|
104
|
+
|
|
105
|
+
```html
|
|
106
|
+
<input name="data[type]" value="product">
|
|
107
|
+
<input name="data[0][name]" value="Item 1">
|
|
108
|
+
<input name="data[1][name]" value="Item 2">
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Result:**
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"data": {
|
|
115
|
+
"type": "product",
|
|
116
|
+
"0": { "name": "Item 1" },
|
|
117
|
+
"1": { "name": "Item 2" }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## API
|
|
125
|
+
|
|
126
|
+
### `APX.tools.packFormToJSON(form)`
|
|
127
|
+
|
|
128
|
+
Converts an HTML form element into a JSON object.
|
|
129
|
+
|
|
130
|
+
**Parameters:**
|
|
131
|
+
- `form` (HTMLFormElement): The form element to convert
|
|
132
|
+
|
|
133
|
+
**Returns:** (Object) The JSON object representation of the form data
|
|
134
|
+
|
|
135
|
+
**Throws:** (TypeError) If `form` is not an `HTMLFormElement`
|
|
136
|
+
|
|
137
|
+
**Example:**
|
|
138
|
+
```javascript
|
|
139
|
+
const form = document.querySelector('#myForm');
|
|
140
|
+
try {
|
|
141
|
+
const data = APX.tools.packFormToJSON(form);
|
|
142
|
+
console.log(data);
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.error('Error:', error.message);
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### `APX('form').pack()`
|
|
149
|
+
|
|
150
|
+
Converts the first selected form element into a JSON object. This is a chainable method on APX objects.
|
|
151
|
+
|
|
152
|
+
**Returns:** (Object) The JSON object representation of the form data
|
|
153
|
+
|
|
154
|
+
**Throws:** (Error) If no element is found or the first element is not a form
|
|
155
|
+
|
|
156
|
+
**Example:**
|
|
157
|
+
```javascript
|
|
158
|
+
try {
|
|
159
|
+
const data = APX('form#myForm').pack();
|
|
160
|
+
console.log(data);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error('Error:', error.message);
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Advanced Features
|
|
169
|
+
|
|
170
|
+
### Conflict Detection
|
|
171
|
+
|
|
172
|
+
The module automatically detects incompatible form structures and throws descriptive errors:
|
|
173
|
+
|
|
174
|
+
```html
|
|
175
|
+
<!-- This will throw an error -->
|
|
176
|
+
<input name="items[0]" value="primitive value">
|
|
177
|
+
<input name="items[0][nested][value]" value="nested value">
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Error:** `Path conflict: "items[0]" is used as a final value, but "items[0][nested][value]" tries to use it as an intermediate path.`
|
|
181
|
+
|
|
182
|
+
### Two-Phase Processing
|
|
183
|
+
|
|
184
|
+
The module uses a two-phase processing architecture:
|
|
185
|
+
|
|
186
|
+
1. **Analysis Phase**: Analyzes all form fields to detect conflicts and structure requirements
|
|
187
|
+
2. **Processing Phase**: Builds the JSON object with intelligent type conversion
|
|
188
|
+
|
|
189
|
+
This ensures correct handling of complex structures and prevents data loss.
|
|
190
|
+
|
|
191
|
+
### ES6+ Best Practices
|
|
192
|
+
|
|
193
|
+
The module is built with modern JavaScript:
|
|
194
|
+
- Arrow functions
|
|
195
|
+
- Destructuring
|
|
196
|
+
- Optional chaining (`?.`)
|
|
197
|
+
- Nullish coalescing (`??`)
|
|
198
|
+
- `for...of` loops
|
|
199
|
+
- `Number.parseInt` / `Number.isNaN`
|
|
200
|
+
- `reduce()` for transformations
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Examples
|
|
205
|
+
|
|
206
|
+
### Complex Form Example
|
|
207
|
+
|
|
208
|
+
```html
|
|
209
|
+
<form id="userForm">
|
|
210
|
+
<input name="name" value="John Doe">
|
|
211
|
+
<input name="email" value="john@example.com">
|
|
212
|
+
|
|
213
|
+
<input name="address[street]" value="123 Main St">
|
|
214
|
+
<input name="address[city]" value="New York">
|
|
215
|
+
<input name="address[zip]" value="10001">
|
|
216
|
+
|
|
217
|
+
<input name="tags[]" value="developer">
|
|
218
|
+
<input name="tags[]" value="designer">
|
|
219
|
+
|
|
220
|
+
<input name="items[0][name]" value="Laptop">
|
|
221
|
+
<input name="items[0][price]" value="999">
|
|
222
|
+
<input name="items[1][name]" value="Mouse">
|
|
223
|
+
<input name="items[1][price]" value="29">
|
|
224
|
+
</form>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
const data = APX('form#userForm').pack();
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Result:**
|
|
232
|
+
```json
|
|
233
|
+
{
|
|
234
|
+
"name": "John Doe",
|
|
235
|
+
"email": "john@example.com",
|
|
236
|
+
"address": {
|
|
237
|
+
"street": "123 Main St",
|
|
238
|
+
"city": "New York",
|
|
239
|
+
"zip": "10001"
|
|
240
|
+
},
|
|
241
|
+
"tags": ["developer", "designer"],
|
|
242
|
+
"items": [
|
|
243
|
+
{ "name": "Laptop", "price": "999" },
|
|
244
|
+
{ "name": "Mouse", "price": "29" }
|
|
245
|
+
]
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Multiple Values
|
|
250
|
+
|
|
251
|
+
If multiple inputs share the same name (without brackets), they are automatically converted to an array:
|
|
252
|
+
|
|
253
|
+
```html
|
|
254
|
+
<input name="color" value="red">
|
|
255
|
+
<input name="color" value="blue">
|
|
256
|
+
<input name="color" value="green">
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**Result:**
|
|
260
|
+
```json
|
|
261
|
+
{
|
|
262
|
+
"color": ["red", "blue", "green"]
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Supported Input Types
|
|
269
|
+
|
|
270
|
+
The module supports all standard HTML form input types:
|
|
271
|
+
- `text`, `email`, `password`, `number`, `tel`, `url`, `search`
|
|
272
|
+
- `checkbox`, `radio`
|
|
273
|
+
- `select` (single and multiple)
|
|
274
|
+
- `textarea`
|
|
275
|
+
- `hidden`
|
|
276
|
+
- Custom input types
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Error Handling
|
|
281
|
+
|
|
282
|
+
The module provides clear error messages for common issues:
|
|
283
|
+
|
|
284
|
+
- **Invalid input**: `TypeError: packFormToJSON expects an HTMLFormElement`
|
|
285
|
+
- **No element found**: `Error: No element found` (when using `.pack()`)
|
|
286
|
+
- **Not a form**: `Error: Element is not a form` (when using `.pack()`)
|
|
287
|
+
- **Path conflicts**: Descriptive error messages indicating the conflicting paths
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Demo
|
|
292
|
+
|
|
293
|
+
See the interactive demo at `demo/modules/tools/index.html` for:
|
|
294
|
+
- Live form examples
|
|
295
|
+
- Dynamic form generation
|
|
296
|
+
- JSON output visualization
|
|
297
|
+
- Form-to-JSON validation tool
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Notes
|
|
302
|
+
|
|
303
|
+
- Empty form fields are included in the result (with empty string values)
|
|
304
|
+
- Checkboxes and radio buttons use their `value` attribute (or `"on"` if no value)
|
|
305
|
+
- Multiple select elements create arrays automatically
|
|
306
|
+
- The module handles edge cases like empty keys, mixed structures, and numeric indices
|
|
307
|
+
- All conversions preserve the original form structure as much as possible
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## License
|
|
312
|
+
|
|
313
|
+
Author : Thibault SAELEN
|
|
314
|
+
Copyright Appius SARL.
|
|
315
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { packFormToJSON } from './packToJson.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Ajoute la méthode pack() aux objets APX pour convertir les formulaires en JSON
|
|
5
|
+
* @param {Object} apx - L'objet APX à augmenter
|
|
6
|
+
* @returns {Object} L'objet APX augmenté
|
|
7
|
+
*/
|
|
8
|
+
export default function (apx) {
|
|
9
|
+
/**
|
|
10
|
+
* Convertit le premier formulaire sélectionné en objet JSON
|
|
11
|
+
* @returns {Object} L'objet JSON résultant
|
|
12
|
+
* @throws {Error} Si aucun formulaire n'est trouvé ou si le premier élément n'est pas un formulaire
|
|
13
|
+
* @example
|
|
14
|
+
* const data = APX('form.myformclass').pack();
|
|
15
|
+
*/
|
|
16
|
+
apx.pack = function () {
|
|
17
|
+
const firstElement = this.first();
|
|
18
|
+
if (!firstElement) {
|
|
19
|
+
throw new Error('No element found');
|
|
20
|
+
}
|
|
21
|
+
if (firstElement.tagName !== 'FORM') {
|
|
22
|
+
throw new Error('Element is not a form');
|
|
23
|
+
}
|
|
24
|
+
return packFormToJSON(firstElement);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return apx;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|