PageSourceSearch

https://www.stentor-music.com/common/js/forms/fields/FieldGroup.js?v=255

js stentor-music.com collected 2026-10-10 01:03:01 UTC 3,824 bytes, 128 lines download raw bytes

1; (function (root, factory) {
2    const ns = root.FieldKit = root.FieldKit || {};
3    ns.icons = ns.icons || {};
4
5    factory(ns);
6})(window, function (ns) {
7    class FieldGroup {
8        /** @type {HTMLElement} */
9        host;
10
11        /**
12         * Lookup by id (label anchors, JS that has the element).
13         *
14         * @type {Record<string, Field>}
15         */
16        idMap = {};
17
18        /**
19         * Lookup by name (server payloads, FormData, etc.).
20         *
21         * @type {Record<string, Field>}
22         */
23        nameMap = {};
24
25        /**
26         * @param {HTMLElement} host
27         * @private
28         */
29        constructor(host) {
30            this.host = host;
31        }
32
33        /**
34         * Register a new {@link Field} so it can be looked up by either
35         * its **id** or **name** attribute.
36         *
37         * @param {Field} field
38         * @returns {void}
39         */
40        addField(field) {
41            // always index by id
42            if (field.id) {
43                this.idMap[field.id] = field;
44            }
45
46            // if the element has a `name`, index by that as well
47            const name = field.element.name;
48            if (name) {
49                this.nameMap[name] = field;
50            }
51        }
52
53        /**
54         * Bulk-apply or clear errors on every registered field.
55         *
56         * @param {Object} object
57         * @returns {void}
58         */
59        setErrors(object = {}) {
60            // clear previous errors
61            Object.values(this.idMap).forEach(field => field.clearError());
62
63            // apply fresh ones
64            Object.entries(object).forEach(([key, error]) => {
65                const field = this.idMap[key] || this.nameMap[key]
66                if (!field) {
67                    return;
68                }
69
70                field.setError(error, key);
71            });
72        }
73    }
74
75    /**
76     * Singleton map
77     * @type {WeakMap<HTMLElement, FieldGroup>}
78     */
79    FieldGroup._map = new WeakMap();
80
81    /**
82     * Get or create the {@link FieldGroup} for a given host element.
83     *
84     * @param {HTMLElement} host
85     * @returns {FieldGroup}
86     */
87    FieldGroup.get = function (host) {
88        if (!FieldGroup._map.has(host)) {
89            FieldGroup._map.set(host, new FieldGroup(host));
90        }
91        return FieldGroup._map.get(host);
92    };
93
94    /**
95     * Find the {@link Field} that matches a given **id** / **name**.
96     *
97     * If **scope** is provided, the search is limited to the group hosted by that
98     * element (or the element matched by the selector).  
99     * Without a scope it scans every registered form / `[data-field‑group]`
100     * on the page, falling back to `<body>` as the default group.
101     *
102     * @param {string}                  key      The field's *id* or *name*.
103     * @param {HTMLElement|string|null} [scope]  Host element or CSS selector to restrict the lookup.
104     * @returns {Field|null} The matching {@link Field} instance, or `null` if none is found.
105     */
106    FieldGroup.getField = function (key, scope = null) {
107        // 1. scoped lookup
108        if (scope) {
109            const host = typeof scope === 'string' ? document.querySelector(scope) : scope;
110            const group = FieldGroup.get(host);
111            return group.idMap[key] || group.nameMap[key] || null;
112        }
113
114        // 2. global lookup across every registered group
115        const groups = document.querySelectorAll('form,[data-field-group],body');
116        for (const host of groups) {
117            const group = FieldGroup.get(host);
118            const field = group.idMap[key] || group.nameMap[key];
119            if (field) {
120                return field;
121            }
122        }
123        return null;
124    }
125
126    // Namespace export
127    ns.FieldGroup = FieldGroup;
128});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.