Bug 1307481 - Part 2: Remove OptionsStore to use ES6 default parameters and PanelFactory in Tooltip.js r=jdescottes
☠☠ backed out by 5ddd619ca0c5 ☠ ☠
authorGabriel Luong <gabriel.luong@gmail.com>
Fri, 07 Oct 2016 13:22:47 -0400
changeset 422567 a9f9f561127275de84173d0f536e6d74a6000730
parent 422566 4b037d0911096b355e762561e3d05f65d053baaa
child 422568 91c6a72e5d0d7779aae8fd514c1e18d5e083c8e4
push id31744
push usermwein@mozilla.com
push dateFri, 07 Oct 2016 21:14:49 +0000
reviewersjdescottes
bugs1307481
milestone52.0a1
Bug 1307481 - Part 2: Remove OptionsStore to use ES6 default parameters and PanelFactory in Tooltip.js r=jdescottes
devtools/client/shared/widgets/tooltip/Tooltip.js
--- a/devtools/client/shared/widgets/tooltip/Tooltip.js
+++ b/devtools/client/shared/widgets/tooltip/Tooltip.js
@@ -29,75 +29,16 @@ const POPUP_EVENTS = ["shown", "hidden",
  * attaching some content in it, or using one of the ready-made content types.
  *
  * A convenient `startTogglingOnHover` method may avoid having to register event
  * handlers yourself if the tooltip has to be shown when hovering over a
  * specific element or group of elements (which is usually the most common case)
  */
 
 /**
- * Container used for dealing with optional parameters.
- *
- * @param {Object} defaults
- *        An object with all default options {p1: v1, p2: v2, ...}
- * @param {Object} options
- *        The actual values.
- */
-function OptionsStore(defaults, options) {
-  this.defaults = defaults || {};
-  this.options = options || {};
-}
-
-OptionsStore.prototype = {
-  /**
-   * Get the value for a given option name.
-   * @return {Object} Returns the value for that option, coming either for the
-   *         actual values that have been set in the constructor, or from the
-   *         defaults if that options was not specified.
-   */
-  get: function (name) {
-    if (typeof this.options[name] !== "undefined") {
-      return this.options[name];
-    }
-    return this.defaults[name];
-  }
-};
-
-/**
- * The low level structure of a tooltip is a XUL element (a <panel>).
- */
-var PanelFactory = {
-  /**
-   * Get a new XUL panel instance.
-   * @param {XULDocument} doc
-   *        The XUL document to put that panel into
-   * @param {OptionsStore} options
-   *        An options store to get some configuration from
-   */
-  get: function (doc, options) {
-    // Create the tooltip
-    let panel = doc.createElement("panel");
-    panel.setAttribute("hidden", true);
-    panel.setAttribute("ignorekeys", true);
-    panel.setAttribute("animate", false);
-
-    panel.setAttribute("consumeoutsideclicks",
-                       options.get("consumeOutsideClick"));
-    panel.setAttribute("noautofocus", options.get("noAutoFocus"));
-    panel.setAttribute("type", "arrow");
-    panel.setAttribute("level", "top");
-
-    panel.setAttribute("class", "devtools-tooltip theme-tooltip-panel");
-    doc.querySelector("window").appendChild(panel);
-
-    return panel;
-  }
-};
-
-/**
  * Tooltip class.
  *
  * Basic usage:
  *   let t = new Tooltip(xulDoc);
  *   t.content = someXulContent;
  *   t.show();
  *   t.hide();
  *   t.destroy();
@@ -141,27 +82,31 @@ var PanelFactory = {
  *
  * Fires these events:
  * - showing : just before the tooltip shows
  * - shown : when the tooltip is shown
  * - hiding : just before the tooltip closes
  * - hidden : when the tooltip gets hidden
  * - keypress : when any key gets pressed, with keyCode
  */
-function Tooltip(doc, options) {
+function Tooltip(doc, {
+  consumeOutsideClick = false,
+  closeOnKeys = [ESCAPE_KEYCODE],
+  noAutoFocus = true,
+  closeOnEvents = [],
+  } = {}) {
   EventEmitter.decorate(this);
 
   this.doc = doc;
-  this.options = new OptionsStore({
-    consumeOutsideClick: false,
-    closeOnKeys: [ESCAPE_KEYCODE],
-    noAutoFocus: true,
-    closeOnEvents: []
-  }, options);
-  this.panel = PanelFactory.get(doc, this.options);
+  this.consumeOutsideClick = consumeOutsideClick;
+  this.closeOnKeys = closeOnKeys;
+  this.noAutoFocus = noAutoFocus;
+  this.closeOnEvents = closeOnEvents;
+
+  this.panel = this._createPanel();
 
   // Create tooltip toggle helper and decorate the Tooltip instance with
   // shortcut methods.
   this._toggle = new TooltipToggle(this);
   this.startTogglingOnHover = this._toggle.start.bind(this._toggle);
   this.stopTogglingOnHover = this._toggle.stop.bind(this._toggle);
 
   // Emit show/hide events when the panel does.
@@ -180,28 +125,27 @@ function Tooltip(doc, options) {
   // Listen to keypress events to close the tooltip if configured to do so
   let win = this.doc.querySelector("window");
   this._onKeyPress = event => {
     if (this.panel.hidden) {
       return;
     }
 
     this.emit("keypress", event.keyCode);
-    if (this.options.get("closeOnKeys").indexOf(event.keyCode) !== -1 &&
+    if (this.closeOnKeys.indexOf(event.keyCode) !== -1 &&
         this.isShown()) {
       event.stopPropagation();
       this.hide();
     }
   };
   win.addEventListener("keypress", this._onKeyPress, false);
 
   // Listen to custom emitters' events to close the tooltip
   this.hide = this.hide.bind(this);
-  let closeOnEvents = this.options.get("closeOnEvents");
-  for (let {emitter, event, useCapture} of closeOnEvents) {
+  for (let {emitter, event, useCapture} of this.closeOnEvents) {
     for (let add of ["addEventListener", "on"]) {
       if (add in emitter) {
         emitter[add](event, this.hide, useCapture);
         break;
       }
     }
   }
 }
@@ -286,18 +230,17 @@ Tooltip.prototype = {
     for (let eventName of POPUP_EVENTS) {
       this.panel.removeEventListener("popup" + eventName,
         this["_onPopup" + eventName], false);
     }
 
     let win = this.doc.querySelector("window");
     win.removeEventListener("keypress", this._onKeyPress, false);
 
-    let closeOnEvents = this.options.get("closeOnEvents");
-    for (let {emitter, event, useCapture} of closeOnEvents) {
+    for (let {emitter, event, useCapture} of this.closeOnEvents) {
       for (let remove of ["removeEventListener", "off"]) {
         if (remove in emitter) {
           emitter[remove](event, this.hide, useCapture);
           break;
         }
       }
     }
 
@@ -435,12 +378,33 @@ Tooltip.prototype = {
 
     // load the document from url into the iframe
     iframe.setAttribute("src", url);
 
     // Put the iframe in the tooltip
     this.content = iframe;
 
     return def.promise;
+  },
+
+  /**
+   * Create the tooltip panel
+   */
+  _createPanel() {
+    let panel = this.doc.createElement("panel");
+    panel.setAttribute("hidden", true);
+    panel.setAttribute("ignorekeys", true);
+    panel.setAttribute("animate", false);
+
+    panel.setAttribute("consumeoutsideclicks",
+                       this.consumeOutsideClick);
+    panel.setAttribute("noautofocus", this.noAutoFocus);
+    panel.setAttribute("type", "arrow");
+    panel.setAttribute("level", "top");
+
+    panel.setAttribute("class", "devtools-tooltip theme-tooltip-panel");
+    this.doc.querySelector("window").appendChild(panel);
+
+    return panel;
   }
 };
 
 module.exports = Tooltip;