/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * A factory to generate FormLike objects that represent a set of related fields * which aren't necessarily marked up with a
element. FormLike's emulate * the properties of an HTMLFormElement which are relevant to form tasks. */ export let FormLikeFactory = { _propsFromForm: ["action", "autocomplete", "ownerDocument"], /** * Create a FormLike object from a . * * @param {HTMLFormElement} aForm * @return {FormLike} * @throws Error if aForm isn't an HTMLFormElement */ createFromForm(aForm) { if (!HTMLFormElement.isInstance(aForm)) { throw new Error("createFromForm: aForm must be a HTMLFormElement"); } let formLike = { elements: [...aForm.elements], rootElement: aForm, }; for (let prop of this._propsFromForm) { formLike[prop] = aForm[prop]; } this._addToJSONProperty(formLike); return formLike; }, /** * Create a FormLike object from an element that is the root of the document * * Currently all not in a are one LoginForm but this * shouldn't be relied upon as the heuristics may change to detect multiple * "forms" (e.g. registration and login) on one page with a . * * @param {HTMLElement} aDocumentRoot * @param {Object} aOptions * @param {boolean} [aOptions.ignoreForm = false] * True to always use owner document as the `form` * @return {formLike} * @throws Error if aDocumentRoot is null */ createFromDocumentRoot(aDocumentRoot, aOptions = {}) { if (!aDocumentRoot) { throw new Error("createFromDocumentRoot: aDocumentRoot is null"); } let formLike = { action: aDocumentRoot.baseURI, autocomplete: "on", ownerDocument: aDocumentRoot.ownerDocument, rootElement: aDocumentRoot, }; // FormLikes can be created when fields are inserted into the DOM. When // many, many fields are inserted one after the other, we create many // FormLikes, and computing the elements list becomes more and more // expensive. Making the elements list lazy means that it'll only // be computed when it's eventually needed (if ever). ChromeUtils.defineLazyGetter(formLike, "elements", function () { let elements = []; for (let el of aDocumentRoot.querySelectorAll("input, select")) { // Exclude elements inside the rootElement that are already in a as // they will be handled by their own FormLike. if (!el.form || aOptions.ignoreForm) { elements.push(el); } } return elements; }); this._addToJSONProperty(formLike); return formLike; }, /** * Create a FormLike object from an //,