Bug 1166365 - Pluralize dropdown logic. r?Gijs r?margaret draft
authorEitan Isaacson <eitan@monotonous.org>
Thu, 21 Jan 2016 11:25:48 -0800
changeset 331582 7e6b1570ce52a1f8d2476246139526f7a8ee37a8
parent 330984 ea39d4a6232c278dd8d805608a07cf9f4cc4c76b
child 331583 08a4c76dab46ec178465b84cae4035a69d1c94fe
push id11019
push userbmo:eitan@monotonous.org
push dateWed, 17 Feb 2016 17:54:47 +0000
reviewersGijs, margaret
bugs1166365
milestone47.0a1
Bug 1166365 - Pluralize dropdown logic. r?Gijs r?margaret MozReview-Commit-ID: KCayCX4r8xQ
toolkit/components/reader/AboutReader.jsm
toolkit/themes/shared/aboutReaderControls.css
--- a/toolkit/components/reader/AboutReader.jsm
+++ b/toolkit/components/reader/AboutReader.jsm
@@ -200,17 +200,17 @@ AboutReader.prototype = {
           }
         }
         break;
       }
 
       // Triggered by Android user pressing BACK while the banner font-dropdown is open.
       case "Reader:CloseDropdown": {
         // Just close it.
-        this._closeDropdown();
+        this._closeDropdowns();
         break;
       }
 
       case "Reader:Removed": {
         if (message.data.url == this._article.url) {
           if (this._isReadingListItem != 0) {
             this._isReadingListItem = 0;
             this._updateToggleButton();
@@ -262,41 +262,50 @@ AboutReader.prototype = {
 
   handleEvent: function(aEvent) {
     if (!aEvent.isTrusted)
       return;
 
     switch (aEvent.type) {
       case "click":
         let target = aEvent.target;
-        while (target && target.id != "reader-popup")
-          target = target.parentNode;
-        if (!target)
+        if (target.classList.contains('dropdown-toggle')) {
+          this._toggleDropdownClicked(aEvent);
+        } else if (!target.closest('.dropdown-popup')) {
           this._toggleToolbarVisibility();
+        }
+
         break;
       case "scroll":
         let isScrollingUp = this._scrollOffset > aEvent.pageY;
         this._setToolbarVisibility(isScrollingUp);
         this._scrollOffset = aEvent.pageY;
         break;
       case "resize":
         this._updateImageMargins();
+        if (this._isToolbarVertical) {
+          this._win.setTimeout(() => {
+            for (let dropdown of this._doc.querySelectorAll('.dropdown.open')) {
+              this._updatePopupPosition(dropdown);
+            }
+          }, 0);
+        }
         break;
 
       case "devicelight":
         this._handleDeviceLight(aEvent.value);
         break;
 
       case "visibilitychange":
         this._handleVisibilityChange();
         break;
 
       case "unload":
         // Close the Banners Font-dropdown, cleanup Android BackPressListener.
-        this._closeDropdown();
+        this._closeDropdowns();
 
         this._mm.removeMessageListener("Reader:Added", this);
         this._mm.removeMessageListener("Reader:Removed", this);
         this._mm.removeMessageListener("Sidebar:VisibilityChange", this);
         this._mm.removeMessageListener("ReadingList:VisibilityStatus", this);
         this._mm.removeMessageListener("Reader:CloseDropdown", this);
         this._mm.removeMessageListener("Reader:AddButton", this);
         this._mm.removeMessageListener("Reader:RemoveButton", this);
@@ -621,18 +630,17 @@ AboutReader.prototype = {
     });
   },
 
   _getToolbarVisibility: function() {
     return this._toolbarElement.hasAttribute("visible");
   },
 
   _setToolbarVisibility: function(visible) {
-    this._closeDropdown();
-
+    this._closeDropdowns();
     if (this._getToolbarVisibility() === visible) {
       return;
     }
 
     if (visible) {
       this._toolbarElement.setAttribute("visible", true);
     } else {
       this._toolbarElement.removeAttribute("visible");
@@ -928,80 +936,71 @@ AboutReader.prototype = {
    * @param   Localizable string providing UI element usage tip.
    */
   _setButtonTip: function(id, titleEntity) {
     let button = this._doc.getElementById(id);
     button.setAttribute("title", gStrings.GetStringFromName(titleEntity));
   },
 
   _setupStyleDropdown: function() {
-    let doc = this._doc;
-    let win = this._win;
+    let dropdownToggle = this._doc.querySelector("#style-dropdown .dropdown-toggle");
+    dropdownToggle.setAttribute("title", gStrings.GetStringFromName("aboutReader.toolbar.typeControls"));
+  },
 
-    let dropdown = doc.getElementById("style-dropdown");
+  _updatePopupPosition: function(dropdown) {
     let dropdownToggle = dropdown.querySelector(".dropdown-toggle");
     let dropdownPopup = dropdown.querySelector(".dropdown-popup");
 
-    // Helper function used to position the popup on desktop,
-    // where there is a vertical toolbar.
-    function updatePopupPosition() {
-      let toggleHeight = dropdownToggle.offsetHeight;
-      let toggleTop = dropdownToggle.offsetTop;
-      let popupTop = toggleTop - toggleHeight / 2;
-      dropdownPopup.style.top = popupTop + "px";
-    }
+    let toggleHeight = dropdownToggle.offsetHeight;
+    let toggleTop = dropdownToggle.offsetTop;
+    let popupTop = toggleTop - toggleHeight / 2;
+
+    dropdownPopup.style.top = popupTop + "px";
+  },
+
+  _toggleDropdownClicked: function(event) {
+    let dropdown = event.target.closest('.dropdown');
 
-    if (this._isToolbarVertical) {
-      win.addEventListener("resize", event => {
-        if (!event.isTrusted)
-          return;
+    if (!dropdown)
+      return;
+
+    event.stopPropagation();
 
-        // Wait for reflow before calculating the new position of the popup.
-        win.setTimeout(updatePopupPosition, 0);
-      }, true);
+    if (dropdown.classList.contains("open")) {
+      this._closeDropdowns();
+    } else {
+      this._openDropdown(dropdown);
+      if (this._isToolbarVertical) {
+        this._updatePopupPosition(dropdown);
+      }
     }
-
-    dropdownToggle.setAttribute("title", gStrings.GetStringFromName("aboutReader.toolbar.typeControls"));
-    dropdownToggle.addEventListener("click", event => {
-      if (!event.isTrusted)
-        return;
-
-      event.stopPropagation();
-
-      if (dropdown.classList.contains("open")) {
-        this._closeDropdown();
-      } else {
-        this._openDropdown();
-        if (this._isToolbarVertical) {
-          updatePopupPosition();
-        }
-      }
-    }, true);
   },
 
   /*
    * If the ReaderView banner font-dropdown is closed, open it.
    */
-  _openDropdown: function() {
-    let dropdown = this._doc.getElementById("style-dropdown");
+  _openDropdown: function(dropdown) {
     if (dropdown.classList.contains("open")) {
       return;
     }
 
+    this._closeDropdowns();
+
     // Trigger BackPressListener initialization in Android.
     dropdown.classList.add("open");
     this._mm.sendAsyncMessage("Reader:DropdownOpened", this.viewId);
   },
 
   /*
-   * If the ReaderView banner font-dropdown is opened, close it.
+   * If the ReaderView has open dropdowns, close them.
    */
-  _closeDropdown: function() {
-    let dropdown = this._doc.getElementById("style-dropdown");
-    if (!dropdown.classList.contains("open")) {
-      return;
+  _closeDropdowns: function() {
+    let openDropdowns = this._doc.querySelectorAll(".dropdown.open:not(.keep-open)");
+    for (let dropdown of openDropdowns) {
+      dropdown.classList.remove("open");
     }
 
     // Trigger BackPressListener cleanup in Android.
-    dropdown.classList.remove("open");
-    this._mm.sendAsyncMessage("Reader:DropdownClosed", this.viewId);
-  },
+    if (openDropdowns.length) {
+      this._mm.sendAsyncMessage("Reader:DropdownClosed", this.viewId);
+    }
+  }
 };
--- a/toolkit/themes/shared/aboutReaderControls.css
+++ b/toolkit/themes/shared/aboutReaderControls.css
@@ -115,32 +115,36 @@
   padding: 0;
 }
 
 .dropdown li {
   margin: 0;
   padding: 0;
 }
 
-/*======= Font style popup =======*/
+/*======= Popup =======*/
 
 .dropdown-popup {
   min-width: 300px;
   text-align: start;
   position: absolute;
   left: 48px; /* offset to account for toolbar width */
   z-index: 1000;
   background-color: #fbfbfb;
   visibility: hidden;
   border-radius: 4px;
   border: 1px solid #b5b5b5;
   border-bottom-width: 0;
   box-shadow: 0 1px 12px #666;
 }
 
+.keep-open .dropdown-popup {
+  z-index: initial;
+}
+
 .dropdown-popup > hr {
   display: none;
 }
 
 .open > .dropdown-popup {
   visibility: visible;
 }
 
@@ -149,16 +153,18 @@
   top: 30px; /* offset arrow from top of popup */
   left: -16px;
   width: 24px;
   height: 24px;
   background-image: url("chrome://global/skin/reader/RM-Type-Controls-Arrow.svg");
   display: block;
 }
 
+/*======= Font style popup =======*/
+
 #font-type-buttons,
 #font-size-buttons,
 #color-scheme-buttons {
   display: flex;
   flex-direction: row;
 }
 
 #font-type-buttons > button:first-child {