Bug 1132301: Part 3 - hide the Loop dropdowns when the content window loses focus, so mouseLeave workarounds can be removed. r=Standard8
☠☠ backed out by 3f3bb18b9f04 ☠ ☠
authorMike de Boer <mdeboer@mozilla.com>
Fri, 27 Mar 2015 14:31:55 +0100
changeset 266452 d241102c104c2a9d1eef2a84efcae657c7f3d967
parent 266451 7d3633bdd4a33914fccbb1d7d7eced48018d865a
child 266453 0e57fb772be5ffe2628824d30fc562a4cf75e571
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersStandard8
bugs1132301
milestone39.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 1132301: Part 3 - hide the Loop dropdowns when the content window loses focus, so mouseLeave workarounds can be removed. r=Standard8
browser/components/loop/content/js/panel.js
browser/components/loop/content/js/panel.jsx
browser/components/loop/content/shared/js/mixins.js
browser/components/loop/test/desktop-local/panel_test.js
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -162,18 +162,17 @@ loop.panel = (function(_, mozL10n) {
                               mozL10n.get("display_name_available_status");
 
       return (
         React.createElement("div", {className: "dropdown"}, 
           React.createElement("p", {className: "dnd-status", onClick: this.showDropdownMenu}, 
             React.createElement("span", null, availabilityText), 
             React.createElement("i", {className: availabilityStatus})
           ), 
-          React.createElement("ul", {className: availabilityDropdown, 
-              onMouseLeave: this.hideDropdownMenu}, 
+          React.createElement("ul", {className: availabilityDropdown}, 
             React.createElement("li", {onClick: this.changeAvailability("available"), 
                 className: "dropdown-menu-item dnd-make-available"}, 
               React.createElement("i", {className: "status status-available"}), 
               React.createElement("span", null, mozL10n.get("display_name_available_status"))
             ), 
             React.createElement("li", {onClick: this.changeAvailability("do-not-disturb"), 
                 className: "dropdown-menu-item dnd-make-unavailable"}, 
               React.createElement("i", {className: "status status-dnd"}), 
@@ -340,18 +339,17 @@ loop.panel = (function(_, mozL10n) {
 
     render: function() {
       var cx = React.addons.classSet;
 
       return (
         React.createElement("div", {className: "settings-menu dropdown"}, 
           React.createElement("a", {className: "button-settings", onClick: this.showDropdownMenu, 
              title: mozL10n.get("settings_menu_button_tooltip")}), 
-          React.createElement("ul", {className: cx({"dropdown-menu": true, hide: !this.state.showMenu}), 
-              onMouseLeave: this.hideDropdownMenu}, 
+          React.createElement("ul", {className: cx({"dropdown-menu": true, hide: !this.state.showMenu})}, 
             React.createElement(SettingsDropdownEntry, {label: mozL10n.get("settings_menu_item_settings"), 
                                    onClick: this.handleClickSettingsEntry, 
                                    displayed: false, 
                                    icon: "settings"}), 
             React.createElement(SettingsDropdownEntry, {label: mozL10n.get("settings_menu_item_account"), 
                                    onClick: this.handleClickAccountEntry, 
                                    icon: "account", 
                                    displayed: this._isSignedIn() && navigator.mozLoop.fxAEnabled}), 
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -162,18 +162,17 @@ loop.panel = (function(_, mozL10n) {
                               mozL10n.get("display_name_available_status");
 
       return (
         <div className="dropdown">
           <p className="dnd-status" onClick={this.showDropdownMenu}>
             <span>{availabilityText}</span>
             <i className={availabilityStatus}></i>
           </p>
-          <ul className={availabilityDropdown}
-              onMouseLeave={this.hideDropdownMenu}>
+          <ul className={availabilityDropdown}>
             <li onClick={this.changeAvailability("available")}
                 className="dropdown-menu-item dnd-make-available">
               <i className="status status-available"></i>
               <span>{mozL10n.get("display_name_available_status")}</span>
             </li>
             <li onClick={this.changeAvailability("do-not-disturb")}
                 className="dropdown-menu-item dnd-make-unavailable">
               <i className="status status-dnd"></i>
@@ -340,18 +339,17 @@ loop.panel = (function(_, mozL10n) {
 
     render: function() {
       var cx = React.addons.classSet;
 
       return (
         <div className="settings-menu dropdown">
           <a className="button-settings" onClick={this.showDropdownMenu}
              title={mozL10n.get("settings_menu_button_tooltip")} />
-          <ul className={cx({"dropdown-menu": true, hide: !this.state.showMenu})}
-              onMouseLeave={this.hideDropdownMenu}>
+          <ul className={cx({"dropdown-menu": true, hide: !this.state.showMenu})}>
             <SettingsDropdownEntry label={mozL10n.get("settings_menu_item_settings")}
                                    onClick={this.handleClickSettingsEntry}
                                    displayed={false}
                                    icon="settings" />
             <SettingsDropdownEntry label={mozL10n.get("settings_menu_item_account")}
                                    onClick={this.handleClickAccountEntry}
                                    icon="account"
                                    displayed={this._isSignedIn() && navigator.mozLoop.fxAEnabled} />
--- a/browser/components/loop/content/shared/js/mixins.js
+++ b/browser/components/loop/content/shared/js/mixins.js
@@ -95,25 +95,28 @@ loop.shared.mixins = (function() {
     },
 
     _onBodyClick: function() {
       this.setState({showMenu: false});
     },
 
     componentDidMount: function() {
       this.documentBody.addEventListener("click", this._onBodyClick);
-      this.documentBody.addEventListener("blur", this.hideDropdownMenu);
+      rootObject.addEventListener("blur", this.hideDropdownMenu);
 
       var menu = this.refs.menu;
       if (!menu) {
         return;
       }
 
       // Correct the position of the menu if necessary.
       var menuNode = menu.getDOMNode();
+      if (!menuNode) {
+        return;
+      }
       var menuNodeRect = menuNode.getBoundingClientRect();
       var bodyRect = {
         height: this.documentBody.offsetHeight,
         width: this.documentBody.offsetWidth
       };
 
       // First we check the vertical overflow.
       var y = menuNodeRect.top + menuNodeRect.height;
@@ -125,17 +128,17 @@ loop.shared.mixins = (function() {
       var x = menuNodeRect.left + menuNodeRect.width;
       if (x >= bodyRect.width) {
         menuNode.style.marginLeft = bodyRect.width - x + "px";
       }
     },
 
     componentWillUnmount: function() {
       this.documentBody.removeEventListener("click", this._onBodyClick);
-      this.documentBody.removeEventListener("blur", this.hideDropdownMenu);
+      rootObject.removeEventListener("blur", this.hideDropdownMenu);
     },
 
     showDropdownMenu: function() {
       this.setState({showMenu: true});
     },
 
     hideDropdownMenu: function() {
       this.setState({showMenu: false});
--- a/browser/components/loop/test/desktop-local/panel_test.js
+++ b/browser/components/loop/test/desktop-local/panel_test.js
@@ -23,16 +23,17 @@ describe("loop.panel", function() {
     requests = [];
     // https://github.com/cjohansen/Sinon.JS/issues/393
     fakeXHR.xhr.onCreate = function (xhr) {
       requests.push(xhr);
     };
 
     fakeWindow = {
       close: sandbox.stub(),
+      addEventListener: function() {},
       document: { addEventListener: function(){} }
     };
     loop.shared.mixins.setRootObject(fakeWindow);
 
     notifications = new loop.shared.models.NotificationCollection();
 
     fakeMozLoop = navigator.mozLoop = {
       doNotDisturb: true,