From 85e81685504566bb2bdc35432f3050d76e617f36 Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Tue, 31 Dec 2024 15:20:47 +0100 Subject: [PATCH 1/3] maint: Align syslab.com maintainer name to now-used wording. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bbc274b79..923f789ac 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ }, "maintainers": [ { - "name": "Syslab.com GmbH", + "name": "syslab.com GmbH", "email": "info@syslab.com", "url": "http://www.syslab.com" }, From 8539df1be9a1810422b3189606f9c077580c3351 Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Tue, 31 Dec 2024 17:17:37 +0100 Subject: [PATCH 2/3] feat(core dom): Add find_inputs to find all inputs in a node tree, including the node itself. --- src/core/dom.js | 13 ++++++++++++- src/core/dom.test.js | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/core/dom.js b/src/core/dom.js index 01529d838..08cb53a8a 100644 --- a/src/core/dom.js +++ b/src/core/dom.js @@ -6,6 +6,9 @@ const logger = logging.getLogger("core dom"); const DATA_PREFIX = "__patternslib__data_prefix__"; const DATA_STYLE_DISPLAY = "__patternslib__style__display"; +const INPUT_SELECTOR = "input, select, textarea, button"; + + /** * Return an array of DOM nodes. * @@ -571,17 +574,25 @@ const find_form = (el) => { const form = el.closest(".pat-subform") || // Special Patternslib subform concept has precedence. el.form || - el.querySelector("input, select, textarea, button")?.form || + el.querySelector(INPUT_SELECTOR)?.form || el.closest("form"); return form; }; +/** + * Find any input type. + */ +const find_inputs = (el) => { + return querySelectorAllAndMe(el, INPUT_SELECTOR); +}; + const dom = { toNodeArray: toNodeArray, querySelectorAllAndMe: querySelectorAllAndMe, wrap: wrap, hide: hide, show: show, + find_inputs: find_inputs, find_parents: find_parents, find_scoped: find_scoped, get_parents: get_parents, diff --git a/src/core/dom.test.js b/src/core/dom.test.js index 1283e8e29..caa17cbcb 100644 --- a/src/core/dom.test.js +++ b/src/core/dom.test.js @@ -1017,3 +1017,44 @@ describe("find_form", function () { expect(dom.find_form(el)).toBe(subform); }); }); + +describe("find_inputs", () => { + it("finds an input within a node structure.", (done) => { + const wrapper = document.createElement("div"); + wrapper.innerHTML = ` +

hello

+
+
+ +
+ + +
+ + `; + const inputs = dom.find_inputs(wrapper); + const input_types = inputs.map((node) => node.nodeName); + + expect(inputs.length).toBe(4); + expect(input_types.includes("INPUT")).toBeTruthy(); + expect(input_types.includes("SELECT")).toBeTruthy(); + expect(input_types.includes("TEXTAREA")).toBeTruthy(); + expect(input_types.includes("BUTTON")).toBeTruthy(); + + done(); + }); + + it("finds the input on the node itself.", (done) => { + const wrapper = document.createElement("input"); + const inputs = dom.find_inputs(wrapper); + const input_types = inputs.map((node) => node.nodeName); + + expect(inputs.length).toBe(1); + expect(input_types.includes("INPUT")).toBeTruthy(); + + done(); + }); +}); From 5afecb881fa091332b56632811cc790a0fe83f7d Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Tue, 31 Dec 2024 17:19:43 +0100 Subject: [PATCH 3/3] feat(pat-depends): Support for required fields. If a dependend field is required but not shown, remove the required attribute Restore it once the dependend field is shown. --- src/pat/depends/depends.js | 25 +++++++++++++++++++++++++ src/pat/depends/index.html | 1 + 2 files changed, 26 insertions(+) diff --git a/src/pat/depends/depends.js b/src/pat/depends/depends.js index 2cc2a5e8c..6a01742ee 100644 --- a/src/pat/depends/depends.js +++ b/src/pat/depends/depends.js @@ -1,5 +1,6 @@ import $ from "jquery"; import Base from "../../core/base"; +import dom from "../../core/dom"; import utils from "../../core/utils"; import logging from "../../core/logging"; import Parser from "../../core/parser"; @@ -34,6 +35,7 @@ export default Base.extend({ } let state = handler.evaluate(); + this.set_input_state(state); switch (options.action) { case "show": utils.hideOrShow($el, state, options, this.name); @@ -77,6 +79,28 @@ export default Base.extend({ } }, + set_input_state(enabled) { + // If not enabled, remove any `required` attributes on input fields. + // Otherwise restore them. + const inputs = dom.find_inputs(this.el); + + for (const el of inputs) { + if (enabled) { + const required = el.dataset.required; + if (typeof required !== "undefined") { + el.setAttribute("required", required); + delete el.dataset.required; + } + } else { + const required = el.getAttribute("required", null); + if (required !== null) { + el.dataset.required = required; + el.removeAttribute("required"); + } + } + } + }, + async onReset(event) { const dependents = $(event.target).data("patDepends.dependents"); await utils.timeout(50); @@ -130,6 +154,7 @@ export default Base.extend({ const $depdendent = $(dependent); const state = handler.evaluate(); + this.set_input_state(state); switch (options.action) { case "show": utils.hideOrShow($depdendent, state, options, this.name); diff --git a/src/pat/depends/index.html b/src/pat/depends/index.html index 2f0df129c..0c6b3ef13 100644 --- a/src/pat/depends/index.html +++ b/src/pat/depends/index.html @@ -45,6 +45,7 @@

pat-depends with checkboxes, radiobuttons and multiselects

data-pat-autosuggest="words: Smooth Cayenne, Kew, Natal Queen, Singapore Spanish, Paulista, Perolera; allow-new-words: false; max-selection-size: 1;" type="text" + required />