Bug 1132301 - Part 3: Hide the Loop dropdowns when the content window loses focus, so mouseLeave workarounds can be removed. r=Standard8, a=lizzard
☠☠ backed out by 9b2e30c662d6 ☠ ☠
authorMike de Boer <mdeboer@mozilla.com>
Fri, 10 Apr 2015 13:23:08 +0200
changeset 265608 c3999b13c644ba1511350539a1ec45a539d5903a
parent 265607 f1064a1b4a2ab8f8e1e9cce0c1c9badf094740a9
child 265609 d83f5a2c95215469d42e0e9300ef4b379926ac2a
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersStandard8, lizzard
bugs1132301
milestone39.0a2
Bug 1132301 - Part 3: Hide the Loop dropdowns when the content window loses focus, so mouseLeave workarounds can be removed. r=Standard8, a=lizzard
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,