Bug 1166365 - Pluralize dropdown logic. r=Gijs,Margaret
authorEitan Isaacson <eitan@monotonous.org>
Thu, 21 Jan 2016 11:25:48 -0800
changeset 286989 51459032ccce51c73fe3b44243ebfef874213065
parent 286981 b6acf4d4fc20431a8ae14bf32cdc6e43a9c0f9ad
child 286990 e3447f8edd06bc0f13e2e201357151e5b92a02a5
push id18032
push usercbook@mozilla.com
push dateMon, 07 Mar 2016 10:38:51 +0000
treeherderfx-team@087905ffec78 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs, Margaret
bugs1166365
milestone47.0a1
Bug 1166365 - Pluralize dropdown logic. r=Gijs,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
@@ -163,17 +163,17 @@ AboutReader.prototype = {
     return _viewId;
   },
 
   receiveMessage: function (message) {
     switch (message.name) {
       // 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:AddButton": {
         if (message.data.id && message.data.image &&
             !this._doc.getElementById(message.data.id)) {
           let btn = this._doc.createElement("button");
           btn.setAttribute("class", "button");
@@ -204,42 +204,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)
-          this._closeDropdown();
+        if (target.classList.contains('dropdown-toggle')) {
+          this._toggleDropdownClicked(aEvent);
+        } else if (!target.closest('.dropdown-popup')) {
+          this._closeDropdowns();
+        }
         break;
       case "scroll":
-        this._closeDropdown();
+        this._closeDropdowns();
         let isScrollingUp = this._scrollOffset > aEvent.pageY;
         this._setSystemUIVisibility(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:CloseDropdown", this);
         this._mm.removeMessageListener("Reader:AddButton", this);
         this._mm.removeMessageListener("Reader:RemoveButton", this);
         this._windowUnloaded = true;
         break;
     }
   },
@@ -713,80 +721,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 {