@conform-to/dom 1.6.1 → 1.7.1
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/README.md +1 -1
- package/dist/dom.d.ts +30 -9
- package/dist/dom.js +363 -14
- package/dist/dom.mjs +354 -14
- package/dist/form.d.ts +0 -10
- package/dist/form.js +5 -98
- package/dist/form.mjs +7 -99
- package/dist/formdata.d.ts +6 -4
- package/dist/formdata.js +41 -12
- package/dist/formdata.mjs +40 -12
- package/dist/index.d.ts +3 -3
- package/dist/index.js +8 -1
- package/dist/index.mjs +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
╚══════╝ ╚═════╝ ╚═╝ ╚══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
Version 1.
|
|
10
|
+
Version 1.7.1 / License MIT / Copyright (c) 2024 Edmund Hung
|
|
11
11
|
|
|
12
12
|
A type-safe form validation library utilizing web fundamentals to progressively enhance HTML Forms with full support for server frameworks like Remix and Next.js.
|
|
13
13
|
|
package/dist/dom.d.ts
CHANGED
|
@@ -3,19 +3,13 @@
|
|
|
3
3
|
* includes `<input>`, `<select>` and `<textarea>`.
|
|
4
4
|
*/
|
|
5
5
|
export type FieldElement = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
|
6
|
-
/**
|
|
7
|
-
* HTML Element that can be used as a form control,
|
|
8
|
-
* includes `<input>`, `<select>`, `<textarea>` and `<button>`.
|
|
9
|
-
*/
|
|
10
|
-
export type FormControl = FieldElement | HTMLButtonElement;
|
|
11
6
|
/**
|
|
12
7
|
* Form Control element. It can either be a submit button or a submit input.
|
|
13
8
|
*/
|
|
14
9
|
export type Submitter = HTMLInputElement | HTMLButtonElement;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
export declare function isFormControl(element: unknown): element is FormControl;
|
|
10
|
+
export declare function isInputElement(element: Element): element is HTMLInputElement;
|
|
11
|
+
export declare function isSelectElement(element: Element): element is HTMLSelectElement;
|
|
12
|
+
export declare function isTextAreaElement(element: Element): element is HTMLTextAreaElement;
|
|
19
13
|
/**
|
|
20
14
|
* A type guard to check if the provided element is a field element, which
|
|
21
15
|
* is a form control excluding submit, button and reset type.
|
|
@@ -41,4 +35,31 @@ export declare function getFormMethod(event: SubmitEvent): 'GET' | 'POST' | 'PUT
|
|
|
41
35
|
* If the submitter is not mounted, it will be appended to the form and removed after submission.
|
|
42
36
|
*/
|
|
43
37
|
export declare function requestSubmit(form: HTMLFormElement | null | undefined, submitter: Submitter | null): void;
|
|
38
|
+
export declare function createFileList(value: File | File[]): FileList;
|
|
39
|
+
type InputCallback = (event: {
|
|
40
|
+
type: 'input' | 'reset' | 'mutation';
|
|
41
|
+
target: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
|
42
|
+
}) => void;
|
|
43
|
+
type FormCallback = (event: {
|
|
44
|
+
type: 'submit' | 'input' | 'reset' | 'mutation';
|
|
45
|
+
target: HTMLFormElement;
|
|
46
|
+
submitter?: HTMLInputElement | HTMLButtonElement | null;
|
|
47
|
+
}) => void;
|
|
48
|
+
export declare function createGlobalFormsObserver(): {
|
|
49
|
+
onFieldUpdate(callback: InputCallback): () => void;
|
|
50
|
+
onFormUpdate(callback: FormCallback): () => void;
|
|
51
|
+
dispose(): void;
|
|
52
|
+
};
|
|
53
|
+
export declare function change(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, value: string | string[] | File | File[] | FileList | null): void;
|
|
54
|
+
export declare function focus(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): void;
|
|
55
|
+
export declare function blur(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): void;
|
|
56
|
+
export declare function normalizeFieldValue(value: unknown): [string[] | null, FileList | null];
|
|
57
|
+
/**
|
|
58
|
+
* Updates the DOM element with the provided value and defaultValue.
|
|
59
|
+
*/
|
|
60
|
+
export declare function updateField(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, options: {
|
|
61
|
+
value?: unknown;
|
|
62
|
+
defaultValue?: unknown;
|
|
63
|
+
}): void;
|
|
64
|
+
export {};
|
|
44
65
|
//# sourceMappingURL=dom.d.ts.map
|
package/dist/dom.js
CHANGED
|
@@ -9,20 +9,18 @@ var util = require('./util.js');
|
|
|
9
9
|
* includes `<input>`, `<select>` and `<textarea>`.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
/**
|
|
13
|
-
* HTML Element that can be used as a form control,
|
|
14
|
-
* includes `<input>`, `<select>`, `<textarea>` and `<button>`.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
12
|
/**
|
|
18
13
|
* Form Control element. It can either be a submit button or a submit input.
|
|
19
14
|
*/
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
function
|
|
25
|
-
return element
|
|
16
|
+
function isInputElement(element) {
|
|
17
|
+
return element.tagName === 'INPUT';
|
|
18
|
+
}
|
|
19
|
+
function isSelectElement(element) {
|
|
20
|
+
return element.tagName === 'SELECT';
|
|
21
|
+
}
|
|
22
|
+
function isTextAreaElement(element) {
|
|
23
|
+
return element.tagName === 'TEXTAREA';
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
/**
|
|
@@ -30,7 +28,15 @@ function isFormControl(element) {
|
|
|
30
28
|
* is a form control excluding submit, button and reset type.
|
|
31
29
|
*/
|
|
32
30
|
function isFieldElement(element) {
|
|
33
|
-
|
|
31
|
+
if (element instanceof Element) {
|
|
32
|
+
if (isInputElement(element)) {
|
|
33
|
+
return element.type !== 'submit' && element.type !== 'button' && element.type !== 'reset';
|
|
34
|
+
}
|
|
35
|
+
if (isSelectElement(element) || isTextAreaElement(element)) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
/**
|
|
@@ -87,18 +93,361 @@ function requestSubmit(form, submitter) {
|
|
|
87
93
|
if (typeof form.requestSubmit === 'function') {
|
|
88
94
|
form.requestSubmit(submitter);
|
|
89
95
|
} else {
|
|
90
|
-
var
|
|
96
|
+
var _event = new SubmitEvent('submit', {
|
|
91
97
|
bubbles: true,
|
|
92
98
|
cancelable: true,
|
|
93
99
|
submitter
|
|
94
100
|
});
|
|
95
|
-
form.dispatchEvent(
|
|
101
|
+
form.dispatchEvent(_event);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function createFileList(value) {
|
|
105
|
+
var dataTransfer = new DataTransfer();
|
|
106
|
+
if (Array.isArray(value)) {
|
|
107
|
+
for (var file of value) {
|
|
108
|
+
dataTransfer.items.add(file);
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
dataTransfer.items.add(value);
|
|
112
|
+
}
|
|
113
|
+
return dataTransfer.files;
|
|
114
|
+
}
|
|
115
|
+
function createGlobalFormsObserver() {
|
|
116
|
+
var inputListeners = new Set();
|
|
117
|
+
var formListeners = new Set();
|
|
118
|
+
var cleanup = null;
|
|
119
|
+
function initialize() {
|
|
120
|
+
var observer = new MutationObserver(handleMutation);
|
|
121
|
+
observer.observe(document.body, {
|
|
122
|
+
subtree: true,
|
|
123
|
+
childList: true,
|
|
124
|
+
attributeFilter: ['form', 'name', 'data-conform']
|
|
125
|
+
});
|
|
126
|
+
document.addEventListener('input', handleInput);
|
|
127
|
+
document.addEventListener('reset', handleReset);
|
|
128
|
+
document.addEventListener('submit', handleSubmit, true);
|
|
129
|
+
return () => {
|
|
130
|
+
document.removeEventListener('input', handleInput);
|
|
131
|
+
document.removeEventListener('reset', handleReset);
|
|
132
|
+
document.removeEventListener('submit', handleSubmit, true);
|
|
133
|
+
observer.disconnect();
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function handleInput(event) {
|
|
137
|
+
var target = event.target;
|
|
138
|
+
if (isFieldElement(target)) {
|
|
139
|
+
inputListeners.forEach(callback => callback({
|
|
140
|
+
type: 'input',
|
|
141
|
+
target
|
|
142
|
+
}));
|
|
143
|
+
var form = target.form;
|
|
144
|
+
if (form) {
|
|
145
|
+
formListeners.forEach(callback => callback({
|
|
146
|
+
type: 'input',
|
|
147
|
+
target: form
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function handleReset(event) {
|
|
153
|
+
var form = event.target;
|
|
154
|
+
if (form instanceof HTMLFormElement) {
|
|
155
|
+
// Reset event is fired before the form is reset, so we need to wait for the next tick
|
|
156
|
+
setTimeout(() => {
|
|
157
|
+
formListeners.forEach(callback => {
|
|
158
|
+
callback({
|
|
159
|
+
type: 'reset',
|
|
160
|
+
target: form
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
var _loop = function _loop(target) {
|
|
164
|
+
if (isFieldElement(target)) {
|
|
165
|
+
inputListeners.forEach(callback => {
|
|
166
|
+
callback({
|
|
167
|
+
type: 'reset',
|
|
168
|
+
target
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
for (var target of form.elements) {
|
|
174
|
+
_loop(target);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function handleSubmit(event) {
|
|
180
|
+
var target = event.target;
|
|
181
|
+
var submitter = event.submitter;
|
|
182
|
+
if (target instanceof HTMLFormElement) {
|
|
183
|
+
formListeners.forEach(callback => callback({
|
|
184
|
+
type: 'submit',
|
|
185
|
+
target,
|
|
186
|
+
submitter
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function handleMutation(mutations) {
|
|
191
|
+
var seenForms = new Set();
|
|
192
|
+
var seenInputs = new Set();
|
|
193
|
+
var collectInputs = node => {
|
|
194
|
+
if (isFieldElement(node)) {
|
|
195
|
+
return [node];
|
|
196
|
+
}
|
|
197
|
+
return node instanceof Element ? Array.from(node.querySelectorAll('input,select,textarea')) : [];
|
|
198
|
+
};
|
|
199
|
+
for (var mutation of mutations) {
|
|
200
|
+
switch (mutation.type) {
|
|
201
|
+
case 'childList':
|
|
202
|
+
{
|
|
203
|
+
var nodes = [...mutation.addedNodes, ...mutation.removedNodes];
|
|
204
|
+
for (var node of nodes) {
|
|
205
|
+
for (var input of collectInputs(node)) {
|
|
206
|
+
seenInputs.add(input);
|
|
207
|
+
if (input.form) {
|
|
208
|
+
seenForms.add(input.form);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
case 'attributes':
|
|
215
|
+
{
|
|
216
|
+
if (isFieldElement(mutation.target)) {
|
|
217
|
+
seenInputs.add(mutation.target);
|
|
218
|
+
if (mutation.target.form) {
|
|
219
|
+
seenForms.add(mutation.target.form);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
var _loop2 = function _loop2(target) {
|
|
227
|
+
formListeners.forEach(callback => {
|
|
228
|
+
callback({
|
|
229
|
+
type: 'mutation',
|
|
230
|
+
target
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
};
|
|
234
|
+
for (var target of seenForms) {
|
|
235
|
+
_loop2(target);
|
|
236
|
+
}
|
|
237
|
+
var _loop3 = function _loop3(_target) {
|
|
238
|
+
inputListeners.forEach(callback => {
|
|
239
|
+
callback({
|
|
240
|
+
type: 'mutation',
|
|
241
|
+
target: _target
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
};
|
|
245
|
+
for (var _target of seenInputs) {
|
|
246
|
+
_loop3(_target);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
onFieldUpdate(callback) {
|
|
251
|
+
var _cleanup;
|
|
252
|
+
cleanup = (_cleanup = cleanup) !== null && _cleanup !== void 0 ? _cleanup : initialize();
|
|
253
|
+
inputListeners.add(callback);
|
|
254
|
+
return () => {
|
|
255
|
+
inputListeners.delete(callback);
|
|
256
|
+
};
|
|
257
|
+
},
|
|
258
|
+
onFormUpdate(callback) {
|
|
259
|
+
var _cleanup2;
|
|
260
|
+
cleanup = (_cleanup2 = cleanup) !== null && _cleanup2 !== void 0 ? _cleanup2 : initialize();
|
|
261
|
+
formListeners.add(callback);
|
|
262
|
+
return () => {
|
|
263
|
+
formListeners.delete(callback);
|
|
264
|
+
};
|
|
265
|
+
},
|
|
266
|
+
dispose() {
|
|
267
|
+
var _cleanup3;
|
|
268
|
+
(_cleanup3 = cleanup) === null || _cleanup3 === void 0 || _cleanup3();
|
|
269
|
+
cleanup = null;
|
|
270
|
+
inputListeners.clear();
|
|
271
|
+
formListeners.clear();
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
function change(element, value) {
|
|
276
|
+
// The value should be set to the element before dispatching the event
|
|
277
|
+
updateField(element, {
|
|
278
|
+
value
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Dispatch input event with the updated input value
|
|
282
|
+
element.dispatchEvent(new InputEvent('input', {
|
|
283
|
+
bubbles: true
|
|
284
|
+
}));
|
|
285
|
+
// Dispatch change event (necessary for select to update the selected option)
|
|
286
|
+
element.dispatchEvent(new Event('change', {
|
|
287
|
+
bubbles: true
|
|
288
|
+
}));
|
|
289
|
+
}
|
|
290
|
+
function focus(element) {
|
|
291
|
+
// Only focusin event will be bubbled
|
|
292
|
+
element.dispatchEvent(new FocusEvent('focusin', {
|
|
293
|
+
bubbles: true
|
|
294
|
+
}));
|
|
295
|
+
element.dispatchEvent(new FocusEvent('focus'));
|
|
296
|
+
}
|
|
297
|
+
function blur(element) {
|
|
298
|
+
// Only focusout event will be bubbled
|
|
299
|
+
element.dispatchEvent(new FocusEvent('focusout', {
|
|
300
|
+
bubbles: true
|
|
301
|
+
}));
|
|
302
|
+
element.dispatchEvent(new FocusEvent('blur'));
|
|
303
|
+
}
|
|
304
|
+
function normalizeFieldValue(value) {
|
|
305
|
+
if (typeof value === 'undefined') {
|
|
306
|
+
return [null, null];
|
|
307
|
+
}
|
|
308
|
+
if (value === null) {
|
|
309
|
+
return [[], createFileList([])];
|
|
310
|
+
}
|
|
311
|
+
if (typeof value === 'string') {
|
|
312
|
+
return [[value], null];
|
|
313
|
+
}
|
|
314
|
+
if (Array.isArray(value)) {
|
|
315
|
+
if (value.every(item => typeof item === 'string')) {
|
|
316
|
+
return [Array.from(value), null];
|
|
317
|
+
}
|
|
318
|
+
if (value.every(item => item instanceof File)) {
|
|
319
|
+
return [null, createFileList(value)];
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (value instanceof FileList) {
|
|
323
|
+
return [null, value];
|
|
324
|
+
}
|
|
325
|
+
if (value instanceof File) {
|
|
326
|
+
return [null, createFileList([value])];
|
|
327
|
+
}
|
|
328
|
+
return [null, null];
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Updates the DOM element with the provided value and defaultValue.
|
|
333
|
+
*/
|
|
334
|
+
function updateField(element, options) {
|
|
335
|
+
var _value$;
|
|
336
|
+
var [value, file] = normalizeFieldValue(options.value);
|
|
337
|
+
var [defaultValue] = normalizeFieldValue(options.defaultValue);
|
|
338
|
+
if (isInputElement(element)) {
|
|
339
|
+
switch (element.type) {
|
|
340
|
+
case 'file':
|
|
341
|
+
{
|
|
342
|
+
element.files = file;
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
case 'checkbox':
|
|
346
|
+
case 'radio':
|
|
347
|
+
{
|
|
348
|
+
if (value) {
|
|
349
|
+
var checked = value.includes(element.value);
|
|
350
|
+
if (element.type === 'checkbox' ? checked !== element.checked : checked) {
|
|
351
|
+
// Simulate a click to update the checked state
|
|
352
|
+
element.click();
|
|
353
|
+
}
|
|
354
|
+
element.checked = checked;
|
|
355
|
+
}
|
|
356
|
+
if (defaultValue) {
|
|
357
|
+
element.defaultChecked = defaultValue.includes(element.value);
|
|
358
|
+
}
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
} else if (isSelectElement(element)) {
|
|
363
|
+
var shouldUnselect = value && value.length === 0;
|
|
364
|
+
for (var option of element.options) {
|
|
365
|
+
if (value) {
|
|
366
|
+
var index = value.indexOf(option.value);
|
|
367
|
+
var selected = index > -1;
|
|
368
|
+
|
|
369
|
+
// Update the selected state of the option
|
|
370
|
+
if (option.selected !== selected) {
|
|
371
|
+
option.selected = selected;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Remove the option from the value array
|
|
375
|
+
if (selected) {
|
|
376
|
+
value.splice(index, 1);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (defaultValue) {
|
|
380
|
+
var _index = defaultValue.indexOf(option.value);
|
|
381
|
+
var _selected = _index > -1;
|
|
382
|
+
|
|
383
|
+
// Update the selected state of the option
|
|
384
|
+
if (option.defaultSelected !== _selected) {
|
|
385
|
+
option.defaultSelected = _selected;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Remove the option from the defaultValue array
|
|
389
|
+
if (_selected) {
|
|
390
|
+
defaultValue.splice(_index, 1);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// We have already removed all selected options from the value and defaultValue array at this point
|
|
396
|
+
var missingOptions = new Set([...(value !== null && value !== void 0 ? value : []), ...(defaultValue !== null && defaultValue !== void 0 ? defaultValue : [])]);
|
|
397
|
+
for (var optionValue of missingOptions) {
|
|
398
|
+
element.options.add(new Option(optionValue, optionValue, defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.includes(optionValue), value === null || value === void 0 ? void 0 : value.includes(optionValue)));
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// If the select element is not multiple and the value is an empty array, unset the selected index
|
|
402
|
+
// This is to prevent the select element from showing the first option as selected
|
|
403
|
+
if (shouldUnselect) {
|
|
404
|
+
element.selectedIndex = -1;
|
|
405
|
+
}
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
var inputValue = (_value$ = value === null || value === void 0 ? void 0 : value[0]) !== null && _value$ !== void 0 ? _value$ : '';
|
|
409
|
+
if (element.value !== inputValue) {
|
|
410
|
+
/**
|
|
411
|
+
* Triggering react custom change event
|
|
412
|
+
* Solution based on dom-testing-library
|
|
413
|
+
* @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
|
|
414
|
+
* @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
|
|
415
|
+
*/
|
|
416
|
+
var {
|
|
417
|
+
set: valueSetter
|
|
418
|
+
} = Object.getOwnPropertyDescriptor(element, 'value') || {};
|
|
419
|
+
var prototype = Object.getPrototypeOf(element);
|
|
420
|
+
var {
|
|
421
|
+
set: prototypeValueSetter
|
|
422
|
+
} = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
|
|
423
|
+
if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
|
|
424
|
+
prototypeValueSetter.call(element, inputValue);
|
|
425
|
+
} else {
|
|
426
|
+
if (valueSetter) {
|
|
427
|
+
valueSetter.call(element, inputValue);
|
|
428
|
+
} else {
|
|
429
|
+
throw new Error('The given element does not have a value setter');
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
if (defaultValue) {
|
|
434
|
+
var _defaultValue$;
|
|
435
|
+
element.defaultValue = (_defaultValue$ = defaultValue[0]) !== null && _defaultValue$ !== void 0 ? _defaultValue$ : '';
|
|
96
436
|
}
|
|
97
437
|
}
|
|
98
438
|
|
|
439
|
+
exports.blur = blur;
|
|
440
|
+
exports.change = change;
|
|
441
|
+
exports.createFileList = createFileList;
|
|
442
|
+
exports.createGlobalFormsObserver = createGlobalFormsObserver;
|
|
443
|
+
exports.focus = focus;
|
|
99
444
|
exports.getFormAction = getFormAction;
|
|
100
445
|
exports.getFormEncType = getFormEncType;
|
|
101
446
|
exports.getFormMethod = getFormMethod;
|
|
102
447
|
exports.isFieldElement = isFieldElement;
|
|
103
|
-
exports.
|
|
448
|
+
exports.isInputElement = isInputElement;
|
|
449
|
+
exports.isSelectElement = isSelectElement;
|
|
450
|
+
exports.isTextAreaElement = isTextAreaElement;
|
|
451
|
+
exports.normalizeFieldValue = normalizeFieldValue;
|
|
104
452
|
exports.requestSubmit = requestSubmit;
|
|
453
|
+
exports.updateField = updateField;
|