Skip to content

Instantly share code, notes, and snippets.

@dfkaye
Created August 22, 2023 21:51
Show Gist options
  • Save dfkaye/938b9bf78f63968491b82cc4378c1c3b to your computer and use it in GitHub Desktop.
Save dfkaye/938b9bf78f63968491b82cc4378c1c3b to your computer and use it in GitHub Desktop.
scoped reset button actions on fields in the same fieldset.
// 16 August 2023
// Scoped reset button actions on fields in the same fieldset.
// This is one way to manage resetting only radio groups or checkboxes in a form
// without resetting every other element.
// We could go further and group such related fields in separate forms to avoid
// any JavaScript with click handler logic.
// This came up because one of the loudest front-end developers on Twitter was
// completely baffled as to why radio elements cannot be completely un-selected
// by the user, even when none of them in the group is checked by default.
// Rather than waste time debating the Why and/or urging a revision to the spec
// for radio groups now 20-something years old, we show how you can reset all
// elements in a form, or some elements in selected fieldsets using a custom
// data attribute with names of resettable elements (in this case only the
// checkable ones).
// We also contrast scoped reset with global reset and scoped submit with
// global submit.
// With that, we start with a template literal that we'll pass into the DOM...
var html = `
<form name=one>
<fieldset name=first data-scope="F">
<legend>first</legend>
<label for="F.1">F1</label>
<input type=radio value=1 name="F" id="F.1">
<label for="F.2">F2</label>
<input type=radio value=2 name="F" value=2 id="F.2">
<hr>
<input type=reset value="Clear first">
<input type=submit value="Submit first">
</fieldset>
</form>
<form name=two>
<fieldset name=other data-scope="O">
<legend>other</legend>
<input type=checkbox name="O" id="O.1">
<label for="O.1">check</label>
<hr>
<input type=reset value="Clear other">
<input type=submit value="Submit other">
<hr>
<label for=t1>t1</label>
<input id=t1 name=t1>
</fieldset>
<hr>
<input type=reset value="Clear all">
<input type=submit value="Submit all">
</form>
`;
// Then insert it using setHTML() (if in Chrome, to avoid the "trusted HTML" CSP
// policy in "blank" windows...
`setHTML` in document.body
? document.body.setHTML(html)
: document.body.innerHTML = html;
// reset and submit examples follow...
/* reset */
document.querySelectorAll(`[type="reset"]`).forEach(reset => {
var fs = reset.closest(`[data-scope]`);
var name = fs && fs.getAttribute("data-scope");
if (!name) {
reset.addEventListener("click", function (e) {
Array.from(document.forms).forEach(form => {
form.reset();
});
console.log("normal course");
});
return;
}
reset.addEventListener("click", function (e) {
e.preventDefault();
// yes, use the form.elements array.
var group = reset.form.elements[name];
var elms = group.length > 1
? Array.from(group)
: [group];
// yes, use defaultChecked.
elms.forEach(function (f) { f.checked = f.defaultChecked; });
});
});
/* submit */
document.querySelectorAll(`[type="submit"]`).forEach(submit => {
var fs = submit.closest(`[data-scope]`);
var name = fs && fs.getAttribute("data-scope");
if (!name) {
submit.addEventListener("click", function (e) {
e.preventDefault();
var data = new FormData;
Array.from(document.forms).forEach(form => {
var formData = new FormData(form);
console.log("form", form.name, ":",);
for (var [k, v] of formData) {
data.set(k, v);
}
});
return console.log("all data:", data);
});
return;
}
submit.addEventListener("click", function (e) {
e.preventDefault();
var { form } = submit;
var formData = new FormData(form);
return console.log("form", form.name, ":", formData)
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment