mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-21 14:47:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
166
toolkit/modules/FormLikeFactory.jsm
Normal file
166
toolkit/modules/FormLikeFactory.jsm
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["FormLikeFactory"];
|
||||
|
||||
const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
||||
|
||||
/**
|
||||
* A factory to generate FormLike objects that represent a set of related fields
|
||||
* which aren't necessarily marked up with a <form> element. FormLike's emulate
|
||||
* the properties of an HTMLFormElement which are relevant to form tasks.
|
||||
*/
|
||||
let FormLikeFactory = {
|
||||
_propsFromForm: [
|
||||
"action",
|
||||
"autocomplete",
|
||||
"ownerDocument",
|
||||
],
|
||||
|
||||
/**
|
||||
* Create a FormLike object from a <form>.
|
||||
*
|
||||
* @param {HTMLFormElement} aForm
|
||||
* @return {FormLike}
|
||||
* @throws Error if aForm isn't an HTMLFormElement
|
||||
*/
|
||||
createFromForm(aForm) {
|
||||
if (!(aForm instanceof Ci.nsIDOMHTMLFormElement)) {
|
||||
throw new Error("createFromForm: aForm must be a nsIDOMHTMLFormElement");
|
||||
}
|
||||
|
||||
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 <input> in a document.
|
||||
*
|
||||
* If the field is in a <form>, construct the FormLike from the form.
|
||||
* Otherwise, create a FormLike with a rootElement (wrapper) according to
|
||||
* heuristics. Currently all <input> not in a <form> are one FormLike 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 <form>.
|
||||
*
|
||||
* Note that two FormLikes created from the same field won't return the same FormLike object.
|
||||
* Use the `rootElement` property on the FormLike as a key instead.
|
||||
*
|
||||
* @param {HTMLInputElement} aField - a field in a document
|
||||
* @return {FormLike}
|
||||
* @throws Error if aField isn't a password or username field in a document
|
||||
*/
|
||||
createFromField(aField) {
|
||||
if (!(aField instanceof Ci.nsIDOMHTMLInputElement) ||
|
||||
!aField.ownerDocument) {
|
||||
throw new Error("createFromField requires a field in a document");
|
||||
}
|
||||
|
||||
let rootElement = this.findRootForField(aField);
|
||||
if (rootElement instanceof Ci.nsIDOMHTMLFormElement) {
|
||||
return this.createFromForm(rootElement);
|
||||
}
|
||||
|
||||
let doc = aField.ownerDocument;
|
||||
let elements = [];
|
||||
for (let el of rootElement.querySelectorAll("input")) {
|
||||
// Exclude elements inside the rootElement that are already in a <form> as
|
||||
// they will be handled by their own FormLike.
|
||||
if (!el.form) {
|
||||
elements.push(el);
|
||||
}
|
||||
}
|
||||
let formLike = {
|
||||
action: doc.baseURI,
|
||||
autocomplete: "on",
|
||||
elements,
|
||||
ownerDocument: doc,
|
||||
rootElement,
|
||||
};
|
||||
|
||||
this._addToJSONProperty(formLike);
|
||||
return formLike;
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine the Element that encapsulates the related fields. For example, if
|
||||
* a page contains a login form and a checkout form which are "submitted"
|
||||
* separately, and the username field is passed in, ideally this would return
|
||||
* an ancestor Element of the username and password fields which doesn't
|
||||
* include any of the checkout fields.
|
||||
*
|
||||
* @param {HTMLInputElement} aField - a field in a document
|
||||
* @return {HTMLElement} - the root element surrounding related fields
|
||||
*/
|
||||
findRootForField(aField) {
|
||||
if (aField.form) {
|
||||
return aField.form;
|
||||
}
|
||||
|
||||
return aField.ownerDocument.documentElement;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a `toJSON` property to a FormLike so logging which ends up going
|
||||
* through dump doesn't include usless garbage from DOM objects.
|
||||
*/
|
||||
_addToJSONProperty(aFormLike) {
|
||||
function prettyElementOutput(aElement) {
|
||||
let idText = aElement.id ? "#" + aElement.id : "";
|
||||
let classText = "";
|
||||
for (let className of aElement.classList) {
|
||||
classText += "." + className;
|
||||
}
|
||||
return `<${aElement.nodeName + idText + classText}>`;
|
||||
}
|
||||
|
||||
Object.defineProperty(aFormLike, "toJSON", {
|
||||
value: () => {
|
||||
let cleansed = {};
|
||||
for (let key of Object.keys(aFormLike)) {
|
||||
let value = aFormLike[key];
|
||||
let cleansedValue = value;
|
||||
|
||||
switch (key) {
|
||||
case "elements": {
|
||||
cleansedValue = [];
|
||||
for (let element of value) {
|
||||
cleansedValue.push(prettyElementOutput(element));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "ownerDocument": {
|
||||
cleansedValue = {
|
||||
location: {
|
||||
href: value.location.href,
|
||||
},
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
case "rootElement": {
|
||||
cleansedValue = prettyElementOutput(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cleansed[key] = cleansedValue;
|
||||
}
|
||||
return cleansed;
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue