@samline/forms 2.8.0 → 2.9.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/CHANGELOG.md +15 -1
- package/README.md +43 -31
- package/dist/browser/global.d.ts +49 -3
- package/dist/browser/global.global.js +12 -12
- package/dist/browser/global.global.js.map +1 -1
- package/dist/browser/index.cjs +222 -35
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.d.cts +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/{chunk-23VZAYA3.js → chunk-6MA5TF6R.js} +223 -36
- package/dist/chunk-6MA5TF6R.js.map +1 -0
- package/dist/index.cjs +222 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{registry-GzopYPCR.d.cts → registry-CPe_lf8-.d.cts} +50 -4
- package/dist/{registry-GzopYPCR.d.ts → registry-CPe_lf8-.d.ts} +50 -4
- package/package.json +9 -6
- package/dist/chunk-23VZAYA3.js.map +0 -1
package/dist/browser/index.cjs
CHANGED
|
@@ -519,6 +519,7 @@ var createDestroy = (state2, _helpers) => () => {
|
|
|
519
519
|
}
|
|
520
520
|
}
|
|
521
521
|
state2.watchedFields.clear();
|
|
522
|
+
state2.groupWatchers.clear();
|
|
522
523
|
state2.subscribers.clear();
|
|
523
524
|
state2.submitHandlers.clear();
|
|
524
525
|
state2.fieldCache.clear();
|
|
@@ -746,9 +747,9 @@ var writeFieldValue = (fields, value) => {
|
|
|
746
747
|
continue;
|
|
747
748
|
}
|
|
748
749
|
if (field instanceof HTMLSelectElement && field.multiple) {
|
|
749
|
-
const
|
|
750
|
+
const selectedValues2 = normalizedArray ?? [normalizedValue];
|
|
750
751
|
for (const option of field.options) {
|
|
751
|
-
option.selected =
|
|
752
|
+
option.selected = selectedValues2.includes(option.value);
|
|
752
753
|
}
|
|
753
754
|
continue;
|
|
754
755
|
}
|
|
@@ -783,8 +784,7 @@ var submitForm = (form3) => {
|
|
|
783
784
|
var createGetValue = (state2, helpers) => (name) => readFieldValue(helpers.getFieldsByName(name));
|
|
784
785
|
|
|
785
786
|
// src/api/observe.ts
|
|
786
|
-
var
|
|
787
|
-
if (state2.isDestroyed) return () => void 0;
|
|
787
|
+
var observeField = (state2, field, callback) => {
|
|
788
788
|
const callbacks = state2.watchedFields.get(field) ?? /* @__PURE__ */ new Set();
|
|
789
789
|
callbacks.add(callback);
|
|
790
790
|
state2.watchedFields.set(field, callbacks);
|
|
@@ -799,6 +799,26 @@ var createObserve = (state2, helpers) => (field, callback) => {
|
|
|
799
799
|
}
|
|
800
800
|
};
|
|
801
801
|
};
|
|
802
|
+
var observeFields = (state2, fields, callback) => {
|
|
803
|
+
const names = Array.from(new Set(fields));
|
|
804
|
+
if (names.length === 0) return () => void 0;
|
|
805
|
+
const entry = { fields: names, callback };
|
|
806
|
+
state2.groupWatchers.add(entry);
|
|
807
|
+
if (state2.element) {
|
|
808
|
+
const values = Object.fromEntries(names.map((name) => [name, state2.api.getValue(name)]));
|
|
809
|
+
callback(values, null, state2.element, state2.api.getState());
|
|
810
|
+
}
|
|
811
|
+
return () => {
|
|
812
|
+
state2.groupWatchers.delete(entry);
|
|
813
|
+
};
|
|
814
|
+
};
|
|
815
|
+
var createObserve = (state2, _helpers) => {
|
|
816
|
+
function observe(field, callback) {
|
|
817
|
+
if (state2.isDestroyed) return () => void 0;
|
|
818
|
+
return Array.isArray(field) ? observeFields(state2, field, callback) : observeField(state2, field, callback);
|
|
819
|
+
}
|
|
820
|
+
return observe;
|
|
821
|
+
};
|
|
802
822
|
|
|
803
823
|
// src/api/on-submit.ts
|
|
804
824
|
var createOnSubmit = (state2, _helpers) => (callback, preventDefault = true) => {
|
|
@@ -870,6 +890,75 @@ var createSetErrors = (state2, helpers) => (fields) => {
|
|
|
870
890
|
return state2.api;
|
|
871
891
|
};
|
|
872
892
|
|
|
893
|
+
// src/api/set-options.ts
|
|
894
|
+
var isGroup = (entry) => typeof entry === "object" && entry !== null && Array.isArray(entry.options);
|
|
895
|
+
var createOption = (entry) => {
|
|
896
|
+
const option = document.createElement("option");
|
|
897
|
+
if (typeof entry === "object") {
|
|
898
|
+
option.value = String(entry.value);
|
|
899
|
+
option.textContent = entry.label ?? String(entry.value);
|
|
900
|
+
option.disabled = Boolean(entry.disabled);
|
|
901
|
+
if (entry.selected) option.defaultSelected = true;
|
|
902
|
+
} else {
|
|
903
|
+
option.value = String(entry);
|
|
904
|
+
option.textContent = String(entry);
|
|
905
|
+
}
|
|
906
|
+
return option;
|
|
907
|
+
};
|
|
908
|
+
var buildNodes = (options) => {
|
|
909
|
+
const nodes = [];
|
|
910
|
+
let hasExplicitSelection = false;
|
|
911
|
+
const track = (option) => {
|
|
912
|
+
if (option.defaultSelected) hasExplicitSelection = true;
|
|
913
|
+
return option;
|
|
914
|
+
};
|
|
915
|
+
for (const entry of options) {
|
|
916
|
+
if (entry === null || entry === void 0) continue;
|
|
917
|
+
if (isGroup(entry)) {
|
|
918
|
+
const group = document.createElement("optgroup");
|
|
919
|
+
group.label = entry.label;
|
|
920
|
+
group.disabled = Boolean(entry.disabled);
|
|
921
|
+
for (const child of entry.options) {
|
|
922
|
+
if (child === null || child === void 0) continue;
|
|
923
|
+
group.appendChild(track(createOption(child)));
|
|
924
|
+
}
|
|
925
|
+
nodes.push(group);
|
|
926
|
+
continue;
|
|
927
|
+
}
|
|
928
|
+
nodes.push(track(createOption(entry)));
|
|
929
|
+
}
|
|
930
|
+
return { nodes, hasExplicitSelection };
|
|
931
|
+
};
|
|
932
|
+
var selectedValues = (select) => Array.from(select.selectedOptions, (option) => option.value);
|
|
933
|
+
var restoreSelection = (select, previous) => {
|
|
934
|
+
if (previous.length === 0) return;
|
|
935
|
+
const options = Array.from(select.options);
|
|
936
|
+
if (select.multiple) {
|
|
937
|
+
for (const option of options) option.selected = previous.includes(option.value);
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
const match = options.find((option) => option.value === previous[0]);
|
|
941
|
+
if (match) match.selected = true;
|
|
942
|
+
};
|
|
943
|
+
var sameValues = (left, right) => left.length === right.length && left.every((value, index) => value === right[index]);
|
|
944
|
+
var createSetOptions = (state2, helpers) => (name, options, config = {}) => {
|
|
945
|
+
if (!state2.element || state2.isDestroyed) return state2.api;
|
|
946
|
+
const selects = helpers.getFieldsByName(name).filter((field) => field instanceof HTMLSelectElement);
|
|
947
|
+
if (selects.length === 0) return state2.api;
|
|
948
|
+
const keepValue = config.keepValue ?? true;
|
|
949
|
+
const changed = [];
|
|
950
|
+
for (const select of selects) {
|
|
951
|
+
const previous = selectedValues(select);
|
|
952
|
+
const { nodes, hasExplicitSelection } = buildNodes(options);
|
|
953
|
+
select.replaceChildren(...nodes);
|
|
954
|
+
if (keepValue && !hasExplicitSelection) restoreSelection(select, previous);
|
|
955
|
+
if (!sameValues(previous, selectedValues(select))) changed.push(select);
|
|
956
|
+
}
|
|
957
|
+
helpers.commitOwnMutations(selects);
|
|
958
|
+
changed[0]?.dispatchEvent(new Event("input", { bubbles: true }));
|
|
959
|
+
return state2.api;
|
|
960
|
+
};
|
|
961
|
+
|
|
873
962
|
// src/api/set-value.ts
|
|
874
963
|
var createSetValue = (state2, helpers) => (name, value) => {
|
|
875
964
|
if (state2.isDestroyed) return state2.api;
|
|
@@ -893,28 +982,46 @@ var createSubscribe = (state2, _helpers) => (listener) => {
|
|
|
893
982
|
};
|
|
894
983
|
|
|
895
984
|
// src/api/unwatch.ts
|
|
896
|
-
var
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
985
|
+
var sameFields = (left, right) => left.length === right.size && left.every((name) => right.has(name));
|
|
986
|
+
var createUnwatch = (state2, _helpers) => {
|
|
987
|
+
function unwatch(field, callback) {
|
|
988
|
+
if (field === void 0 || field === "") {
|
|
989
|
+
state2.watchedFields.clear();
|
|
990
|
+
state2.groupWatchers.clear();
|
|
991
|
+
return state2.api;
|
|
992
|
+
}
|
|
993
|
+
if (Array.isArray(field)) {
|
|
994
|
+
const names = new Set(field);
|
|
995
|
+
for (const entry of Array.from(state2.groupWatchers)) {
|
|
996
|
+
if (!sameFields(entry.fields, names)) continue;
|
|
997
|
+
if (callback && entry.callback !== callback) continue;
|
|
998
|
+
state2.groupWatchers.delete(entry);
|
|
999
|
+
}
|
|
1000
|
+
return state2.api;
|
|
1001
|
+
}
|
|
1002
|
+
if (!callback) {
|
|
1003
|
+
state2.watchedFields.delete(field);
|
|
1004
|
+
return state2.api;
|
|
1005
|
+
}
|
|
1006
|
+
const callbacks = state2.watchedFields.get(field);
|
|
1007
|
+
callbacks?.delete(callback);
|
|
1008
|
+
if (callbacks && callbacks.size === 0) {
|
|
1009
|
+
state2.watchedFields.delete(field);
|
|
1010
|
+
}
|
|
903
1011
|
return state2.api;
|
|
904
1012
|
}
|
|
905
|
-
|
|
906
|
-
callbacks?.delete(callback);
|
|
907
|
-
if (callbacks && callbacks.size === 0) {
|
|
908
|
-
state2.watchedFields.delete(field);
|
|
909
|
-
}
|
|
910
|
-
return state2.api;
|
|
1013
|
+
return unwatch;
|
|
911
1014
|
};
|
|
912
1015
|
|
|
913
1016
|
// src/api/watch.ts
|
|
914
|
-
var createWatch = (state2, helpers) =>
|
|
1017
|
+
var createWatch = (state2, helpers) => {
|
|
915
1018
|
const observe = createObserve(state2, helpers);
|
|
916
|
-
|
|
917
|
-
|
|
1019
|
+
function watch(field, callback) {
|
|
1020
|
+
if (Array.isArray(field)) observe(field, callback);
|
|
1021
|
+
else observe(field, callback);
|
|
1022
|
+
return state2.api;
|
|
1023
|
+
}
|
|
1024
|
+
return watch;
|
|
918
1025
|
};
|
|
919
1026
|
|
|
920
1027
|
// src/core/validation.ts
|
|
@@ -1067,6 +1174,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1067
1174
|
attributes,
|
|
1068
1175
|
validators: normalizedOptions.validators ?? {},
|
|
1069
1176
|
watchedFields: /* @__PURE__ */ new Map(),
|
|
1177
|
+
groupWatchers: /* @__PURE__ */ new Set(),
|
|
1070
1178
|
subscribers: /* @__PURE__ */ new Set(),
|
|
1071
1179
|
submitHandlers: /* @__PURE__ */ new Set(),
|
|
1072
1180
|
fieldCache: /* @__PURE__ */ new Map(),
|
|
@@ -1237,7 +1345,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1237
1345
|
}
|
|
1238
1346
|
return affected;
|
|
1239
1347
|
};
|
|
1240
|
-
const
|
|
1348
|
+
const emitSingleWatchers = (name) => {
|
|
1241
1349
|
if (!state2.element || !state2.api) return;
|
|
1242
1350
|
const callbacks = state2.watchedFields.get(name);
|
|
1243
1351
|
if (!callbacks || callbacks.size === 0) return;
|
|
@@ -1246,6 +1354,23 @@ var createFormController = (target, options = {}) => {
|
|
|
1246
1354
|
const snapshot = state2.api.getState();
|
|
1247
1355
|
callbacks.forEach((callback) => callback(value, fieldElement, state2.element, snapshot));
|
|
1248
1356
|
};
|
|
1357
|
+
const emitGroupWatchers = (names) => {
|
|
1358
|
+
if (!state2.element || !state2.api || state2.groupWatchers.size === 0) return;
|
|
1359
|
+
let snapshot;
|
|
1360
|
+
for (const entry of Array.from(state2.groupWatchers)) {
|
|
1361
|
+
const changed = names ? names.find((name) => entry.fields.includes(name)) : null;
|
|
1362
|
+
if (changed === void 0) continue;
|
|
1363
|
+
snapshot ?? (snapshot = state2.api.getState());
|
|
1364
|
+
const values = Object.fromEntries(
|
|
1365
|
+
entry.fields.map((field) => [field, state2.api.getValue(field)])
|
|
1366
|
+
);
|
|
1367
|
+
entry.callback(values, changed, state2.element, snapshot);
|
|
1368
|
+
}
|
|
1369
|
+
};
|
|
1370
|
+
const emitFieldWatchers = (name) => {
|
|
1371
|
+
emitSingleWatchers(name);
|
|
1372
|
+
emitGroupWatchers([name]);
|
|
1373
|
+
};
|
|
1249
1374
|
const runAutoSubmit = () => {
|
|
1250
1375
|
state2.autoSubmitTimer = null;
|
|
1251
1376
|
if (!state2.element || state2.isDestroyed || !state2.autoSubmitEnabled) return;
|
|
@@ -1266,8 +1391,20 @@ var createFormController = (target, options = {}) => {
|
|
|
1266
1391
|
}
|
|
1267
1392
|
runAutoSubmit();
|
|
1268
1393
|
};
|
|
1394
|
+
const selectSnapshots = /* @__PURE__ */ new WeakMap();
|
|
1395
|
+
const readSelectSnapshot = (select) => Array.from(select.selectedOptions, (option) => option.value).join("\0");
|
|
1396
|
+
const snapshotSelect = (select) => {
|
|
1397
|
+
selectSnapshots.set(select, readSelectSnapshot(select));
|
|
1398
|
+
};
|
|
1399
|
+
const snapshotAllSelects = () => {
|
|
1400
|
+
if (!state2.element) return;
|
|
1401
|
+
for (const field of getNamedFields(state2.element)) {
|
|
1402
|
+
if (field instanceof HTMLSelectElement) snapshotSelect(field);
|
|
1403
|
+
}
|
|
1404
|
+
};
|
|
1269
1405
|
const emitAllFieldWatchers = () => {
|
|
1270
|
-
for (const name of Array.from(state2.watchedFields.keys()))
|
|
1406
|
+
for (const name of Array.from(state2.watchedFields.keys())) emitSingleWatchers(name);
|
|
1407
|
+
emitGroupWatchers(null);
|
|
1271
1408
|
};
|
|
1272
1409
|
const applyReset = () => {
|
|
1273
1410
|
if (!state2.element || state2.isDestroyed) return;
|
|
@@ -1279,6 +1416,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1279
1416
|
state2.validationElementErrors.clear();
|
|
1280
1417
|
clearAttributes(state2.element, [attributes.error, attributes.filled, "aria-invalid"]);
|
|
1281
1418
|
syncVisualState();
|
|
1419
|
+
snapshotAllSelects();
|
|
1282
1420
|
emitAllFieldWatchers();
|
|
1283
1421
|
notifySubscribers();
|
|
1284
1422
|
};
|
|
@@ -1293,7 +1431,8 @@ var createFormController = (target, options = {}) => {
|
|
|
1293
1431
|
validateNames,
|
|
1294
1432
|
emitFieldWatchers,
|
|
1295
1433
|
scheduleAutoSubmit,
|
|
1296
|
-
applyReset
|
|
1434
|
+
applyReset,
|
|
1435
|
+
commitOwnMutations: (selects) => commitOwnMutations(selects)
|
|
1297
1436
|
};
|
|
1298
1437
|
const handleDelegatedEvent = (event) => {
|
|
1299
1438
|
const target2 = event.target;
|
|
@@ -1301,6 +1440,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1301
1440
|
const name = target2.name;
|
|
1302
1441
|
if (!name) return;
|
|
1303
1442
|
clearFieldCache();
|
|
1443
|
+
if (target2 instanceof HTMLSelectElement) snapshotSelect(target2);
|
|
1304
1444
|
const canonical = resolveCanonicalForName(state2, name) ?? name;
|
|
1305
1445
|
const displayName = resolveDisplayNameForName(state2, name);
|
|
1306
1446
|
if (normalizedOptions.clearManualErrorsOnChange) {
|
|
@@ -1311,8 +1451,9 @@ var createFormController = (target, options = {}) => {
|
|
|
1311
1451
|
if (state2.isValidated && affectedValidationNames.some((field) => state2.validators[field] !== void 0)) {
|
|
1312
1452
|
validateNames(affectedValidationNames);
|
|
1313
1453
|
}
|
|
1314
|
-
|
|
1315
|
-
if (canonical !== name)
|
|
1454
|
+
emitSingleWatchers(canonical);
|
|
1455
|
+
if (canonical !== name) emitSingleWatchers(name);
|
|
1456
|
+
emitGroupWatchers(canonical !== name ? [canonical, name] : [canonical]);
|
|
1316
1457
|
notifySubscribers();
|
|
1317
1458
|
scheduleAutoSubmit();
|
|
1318
1459
|
};
|
|
@@ -1393,18 +1534,62 @@ var createFormController = (target, options = {}) => {
|
|
|
1393
1534
|
const cancel = () => clearTimeout(timer);
|
|
1394
1535
|
state2.cleanups.add(cancel);
|
|
1395
1536
|
};
|
|
1537
|
+
const touchesFields = (node) => node instanceof Element && (isFieldElement(node) || node.querySelector("input, select, textarea") !== null);
|
|
1538
|
+
const isStructural = (record) => record.type === "attributes" || Array.from(record.addedNodes).some(touchesFields) || Array.from(record.removedNodes).some(touchesFields);
|
|
1539
|
+
const isOptionNode = (node) => node instanceof HTMLOptionElement || node instanceof HTMLOptGroupElement;
|
|
1540
|
+
const optionListOwner = (record) => {
|
|
1541
|
+
if (record.type !== "childList") return null;
|
|
1542
|
+
const touchesOptions = Array.from(record.addedNodes).some(isOptionNode) || Array.from(record.removedNodes).some(isOptionNode);
|
|
1543
|
+
if (!touchesOptions) return null;
|
|
1544
|
+
const target2 = record.target;
|
|
1545
|
+
if (target2 instanceof HTMLSelectElement) return target2;
|
|
1546
|
+
if (target2 instanceof HTMLOptGroupElement && target2.parentElement instanceof HTMLSelectElement) {
|
|
1547
|
+
return target2.parentElement;
|
|
1548
|
+
}
|
|
1549
|
+
return null;
|
|
1550
|
+
};
|
|
1551
|
+
const handleMutations = (records) => {
|
|
1552
|
+
if (state2.isDestroyed) return;
|
|
1553
|
+
const structural = records.some(isStructural);
|
|
1554
|
+
const changedNames = /* @__PURE__ */ new Set();
|
|
1555
|
+
for (const record of records) {
|
|
1556
|
+
const select = optionListOwner(record);
|
|
1557
|
+
if (!select || !select.name) continue;
|
|
1558
|
+
const next = readSelectSnapshot(select);
|
|
1559
|
+
if (selectSnapshots.get(select) !== next) changedNames.add(select.name);
|
|
1560
|
+
selectSnapshots.set(select, next);
|
|
1561
|
+
}
|
|
1562
|
+
if (!structural && changedNames.size === 0) return;
|
|
1563
|
+
clearFieldCache();
|
|
1564
|
+
if (structural) {
|
|
1565
|
+
snapshotAllSelects();
|
|
1566
|
+
if (state2.isValidated) validateNames();
|
|
1567
|
+
else syncVisualState();
|
|
1568
|
+
} else {
|
|
1569
|
+
const affected = /* @__PURE__ */ new Set();
|
|
1570
|
+
for (const name of changedNames) {
|
|
1571
|
+
for (const field of getAffectedValidationNames(name)) affected.add(field);
|
|
1572
|
+
}
|
|
1573
|
+
const names = Array.from(affected);
|
|
1574
|
+
syncVisualState(Array.from(changedNames));
|
|
1575
|
+
if (state2.isValidated && names.some((field) => state2.validators[field] !== void 0)) {
|
|
1576
|
+
validateNames(names);
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
for (const name of changedNames) emitFieldWatchers(name);
|
|
1580
|
+
notifySubscribers();
|
|
1581
|
+
};
|
|
1582
|
+
const commitOwnMutations = (selects) => {
|
|
1583
|
+
selects.forEach(snapshotSelect);
|
|
1584
|
+
const pending = state2.mutationObserver?.takeRecords() ?? [];
|
|
1585
|
+
const foreign = pending.filter(
|
|
1586
|
+
(record) => !selects.some((select) => select.contains(record.target))
|
|
1587
|
+
);
|
|
1588
|
+
if (foreign.length > 0) handleMutations(foreign);
|
|
1589
|
+
};
|
|
1396
1590
|
const startMutationObserver = () => {
|
|
1397
1591
|
if (!state2.element || typeof MutationObserver === "undefined") return;
|
|
1398
|
-
|
|
1399
|
-
const isRelevant = (record) => record.type === "attributes" || Array.from(record.addedNodes).some(touchesFields) || Array.from(record.removedNodes).some(touchesFields);
|
|
1400
|
-
state2.mutationObserver = new MutationObserver((records) => {
|
|
1401
|
-
if (state2.isDestroyed || !records.some(isRelevant)) return;
|
|
1402
|
-
clearFieldCache();
|
|
1403
|
-
if (state2.isValidated) {
|
|
1404
|
-
validateNames();
|
|
1405
|
-
} else syncVisualState();
|
|
1406
|
-
notifySubscribers();
|
|
1407
|
-
});
|
|
1592
|
+
state2.mutationObserver = new MutationObserver(handleMutations);
|
|
1408
1593
|
state2.mutationObserver.observe(state2.element, {
|
|
1409
1594
|
childList: true,
|
|
1410
1595
|
subtree: true,
|
|
@@ -1433,6 +1618,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1433
1618
|
setErrors: createSetErrors(state2, helpers),
|
|
1434
1619
|
clearErrors: createClearErrors(state2, helpers),
|
|
1435
1620
|
setValue: createSetValue(state2, helpers),
|
|
1621
|
+
setOptions: createSetOptions(state2, helpers),
|
|
1436
1622
|
getValue: createGetValue(state2, helpers),
|
|
1437
1623
|
getField: createGetField(state2, helpers),
|
|
1438
1624
|
validate: createValidate(state2, helpers),
|
|
@@ -1452,6 +1638,7 @@ var createFormController = (target, options = {}) => {
|
|
|
1452
1638
|
addListener2(document, "input", handleExternalDelegatedEvent);
|
|
1453
1639
|
addListener2(state2.element, "submit", handleSubmitEvent);
|
|
1454
1640
|
addListener2(state2.element, "reset", handleResetEvent);
|
|
1641
|
+
snapshotAllSelects();
|
|
1455
1642
|
startMutationObserver();
|
|
1456
1643
|
}
|
|
1457
1644
|
if (normalizedOptions.autoSubmit) {
|