Bug 1437512 - Part 1 - Support "panelview" elements located anywhere in the document. r=Gijs draft
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Mon, 12 Feb 2018 16:44:00 +0000
changeset 753910 435c6740fed8920a6223798d54ea4265ea8043f6
parent 753909 88ff71918246c90d35c429cb4b04691b3f1001c0
child 753911 750cd995b6f84dea1c36992c0e66ea3e01fee281
child 754418 454be547dc43070a4e1bf90ccd49b07a8622b8fe
child 754452 87c460c36b5a93da0f8bfcc2156910cbb0060a50
push id98719
push userpaolo.mozmail@amadzone.org
push dateMon, 12 Feb 2018 17:22:56 +0000
reviewersGijs
bugs1437512
milestone60.0a1
Bug 1437512 - Part 1 - Support "panelview" elements located anywhere in the document. r=Gijs The showSubView public method now aligns with its callers and doesn't return a Promise anymore. The showMainView method still returns a Promise because at the moment it is used externally for asynchronous cleanup. MozReview-Commit-ID: FcnEx5f5HKh
browser/components/customizableui/PanelMultiView.jsm
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -476,33 +476,56 @@ this.PanelMultiView = class extends this
     let subviews = Array.from(viewNodeContainer.childNodes);
     for (let subview of subviews) {
       // XBL lists the 'children' XBL element explicitly. :-(
       if (subview.nodeName != "children")
         this._panelViewCache.appendChild(subview);
     }
   }
 
+  /**
+   * Slides in the specified view as a subview.
+   *
+   * @param viewIdOrNode
+   *        DOM element or string ID of the <panelview> to display.
+   * @param anchor
+   *        DOM element that triggered the subview, which will be highlighted
+   *        and whose "label" attribute will be used for the title of the
+   *        subview when a "title" attribute is not specified.
+   */
+  showSubView(viewIdOrNode, anchor) {
+    let viewNode = typeof viewIdOrNode == "string" ?
+                   this.document.getElementById(viewIdOrNode) : viewIdOrNode;
+    if (!viewNode) {
+      throw new Error(`Subview ${viewIdOrNode} doesn't exist.`);
+    }
+
+    this._showView(viewNode, anchor);
+  }
+
+  /**
+   * Navigates backwards by sliding out the most recent subview.
+   */
   goBack() {
     if (this.openViews.length < 2) {
       // This may be called by keyboard navigation or external code when only
       // the main view is open.
       return;
     }
 
     let previous = this.openViews.pop().node;
     let current = this._currentSubView;
-    this.showSubView(current, null, previous);
+    this._showView(current, null, previous);
   }
 
   showMainView() {
     if (!this.node || !this._mainViewId)
       return Promise.resolve();
 
-    return this.showSubView(this._mainView);
+    return this._showView(this._mainView);
   }
 
   /**
    * Ensures that all the panelviews, that are currently part of this instance,
    * are hidden, except one specifically.
    *
    * @param {panelview} [nextPanelView]
    *        The PanelView object to ensure is visible. Optional.
@@ -522,62 +545,54 @@ this.PanelMultiView = class extends this
 
     if (!this.openViews.includes(nextPanelView))
       this.openViews.push(nextPanelView);
 
     nextPanelView.current = true;
     this.showingSubView = nextPanelView.node.id != this._mainViewId;
   }
 
-  showSubView(aViewId, aAnchor, aPreviousView) {
+  _showView(viewNode, anchor, previousView) {
     this._currentShowPromise = (async () => {
-      // Support passing in the node directly.
-      let viewNode = typeof aViewId == "string" ? this.node.querySelector("#" + aViewId) : aViewId;
-      if (!viewNode) {
-        viewNode = this.document.getElementById(aViewId);
-        if (viewNode) {
-          this._viewStack.appendChild(viewNode);
-        } else {
-          throw new Error(`Subview ${aViewId} doesn't exist!`);
-        }
-      } else if (viewNode.parentNode == this._panelViewCache) {
-        this._viewStack.appendChild(viewNode);
-      }
-
       let nextPanelView = PanelView.forNode(viewNode);
       this.knownViews.add(nextPanelView);
 
       viewNode.panelMultiView = this.node;
 
-      let previousViewNode = aPreviousView || this._currentSubView;
+      let previousViewNode = previousView || this._currentSubView;
+
+      if (viewNode.parentNode != this._viewStack) {
+        this._viewStack.appendChild(viewNode);
+      }
+
       // If the panelview to show is the same as the previous one, the 'ViewShowing'
       // event has already been dispatched. Don't do it twice.
       let showingSameView = viewNode == previousViewNode;
 
       let prevPanelView = PanelView.forNode(previousViewNode);
       prevPanelView.captureKnownSize();
 
       this._viewShowing = viewNode;
 
-      let reverse = !!aPreviousView;
+      let reverse = !!previousView;
       if (!reverse) {
         // We are opening a new view, either because we are navigating forward
         // or because we are showing the main view. Some properties of the view
         // may vary between panels, so we make sure to update them every time.
         // Firstly, make sure that the header matches how the view was opened.
         nextPanelView.headerText = viewNode.getAttribute("title") ||
-                                   (aAnchor && aAnchor.getAttribute("label"));
+                                   (anchor && anchor.getAttribute("label"));
         // The main view of a panel can be a subview in another one.
         let isMainView = viewNode.id == this._mainViewId;
         nextPanelView.mainview = isMainView;
         // The constrained width of subviews may also vary between panels.
         nextPanelView.minMaxWidth = isMainView ? 0 : prevPanelView.knownWidth;
       }
 
-      if (aAnchor) {
+      if (anchor) {
         viewNode.classList.add("PanelUI-subView");
       }
 
       if (!showingSameView || !viewNode.hasAttribute("current")) {
         // Emit the ViewShowing event so that the widget definition has a chance
         // to lazily populate the subview with things or perhaps even cancel this
         // whole operation.
         let detail = {
@@ -602,17 +617,17 @@ this.PanelMultiView = class extends this
           return;
         }
       }
 
       // Now we have to transition the panel. If we've got an older transition
       // still running, make sure to clean it up.
       await this._cleanupTransitionPhase();
       if (!showingSameView && this._panel.state == "open") {
-        await this._transitionViews(previousViewNode, viewNode, reverse, aAnchor);
+        await this._transitionViews(previousViewNode, viewNode, reverse, anchor);
         nextPanelView.focusSelectedElement();
       } else {
         this.hideAllViewsExcept(nextPanelView);
       }
     })().catch(e => Cu.reportError(e));
     return this._currentShowPromise;
   }