ortunado
ortunadoβ€’3y ago

ortunado – 17-21 Nov 8

Could anyone have idea, how to manage querySelectorAll to select all input elements, but not the ones inside another form? For example,
<form class=".form" data-form="Form1">
<div>
<input /> <= This input would like to be selected.
</div>
<div>
<input /> <= This input would like to be selected.
</div>
<form class=".form" data-form="Form2">
<div>
<input /> <= This input would like to NOT be selected.
</div>
<input /> <= This input would like to NOT be selected.
</form>
<input /> <= This input would like to be selected.
</form>
<form class=".form" data-form="Form1">
<div>
<input /> <= This input would like to be selected.
</div>
<div>
<input /> <= This input would like to be selected.
</div>
<form class=".form" data-form="Form2">
<div>
<input /> <= This input would like to NOT be selected.
</div>
<input /> <= This input would like to NOT be selected.
</form>
<input /> <= This input would like to be selected.
</form>
29 Replies
ortunado
ortunadoOPβ€’3y ago
The easiest would be to use element.closest() but could there be any other way?
Louis
Louisβ€’3y ago
Which inputs do you want here? Can you annotate them please
ortunado
ortunadoOPβ€’3y ago
Edited the original message. This is the current version with JS, would like to not use element.closest
document.querySelector(`[data-form="${uniqueId}"]`)?.querySelectorAll("input:not([form]), textarea:not([form]), select:not([form]), button:not([form])").forEach(element => {
const closestForm = element.closest(".form");
if (closestForm.getAttribute("data-form") !== uniqueId) {
return;
}

element.setAttribute("form", uniqueId);
});
document.querySelector(`[data-form="${uniqueId}"]`)?.querySelectorAll("input:not([form]), textarea:not([form]), select:not([form]), button:not([form])").forEach(element => {
const closestForm = element.closest(".form");
if (closestForm.getAttribute("data-form") !== uniqueId) {
return;
}

element.setAttribute("form", uniqueId);
});
EvokeMe
EvokeMeβ€’3y ago
const querySelectorWithDepth = (selectorParent, selector, not = 'form') =>
[
`${selectorParent} > :not(${not}) ${selector}`,
`${selectorParent} > ${selector}`,
].reduce((r, v) => r.concat(...(document.querySelectorAll(v) || [])), [])
const querySelectorWithDepth = (selectorParent, selector, not = 'form') =>
[
`${selectorParent} > :not(${not}) ${selector}`,
`${selectorParent} > ${selector}`,
].reduce((r, v) => r.concat(...(document.querySelectorAll(v) || [])), [])
querySelectorWithDepth(`[data-form="Form1"]`, `input`)
querySelectorWithDepth(`[data-form="Form1"]`, `input`)
Louis
Louisβ€’3y ago
Query selector CSS power πŸ’ͺ that's really nice πŸ‘ digging around doing a React 18 upgrade but I probably would've come up with something a bit worse anyway
EvokeMe
EvokeMeβ€’3y ago
And we need remove last small thing. Right now any depth. πŸ™‚
Louis
Louisβ€’3y ago
Beautiful bit of DOM work there
EvokeMe
EvokeMeβ€’3y ago
Also we can merge rules:
const querySelectorWithDepth = (
selectorParent,
selector,
not = ':not(form)',
) =>
document.querySelectorAll(
`${selectorParent} > ${not} ${selector}, ${selectorParent} > ${selector}`,
)
const querySelectorWithDepth = (
selectorParent,
selector,
not = ':not(form)',
) =>
document.querySelectorAll(
`${selectorParent} > ${not} ${selector}, ${selectorParent} > ${selector}`,
)
And form cannot be in form.
Louis
Louisβ€’3y ago
Can you merge query selector selectors like that in the same way you can merge CSS ruleset selectors? I never knew that
EvokeMe
EvokeMeβ€’3y ago
Right.
Louis
Louisβ€’3y ago
Damn, TIL
EvokeMe
EvokeMeβ€’3y ago
<a:7119_Jotaro_Dancing:608310437955502146>
Louis
Louisβ€’3y ago
Haven't had to work with the DOM at a low level for a few years now but that's wicked! Although as an aside, I don't think it's semantically correct to nest forms anyway so πŸ€·β€β™‚οΈ
EvokeMe
EvokeMeβ€’3y ago
Same, now lying in bed a little sick recovered it from memory and docs.
Louis
Louisβ€’3y ago
The days before querySelector were doom and gloom The DOM methods are so powerful but god forbid I have to work with them at that low a level again
ortunado
ortunadoOPβ€’3y ago
Edit fiddle - JSFiddle - Code Playground
Test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle code editor.
ortunado
ortunadoOPβ€’3y ago
This seems to get all the inputs expect the one after, may I be doing something wrong? Thanks for great help πŸ™‚ Yes, I do agree nesting forms are kinda lame, and you need to do some kind of magic, to match each submit, not really sure why the colleagues have done that.
Louis
Louisβ€’3y ago
If that's internal code that you own then you should just fix it IMO. Nesting forms isn't okay
Louis
Louisβ€’3y ago
Has someone been documenting their solutions? awesome a nice idea if so
EvokeMe
EvokeMeβ€’3y ago
Yep, yep! πŸ™‚ Inside vite a couple of nice libs like: generouted U can take a look folder: tech is about different things! πŸ™‚ And issues - it's about solutions.
Louis
Louisβ€’3y ago
Very nice! That's a really cool idea
ortunado
ortunadoOPβ€’3y ago
May I ask, how would I edit it, if the 2nd form is, for example, nested deeper in divs?
EvokeMe
EvokeMeβ€’3y ago
Don't know about any depth, maybe need to go to xpath.
ortunado
ortunadoOPβ€’3y ago
ok thanks
EvokeMe
EvokeMeβ€’3y ago
Solved. Example in repo updated @ortunado
function* evaluteNodes(result, node) {
while ((node = result.iterateNext())) yield node
}

const evaluate = () => [
...evaluteNodes(
document.evaluate(
`//form[@data-form="Form1"]//input[not(ancestor::form[@data-form="Form2"])]`,
document,
null,
XPathResult.ANY_TYPE,
null,
),
),
]
function* evaluteNodes(result, node) {
while ((node = result.iterateNext())) yield node
}

const evaluate = () => [
...evaluteNodes(
document.evaluate(
`//form[@data-form="Form1"]//input[not(ancestor::form[@data-form="Form2"])]`,
document,
null,
XPathResult.ANY_TYPE,
null,
),
),
]
ortunado
ortunadoOPβ€’3y ago
@EvokeMe Thanks for your persistence, what a interesting way to solve it. ❀️
Unknown User
Unknown Userβ€’3y ago
Message Not Public
Sign In & Join Server To View
reactibot
reactibotβ€’3y ago
This thread hasn’t had any activity in 12 hours, so it’s now locked. Threads are closed automatically after 12 hours. If you have a followup question, you may want to reply to this thread so other members know they're related. https://discord.com/channels/102860784329052160/565213527673929729/1039590471149813850