If I do the following:
<html>
<head>
<script type='text/javascript'>
window.addEventListener('load', () => {
const form = document.forms[0];
const sel = form.querySelectorAll('input,select,fieldset,textarea');
console.log(sel);
});
</script>
</head>
<form>
<input type='text' name='e00'/>
<input type='text' name='e01'/>
<fieldset>
<input type='text' name='e10'/>
<input type='text' name='e11'/>
<fieldset>
<input type='text' name='e20'/>
</fieldset>
</fieldset>
<input type='text' name='e02'/>
</form>
</html>
The querySelectorAll call (or form.elements) returns all form elements in a collection like:
0: input e00
1: input e01
2: fieldset
3: input e10
4: input e11
5: fieldset
6: input e20
7: input e02
But this does not tell me which input elements are within each fieldset. All form elements are flattened into the elements / querySelectorAll result.
Q: Is there a way to traverse the hierarchy of form elements such that I can determine which are within each fieldset?
The fieldset element has an elements collection as well. So perhaps when I encounter a fieldset I can traverse it’s elements and then use that knowledge to ignore them in the parent elements collections. But that seems awful clumsy. Is there a better way?
UPDATE:
I suppose I could just do this:
function traverse(node, ret) {
switch (node.tagName) {
case 'SELECT':
case 'INPUT':
case 'TEXTAREA':
ret[node.name] = node.tagName;
return;
case 'FORM':
case 'FIELDSET':
ret = ret[node.name] = {};
break;
}
for (let ci = 0; ci < node.children.length; ci++) {
traverse(node.children[ci], ret);
}
}
window.addEventListener('load', () => {
const form = document.forms[0];
let obj = {};
traverse(form, obj);
console.log(obj);
});
which captures the fieldset tree structure:
f0:
e00: "INPUT"
e01: "INPUT"
e02: "INPUT"
s00:
e10: "INPUT"
e11: "INPUT"
s10:
e20: "INPUT"