Bug 1330111 - Add FormLikeFactory.findRootForField API. r=johannh
☠☠ backed out by 22ec133c5af9 ☠ ☠
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Tue, 31 Jan 2017 23:54:45 -0800
changeset 341054 a0a695d7f3df195ba8c8065b596dfec040ef4583
parent 341053 e0f1b702887202ed0f388943d0598369ebb54b99
child 341055 678b0803aa1c11802436cc8f12ff1c4bdb624572
push id86621
push usermozilla@noorenberghe.ca
push dateTue, 07 Feb 2017 05:12:02 +0000
treeherdermozilla-inbound@d71bc4a09493 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjohannh
bugs1330111
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1330111 - Add FormLikeFactory.findRootForField API. r=johannh MozReview-Commit-ID: 6qo0hVx3J6p
toolkit/modules/FormLikeFactory.jsm
--- a/toolkit/modules/FormLikeFactory.jsm
+++ b/toolkit/modules/FormLikeFactory.jsm
@@ -63,42 +63,61 @@ let FormLikeFactory = {
    * @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");
     }
 
-    if (aField.form) {
-      return this.createFromForm(aField.form);
+    let rootElement = this.findRootForField(aField);
+    if (rootElement instanceof Ci.nsIDOMHTMLFormElement) {
+      return this.createFromForm(rootElement);
     }
 
     let doc = aField.ownerDocument;
     let elements = [];
-    for (let el of doc.documentElement.querySelectorAll("input")) {
+    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",
-      // Exclude elements inside the rootElement that are already in a <form> as
-      // they will be handled by their own FormLike.
       elements,
       ownerDocument: doc,
-      rootElement: doc.documentElement,
+      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) {