Skip to content

Commit

Permalink
feat(core dom): find_form - find a related form element.
Browse files Browse the repository at this point in the history
Add a function to find a related form element. If called on any element
it would first try to get a input element and get it's associated form -
which can be different and as a last resort to find the element's
enclosing form. Otherwise return undefined.
  • Loading branch information
thet committed Nov 9, 2023
1 parent 8c01058 commit 01b348d
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/core/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,25 @@ const element_uuid = (el) => {
return get_data(el, "uuid");
};

/**
* Find a related form element.
*
* @param {Node} el - The DOM node to start the search from.
* @returns {Node} - The closest form element.
*
* @example
* find_form(document.querySelector("input"));
*/
const find_form = (el) => {
// Prefer input.form which allows for input outside form elements and fall
// back to search for a parent form.
return (
el.form ||
el.querySelector("input, select, textarea, button")?.form ||
el.closest("form")
);
};

const dom = {
toNodeArray: toNodeArray,
querySelectorAllAndMe: querySelectorAllAndMe,
Expand Down Expand Up @@ -585,6 +604,7 @@ const dom = {
get_visible_ratio: get_visible_ratio,
escape_css_id: escape_css_id,
element_uuid: element_uuid,
find_form: find_form,
add_event_listener: events.add_event_listener, // BBB export. TODO: Remove in an upcoming version.
remove_event_listener: events.remove_event_listener, // BBB export. TODO: Remove in an upcoming version.
};
Expand Down
100 changes: 100 additions & 0 deletions src/core/dom.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -903,3 +903,103 @@ describe("element_uuid", function () {
window.crypto.randomUUID = orig_randomUUID;
});
});

describe("find_form", function () {
it("example 1", function () {
document.body.innerHTML = `
<form>
<div id="start"></div>
</form>
`;
const el = document.querySelector("#start");
const form = document.querySelector("form");
expect(dom.find_form(el)).toBe(form);
});

it("example 2", function () {
document.body.innerHTML = `
<form>
<input>
</form>
`;
const el = document.querySelector("input");
const form = document.querySelector("form");
expect(dom.find_form(el)).toBe(form);
});

it("example 3", function () {
document.body.innerHTML = `
<form id="the-form">
</form>
<input form="the-form">
`;
const el = document.querySelector("input");
const form = document.querySelector("#the-form");
expect(dom.find_form(el)).toBe(form);
});

it("example 4", function () {
document.body.innerHTML = `
<form id="the-form">
</form>
<form id="other-form">
<input form="the-form">
</form>
`;
const el = document.querySelector("input");
const form = document.querySelector("#the-form");
expect(dom.find_form(el)).toBe(form);
});

it("example 5", function () {
document.body.innerHTML = `
<form id="the-form">
</form>
<form id="other-form">
<input form="the-form">
</form>
`;
const el = document.querySelector("#other-form");
const form = document.querySelector("#the-form");
expect(dom.find_form(el)).toBe(form);
});

it("example 6", function () {
document.body.innerHTML = `
<form id="the-form">
</form>
<form id="other-form">
<select form="the-form"></select>
</form>
`;
const el = document.querySelector("#other-form");
const form = document.querySelector("#the-form");
expect(dom.find_form(el)).toBe(form);
});

it("example 7", function () {
document.body.innerHTML = `
<form id="the-form">
</form>
<form id="other-form">
<textarea form="the-form"></textarea>
</form>
`;
const el = document.querySelector("#other-form");
const form = document.querySelector("#the-form");
expect(dom.find_form(el)).toBe(form);
});

it("example 8", function () {
document.body.innerHTML = `
<form id="the-form">
</form>
<form id="other-form">
<button form="the-form"></button>
</form>
`;
const el = document.querySelector("#other-form");
const form = document.querySelector("#the-form");
expect(dom.find_form(el)).toBe(form);
});
});

0 comments on commit 01b348d

Please sign in to comment.