Bug 1565075 - Fix autocomplete click behavior. r=mkmelin,jorgk DONTBUILD
authorAlessandro Castellani <alessandro@thunderbird.net>
Fri, 20 Sep 2019 10:17:50 +0200
changeset 36889 5156145ef2bc381ee7fb019a78a4043c509f5756
parent 36888 41d027b5083466f12c7e633ba703edffe9117935
child 36890 b4cd90465304c1255669d738be976b6145c737f3
push id395
push userclokep@gmail.com
push dateMon, 02 Dec 2019 19:38:57 +0000
reviewersmkmelin, jorgk
bugs1565075
Bug 1565075 - Fix autocomplete click behavior. r=mkmelin,jorgk DONTBUILD
calendar/base/content/dialogs/calendar-event-dialog-attendees-custom-elements.js
mail/components/addrbook/content/abEditListDialog.xul
mail/components/addrbook/content/abMailListDialog.xul
mail/components/compose/content/addressingWidgetOverlay.js
mail/components/compose/content/messengercompose.xul
mailnews/addrbook/content/abMailListDialog.js
--- a/calendar/base/content/dialogs/calendar-event-dialog-attendees-custom-elements.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog-attendees-custom-elements.js
@@ -620,25 +620,25 @@
 
       // The template could have its fields disabled,
       // that's why we need to reset their status.
       input.removeAttribute("disabled");
       userTypeIcon.removeAttribute("disabled");
       roleStatusIcon.removeAttribute("disabled");
 
       if (this.mIsReadOnly || this.mIsInvitation) {
-        input.setAttribute("disabled", "true");
+        input.setAttribute("disabled", "disabled");
         userTypeIcon.setAttribute("disabled", "true");
         roleStatusIcon.setAttribute("disabled", "true");
       }
 
       // Disable the input-field [name <email>] if this attendee
       // appears to be the organizer.
       if (disableIfOrganizer && attendee && attendee.isOrganizer) {
-        input.setAttribute("disabled", "true");
+        input.setAttribute("disabled", "disabled");
       }
 
       this.mMaxAttendees++;
 
       if (!attendee) {
         attendee = this.createAttendee();
       }
 
@@ -660,16 +660,20 @@
       // Don't set value with null, otherwise autocomplete stops working,
       // but make sure attendee and dirty are set.
       if (inputValue.length) {
         input.value = inputValue;
       }
       input.attendee = attendee;
       input.setAttribute("dirty", "true");
 
+      input.popup.addEventListener("click", () => {
+        this.returnHit(input);
+      });
+
       if (attendee) {
         // Set up userType.
         setElementValue(userTypeIcon, attendee.userType || false, "cutype");
         this.updateTooltip(userTypeIcon);
 
         // Set up role/status icon.
         if (attendee.isOrganizer) {
           roleStatusIcon.setAttribute("class", "status-icon");
@@ -722,40 +726,31 @@
         if (this.mIsReadOnly || this.mIsInvitation) {
           input.setAttribute("disabled", "true");
           roleStatusIcon.setAttribute("disabled", "true");
           userTypeIcon.setAttribute("disabled", "true");
         }
 
         this.mMaxAttendees++;
 
-        input.value = null;
-        input.removeAttribute("value");
+        input.value = "";
         input.attendee = newAttendee;
+        input.popup.addEventListener("click", () => {
+          this.returnHit(input);
+        });
 
         // Set role and participation status.
         roleStatusIcon.setAttribute("class", "role-icon");
         roleStatusIcon.setAttribute("role", "REQ-PARTICIPANT");
         userTypeIcon.setAttribute("cutype", "INDIVIDUAL");
 
         // Set tooltip for rolenames and usertype icon.
         this.updateTooltip(roleStatusIcon);
         this.updateTooltip(userTypeIcon);
 
-        // We always clone the first row. The problem is that the first row could be focused.
-        // When we clone that row, we end up with a cloned XUL textbox that has a focused
-        // attribute set. Therefore we think we're focused and don't properly refocus.
-        // The best solution to this would be to clone a template row that didn't really have
-        // any presentation, rather than using the real visible first row of the listbox.
-        // For now we'll just put in a hack that ensures the focused attribute is never copied
-        // when the node is cloned.
-        if (input.getAttribute("focused") != "") {
-          input.removeAttribute("focused");
-        }
-
         // focus on new input widget
         if (setFocus) {
           this.setFocus(newNode);
         }
       }
       return newNode;
     }
 
--- a/mail/components/addrbook/content/abEditListDialog.xul
+++ b/mail/components/addrbook/content/abEditListDialog.xul
@@ -67,15 +67,14 @@
                       autocompletesearchparam="{}"
                       timeout="300"
                       maxrows="4"
                       completedefaultindex="true"
                       forcecomplete="true"
                       completeselectedindex="true"
                       minresultsforpopup="3"
                       onkeypress="awAbRecipientKeyPress(event, this);"
-                      onkeydown="awRecipientKeyDown(event, this);"
-                      onclick="onRecipientClicked(event, this);"/>
+                      onkeydown="awRecipientKeyDown(event, this);"/>
         </hbox>
       </richlistitem>
     </richlistbox>
   </vbox>
 </dialog>
--- a/mail/components/addrbook/content/abMailListDialog.xul
+++ b/mail/components/addrbook/content/abMailListDialog.xul
@@ -80,15 +80,14 @@
                       autocompletesearchparam="{}"
                       timeout="300"
                       maxrows="4"
                       completedefaultindex="true"
                       forcecomplete="true"
                       completeselectedindex="true"
                       minresultsforpopup="3"
                       onkeypress="awAbRecipientKeyPress(event, this);"
-                      onkeydown="awRecipientKeyDown(event, this);"
-                      onclick="onRecipientClicked(event, this);"/>
+                      onkeydown="awRecipientKeyDown(event, this);"/>
         </hbox>
       </richlistitem>
     </richlistbox>
   </vbox>
 </dialog>
--- a/mail/components/compose/content/addressingWidgetOverlay.js
+++ b/mail/components/compose/content/addressingWidgetOverlay.js
@@ -259,16 +259,19 @@ function CompFields2Recipients(msgCompFi
     );
   }
 }
 
 function awSetInputAndPopupId(inputElem, popupElem, rowNumber) {
   popupElem.id = "addressCol1#" + rowNumber;
   inputElem.id = "addressCol2#" + rowNumber;
   inputElem.setAttribute("aria-labelledby", popupElem.id);
+  inputElem.popup.addEventListener("click", () => {
+    awReturnHit(inputElem);
+  });
 }
 
 /**
  * Set value of the recipient input field at row rowNumber and set up
  * the recipient type menulist.
  *
  * @param inputElem                 recipient input element
  * @param inputValue                recipient value (address)
@@ -879,34 +882,16 @@ function awSetAutoComplete(rowNumber) {
   var selectElem = awGetPopupElement(rowNumber);
   _awSetAutoComplete(selectElem, inputElem);
 }
 
 function awRecipientOnFocus(inputElement) {
   inputElement.select();
 }
 
-function onRecipientClicked(event, inputElement) {
-  // If the clicked element has a "panel" somewhere in its ancestors, it was
-  // inside the auto-complete results popup and we want to advance to next row.
-  let targetNode = event.originalTarget;
-  while (targetNode) {
-    if (targetNode.id.startsWith("addressCol")) {
-      // We're not on the auto-complete popup, so return to avoid
-      // climbing up the hierarchy.
-      return;
-    }
-    if (targetNode.localName == "panel") {
-      awReturnHit(inputElement);
-      return;
-    }
-    targetNode = targetNode.parentNode;
-  }
-}
-
 /**
  * Handles keypress events for the email address inputs (that auto-fill)
  * in the Address Book Mailing List dialogs. When a comma-separated list of
  * addresses is entered on one row, split them into one address per row. Only
  * add a new blank row on "Enter" key. On "Tab" key focus moves to the "Cancel"
  * button.
  *
  * @param {KeyboardEvent} event  The DOM keypress event.
--- a/mail/components/compose/content/messengercompose.xul
+++ b/mail/components/compose/content/messengercompose.xul
@@ -2046,17 +2046,16 @@
                             completedefaultindex="true"
                             forcecomplete="true"
                             completeselectedindex="true"
                             minresultsforpopup="2"
                             ignoreblurwhilesearching="true"
                             onfocus="awRecipientOnFocus(this);"
                             onchange="onRecipientsChanged();"
                             oninput="onRecipientsChanged();"
-                            onclick="onRecipientClicked(event, this);"
                             onkeypress="awRecipientKeyPress(event, this)"
                             onkeydown="awRecipientKeyDown(event, this)"
                             disableonsend="true"/>
               </hbox>
             </richlistitem>
           </richlistbox>
           <hbox id="subject-box">
             <hbox class="aw-firstColBox"/>
--- a/mailnews/addrbook/content/abMailListDialog.js
+++ b/mailnews/addrbook/content/abMailListDialog.js
@@ -210,16 +210,21 @@ function OnLoadNewMailList() {
         firstTextBox.focus();
       },
       0,
       listName
     );
   }
 
   NotifyLoadListeners(directory);
+
+  let input = document.getElementById("addressCol1#1");
+  input.popup.addEventListener("click", () => {
+    awReturnHit(input);
+  });
 }
 
 function EditListOKButton(event) {
   // edit mailing list in database
   if (GetListValue(gEditList, false)) {
     if (gListCard) {
       // modify the list card (for the results pane) from the mailing list
       gListCard.displayName = gEditList.dirName;
@@ -300,16 +305,22 @@ function OnLoadEditList() {
   }
 
   // workaround for bug 118337 - for mailing lists that have more rows than fits inside
   // the display, the value of the textbox inside the new row isn't inherited into the input -
   // the first row then appears to be duplicated at the end although it is actually empty.
   // see awAppendNewRow which copies first row and clears it
   setTimeout(AppendLastRow, 0);
   NotifyLoadListeners(gEditList);
+
+  document.querySelectorAll(`input[is="autocomplete-input"]`).forEach(input => {
+    input.popup.addEventListener("click", () => {
+      awReturnHit(input);
+    });
+  });
 }
 
 function AppendLastRow() {
   AppendNewRowAndSetFocus();
   awFitDummyRows(1);
 
   // focus on first name
   let listName = document.getElementById("ListName");
@@ -332,16 +343,19 @@ function SetInputValue(inputValue, paren
 
   var newNode = templateNode.cloneNode(true);
   parentNode.appendChild(newNode); // we need to insert the new node before we set the value of the select element!
 
   var input = newNode.querySelector(`input[is="autocomplete-input"]`);
   if (input) {
     input.value = inputValue;
     input.setAttribute("id", "addressCol1#" + top.MAX_RECIPIENTS);
+    input.popup.addEventListener("click", () => {
+      awReturnHit(input);
+    });
   }
 }
 
 function awClickEmptySpace(target, setFocus) {
   if (target == null || target.localName != "hbox") {
     return;
   }
 
@@ -416,16 +430,19 @@ function awAppendNewRow(setFocus) {
     }
 
     top.MAX_RECIPIENTS++;
 
     input = newNode.querySelector(`input[is="autocomplete-input"]`);
     if (input) {
       input.value = "";
       input.setAttribute("id", "addressCol1#" + top.MAX_RECIPIENTS);
+      input.popup.addEventListener("click", () => {
+        awReturnHit(input);
+      });
     }
     // Focus the new input widget.
     if (setFocus && input) {
       awSetFocusTo(input);
     }
   }
   return input;
 }